|
寫了一個DS1302的程序,在開發(fā)板上成功運行,通過LCD1602顯示時間,現(xiàn)在分享出來,給像我這樣的單片機萌新一個參考吧。
從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顯示的數(shù)字字符
- void X() //關(guān)閉數(shù)碼管
- {
- DU=1;
- P0=0x00;
- DU=0;
- }
- void Delay()
- {
- _nop_();
- }
- void Write_Bit_DS1302(unsigned char DAT) //向DS1302寫入一字節(jié)的數(shù)據(jù)
- {
- unsigned char i;
- CLK=0;
- Delay();
- for(i=0;i<8;i++)
- {
- IO=DAT&0x01; //低位在前,高位在后
- Delay();
- CLK=1; //時鐘信號上升沿,寫入數(shù)據(jù)
- Delay();
- CLK=0; //重新拉低CLK,形成脈沖
- DAT>>=1; //將DAT的各數(shù)據(jù)位右移1位,準備寫入下一數(shù)據(jù)位
- }
- }
- void Write_DS1302(unsigned char CMD,unsigned char DAT) //向DS1302寫入命令和數(shù)據(jù)
- {
- RST=0; //禁止數(shù)據(jù)傳輸
- CLK=0; //在寫入數(shù)據(jù)前確保CLK置低電平
- RST=1; //開始數(shù)據(jù)傳輸
- Delay();
- Write_Bit_DS1302(CMD); //寫入命令
- Write_Bit_DS1302(DAT); //寫入數(shù)據(jù)
- CLK=1;
- RST=0;
- }
- unsigned char Read_Bit_DS1302() //從DS1302讀出一字節(jié)的數(shù)據(jù)
- {
- unsigned char i,DAT;
- Delay();
- for(i=0;i<8;i++)
- {
- DAT>>=1;
- if(IO==1)
- {
- DAT|=0x80;
- }
- CLK=1;
- Delay();
- CLK=0; //時鐘信號下降沿,讀出數(shù)據(jù)
- Delay();
- }
- return DAT;
- }
- unsigned char Read_DS1302(unsigned char CMD) //向DS1302寫入命令后再從DS1302讀出數(shù)據(jù)
- {
- unsigned char DAT;
- RST=0;
- CLK=0;
- RST=1;
- Write_Bit_DS1302(CMD); //寫入命令
- DAT=Read_Bit_DS1302(); //讀出數(shù)據(jù)
- CLK=1;
- RST=0;
- return DAT;
- }
- void Init_DS1302() //DS1302初始化
- {
- unsigned char X;
- X=Read_DS1302(0x81);
- if(X&0x80) //判斷DS1302是否處于運行狀態(tài)
- {
- Write_DS1302(0x8e,0x00); //允許將數(shù)據(jù)寫入DS1302的寄存器
- Write_DS1302(0x80,((00/10)<<4|(00%10))); //寫入“秒”的初始值,需要將LCD1602顯示的數(shù)字的ASCII值轉(zhuǎn)換成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); //禁止將數(shù)據(jù)寫入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“寫數(shù)據(jù)”操作
- {
- 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時應(yīng)給LCD1602一段較長的響應(yīng)時間
- Delay5ms();
- Delay5ms();
- Write_Com(0x38); //顯示模式設(shè)置:16*2顯示、5*7點陣,連續(xù)寫入3次,確保LCD1602初始化成功
- Delay5ms();
- Write_Com(0x38);
- Delay5ms();
- Write_Com(0x38);
- Delay5ms();
- Write_Com(0x0c); //顯示模式設(shè)置:開顯示、光標不顯示、光標不閃爍
- Delay5ms();
- Write_Com(0x06); //顯示模式設(shè)置:光標右移,字符不右移
- Delay5ms();
- Write_Com(0x01); //清除屏幕
- Delay5ms();
- }
- void Display_Second(unsigned char x) //LCD1602顯示“秒”的數(shù)值
- {
- unsigned char i,j;
- i=x/10; //取數(shù)值的十位
- j=x%10; //取數(shù)值的個位
- Write_Com(0x80+0x49); //寫入在LCD1602上顯示的位置
- Write_Dat(num[i]);
- Write_Dat(num[j]);
- Delay5ms();
- }
- void Display_Minute(unsigned char x) //LCD1602顯示“分”的數(shù)值
- {
- 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顯示“時”的數(shù)值
- {
- 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顯示“日”的數(shù)值
- {
- 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顯示“月”的數(shù)值
- {
- 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顯示“年”的數(shù)值
- {
- 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讀出的數(shù)據(jù)
- 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碼轉(zhuǎn)換成對應(yīng)的ASCII值
- Display_Second(second);
- temp=Read_DS1302(0x83);
- minute=((temp&0x70)>>4)*10+(temp&0x0f); //將“分”的BCD碼轉(zhuǎn)換成對應(yīng)的ASCII值
- Display_Minute(minute);
- temp=Read_DS1302(0x85);
- hour=((temp&0x70)>>4)*10+(temp&0x0f); //將“時”的BCD碼轉(zhuǎn)換成對應(yīng)的ASCII值
- Display_Hour(hour);
- temp=Read_DS1302(0x87);
- day=((temp&0x70)>>4)*10+(temp&0x0f); //將“日”的BCD碼轉(zhuǎn)換成對應(yīng)的ASCII值
- Display_Day(day);
- temp=Read_DS1302(0x89);
- month=((temp&0x70)>>4)*10+(temp&0x0f); //將“月”的BCD碼轉(zhuǎn)換成對應(yīng)的ASCII值
- Display_Month(month);
- temp=Read_DS1302(0x8d);
- year=((temp&0x70)>>4)*10+(temp&0x0f); //將“年”的BCD碼轉(zhuǎn)換成對應(yīng)的ASCII值
- Display_Year(year);
- }
- }
復(fù)制代碼
以下為原理圖
|
評分
-
查看全部評分
|