標題: 51單片機DS1302時鐘程序分段式編寫,調(diào)試良好 [打印本頁]

作者: 3910    時間: 2022-5-1 22:34
標題: 51單片機DS1302時鐘程序分段式編寫,調(diào)試良好
單片機源程序如下:
  1. /*-----------------------------------------------
  2.   名稱:DS1302時鐘數(shù)碼管顯示 串口更新
  3.   內(nèi)容:DS1302實時時鐘數(shù)碼管顯示,時間和日期切換顯示 按下按鍵,循環(huán)切換
  4.         時間格式xx-xx-xx
  5.                 日期格式xx-xx-xx
  6.                 周秒格式-x-   xx
  7.                 開發(fā)板使用12M晶振,通過dofly自帶的串口調(diào)試軟件,打開串口,波特率默認2400,點擊更新時間即可,如果不行,按下開發(fā)板復位重新更新
  8. ------------------------------------------------*/
  9. #include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義
  10. #include "ds1302.h"

  11. #define KeyPort P3 //定義按鍵端口

  12. #define DataPort P0 //定義數(shù)據(jù)端口 程序中遇到DataPort 則用P0 替換

  13. sbit LATCH1=P2^2;//定義鎖存使能端口 段鎖存
  14. sbit LATCH2=P2^3;//                 位鎖存

  15. bit ReadTimeFlag;//定義讀時間標志
  16. bit SetFlag;     //更新時間標志位
  17. unsigned char time_buf2[16];

  18. unsigned char code dofly_DuanMa[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};// 顯示段碼值0~9
  19. unsigned char code dofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//分別對應相應的數(shù)碼管點亮,即位碼
  20. unsigned char TempData[5]; //存儲顯示值的全局變量

  21. void DelayUs2x(unsigned char t);//us級延時函數(shù)聲明
  22. void DelayMs(unsigned char t); //ms級延時
  23. void Display(unsigned char FirstBit,unsigned char Num);//數(shù)碼管顯示函數(shù)
  24. unsigned char KeyScan(void);//鍵盤掃描
  25. void Init_Timer0(void);//定時器初始化
  26. void UART_Init(void);
  27. /*------------------------------------------------
  28.                     主函數(shù)
  29. ------------------------------------------------*/
  30. void main (void)
  31. {
  32. unsigned char i,num,displaynum;                  

  33. Init_Timer0();
  34. Ds1302_Init();
  35. UART_Init();
  36. while (1)         //主循環(huán)
  37.   {


  38. if(SetFlag)     //如果接收到串口信息則更新時鐘
  39.   {
  40.         for(i=0;i<8;i++)
  41.                 {
  42.                 time_buf1[i]=time_buf2[2*i]*10+time_buf2[2*i+1];
  43.                 }//數(shù)據(jù)整合,如2個數(shù) 1和5整合成15
  44.                 Ds1302_Write_Time();
  45.                 SetFlag=0;       //時鐘信息更新后標志位清零
  46.    }

  47. num=KeyScan();
  48. if(num==5)
  49.   {
  50.    displaynum++;
  51.    if(displaynum==3)
  52.       displaynum=0;
  53.   }
  54. if(ReadTimeFlag==1)
  55. {
  56.   ReadTimeFlag=0;
  57.   Ds1302_Read_Time();
  58. if(displaynum==0) //顯示時間
  59. {
  60. TempData[0]=dofly_DuanMa[time_buf1[4]/10];//時                        //數(shù)據(jù)的轉(zhuǎn)換,因我們采用數(shù)碼管0~9的顯示,將數(shù)據(jù)分開
  61. TempData[1]=dofly_DuanMa[time_buf1[4]%10];       
  62. TempData[2]=0x40;        //加入"-"
  63. TempData[3]=dofly_DuanMa[time_buf1[5]/10];//分
  64. TempData[4]=dofly_DuanMa[time_buf1[5]%10];

  65. }
  66. else if(displaynum==1)//顯示日期
  67. {

  68. TempData[0]=dofly_DuanMa[time_buf1[2]/10];//月
  69. TempData[1]=dofly_DuanMa[time_buf1[2]%10];
  70. TempData[2]=0x40;        //加入"-"
  71. TempData[3]=dofly_DuanMa[time_buf1[3]/10];//日
  72. TempData[4]=dofly_DuanMa[time_buf1[3]%10];       
  73. }
  74. else if(displaynum==2)//顯示周  秒
  75. {
  76. TempData[0]=0x40;                                //數(shù)據(jù)的轉(zhuǎn)換,因我們采用數(shù)碼管0~9的顯示,將數(shù)據(jù)分開
  77. TempData[1]=dofly_DuanMa[time_buf1[7]%10];//周
  78. TempData[2]=0x40;        //加入"-"

  79. TempData[3]=dofly_DuanMa[time_buf1[6]/10];//秒
  80. TempData[4]=dofly_DuanMa[time_buf1[6]%10];       
  81. }
  82. }       
  83. }
  84. }
  85. /*------------------------------------------------
  86.               串口通訊初始化
  87. ------------------------------------------------*/
  88. void UART_Init(void)
  89. {
  90.     SCON  = 0x50;                        // SCON: 模式 1, 8-bit UART, 使能接收  
  91.     TMOD |= 0x20;               // TMOD: timer 1, mode 2, 8-bit 重裝
  92.     TH1   = 0xF3;               // TH1:  重裝值 2400 波特率 晶振 12MHz  
  93.     TR1   = 1;                  // TR1:  timer 1 打開                        
  94.     EA    = 1;                  //打開總中斷
  95.     ES    = 1;                  //打開串口中斷
  96. }
  97. /*------------------------------------------------
  98. uS延時函數(shù),含有輸入?yún)?shù) unsigned char t,無返回值
  99. unsigned char 是定義無符號字符變量,其值的范圍是
  100. 0~255 這里使用晶振12M,精確延時請使用匯編,大致延時
  101. 長度如下 T=tx2+5 uS
  102. ------------------------------------------------*/
  103. void DelayUs2x(unsigned char t)
  104. {   
  105. while(--t);
  106. }
  107. /*------------------------------------------------
  108. mS延時函數(shù),含有輸入?yún)?shù) unsigned char t,無返回值
  109. unsigned char 是定義無符號字符變量,其值的范圍是
  110. 0~255 這里使用晶振12M,精確延時請使用匯編
  111. ------------------------------------------------*/
  112. void DelayMs(unsigned char t)
  113. {
  114.      
  115. while(t--)
  116. {
  117.      //大致延時1mS
  118.      DelayUs2x(245);
  119.          DelayUs2x(245);
  120. }
  121. }
  122. /*------------------------------------------------
  123. 顯示函數(shù),用于動態(tài)掃描數(shù)碼管
  124. 輸入?yún)?shù) FirstBit 表示需要顯示的第一位,如賦值2表示從第三個數(shù)碼管開始顯示
  125. 如輸入0表示從第一個顯示。
  126. Num表示需要顯示的位數(shù),如需要顯示99兩位數(shù)值則該值輸入2
  127. ------------------------------------------------*/
  128. void Display(unsigned char FirstBit,unsigned char Num)
  129. {
  130.       static unsigned char i=0;
  131.           

  132.            DataPort=0;   //清空數(shù)據(jù),防止有交替重影
  133.        LATCH1=1;     //段鎖存
  134.        LATCH1=0;

  135.        DataPort=dofly_WeiMa[i+FirstBit]; //取位碼
  136.        LATCH2=1;     //位鎖存
  137.        LATCH2=0;

  138.        DataPort=TempData[i]; //取顯示數(shù)據(jù),段碼
  139.        LATCH1=1;     //段鎖存
  140.        LATCH1=0;
  141.       
  142.            i++;
  143.        if(i==Num)
  144.               i=0;


  145. }
  146. /*------------------------------------------------
  147.                     定時器初始化子程序
  148. ------------------------------------------------*/
  149. void Init_Timer0(void)
  150. {
  151. TMOD |= 0x01;          //使用模式1,16位定時器,使用"|"符號可以在使用多個定時器時不受影響                     
  152. //TH0=0x00;              //給定初值
  153. //TL0=0x00;
  154. EA=1;            //總中斷打開
  155. ET0=1;           //定時器中斷打開
  156. TR0=1;           //定時器開關打開
  157. }
  158. /*------------------------------------------------
  159.                  定時器中斷子程序
  160. ------------------------------------------------*/
  161. void Timer0_isr(void) interrupt 1
  162. {
  163. static unsigned int num;
  164. TH0=(65536-2000)/256;                  //重新賦值 2ms
  165. TL0=(65536-2000)%256;

  166. Display(0,5);       // 調(diào)用數(shù)碼管掃描
  167. num++;
  168. if(num==50)        //大致100ms
  169.    {
  170.     num=0;
  171.     ReadTimeFlag=1; //讀標志位置1
  172.         }
  173. }

  174. /*------------------------------------------------
  175. 按鍵掃描函數(shù),返回掃描鍵值
  176. ------------------------------------------------*/
  177. unsigned char KeyScan(void)
  178. {
  179. unsigned char keyvalue;
  180. if(KeyPort!=0xff)
  181.    {
  182.     DelayMs(10);
  183.     if(KeyPort!=0xff)
  184.            {
  185.             keyvalue=KeyPort;
  186.             while(KeyPort!=0xff);
  187.                 switch(keyvalue)
  188.                 {
  189.                  case 0xfe:return 1;break;
  190.                  case 0xfd:return 2;break;
  191.                  case 0xfb:return 3;break;
  192.                  case 0xf7:return 4;break;
  193.                  case 0xef:return 5;break;
  194.                  case 0xdf:return 6;break;
  195.                  case 0xbf:return 7;break;
  196.                  case 0x7f:return 8;break;
  197.                  default:return 0;break;
  198.                 }
  199.           }
  200.    }
  201.    return 0;
  202. }
  203. /*------------------------------------------------
  204.                   串口中斷程序
  205. ------------------------------------------------*/
  206. void UART_SER (void) interrupt 4 //串行中斷服務程序
  207. {
  208.     unsigned char Temp;          //定義臨時變量
  209.     unsigned char i;
  210.     if(RI)                        //判斷是接收中斷產(chǎn)生
  211.      {
  212.           RI=0;                      //標志位清零
  213.           Temp=SBUF;                 //讀入緩沖區(qū)的值
  214.           time_buf2[i]=Temp&0x0F;
  215.           i++;
  216.           if(i==16)                  //連續(xù)接收16個字符信息
  217.            {
  218.             i=0;
  219.                 SetFlag=1;               //接收完成標志位置1
  220.            }
  221.       SBUF=Temp; //把接收到的值再發(fā)回電腦端
  222.          }
  223.    if(TI)  //如果是發(fā)送標志位,清零
  224.      TI=0;
  225. }
復制代碼
Keil2代碼下載:
Keil2代碼只能用Keil2打開.7z (17.95 KB, 下載次數(shù): 49)



作者: shenqiwei    時間: 2022-5-4 03:47
程序很好,有清晰的思路,模塊編程
作者: cba_cba    時間: 2022-5-4 10:09
一個字,牛。 模塊化的編程思路。
作者: tongguan123    時間: 2022-5-27 00:00
很標準的編寫,閱讀性也強,多謝樓主的分享!
但我有一個問題想問一下,沒有用LCD1602顯示,作者用的是數(shù)碼管,用的是幾位數(shù)碼管?數(shù)碼管和單片機的管腳是怎樣連接的?還望指教!多謝了!

作者: tongguan123    時間: 2022-5-27 00:07
分析你程序,位碼是8位的話,然后通過按鍵切換時間和日期,并在數(shù)碼管顯示。這樣來看的話,顯示的時候中間是沒有間隔的,數(shù)字是連續(xù)的,是這樣嗎?請幫我解釋一下,謝謝!
作者: tongguan123    時間: 2022-5-27 00:20
我是一名初學者,說的不對的地方,還請樓主多擔待!
作者: 3910    時間: 2022-9-25 14:09
tongguan123 發(fā)表于 2022-5-27 00:07
分析你程序,位碼是8位的話,然后通過按鍵切換時間和日期,并在數(shù)碼管顯示。這樣來看的話,顯示的時候中間 ...

顯示是不連續(xù)的,但頻率超過人眼識別頻率了,所以看起來是一秒動一下
作者: DZZGDZ    時間: 2023-2-5 09:45
有參考電路圖嗎?
作者: DZZGDZ    時間: 2023-2-5 09:46
3910 發(fā)表于 2022-9-25 14:09
顯示是不連續(xù)的,但頻率超過人眼識別頻率了,所以看起來是一秒動一下

有原理圖嗎?電路如何連接的?




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1