历史上的今天
今天是:2025年04月17日(星期四)
2020年04月17日 | 单片机实现具有掉电记忆功能的计时器
2020-04-17 来源:eefocus
项目描述:
用单片机实现0 ~ 99s的计时,将计时实时显示在LCD上,并用24C02实现掉电记忆。
仿真原理图如下:

C语言代码如下:
/*------------------------
FileName: clock.h
Function: 头文件
Author: Zhang Kaizhou
Date: 2019-6-12 18:07:29
------------------------*/
#include #include #include #define uchar unsigned char #define uint unsigned int /*IIC总线端口定义*/ sbit SDA = P2^0; sbit SCL = P2^1; /*LCD1602显示模块端口定义*/ sbit lcdrs = P1^2; sbit lcdrw = P1^3; sbit lcden = P1^4; /*主函数模块函数声明*/ void writeData24C02(uchar address, uchar dat); void readData24C02(uchar address, uchar * dat); void checkData(uchar * dat); void timerInit(); /*IIC总线模块函数声明*/ void initIIC(); void startIIC(); void responseIIC(); void stopIIC(); void writeDataIIC(uchar dat); void readDataIIC(uchar * dat); /*LCD1602显示模块函数声明*/ void LCDInit(); void display(uchar dat1, uchar dat2); void writeCommand(uchar command); void writeDataLCD(uchar dat); void delay(uchar xms); /*-------------------------------------------- FileName: main.c Function: 用单片机实现0 ~ 99s的计时, 将计时实时显示在LCD上,并用24C02实现掉电记忆; Author: Zhang Kaizhou Date: 2019-6-12 18:06:18 --------------------------------------------*/ #include "clock.h" /*定义全局变量*/ uchar second = 0, count = 0; bit flag = 0; void main(){ LCDInit(); initIIC(); readData24C02(1, &second); // 通过IIC总线将24C02的第1个存储单元中的数据读取到变量second中 checkData(&second); // 首次读取数据时,原来芯片中的数据可能超过100(非法数据) timerInit(); TR0 = 1; // 开始计时 while(1){ display(second / 10, second % 10); if(flag){ flag = 0; writeData24C02(1, second); } } } /*向24C02的任意地址address处写入数据dat*/ void writeData24C02(uchar address, uchar dat){ startIIC(); writeDataIIC(0xa0); // 向IIC总线发送寻址信号,并声明要进行写操作 responseIIC(); writeDataIIC(address); responseIIC(); writeDataIIC(dat); responseIIC(); stopIIC(); } /*从24C02的任意地址address处读出数据到变量dat*/ void readData24C02(uchar address, uchar * dat){ startIIC(); writeDataIIC(0xa0); responseIIC(); writeDataIIC(address); responseIIC(); startIIC(); writeDataIIC(0xa1); // 向IIC总线发送寻址信号,并声明要进行读操作 responseIIC(); readDataIIC(dat); stopIIC(); } /*检测从24C02读取的数据是否合法*/ void checkData(uchar * dat){ if((* dat) > 100){ * dat = 0; } } /*timer初始化*/ void timerInit(){ TMOD = 0x01; // timer0 定时模式 工作方式1(16位定时器) TH0 = (65536 - 46080) / 256; // 系统晶振为11.0592MHz,定时50ms TL0 = (65536 - 46080) % 256; ET0 = 1; // 开定时器0溢出中断 EA = 1; // 开全局中断 } /*timer0溢出中断服务程序*/ void timer0Service() interrupt 1{ TH0 = (65536 - 46080) / 256; // 重装初值 TL0 = (65536 - 46080) % 256; count++; if(count == 20){ // 50ms * 20 = 1s count = 0; second++; flag = 1; if(second == 100){ // 0 ~ 99s second = 0; } } } /*------------------------------ FileName: IIC.c Function: 实现IIC总线的基本操作 Author: Zhang Kaizhou Date: 2019-6-12 18:08:47 ------------------------------*/ #include "clock.h" /*IIC总线初始化*/ void initIIC(){ SCL = 1; _nop_(); SDA = 1; _nop_(); } /*IIC总线启动信号*/ void startIIC(){ // 在SCL高电平期间,SDA产生一个下降沿表示启动 SDA = 1; _nop_(); SCL = 1; _nop_(); SDA = 0; _nop_(); } /*IIC总线应答信号*/ void responseIIC(){ // 从机在SCL高电平期间将SDA拉低表示应答 SDA = 0; _nop_(); SCL = 1; _nop_(); SCL = 0; _nop_(); } /*IIC总线停止信号*/ void stopIIC(){ // 在SCL高电平期间,SDA产生一个上升沿表示停止 SDA = 0; _nop_(); SCL = 1; _nop_(); SDA = 1; _nop_(); } /*向IIC总线写一个字节数据*/ void writeDataIIC(uchar dat){ uchar i, temp; temp = dat; for(i = 0; i < 8; i++){ temp = temp << 1; SCL = 0; _nop_(); SDA = CY; _nop_(); SCL = 1; _nop_(); } SCL = 0; _nop_(); SDA = 1; _nop_(); } /*从IIC总线读一个字节数据*/ void readDataIIC(uchar * dat){ uchar i; SCL = 0; _nop_(); SDA = 1; _nop_(); for(i = 0; i < 8; i++){ SCL = 1; _nop_(); * dat = ((* dat) << 1) | SDA; SCL = 0; _nop_(); } } /*----------------------------- FileName:display.c Function: LCD1602显示函数 Author: Zhang Kaizhou Date: 2019-6-12 18:09:16 ------------------------------*/ #include "clock.h" uchar code table0[] = {"Timekeeping"}; uchar code table1[] = {"Time:"}; uchar code table2[] = {"0123456789"}; uchar num = 0; /*初始化LCD1602的设置*/ void LCDInit(){ uchar i; lcden = 0; // 拉低使能端,准备产生使能高脉冲信号 writeCommand(0x38); // 显示模式设置(16x2, 5x7点阵,8位数据接口) writeCommand(0x0c); // 开显示,不显示光标 writeCommand(0x06); // 写一个字符后地址指针自动加1 writeCommand(0x01); // 显示清零,数据指针清零 /*LCD上电界面*/ writeCommand(0x80); // 将数据指针定位到第一行首 for(i = 0; i < strlen(table0); i++){ writeDataLCD(table0[i]); delay(5); } writeCommand(0x80 + 0x40); // 将数据指针定位到第二行首 for(i = 0; i < strlen(table1); i++){ writeDataLCD(table1[i]); delay(5); } } /*LCD显示函数*/ void display(uchar dat1, uchar dat2){ writeCommand(0x80 + 0x40 + strlen(table1)); writeDataLCD(table2[dat1]); delay(5); writeCommand(0x80 + 0x40 + strlen(table1) + 1); writeDataLCD(table2[dat2]); delay(5); } /*写指令函数*/ void writeCommand(uchar command){ lcdrs = 0; // 命令选择 lcdrw = 0; P0 = command; delay(5); lcden = 1; // 产生一个正脉冲使能信号 delay(5); lcden = 0; } /*写数据函数*/ void writeDataLCD(uchar dat){ lcdrs = 1; // 数据选择 lcdrw = 0; P0 = dat; delay(5); lcden = 1; delay(5); lcden = 0; } /*延时xms函数*/ void delay(uchar xms){ uchar i, j; for(i = xms; i > 0; i--) for(j = 110; j > 0; j--); }
上一篇:51单片机之计时器
史海拾趣
|
观察琳琅满目的电子产品,我们不难发现触摸屏的采用已经越来越普及,从手机到GPS,从数码相机到刚刚上市的iPad,消费者已经不再满足于简单的点击、拉伸,触摸控制技术的发展可谓日新月异。 市场调研机构iSuppli的预测,未来几年全球触摸屏幕设备的 ...… 查看全部问答> |
|
我在网吧,发现网吧的电脑上,系统不允许动态加载驱动程序,凡是有会动态加载驱动程序的比如CPU-Z、或VirtualPC2007安装程序等等都无法执行。我想请教一下到底系统是哪里被设置了,如何才能解开这些限制呢?我就是想在网吧的电脑上使用VPC2007在自 ...… 查看全部问答> |
|
威视锐ZYNQ开发板-ZingSK高清视频接口实例--HDMI 1. 概述ZingSK开发套件采用核心板加底板的方式,方便用户使用自定义的低成本的底板. ZingSK配套的底板也拥有丰富的接口, ZingSK外观如图1. 图1 本实例主要介绍底板上高清多媒体接口HDMI的使用,并通过软硬件协同设计的方法来实现彩条输出.通过ZYNQ ...… 查看全部问答> |
|
msp430 DCO外接电阻(ROSC)设置频率 无效 求助 此为TI官网例程,msp430f2618 DCO外接电阻(ROSC)设置频率,用IAR编译,430仿真器JTAG口下载仿真,单步调试到标志处(如下代码黄色背景)处程序跑飞,不能继续,实在不明白为什么,求高手知道。 (代码说明中下滑线处说这可能影响到JTAG重新建立链 ...… 查看全部问答> |
|
今天做STM32的录音实验,遇到喇叭一直长鸣的问题,请求各位大侠帮忙。情况是这样的,板子是SEM32F4探索者V2.2,插了一个4g的SD卡,开发环境是KEIL5,程序是光盘里面的录音实验原代码,没有改动,编译通过,用JLINK正常下载,程序运行时,喇叭就开始 ...… 查看全部问答> |




