目录
4.2 手动设置时间、重新上电显示最后设置的时间 main.c
1:读取DS1302计时器时间,在LCD1602液晶显示屏上显示。

2:使用按键手动设置DS1302计时器时间,下电后重新上电显示。







-
- //引脚定义
- sbit DS1302_SCLK=P3^6; //时钟针脚 输入. SCLK 用来同步串行接口上的数据动作.此管脚内部有一个
- //40kΩ(典型值)的下拉电阻连接到地
-
- sbit DS1302_IO=P3^4; //数据针脚 推挽输出.I/O 管脚是三线接口的双向数据管脚.此管脚内部有
- //一个 40kΩ(典型值)的下拉电阻连接到地
-
- sbit DS1302_CE=P3^5; //重置位针脚 CE信号在读写时必须保持高电平.此管脚内部有一个 40kΩ(典
- //型值)的下拉电阻连接到地. 注意:先前的数据手册修正把 CE当作
- //RST. 管脚的功能没有改变.

寄存器地址

根据上面的寄存器说明,我们程序中要申明对应的寄存器地址
-
-
-
- //寄存器写入地址/指令定义
- #define DS1302_YEAR 0x8C //年
- #define DS1302_MONTH 0x88 //月
- #define DS1302_DATE 0x86 //日
- #define DS1302_HOUR 0x84 //时
- #define DS1302_MINUTE 0x82 //分
- #define DS1302_SECOND 0x80 //秒
- #define DS1302_WEEK 0x8A //星期
- #define DS1302_WP 0x8E //写保护位
- //控制寄存器的位 7是写保护位,前 7位(位 0至位 6)被强制为 0且读取时总是读 0. 在任
- //何对时钟或 RAM的写操作以前,位 7必须为 0.当为高时,写保护位禁止任何寄存器的写操
- //作. 初始加电状态未定义. 因此,在试图写器件之前应该清除 WP位.

根据上面的时序图我们需要写一个函数,传入寄存器地址,返回对应的数据。
-
- /**
- * 函 数:DS1302读一个字节
- * 参 数:Addr 命令字/DS1302寄存器地址
- * 返 回 值:无
- */
- unsigned char DS1302_ReadByte(unsigned char Addr)
- {
- unsigned char i,Data=0x00;
- Addr|=0x01; //将指令转换为读指令
- DS1302_CE=1; //读写数据时都置高电平
- for(i=0;i<8;i++)
- {
- DS1302_IO=Addr&(0x01<
- DS1302_SCLK=0;
- DS1302_SCLK=1;
- }
- for(i=0;i<8;i++)
- {
- DS1302_SCLK=1;
- DS1302_SCLK=0;
- if(DS1302_IO){Data|=(0x01<
- }
- DS1302_CE=0;
- DS1302_IO=0; //读取后将IO设置为0,否则读出的数据会出错
- return Data;
- }
2.3.2 写数据

同样更具上面的时序图 ,写一个方法传入地址和需要写入的数据,然后将其操作写入到寄存器中。
-
- /**
- * 函 数:DS1302写一个字节
- * 参 数:Addr 命令字/DS1302寄存器地址
- Data 要写入的数据
- * 返 回 值:无
- */
- void DS1302_WriteByte(unsigned char Addr,Data)
- {
- unsigned char i;
- DS1302_CE=1;//读写数据时都置高电平
- /*在IO上先写入寄存器地址*/
- for(i=0;i<8;i++)
- {
- DS1302_IO=Addr&(0x01<//地址
- DS1302_SCLK=1; //高电平
- DS1302_SCLK=0; //低电平
- }
- for(i=0;i<8;i++)
- {
- DS1302_IO=Data&(0x01<
- DS1302_SCLK=1;
- DS1302_SCLK=0;
- }
- DS1302_CE=0;
- }
2.4 BCD码
BCD码(Binary Coded Decimal),用4位二进制数来表示1位十进制数
最小000 表示0 ,最大1001 表示9
例:0001 0011表示13,1000 0101表示85,0001 1010不合法
在十六进制中的体现:0x13表示13,0x85表示85,0x1A不合法
BCD码转十进制:DEC=BCD/16*10+BCD%16; (2位BCD)
十进制转BCD码:BCD=DEC/10*16+DEC%10; (2位BCD)
补充完读写操作如下
- //时间数组,索引0~6分别为年、月、日、时、分、秒、星期
- unsigned char DS1302_Time[]={24,6,26,18,59,55,3};
-
- /**
- * 函 数:DS1302设置时间,调用之后,DS1302_Time数组的数字会被设置到DS1302中
- * 参 数:无
- * 返 回 值:无
- */
- 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_WEEK,DS1302_Time[6]/10*16+DS1302_Time[6]%10);
- DS1302_WriteByte(DS1302_WP,0x80);
- }
-
- /**
- * 函 数:DS1302读取时间,调用之后,DS1302中的数据会被读取到DS1302_Time数组中
- * 参 数:无
- * 返 回 值:无
- */
- 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_WEEK);
- DS1302_Time[6]=Temp/16*10+Temp%16;
- }
2.5 可编程涓流充电器

绝对最大额定值
任何管脚与地之间的电压范围……………………………………………….-0.5V- +7.0V
工作温度范围,商用级……………………………………………………….0°C - +70°C
工作温度范围,工业级(IND)………………………………………………-40°C - +85°C
存储温度范围…………………………………………………………………-55°C - +125°C
焊接温度(导线,10秒钟)………………………………………………………………….260°C
焊接温度(表面安装)………………………………………………见 IPC/JEDEC J-STD-020
超出绝对最大额定值表中列出的应力会使器件产生永久损坏.这些只是额定值,不包括处于或者超出明书
的工作区间所指明的状态的功能性操作. 长期处于绝对最大额定值会影响器件的可靠性

这一块后面做到定时开关机在详细补充。
2.6 时钟动态设置
要做可以设置的时间,首先需要操作按键,我们用独立按键模块来实现。
K1:切换模式(0-显示模式【默认】,1-设置模式)
K2:在设置模式下选中要设置的项【年、月、日、时、分、秒、星期】
K3:实现当前选中项的值-1
K4:实现当前选中项的值+1
- if(KeyNum==2)//按键2按下
- {
- //设置索引加1
- }
- if(KeyNum==4)//按键3按下
- {
- //设置位数字+1
- }
- if(KeyNum==3)//按键3按下
- {
- //设置位数字-1
- }
-
-
-
- if(KeyNum==1)//按键1按下
- {
- if(MODE==0){MODE=1;TimeSetSelect=0;}//功能切换
- else if(MODE==1){MODE=0;DS1302_SetTime();}//保存设置的时间
- }
- switch(MODE)//根据不同的功能执行不同的函数
- {
- case 0:TimeShow();break; //0 显示模式
- case 1:TimeSet();break; //1 设置模式
- }
在设置模式下我们希望设置位闪烁(原理是500毫秒显示空,500毫秒显示数值)
-
- void Timer1_Routine() interrupt 1
- {
- static unsigned int T0Count;
- TL0 = 0x18; //设置定时初值
- TH0 = 0xFC; //设置定时初值
- T0Count++;
- if(T0Count>=500)//每500ms进入一次
- {
- T0Count=0;
- TimeSetFlashFlag=!TimeSetFlashFlag;//闪烁标志位取反
- }
- }
三,创建Keil项目
详细参考:51单片机STC89C52RC——创建Keil项目-CSDN博客
四,代码
LCD1602.c
- #include
-
- //引脚配置:
- sbit LCD_RS=P2^6;
- sbit LCD_RW=P2^5;
- sbit LCD_EN=P2^7;
- #define LCD_DataPort P0
-
- /**
- * 函 数:LCD1602延时函数,12MHz调用可延时1ms
- * 参 数:无
- * 返 回 值:无
- */
- void LCD_Delay()
- {
- unsigned char i, j;
-
- i = 2;
- j = 239;
- do
- {
- while (--j);
- } while (--i);
- }
- /**
- * 函 数:LCD1602写命令
- * 参 数:Command 要写入的命令
- * 返 回 值:无
- */
- void LCD_WriteCommand(unsigned char Command)
- {
- LCD_RS=0;
- LCD_RW=0;
- LCD_DataPort=Command;
- LCD_EN=1;
- LCD_Delay();
- LCD_EN=0;
- LCD_Delay();
- }
- /**
- * 函 数:LCD1602写数据
- * 参 数:Data 要写入的数据
- * 返 回 值:无
- */
- void LCD_WriteData(unsigned char Data)
- {
- LCD_RS=1;
- LCD_RW=0;
- LCD_DataPort=Data;
- LCD_EN=1;
- LCD_Delay();
- LCD_EN=0;
- LCD_Delay();
- }
- /**
- * 函 数:LCD1602设置光标位置
- * 参 数:Line 行位置,范围:1~2
- * 返 回 值:Column 列位置,范围:1~16
- */
- void LCD_SetCursor(unsigned char Line,unsigned char Column)
- {
- if(Line==1)
- {
- LCD_WriteCommand(0x80|(Column-1));
- }
- else if(Line==2)
- {
- LCD_WriteCommand(0x80|(Column-1+0x40));
- }
- }
- /**
- * 函 数:LCD1602初始化函数
- * 参 数:无
- * 返 回 值:无
- */
- void LCD_Init()
- {
- LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
- LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
- LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
- LCD_WriteCommand(0x01);//光标复位,清屏
- }
- /**
- * 函 数:在LCD1602指定位置上显示一个字符
- * 参 数: Line 行位置,范围:1~2,
- * Column 列位置,范围:1~16,
- * Char 要显示的字符
- * 返 回 值:无
- */
- void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
- {
- LCD_SetCursor(Line,Column);
- LCD_WriteData(Char);
- }
- /**
- * 函 数:在LCD1602指定位置开始显示所给字符串
- * 参 数: Line 起始行位置,范围:1~2,
- * Column 起始列位置,范围:1~16,
- * String 要显示的字符串
- * 返 回 值:无
- */
- void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
- {
- unsigned char i;
- LCD_SetCursor(Line,Column);
- for(i=0;String[i]!='\0';i++)
- {
- LCD_WriteData(String[i]);
- }
- }
- /**
- * 函 数:返回值=X的Y次方
- * 参 数:X底数,Y指数
- * 返 回 值:X的Y次方
- */
- int LCD_Pow(int X,int Y)
- {
- unsigned char i;
- int Result=1;
- for(i=0;i
- {
- Result*=X;
- }
- return Result;
- }
- /**
- * 函 数:在LCD1602指定位置开始显示所给数字
- * 参 数: Line 起始行位置,范围:1~2
- * Column 起始列位置,范围:1~16
- * Number 要显示的数字,范围:0~65535
- * Length 要显示数字的长度,范围:1~5
- * 返 回 值:无
- */
- void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
- {
- unsigned char i;
- LCD_SetCursor(Line,Column);
- for(i=Length;i>0;i--)
- {
- LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
- }
- }
- /**
- * 函 数:在LCD1602指定位置开始以有符号十进制显示所给数字
- * 参 数: Line 起始行位置,范围:1~2
- * Column 起始列位置,范围:1~16
- * Number 要显示的数字,范围:-32768~32767
- * Length 要显示数字的长度,范围:1~5
- * 返 回 值:无
- */
- void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
- {
- unsigned char i;
- unsigned int Number1;
- LCD_SetCursor(Line,Column);
- if(Number>=0)
- {
- LCD_WriteData('+');
- Number1=Number;
- }
- else
- {
- LCD_WriteData('-');
- Number1=-Number;
- }
- for(i=Length;i>0;i--)
- {
- LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
- }
- }
- /**
- * 函 数:在LCD1602指定位置开始以十六进制显示所给数字
- * 参 数: Line 起始行位置,范围:1~2
- * Column 起始列位置,范围:1~16
- * Number 要显示的数字,范围:0~0xFFFF
- * Length 要显示数字的长度,范围:1~4
- * 返 回 值:无
- */
- void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
- {
- unsigned char i,SingleNumber;
- LCD_SetCursor(Line,Column);
- for(i=Length;i>0;i--)
- {
- SingleNumber=Number/LCD_Pow(16,i-1)%16;
- if(SingleNumber<10)
- {
- LCD_WriteData(SingleNumber+'0');
- }
- else
- {
- LCD_WriteData(SingleNumber-10+'A');
- }
- }
- }
- /**
- * 函 数:在LCD1602指定位置开始以二进制显示所给数字
- * 参 数: Line 起始行位置,范围:1~2
- * Column 起始列位置,范围:1~16
- * Number 要显示的数字,范围:0~1111 1111 1111 1111
- * Length 要显示数字的长度,范围:1~16
- * 返 回 值:无
- */
- void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
- {
- unsigned char i;
- LCD_SetCursor(Line,Column);
- for(i=Length;i>0;i--)
- {
- LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
- }
- }
LCD1602.h
- #ifndef __LCD1602_H__
- #define __LCD1602_H__
-
- //用户调用函数:
- void LCD_Init();
- void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);
- void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);
- void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
- void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
- void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
- void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
-
- #endif
Delay.c
- /**
- * 函 数:延时函数 毫秒
- * 参 数:ms 延时多少毫秒
- * 返 回 值:无
- */
- void Delay_ms(int ms) //@12.000MHz
- {
- unsigned char data i, j;
- while(ms--)
- {
- i = 2;
- j = 239;
- do
- {
- while (--j);
- } while (--i);
- }
- }
- /**
- * 函 数:延时函数 毫秒
- * 参 数:ms 延时多少毫秒
- * 返 回 值:无
- */
- void Delay_us(int ms) //@12.000MHz
- {
- unsigned char data i, j;
- while(ms--)
- {
- i = 2;
- j = 239;
- do
- {
- while (--j);
- } while (--i);
- }
- }
- /**
- * 函 数:延时函数 10微秒
- * 参 数:无
- * 返 回 值:无
- */
- void Delay_10us(int _10us) //@11.0592MHz
- {
- unsigned char data i;
- while(_10us--)
- {
- i = 2;
- while (--i);
- }
- }
Delay.h
- #ifndef __DELAY_H_
- #defind __DELAY_H_
- void Delay_ms(int ms);
- void Delay_10us(int _10us);
- #endif
DS1302.c
- #include
-
- //引脚定义
- sbit DS1302_SCLK=P3^6; //时钟针脚 输入. SCLK 用来同步串行接口上的数据动作.此管脚内部有一个
- //40kΩ(典型值)的下拉电阻连接到地
-
- sbit DS1302_IO=P3^4; //数据针脚 推挽输出.I/O 管脚是三线接口的双向数据管脚.此管脚内部有
- //一个 40kΩ(典型值)的下拉电阻连接到地
-
- sbit DS1302_CE=P3^5; //重置位针脚 CE信号在读写时必须保持高电平.此管脚内部有一个 40kΩ(典
- //型值)的下拉电阻连接到地. 注意:先前的数据手册修正把 CE当作
- //RST. 管脚的功能没有改变.
-
-
- //寄存器写入地址/指令定义
- #define DS1302_YEAR 0x8C //年
- #define DS1302_MONTH 0x88 //月
- #define DS1302_DATE 0x86 //日
- #define DS1302_HOUR 0x84 //时
- #define DS1302_MINUTE 0x82 //分
- #define DS1302_SECOND 0x80 //秒
- #define DS1302_WEEK 0x8A //星期
- #define DS1302_WP 0x8E //写保护位
- //控制寄存器的位 7是写保护位,前 7位(位 0至位 6)被强制为 0且读取时总是读 0. 在任
- //何对时钟或 RAM的写操作以前,位 7必须为 0.当为高时,写保护位禁止任何寄存器的写操
- //作. 初始加电状态未定义. 因此,在试图写器件之前应该清除 WP位.
-
- //时间数组,索引0~6分别为年、月、日、时、分、秒、星期
- unsigned char DS1302_Time[]={24,6,26,18,59,55,3};
-
- /**
- * 函 数:DS1302初始化
- * 参 数:无
- * 返 回 值:无
- */
- void DS1302_Init(void)
- {
- DS1302_CE=0; //重置数据引脚,没有读写数据时给低电平
- DS1302_SCLK=0; //时钟引脚,没有读写操作时给低电平
- }
-
- /**
- * 函 数:DS1302写一个字节
- * 参 数:Addr 命令字/DS1302寄存器地址
- Data 要写入的数据
- * 返 回 值:无
- */
- void DS1302_WriteByte(unsigned char Addr,Data)
- {
- unsigned char i;
- DS1302_CE=1;//读写数据时都置高电平
- /*在IO上先写入寄存器地址*/
- for(i=0;i<8;i++)
- {
- DS1302_IO=Addr&(0x01<//地址
- DS1302_SCLK=1; //高电平
- DS1302_SCLK=0; //低电平
- }
- for(i=0;i<8;i++)
- {
- DS1302_IO=Data&(0x01<
- DS1302_SCLK=1;
- DS1302_SCLK=0;
- }
- DS1302_CE=0;
- }
-
- /**
- * 函 数:DS1302读一个字节
- * 参 数:Addr 命令字/DS1302寄存器地址
- * 返 回 值:无
- */
- unsigned char DS1302_ReadByte(unsigned char Addr)
- {
- unsigned char i,Data=0x00;
- Addr|=0x01; //将指令转换为读指令
- DS1302_CE=1; //读写数据时都置高电平
- for(i=0;i<8;i++)
- {
- DS1302_IO=Addr&(0x01<
- DS1302_SCLK=0;
- DS1302_SCLK=1;
- }
- for(i=0;i<8;i++)
- {
- DS1302_SCLK=1;
- DS1302_SCLK=0;
- if(DS1302_IO){Data|=(0x01<
- }
- DS1302_CE=0;
- DS1302_IO=0; //读取后将IO设置为0,否则读出的数据会出错
- return Data;
- }
-
- /**
- * 函 数:DS1302设置时间,调用之后,DS1302_Time数组的数字会被设置到DS1302中
- * 参 数:无
- * 返 回 值:无
- */
- 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_WEEK,DS1302_Time[6]/10*16+DS1302_Time[6]%10);
- DS1302_WriteByte(DS1302_WP,0x80);
- }
-
- /**
- * 函 数:DS1302读取时间,调用之后,DS1302中的数据会被读取到DS1302_Time数组中
- * 参 数:无
- * 返 回 值:无
- */
- 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_WEEK);
- DS1302_Time[6]=Temp/16*10+Temp%16;
- }
DS1302.h
- #ifndef __DS1302_H__
- #define __DS1302_H__
-
- //外部可调用时间数组,索引0~6分别为年、月、日、时、分、秒、星期
- extern unsigned char DS1302_Time[];
-
- void DS1302_Init(void);
- void DS1302_WriteByte(unsigned char Addr,Data);
- unsigned char DS1302_ReadByte(unsigned char Addr);
- void DS1302_SetTime(void);
- void DS1302_ReadTime(void);
-
- #endif
4.1 读写显示时间 main.c
- #include
- #include "LCD1602.h"
- #include "DS1302.h"
-
- void main()
- {
- LCD_Init(); //LCD1602 液晶显示屏初始化
- DS1302_Init(); //DS1302 时钟初始化
- LCD_ShowString(1,1," - - W: ");//静态字符初始化显示
- LCD_ShowString(2,1," : : ");
-
- DS1302_SetTime();//设置时间
-
- while(1)
- {
- DS1302_ReadTime();//读取时间
- LCD_ShowNum(1,1,DS1302_Time[0]+2000,4);//显示年
- LCD_ShowNum(1,6,DS1302_Time[1],2);//显示月
- LCD_ShowNum(1,9,DS1302_Time[2],2);//显示日
- LCD_ShowNum(2,3,DS1302_Time[3],2);//显示时
- LCD_ShowNum(2,6,DS1302_Time[4],2);//显示分
- LCD_ShowNum(2,9,DS1302_Time[5],2);//显示秒
- LCD_ShowNum(1,14,DS1302_Time[6],1);//显示星期
- }
- }
-
4.2 手动设置时间、重新上电显示最后设置的时间 main.c
- #include
- #include "LCD1602.h"
- #include "DS1302.h"
- #include "Key.h"
- #include "Timer1.h"
- unsigned char KeyNum,MODE,TimeSetSelect,TimeSetFlashFlag;
- /**
- * 函 数:显示时间
- * 参 数:无
- * 返 回 值:无
- */
- void TimeShow(void)//时间显示功能
- {
- DS1302_ReadTime();//读取时间
- LCD_ShowNum(1,1,DS1302_Time[0]+2000,4);//显示年
- LCD_ShowNum(1,6,DS1302_Time[1],2);//显示月
- LCD_ShowNum(1,9,DS1302_Time[2],2);//显示日
- LCD_ShowNum(2,3,DS1302_Time[3],2);//显示时
- LCD_ShowNum(2,6,DS1302_Time[4],2);//显示分
- LCD_ShowNum(2,9,DS1302_Time[5],2);//显示秒
- LCD_ShowNum(1,14,DS1302_Time[6],1);//显示星期
- }
-
- /**
- * 函 数:设置时间
- * 参 数:无
- * 返 回 值:无
- */
- void TimeSet(void)//时间设置功能
- {
- if(KeyNum==2)//按键2按下
- {
- TimeSetSelect++;//设置选择位加1
- TimeSetSelect%=7;//越界清零
- }
- if(KeyNum==4)//按键3按下
- {
- DS1302_Time[TimeSetSelect]++;//时间设置位数值加1
- if(DS1302_Time[0]>99){DS1302_Time[0]=0;}//年越界判断
- if(DS1302_Time[1]>12){DS1302_Time[1]=1;}//月越界判断
- if( DS1302_Time[1]==1 || DS1302_Time[1]==3 || DS1302_Time[1]==5 || DS1302_Time[1]==7 ||
- DS1302_Time[1]==8 || DS1302_Time[1]==10 || DS1302_Time[1]==12)//日越界判断
- {
- if(DS1302_Time[2]>31){DS1302_Time[2]=1;}//大月
- }
- else if(DS1302_Time[1]==4 || DS1302_Time[1]==6 || DS1302_Time[1]==9 || DS1302_Time[1]==11)
- {
- if(DS1302_Time[2]>30){DS1302_Time[2]=1;}//小月
- }
- else if(DS1302_Time[1]==2)
- {
- if(DS1302_Time[0]%4==0)
- {
- if(DS1302_Time[2]>29){DS1302_Time[2]=1;}//闰年2月
- }
- else
- {
- if(DS1302_Time[2]>28){DS1302_Time[2]=1;}//平年2月
- }
- }
- if(DS1302_Time[3]>23){DS1302_Time[3]=0;}//时越界判断
- if(DS1302_Time[4]>59){DS1302_Time[4]=0;}//分越界判断
- if(DS1302_Time[5]>59){DS1302_Time[5]=0;}//秒越界判断
- if(DS1302_Time[6]>6){DS1302_Time[6]=0;}//星期越界判断
- }
- if(KeyNum==3)//按键3按下
- {
- DS1302_Time[TimeSetSelect]--;//时间设置位数值减1
- if(DS1302_Time[0]<0){DS1302_Time[0]=99;}//年越界判断
- if(DS1302_Time[1]<1){DS1302_Time[1]=12;}//月越界判断
- if( DS1302_Time[1]==1 || DS1302_Time[1]==3 || DS1302_Time[1]==5 || DS1302_Time[1]==7 ||
- DS1302_Time[1]==8 || DS1302_Time[1]==10 || DS1302_Time[1]==12)//日越界判断
- {
- if(DS1302_Time[2]<1){DS1302_Time[2]=31;}//大月
- if(DS1302_Time[2]>31){DS1302_Time[2]=1;}
- }
- else if(DS1302_Time[1]==4 || DS1302_Time[1]==6 || DS1302_Time[1]==9 || DS1302_Time[1]==11)
- {
- if(DS1302_Time[2]<1){DS1302_Time[2]=30;}//小月
- if(DS1302_Time[2]>30){DS1302_Time[2]=1;}
- }
- else if(DS1302_Time[1]==2)
- {
- if(DS1302_Time[0]%4==0)
- {
- if(DS1302_Time[2]<1){DS1302_Time[2]=29;}//闰年2月
- if(DS1302_Time[2]>29){DS1302_Time[2]=1;}
- }
- else
- {
- if(DS1302_Time[2]<1){DS1302_Time[2]=28;}//平年2月
- if(DS1302_Time[2]>28){DS1302_Time[2]=1;}
- }
- }
- if(DS1302_Time[3]<0){DS1302_Time[3]=23;}//时越界判断
- if(DS1302_Time[4]<0){DS1302_Time[4]=59;}//分越界判断
- if(DS1302_Time[5]<0){DS1302_Time[5]=59;}//秒越界判断
- if(DS1302_Time[6]<0){DS1302_Time[6]=6;}//星期越界判断
- }
- //更新显示,根据TimeSetSelect和TimeSetFlashFlag判断可完成闪烁功能
- if(TimeSetSelect==0 && TimeSetFlashFlag==1){LCD_ShowString(1,3," ");}
- else {LCD_ShowNum(1,3,DS1302_Time[0],2);}
- if(TimeSetSelect==1 && TimeSetFlashFlag==1){LCD_ShowString(1,6," ");}
- else {LCD_ShowNum(1,6,DS1302_Time[1],2);}
- if(TimeSetSelect==2 && TimeSetFlashFlag==1){LCD_ShowString(1,9," ");}
- else {LCD_ShowNum(1,9,DS1302_Time[2],2);}
- if(TimeSetSelect==3 && TimeSetFlashFlag==1){LCD_ShowString(2,3," ");}
- else {LCD_ShowNum(2,3,DS1302_Time[3],2);}
- if(TimeSetSelect==4 && TimeSetFlashFlag==1){LCD_ShowString(2,6," ");}
- else {LCD_ShowNum(2,6,DS1302_Time[4],2);}
- if(TimeSetSelect==5 && TimeSetFlashFlag==1){LCD_ShowString(2,9," ");}
- else {LCD_ShowNum(2,9,DS1302_Time[5],2);}
- if(TimeSetSelect==6 && TimeSetFlashFlag==1){LCD_ShowString(1,14," ");}
- else {LCD_ShowNum(1,14,DS1302_Time[6],1);}
- }
- void main()
- {
- LCD_Init(); //LCD1602 液晶显示屏初始化
- DS1302_Init(); //DS1302 时钟初始化
- Timer1_Init(); //初始化定时器
- LCD_ShowString(1,1," - - W: ");//静态字符初始化显示
- LCD_ShowString(2,1," : : ");
-
-
- while(1)
- {
- KeyNum=Key();//读取键码
- if(KeyNum==1)//按键1按下
- {
- if(MODE==0){MODE=1;TimeSetSelect=0;}//功能切换
- else if(MODE==1){MODE=0;DS1302_SetTime();}//保存设置的时间
- }
- switch(MODE)//根据不同的功能执行不同的函数
- {
- case 0:TimeShow();break; //0 显示模式
- case 1:TimeSet();break; //1 设置模式
- }
- }
- }
-
-
- void Timer1_Routine() interrupt 1
- {
- static unsigned int T0Count;
- TL0 = 0x18; //设置定时初值
- TH0 = 0xFC; //设置定时初值
- T0Count++;
- if(T0Count>=500)//每500ms进入一次
- {
- T0Count=0;
- TimeSetFlashFlag=!TimeSetFlashFlag;//闪烁标志位取反
- }
- }
Timer1.c
- #include
- /**
- * 函 数:定时器0初始化,1毫秒@12.000MHz
- * 参 数:无
- * 返 回 值:无
- */
- void Timer1_Init(void)
- {
- TMOD &= 0xF0; //设置定时器模式
- TMOD |= 0x01; //设置定时器模式
- TL0 = 0x18; //设置定时初值
- TH0 = 0xFC; //设置定时初值
- TF0 = 0; //清除TF0标志
- TR0 = 1; //定时器0开始计时
- ET0=1; //允许时钟1中断
- EA=1; //打开总中断
- PT0=0; //优先级设置为最高(0-3)
- }
-
- /*定时器中断函数模板 关联较多,直接将其写入mian.c 中
- void Timer1_Routine() interrupt 1
- {
- static unsigned int T0Count;
- TL0 = 0x18; //设置定时初值
- TH0 = 0xFC; //设置定时初值
- T0Count++;
- if(T0Count>=1000)
- {
- T0Count=0;
-
- }
- }
- */
Timer1.h
- #ifndef __TIMER1_H__
- #define __TIMER1_H__
-
- void Timer1_Init(void);
-
- #endif
五,代码编译、下载到51单片机
代码编译请参考
《51单片机STC89C52RC——代码编译-CSDN博客》
代码下载请参考
《51单片机STC89C52RC——STCAI-ISP代码下载-CSDN博客》
-
相关阅读:
软件产品确认测试包括哪些方面
java计算机毕业设计springboot+vue留学服务管理平台系统(源码+系统+mysql数据库+Lw文档)
MySQL导入导出、视图、索引、执行计划
TSC2012HYDT双向电流感应放大器芯片中文资料规格书PDF数据手册引脚图参数概述
Flask 的 ORM 模型 - 概述
Doris 集群的手动部署
【数据治理】2021年 中国数据治理行业:全链产业图谱梳理
Android 12(S) 图像显示系统 - BufferQueue的工作流程(十)
Jenkins nginx自动化构建前端vue项目
IDA Pro与x64dbg联动调试记录
-
原文地址:https://blog.csdn.net/oopxiajun2011/article/details/139983492