|
写了一个DS1302的程序,在开发板上成功运行,通过LCD1602显示时间,现在分享出来,给像我这样的单片机萌新一个参考吧。
从2021年5月11日0时0分0秒开始计时并在LCD1602上显示,源码如下:
- #include<reg52.h>
- #include<intrins.h>
- sbit RST=P2^4;
- sbit CLK=P2^1;
- sbit IO=P2^0;
- sbit RS=P1^0;
- sbit RW=P1^1;
- sbit E=P2^5;
- sbit DU=P2^6;
- unsigned char num[]={"0123456789"}; //LCD1602显示的数字字符
- void X() //关闭数码管
- {
- DU=1;
- P0=0x00;
- DU=0;
- }
- void Delay()
- {
- _nop_();
- }
- void Write_Bit_DS1302(unsigned char DAT) //向DS1302写入一字节的数据
- {
- unsigned char i;
- CLK=0;
- Delay();
- for(i=0;i<8;i++)
- {
- IO=DAT&0x01; //低位在前,高位在后
- Delay();
- CLK=1; //时钟信号上升沿,写入数据
- Delay();
- CLK=0; //重新拉低CLK,形成脉冲
- DAT>>=1; //将DAT的各数据位右移1位,准备写入下一数据位
- }
- }
- void Write_DS1302(unsigned char CMD,unsigned char DAT) //向DS1302写入命令和数据
- {
- RST=0; //禁止数据传输
- CLK=0; //在写入数据前确保CLK置低电平
- RST=1; //开始数据传输
- Delay();
- Write_Bit_DS1302(CMD); //写入命令
- Write_Bit_DS1302(DAT); //写入数据
- CLK=1;
- RST=0;
- }
- unsigned char Read_Bit_DS1302() //从DS1302读出一字节的数据
- {
- unsigned char i,DAT;
- Delay();
- for(i=0;i<8;i++)
- {
- DAT>>=1;
- if(IO==1)
- {
- DAT|=0x80;
- }
- CLK=1;
- Delay();
- CLK=0; //时钟信号下降沿,读出数据
- Delay();
- }
- return DAT;
- }
- unsigned char Read_DS1302(unsigned char CMD) //向DS1302写入命令后再从DS1302读出数据
- {
- unsigned char DAT;
- RST=0;
- CLK=0;
- RST=1;
- Write_Bit_DS1302(CMD); //写入命令
- DAT=Read_Bit_DS1302(); //读出数据
- CLK=1;
- RST=0;
- return DAT;
- }
- void Init_DS1302() //DS1302初始化
- {
- unsigned char X;
- X=Read_DS1302(0x81);
- if(X&0x80) //判断DS1302是否处于运行状态
- {
- Write_DS1302(0x8e,0x00); //允许将数据写入DS1302的寄存器
- Write_DS1302(0x80,((00/10)<<4|(00%10))); //写入“秒”的初始值,需要将LCD1602显示的数字的ASCII值转换成BCD码
- Write_DS1302(0x82,((00/10)<<4|(00%10))); //写入“分”的初始值
- Write_DS1302(0x84,((00/10)<<4|(00%10))); //写入“时”的初始值
- Write_DS1302(0x86,((11/10)<<4|(11%10))); //写入“日”的初始值
- Write_DS1302(0x88,((5/10)<<4|(5%10))); //写入“月”的初始值
- Write_DS1302(0x8c,((21/10)<<4|(21%10))); //写入“年”的初始值
- Write_DS1302(0x8e,0x80); //禁止将数据写入DS1302的寄存器
- }
- }
- void Delay5ms()
- {
- unsigned char i,j;
- _nop_();
- i=9;
- j=244;
- do
- {
- while(--j);
- }
- while(--i);
- }
- int ReadBusy() //LCD1602“读忙”操作
- {
- int temp;
- RS=0;
- RW=1;
- _nop_();
- P0=0xff;
- _nop_();
- E=1;
- _nop_();
- temp=P0;
- _nop_();
- E=0;
- return(temp&0x80);
- }
- void Write_Com(char com) //LCD1602“写命令”操作
- {
- while(ReadBusy());
- RS=0;
- RW=0;
- E=0;
- _nop_();
- P0=com;
- _nop_();
- E=1;
- Delay5ms();
- E=0;
- Delay5ms();
- }
- void Write_Dat(char dat) //LCD1602“写数据”操作
- {
- while(ReadBusy());
- RS=1;
- RW=0;
- E=0;
- _nop_();
- P0=dat;
- _nop_();
- E=1;
- Delay5ms();
- E=0;
- Delay5ms();
- }
- void LCD1602_Init() //LCD1602初始化
- {
- Delay5ms(); //延时15ms,首次写入LCD1602时应给LCD1602一段较长的响应时间
- Delay5ms();
- Delay5ms();
- Write_Com(0x38); //显示模式设置:16*2显示、5*7点阵,连续写入3次,确保LCD1602初始化成功
- Delay5ms();
- Write_Com(0x38);
- Delay5ms();
- Write_Com(0x38);
- Delay5ms();
- Write_Com(0x0c); //显示模式设置:开显示、光标不显示、光标不闪烁
- Delay5ms();
- Write_Com(0x06); //显示模式设置:光标右移,字符不右移
- Delay5ms();
- Write_Com(0x01); //清除屏幕
- Delay5ms();
- }
- void Display_Second(unsigned char x) //LCD1602显示“秒”的数值
- {
- unsigned char i,j;
- i=x/10; //取数值的十位
- j=x%10; //取数值的个位
- Write_Com(0x80+0x49); //写入在LCD1602上显示的位置
- Write_Dat(num[i]);
- Write_Dat(num[j]);
- Delay5ms();
- }
- void Display_Minute(unsigned char x) //LCD1602显示“分”的数值
- {
- unsigned char i,j;
- i=x/10;
- j=x%10;
- Write_Com(0x80+0x46);
- Write_Dat(num[i]);
- Write_Dat(num[j]);
- Delay5ms();
- }
- void Display_Hour(unsigned char x) //LCD1602显示“时”的数值
- {
- unsigned char i,j;
- i=x/10;
- j=x%10;
- Write_Com(0x80+0x43);
- Write_Dat(num[i]);
- Write_Dat(num[j]);
- Delay5ms();
- }
- void Display_Day(unsigned char x) //LCD1602显示“日”的数值
- {
- unsigned char i,j;
- i=x/10;
- j=x%10;
- Write_Com(0x80+0x0c);
- Write_Dat(num[i]);
- Write_Dat(num[j]);
- Delay5ms();
- }
- void Display_Month(unsigned char x) //LCD1602显示“月”的数值
- {
- unsigned char i,j;
- i=x/10;
- j=x%10;
- Write_Com(0x80+0x09);
- Write_Dat(num[i]);
- Write_Dat(num[j]);
- Delay5ms();
- }
- void Display_Year(unsigned char x) //LCD1602显示“年”的数值
- {
- unsigned char i,j;
- i=x/10;
- j=x%10;
- Write_Com(0x80+0x06);
- Write_Dat(num[i]);
- Write_Dat(num[j]);
- Delay5ms();
- }
- void main()
- {
- unsigned char second,minute,hour,day,month,year;
- unsigned char temp; //暂存从DS1302读出的数据
- X();
- LCD1602_Init();
- Write_Com(0x80+0x01);
- Write_Dat('D');
- Write_Dat('A');
- Write_Dat('T');
- Write_Dat('E');
- Write_Dat(':');
- Delay5ms();
- Write_Com(0x80+0x08);
- Write_Dat('-');
- Delay5ms();
- Write_Com(0x80+0x0b);
- Write_Dat('-');
- Delay5ms();
- Write_Com(0x80+0x45);
- Write_Dat(':');
- Delay5ms();
- Write_Com(0x80+0x48);
- Write_Dat(':');
- Delay5ms();
- Init_DS1302();
-
- while(1)
- {
- temp=Read_DS1302(0x81);
- second=((temp&0x70)>>4)*10+(temp&0x0f); //将“秒”的BCD码转换成对应的ASCII值
- Display_Second(second);
- temp=Read_DS1302(0x83);
- minute=((temp&0x70)>>4)*10+(temp&0x0f); //将“分”的BCD码转换成对应的ASCII值
- Display_Minute(minute);
- temp=Read_DS1302(0x85);
- hour=((temp&0x70)>>4)*10+(temp&0x0f); //将“时”的BCD码转换成对应的ASCII值
- Display_Hour(hour);
- temp=Read_DS1302(0x87);
- day=((temp&0x70)>>4)*10+(temp&0x0f); //将“日”的BCD码转换成对应的ASCII值
- Display_Day(day);
- temp=Read_DS1302(0x89);
- month=((temp&0x70)>>4)*10+(temp&0x0f); //将“月”的BCD码转换成对应的ASCII值
- Display_Month(month);
- temp=Read_DS1302(0x8d);
- year=((temp&0x70)>>4)*10+(temp&0x0f); //将“年”的BCD码转换成对应的ASCII值
- Display_Year(year);
- }
- }
复制代码
以下为原理图
|
评分
-
查看全部评分
|