轻松学51单片机--基于普中科技开发板练习蓝桥杯及机器人大赛等(8-DS1302实时时钟)
1、DS1302
DS1302是一款实时时钟芯片,可以用于实时计时和日期显示等应用。它具有低功耗、精度高、芯片体积小等特点,非常适合嵌入式系统和小型电子设备中使用。
DS1302具有多个功能和特性,包括:
-
时钟功能:可以显示年、月、日、时、分、秒,并支持12小时和24小时制。
-
计时功能:可以计时长达99小时59分59秒,并支持计时暂停和复位。
-
闹钟功能:可以设置闹钟时间,并在闹钟时间到达时触发中断。
-
电源监控功能:可以监测电池电压,并在电池电压低于设定阈值时触发中断。
-
数据存储功能:可以存储时钟和计时数据,断电后仍能保持数据不丢失。
-
串行接口:可以通过SPI或I2C接口与主控芯片通信。
DS1302的引脚布局简单明了,包括VCC、GND、RST、CLK、DAT等。
使用DS1302时,需要先通过SPI或I2C接口与主控芯片建立通信,然后通过写入和读取寄存器的方式来控制和获取DS1302的各种功能。
总之,DS1302是一款功能丰富、易于使用的实时时钟芯片,可以广泛应用于各种嵌入式系统和电子设备中。
2、DS1302驱动代码解读
(1)引脚定义
DS1302 与单片机之间能简单地采用同步串行的方式进行通信 仅需用到三个口线 :(1)RES 复位(2)I/O 数据线(3)SCLK串行时钟。
//引脚定义
sbit DS1302_SCLK=P3^6;
sbit DS1302_IO=P3^4;
sbit DS1302_CE=P3^5;
(2)寄存器定义
#define DS1302_SECOND 0x80
#define DS1302_MINUTE 0x82
#define DS1302_HOUR 0x84
#define DS1302_DATE 0x86
#define DS1302_MONTH 0x88
#define DS1302_DAY 0x8A
#define DS1302_YEAR 0x8C
#define DS1302_WP 0x8E
这里定义的寄存器为读寄存器的地址,如果是写需要将命令地址参数最后一位置1。Command|=0x01; //将指令转换为读指令
写命令用于设置时间日期,读命令用于显示时间日期。
(3)定义全局变量时间数组
//时间数组,索引0~6分别为年、月、日、时、分、秒、星期
unsigned char DS1302_Time[]={24,05,16,12,00,00,6};
这里的定义只是本文件内有效,如果要在main文件中的函数中也生效,需要在头文件中加extern进行声明。
(4)DS1302字节读写时序
我们需要根据DS1302的数据手册关于读写时序的定义来完成读写字节函数的代码
读写开始前,CE和SCLK保持低电平。
void DS1302_Init(void)
{DS1302_CE=0;DS1302_SCLK=0;
}
单字节读,先给寄存器的地址,表明读哪个寄存器的值,然后再把寄存器的值读到IO口P3^4上。
unsigned char DS1302_ReadByte(unsigned char Command)
{unsigned char i,Data=0x00;Command|=0x01; //将指令转换为读指令DS1302_CE=1;for(i=0;i<8;i++){DS1302_IO=Command&(0x01<<i);DS1302_SCLK=0;DS1302_SCLK=1;}for(i=0;i<8;i++){DS1302_SCLK=1;DS1302_SCLK=0;if(DS1302_IO){Data|=(0x01<<i);}}DS1302_CE=0;DS1302_IO=0; //读取后将IO设置为0,否则读出的数据会出错return Data;
}
单字节写,先给要写的寄存器地址,然后将数据从IO端口发给DS1302。
void DS1302_WriteByte(unsigned char Command,Data)
{unsigned char i;DS1302_CE=1;for(i=0;i<8;i++){DS1302_IO=Command&(0x01<<i);DS1302_SCLK=1;DS1302_SCLK=0;}for(i=0;i<8;i++){DS1302_IO=Data&(0x01<<i);DS1302_SCLK=1;DS1302_SCLK=0;} DS1302_CE=0;
}
(4)DS1302的读写时间日期
DS1302寄存器存储的时间和日期是以BCD码的形式存储的,因此在设置时间和读出时间的时候需要将十进制转BCD写入DS1302或将BCD转十进制后读取。有一点要注意就是设置时间日期的时候,要把DS1302写保护寄存器0x8E的WP为清零才能进行写入,写完后置1。
void DS1302_SetTime(void)
{DS1302_WriteByte(DS1302_WP,0x00);DS1302_WriteByte(DS1302_YEAR,DS1302_Time[0]/10*16+DS1302_Time[0]%10);//十进制转BCD码后写入DS1302_WriteByte(DS1302_MONTH,DS1302_Time[1]/10*16+DS1302_Time[1]%10);DS1302_WriteByte(DS1302_DATE,DS1302_Time[2]/10*16+DS1302_Time[2]%10);DS1302_WriteByte(DS1302_HOUR,DS1302_Time[3]/10*16+DS1302_Time[3]%10);DS1302_WriteByte(DS1302_MINUTE,DS1302_Time[4]/10*16+DS1302_Time[4]%10);DS1302_WriteByte(DS1302_SECOND,DS1302_Time[5]/10*16+DS1302_Time[5]%10);DS1302_WriteByte(DS1302_DAY,DS1302_Time[6]/10*16+DS1302_Time[6]%10);DS1302_WriteByte(DS1302_WP,0x80);
}void DS1302_ReadTime(void)
{unsigned char Temp;Temp=DS1302_ReadByte(DS1302_YEAR);DS1302_Time[0]=Temp/16*10+Temp%16;//BCD码转十进制后读取Temp=DS1302_ReadByte(DS1302_MONTH);DS1302_Time[1]=Temp/16*10+Temp%16;Temp=DS1302_ReadByte(DS1302_DATE);DS1302_Time[2]=Temp/16*10+Temp%16;Temp=DS1302_ReadByte(DS1302_HOUR);DS1302_Time[3]=Temp/16*10+Temp%16;Temp=DS1302_ReadByte(DS1302_MINUTE);DS1302_Time[4]=Temp/16*10+Temp%16;Temp=DS1302_ReadByte(DS1302_SECOND);DS1302_Time[5]=Temp/16*10+Temp%16;Temp=DS1302_ReadByte(DS1302_DAY);DS1302_Time[6]=Temp/16*10+Temp%16;
}
3、DS1302实现电子钟
(1)实现要求
开机显示设定的时间12:00:00。
矩阵键盘key1被按下为切换数码管显示(数码管显示模式 0-时钟显示,1-闹钟显示,2-日期显示,3-时钟设置,4-闹钟设置5-日期设置)时钟设置,日期设置:将当前时钟读进来进行设置。
在设置界面3-4-5,数码管对应位闪烁。
矩阵键盘key2按下为切换时钟闹钟设置的时分秒,日期的年月日。按一下则切换下一个。
矩阵键盘key3按下是闪烁的时分秒年月日数码管数字加一。
矩阵键盘key4按下是闪烁的时分秒年月日数码管数字减一。
矩阵键盘key5按下为确认键,设置确认后返回到对应的显示界面。
如果时钟走到闹钟的时间,则led0闪烁,按下key6关闭闪烁。
(2)键盘抖动与数码管闪烁
由于在按键驱动里面并没有使用软件消抖,因此如果不进行按键消抖处理,会出现在调整时间闹钟日期按键盘的时候出现按一下数字跳动的厉害。数码管如果不减速,也会出现在设置界面的时候,时、分、秒对应的数码管频闪,不正常。
unsigned char Key_Slow_Down;//按键减速专用变量 防抖动
unsigned char Seg_Slow_Down;//数码管减速专用变量 防闪烁
在定时器0中断服务函数里面
if(++Key_Slow_Down == 10) Key_Slow_Down = 0;
if(++Seg_Slow_Down == 600) Seg_Slow_Down = 0;
对变量累加,1ms一次,按键加到10ms,Key_Slow_Down=0,而在按键处理函数中。
只有Key_Slow_Down=0的时候才会执行按键相应的动作,否则由于return的存在,后面的代码将不会执行。同理数码管也是这样。具体到Key_Slow_Down与Seg_Slow_Down在定时器里的值是多少最合适,可以根据具体场景以及使用的传感器情况来进行设置。
(3)Seg_Disp_Mode数码管显示模式
本实验有6个显示模式, 0-时钟显示,1-闹钟显示,2-日期显示,3-时钟设置,4-闹钟设置5-日期设置。注意对应关系。这个实验和上一个定时器实现电子钟比较类似。就不再赘述了。代码以及仿真图附上,请同学们下载到开发板或者仿真图上验证。