找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 4944|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

51單片機(jī)初學(xué)實(shí)踐:用DS1302模塊和LCD1602顯示屏實(shí)現(xiàn)電子鐘

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
本帖最后由 ricebucket 于 2020-7-12 22:10 編輯

作為51單片機(jī)初學(xué)者,制作一個(gè)電子鐘是不可缺少的實(shí)踐內(nèi)容。周末用STC89C52RC+DS1302模塊+LCD1602顯示屏+DS18B20數(shù)字溫度傳感器實(shí)現(xiàn)了一個(gè)電子鐘,
顯示效果如下:




可以用串口命令修改RTC時(shí)鐘:



實(shí)踐過程中的一些經(jīng)驗(yàn)分享:
1、DS1302模塊的RST,CLK和IO口最好加上4.7k以上的上拉電阻,提高RTC數(shù)據(jù)讀寫可靠性,這個(gè)問題讓我花了不少時(shí)間,最后在Vcc2和IO引腳之間焊接了一個(gè)10k電阻解決問題,如圖所示:



2、DS1302模塊的讀寫接口類似于I2C,使用burst mode+結(jié)構(gòu)體或者數(shù)值可以提高讀寫效率:

  1. typedef struct rtc_data
  2. {
  3.         uint8 SS;        //秒
  4.         uint8 MI;        //分
  5.         uint8 HH;        //小時(shí)
  6.         uint8 DD;        //日
  7.         uint8 MM;        //月
  8.         uint8 DOW;        //星期
  9.         uint8 YY;        //年
  10. } T_RTC_DATA;
復(fù)制代碼
  1. void DS1302_Burst_Write(T_RTC_DATA *rtc_dat)
  2. {
  3.         uint8 i, *p = (uint8 *)rtc_dat;

  4.         DS1302_RST = 1;        //使能片選信號(hào)
  5.         _nop_();

  6.         DS1302_Write_Byte(DS1302_BURST_WRITE_ADDR);

  7.         for(i=0; i<sizeof(T_RTC_DATA); i++)
  8.         {
  9.                 DS1302_Write_Byte(*p++);
  10.         }

  11.         DS1302_RST = 0;
  12.         _nop_();
  13. }

  14. void DS1302_Burst_Read(T_RTC_DATA *rtc_dat)
  15. {
  16.         uint8 i, *p = (uint8 *)rtc_dat;

  17.         DS1302_RST = 1;        //使能片選信號(hào)
  18.         _nop_();

  19.         DS1302_Write_Byte(DS1302_BURST_READ_ADDR);

  20.         for(i=0; i<sizeof(T_RTC_DATA); i++)
  21.         {
  22.                 *p++ = DS1302_Read_Byte();
  23.         }

  24.         DS1302_RST = 0;
  25. }
復(fù)制代碼


3、DS18B20溫度傳感器采用one wire協(xié)議,時(shí)序要求精確,讀寫問題不大,主要還是溫度讀取后的轉(zhuǎn)換和顯示,尤其是小數(shù)位的顯示,使用長度16的lookup table,可以減少重復(fù)計(jì)算:

  1. bit DS18B20_Get_Temperature(int *temp, int *sign)
  2. {
  3.         bit ack;
  4.         uint8 LSB, MSB;

  5.         ack = DS18B20_Get_Ack();
  6.         if(ack == 0)
  7.         {
  8.                 DS18B20_Write_Byte(0xCC); //跳過ROM
  9.                 DS18B20_Write_Byte(0xBE); //跳過溫度采集
  10.                 LSB = DS18B20_Read_Byte(); //讀低字節(jié)溫度值
  11.                 MSB = DS18B20_Read_Byte(); //讀高字節(jié)溫度值
  12.                 *temp = ((int)MSB<<8) + LSB;

  13.                 if(0 > *temp)
  14.                 {
  15.                         *temp -= 1;
  16.                         *temp  = ~*temp; //對(duì)負(fù)溫度數(shù)據(jù)取補(bǔ)碼
  17.                         *sign = -1; // 負(fù)數(shù)
  18.                 }
  19.                 else
  20.                 {
  21.                         *sign = 1; // 正數(shù)
  22.                 }
  23.         }
  24.         return ~ack;
  25. }
復(fù)制代碼
  1.         // DS18B20的小數(shù)位四舍五入顯示結(jié)果速查表,4bit=索引取值范圍 0 - 15
  2.         uint8 code dect_lookup_tab[] = {0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 9};
復(fù)制代碼
  1.                         slen = 0;
  2.                         sbuf[slen++] = ds18b20_temp_sign_s < 0 ? '-' : '+';
  3.                         
  4.                         intT %= 100;
  5.                         
  6.                         if(intT > 10) sbuf[slen++] = '0' + intT / 10;
  7.                         sbuf[slen++] = '0' + intT % 10;
  8.                         sbuf[slen++] = '.';
  9.                         
  10.                         sbuf[slen++] = '0' + dect_lookup_tab[decT]; // 使用之前已經(jīng)算好的四舍五入結(jié)果查表,速度更快。
  11.                         //sbuf[slen++] = '0' + (decT*10) / 16;  //二進(jìn)制的小數(shù)部分轉(zhuǎn)換為1位十進(jìn)制位, 小數(shù)部分轉(zhuǎn)換為可顯示的數(shù)字字符
  12.                         
  13.                         sbuf[slen++] = '\0';                 //添加字符串結(jié)束符
  14.                         LCD1602_Show_Str(10, 0, sbuf);     //顯示到液晶屏上
復(fù)制代碼



4、uart命令部分,可以使用串口中斷接收輸入到UART_Rxd_Buf,然后選擇一個(gè)合適的定時(shí)器間隔讀取,解析并執(zhí)行,詳見附件代碼。

  1. /* 串口動(dòng)作函數(shù),根據(jù)接收到的命令幀執(zhí)行響應(yīng)的動(dòng)作
  2.    buf-接收到的命令幀指針,len-命令幀長度 */
  3. void Uart_Cmd_Handler(uint8 *buf)
  4. {
  5.     int8 slen = 0;

  6.         printf(">cmd recv: [%s]\r\n", buf);

  7.         if(0 == strncmp("rtc set ", buf, 8))
  8.         {
  9.                 if(0 != UART_Cmd_Exec_RTC_Set(buf+8))
  10.                 {
  11.                         printf(">cmd exec: failed.\r\n");
  12.                 }
  13.         }
  14.         else
  15.         {
  16.                 printf(">cmd unrecognized.\r\n");
  17.         }
  18. }
復(fù)制代碼

5、main函數(shù)內(nèi)容:
  1. void main()
  2. {
  3.     int8 slen = 0;
  4.         uint8 pdata uart_cmd_buf[64] = {0};

  5.     EA = 1;        //開總中斷
  6.         DS18B20_Start();
  7.         UART_Config(9600);
  8.     ConfigTimer0(TIMER0_SLICE_MS);        //T0定時(shí)10ms

  9.     DS1302_Init();        //初始化RTC時(shí)鐘
  10.     LCD1602_Init();        //初始化液晶

  11.         LCD1602_Show_Str(0, 0, "**:**:**");
  12.         LCD1602_Show_Str(0, 1, "20**#**#**# ???");
  13.         LCD1602_Show_Char(15, 0, 0);        //5x7字符 ℃
  14.         LCD1602_Show_Char(4, 1, 1);        //5x7字符 年
  15.         LCD1602_Show_Char(7, 1, 2);        //5x7字符 月
  16.         LCD1602_Show_Char(10, 1, 3);        //5x7字符 日

  17.     while(1)
  18.     {
  19.                 Uart_Cmd_Check(&uart_cmd_buf, sizeof(uart_cmd_buf)-1);

  20.         if (timer_flag_250ms)  //每250ms讀取依次時(shí)間
  21.         {
  22.                         ReadAndShowRtc();
  23.             timer_flag_250ms = 0;
  24.         }
  25.         if (timer_flag_3s)  //每隔3s執(zhí)行以下分支
  26.         {
  27.                         ReadAndShowTemperature();
  28.             timer_flag_3s = 0;
  29.                 }
  30.     }
  31. }
復(fù)制代碼


附件文件列表如圖所示:



以上代碼使用C51開發(fā)板調(diào)試,接線簡(jiǎn)單,具體端口可參看config.h

初學(xué)單片機(jī),難免有錯(cuò)漏之處,還請(qǐng)各位壇友不吝賜教。


DS1302_UART_LCD1602_STC89C52RC.7z (2.35 MB, 下載次數(shù): 81)

評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏6 分享淘帖 頂1 踩
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表