单片机/MCU论坛
直播中

Sensation_ANG

4年用户 1经验值
擅长:可编程逻辑 嵌入式技术 处理器/DSP
私信 关注
[文章]

时钟控制器(电子时钟)

`基于电子钟的控制器,其实相当于是闹钟的功能。学习来源是根据宋雪松老师的《手把手教你学单片机》。通过stc89c52+LCD1602+DS1302+矩阵按键+LED小灯实现的。具体现象,到固定时间小灯会自主亮灭。程序分为5个部分。程序所实现的现象为在10:00,10:02,10:05开始亮,在10:01,10:04,10:06开始灭。
protues的仿真图在下方

一:LCD1602液晶模块
  1. #include
  2. //控制LCD1602的位
  3. #define LCD1602_DB P0        //数据位
  4. ***it LCD1602_RS = P2^6;        //指令/数据选择信号
  5. ***it LCD1602_RW = P2^5;        //读写选择信号
  6. ***it LCD1602_E = P2^7;        //使能信号

  7. /*LCD1602状态检测函数DB7为忙标志位,为1时禁止,为0是工作*/
  8. void LcdWaitReady()
  9. {
  10.         unsigned char sta;                //用来缓存LCD1602_DB的值

  11.         LCD1602_DB = 0xff;                //赋初值
  12.         LCD1602_RS = 0;
  13.         LCD1602_RW = 1;
  14.         do {
  15.                 LCD1602_E = 1;
  16.                 sta = LCD1602_DB;
  17.                 LCD1602_E = 0;
  18.         }while (sta&0x80);         //当DB7为0时结束循环
  19. }

  20. /*LCD1602写指令函数,形参cmd-要输入的指令*/
  21. void LcdWriteCmd(unsigned char cmd)
  22. {
  23.         LcdWaitReady();                //检测状态函数
  24.         LCD1602_RS = 0;                //根据LCD1602时序图所写
  25.         LCD1602_RW = 0;
  26.         LCD1602_DB = cmd;
  27.         LCD1602_E = 1;
  28.         LCD1602_E = 0;        
  29. }

  30. /*LCD1602设置坐标函数,形参(x,y)-书写坐标*/
  31. void LcdSetCursor(unsigned char x, unsigned char y)
  32. {
  33.         unsigned char addr;                        //书写地址

  34.         if (y == 0)
  35.                 addr = x + 0x00;
  36.         else
  37.                 addr = x + 0x40;
  38.         LcdWriteCmd(addr | 0x80);  //写入书写的地址
  39. }

  40. /*LCD1602写入数据函数,形参dat-要写入的数据*/
  41. void LcdWriteDat(unsigned char dat)
  42. {
  43.         LcdWaitReady();                                //状态检测函数
  44.         LCD1602_RS = 1;
  45.         LCD1602_RW = 0;
  46.         LCD1602_DB = dat;
  47.         LCD1602_E = 1;
  48.         LCD1602_E = 0;
  49. }

  50. /*LCD1602开光标函数*/
  51. void LcdOpenCursor()
  52. {
  53.         LcdWriteCmd(0x0f);
  54. }

  55. /*LCD1602关闭光标函数*/
  56. void LcdCloseCursor()
  57. {
  58.         LcdWriteCmd(0x0c);
  59. }

  60. /*LCD1602显示字符函数,形参(x,y)-代表书写坐标,str-所写字符串的指针*/
  61. void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str)
  62. {
  63.         LcdSetCursor(x, y);                        //设置坐标函数
  64.         while (*str != '\0')
  65.         {
  66.                 LcdWriteDat(*str++);         //写数据函数
  67.         }
  68. }

  69. /*LCD1602液晶初始化函数*/
  70. void InitLcd1602()
  71. {
  72.         LcdWriteCmd(0x38);        //写指令函数。功能设置,8位数据总线,两行显示,5*7点阵
  73.         LcdWriteCmd(0x0c);        //显示开关控制,开显示,游标不显示
  74.         LcdWriteCmd(0x06);        //完成一个字符码传送后,光标右移,地址自动加1
  75.         LcdWriteCmd(0x01);        //清显示
  76. }

二:矩阵按键模块
  1. #include
  2. //控制按键的位
  3. ***it keyout1 = P1^7;
  4. ***it keyout2 = P1^6;
  5. ***it keyout3 = P1^5;
  6. ***it keyout4 = P1^4;
  7. ***it keyin1 = P1^3;
  8. ***it keyin2 = P1^2;
  9. ***it keyin3 = P1^1;
  10. ***it keyin4 = P1^0;

  11. unsigned char code KeyCodeMap[4][4] = {         //矩阵按键编号到标准键盘键码的印射表
  12.         {'1', '2', '3', 0x26},                                 //数字键1,数字键2,数字键3,向上键
  13.         {'4', '5', '6', 0x25},                                 //数字键4,数字键5,数字键6,向左键
  14.         {'7', '8', '9', 0x28},                                 //数字键7,数字键8,数字键9,向下键
  15.         {'0', 0x1b, 0x0d, 0x27}                                 //数字键0,ESC键,回车键,向右键
  16. };
  17. //用来保存按键的状态
  18. unsigned char keysta[4][4] = {
  19.         {1, 1, 1, 1},{1, 1, 1, 1},{1, 1, 1, 1},{1, 1, 1, 1}
  20. };

  21. extern void KeyAction(unsigned char keycode);

  22. /*按键驱动函数,用来调用按键*/
  23. void KeyDriver()
  24. {        //用来保存上一次按键的状态
  25.         static unsigned char backup[4][4] = {
  26.                 {1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}
  27.         };
  28.         unsigned char i;
  29.         unsigned char j;

  30.         for (i = 0; i < 4; i++)        //构建两层循环来完成对矩阵按键的扫描
  31.         {
  32.                 for (j = 0; j < 4; j++)
  33.                 {
  34.                         if (keysta[i][j] != backup[i][j])
  35.                         {
  36.                                 if (backup[i][j] != 0)
  37.                                 {
  38.                                         KeyAction(KeyCodeMap[i][j]); //通过按键位置来执行相应的程序
  39.                                 }
  40.                                 backup[i][j] = keysta[i][j];
  41.                         }
  42.                 }
  43.         }        
  44. }

  45. /*按键扫描函数,通过定时器0中断来完成1ms扫描一次*/
  46. void KeyScan()
  47. {
  48.         static unsigned char keyout = 0;
  49.         static unsigned char keybuff[4][4] = {        //用来消抖
  50.                 {0xff, 0xff, 0xff, 0xff},{0xff, 0xff, 0xff, 0xff},
  51.                 {0xff, 0xff, 0xff, 0xff},{0xff, 0xff, 0xff, 0xff}
  52.         };
  53.         unsigned char i;

  54.         //将一行的4个按键值移入缓冲区
  55.         keybuff[keyout][0] = (keybuff[keyout][0] << 1)|keyin1;
  56.         keybuff[keyout][1] = (keybuff[keyout][1] << 1)|keyin2;
  57.         keybuff[keyout][2] = (keybuff[keyout][2] << 1)|keyin3;
  58.         keybuff[keyout][3] = (keybuff[keyout][3] << 1)|keyin4;
  59.         //消抖后更新按键状态
  60.         for (i = 0; i < 4; i++)
  61.         {
  62.                 if ((keybuff[keyout][i]&0x0f) == 0x0f)
  63.                 {//连续4次扫描值为1,即4*4ms内都是弹起状态时,可以认为按键已稳定弹起
  64.                         keysta[keyout][i] = 1;
  65.                 }
  66.                 else if ((keybuff[keyout][i]&0x0f) == 0x00)
  67.                 {//连续4次扫描值为0,即4*4ms内都是按下状态时,可以认为按键已稳定按下
  68.                         keysta[keyout][i] = 0;
  69.                 }
  70.         }
  71.         keyout++;
  72.         if (keyout >= 4)
  73.                 keyout = 0;
  74.         switch (keyout)
  75.         {  //每次拉低一个按键的值
  76.                 case 0:keyout1=0;keyout2=1;keyout3=1;keyout4=1;break;
  77.                 case 1:keyout1=1;keyout2=0;keyout3=1;keyout4=1;break;
  78.                 case 2:keyout1=1;keyout2=1;keyout3=0;keyout4=1;break;
  79.                 case 3:keyout1=1;keyout2=1;keyout3=1;keyout4=0;break;
  80.                 default:break;
  81.         }
  82. }
三:DS1302时钟芯片模块(单字节读出函数未使用)
  1. #include
  2. #include
  3. //控制DS1302时钟的位
  4. ***it DS1302_SK = P3^6;                        //时钟信号端,通过控制其高低电平来输入/输出数据
  5. ***it DS1302_IO = P3^4;                        //输入输出数据端
  6. ***it DS1302_CE = P3^5;                        //使能端,高电平时有效

  7. struct sTime {                                           //定义时间结构体
  8.         unsigned char year;                        //年
  9.         unsigned char mon;                        //月
  10.         unsigned char day;                        //日
  11.         unsigned char hour;                        //时
  12.         unsigned char min;                        //分
  13.         unsigned char sec;                        //秒
  14.         unsigned char week;                        //星期
  15. };

  16. /*DS1302读出函数,根据时序图编写,返回值为读出的数据*/
  17. unsigned char DS1302ByteRead()
  18. {
  19.         unsigned char dat = 0;
  20.         unsigned char mask;

  21.         for (mask=0x01; mask!=0; mask<<=1)
  22.         {
  23.                 if (DS1302_IO != 0)
  24.                         dat |= mask;
  25.                 DS1302_SK = 1;        //先准备好数据,然后拉高SK
  26.                 _nop_();
  27.                 DS1302_SK = 0;        //拉低SK
  28.                 _nop_();
  29.         }

  30.         return dat;
  31. }

  32. /*DS1302写入函数,根据时序图编写,dat-写入的数据*/
  33. void DS1302ByteWrite(unsigned char dat)
  34. {
  35.         unsigned char mask;

  36.         for (mask=0x01; mask!=0; mask<<=1)
  37.         {
  38.                 if ((mask&dat) != 0) //将输入数据的位从最低位依次输入
  39.                         DS1302_IO = 1;
  40.                 else
  41.                         DS1302_IO = 0;
  42.                 DS1302_SK = 1;                 //先准备好数据,拉高SK,数据采样
  43.                 _nop_();
  44.                 DS1302_SK = 0;                 //拉低SK,数据输出
  45.                 _nop_();
  46.         }
  47.         DS1302_IO = 1;                            //释放IO引脚
  48. }

  49. /*DS1302单字节读出函数,addr-写入要读字节的寄存器地址,返回值为读出的数据*/
  50. unsigned char DS1302SingleRead(unsigned char addr)
  51. {
  52.         unsigned char dat;

  53.         DS1302_CE = 1;
  54.         _nop_();
  55.         DS1302ByteWrite(addr);
  56.         dat = DS1302ByteRead();
  57.         DS1302_CE = 0;
  58.         _nop_();

  59.         return dat;
  60. }

  61. /*DS1302单字节写入函数,addr-写入字节的寄存器地址,dat-写入数据*/
  62. void DS1302SingleWrite(unsigned addr, unsigned dat)
  63. {
  64.         DS1302_CE = 1;
  65.         _nop_();
  66.         DS1302ByteWrite(addr);
  67.         DS1302ByteWrite(dat);
  68.         DS1302_CE = 0;
  69.         _nop_();
  70. }

  71. /*DS1302Burst写入模式,一次写入8个字节,dat-写入数据的指针*/
  72. void DS1302BurstWrite(unsigned char *dat)
  73. {
  74.         unsigned char i;

  75.         DS1302_CE = 1;
  76.         _nop_();
  77.         DS1302ByteWrite(0xbe);
  78.         for (i = 0; i < 8; i++)
  79.         {
  80.                 DS1302ByteWrite(*dat++);
  81.         }
  82.         DS1302_CE = 0;
  83.         _nop_();
  84. }

  85. /*DS1302Burst读出模式,一次读出8个字节,dat-存储读出数据的指针*/
  86. void DS1302BurstRead(unsigned char * dat)
  87. {
  88.         unsigned char i;

  89.         DS1302_CE = 1;
  90.         _nop_();
  91.         DS1302ByteWrite(0xbf);
  92.         for (i = 0; i < 8; i++)
  93.         {
  94.                 *dat++ = DS1302ByteRead();
  95.         }
  96.         DS1302_CE = 0;
  97.         _nop_();
  98. }

  99. /*获取实时时间,time-存储时间的结构体*/
  100. void GetRealTime(struct sTime * time)
  101. {
  102.         unsigned char buf[8];

  103.         DS1302BurstRead(buf);
  104.         time->year = buf[6] + 0x2000;
  105.         time->week = buf[5];
  106.         time->mon = buf[4];
  107.         time->day = buf[3];
  108.         time->hour = buf[2];
  109.         time->min = buf[1];
  110.         time->sec = buf[0];
  111. }

  112. /*设置实时时间,dat-要写入的数据的结构体*/
  113. void SetRealTime(struct sTime * dat)
  114. {
  115.         unsigned char buf[8];

  116.         buf[7] = 0x00;
  117.         buf[6] = dat->year;
  118.         buf[5] = dat->week;
  119.         buf[4] = dat->mon;
  120.         buf[3] = dat->day;
  121.         buf[2] = dat->hour;
  122.         buf[1] = dat->min;
  123.         buf[0] = dat->sec;
  124.         DS1302BurstWrite(buf);
  125. }

  126. /*初始化DS1302函数*/
  127. void InitDS1302()
  128. {
  129.         struct sTime code InitTime[] = {0x2019, 0x10, 0x11, 0x09, 0x59, 0x50, 0x05};

  130.         DS1302_CE = 0;
  131.         _nop_();                                       //延时一个机器周期
  132.         DS1302_SK = 0;
  133.         _nop_();
  134.         DS1302SingleWrite(0x8e, 0x00); //撤销写保护,0x8e-写保护位的地址,0x00-撤销写保护
  135.         SetRealTime(InitTime);                   //设置初始时间
  136.         DS1302SingleWrite(0x8e, 0x80); //添加写保护
  137. }
四:设置时间函数
  1. #include

  2. struct sTime {                                        //定义时间结构体
  3.         unsigned char year;                        //年
  4.         unsigned char mon;                    //月
  5.         unsigned char day;                        //日
  6.         unsigned char hour;                        //时
  7.         unsigned char min;                        //分
  8.         unsigned char sec;                        //秒
  9.         unsigned char week;                        //星期
  10. };

  11. struct sTime bufTime;                        //时间缓冲区
  12. unsigned char setIndex = 0;                //设置标志位
  13. /*函数声明*/
  14. extern void RefreshTime();
  15. extern void LcdSetCursor(unsigned char x, unsigned char y);
  16. extern void SetRealTime(struct sTime * dat);
  17. extern void LcdCloseCursor();
  18. extern void LcdOpenCursor();

  19. /*刷新当前设置位的光标指示*/
  20. void RefreshSetShow()
  21. {
  22.         switch(setIndex)
  23.         {
  24.                 case 1:LcdSetCursor(2, 0);break;
  25.                 case 2:LcdSetCursor(3, 0);break;
  26.                 case 3:LcdSetCursor(5, 0);break;
  27.                 case 4:LcdSetCursor(6, 0);break;
  28.                 case 5:LcdSetCursor(8, 0);break;
  29.                 case 6:LcdSetCursor(9, 0);break;
  30.                 case 7:LcdSetCursor(15, 0);break;
  31.                 case 8:LcdSetCursor(4, 1);break;
  32.                 case 9:LcdSetCursor(5, 1);break;
  33.                 case 10:LcdSetCursor(7, 1);break;
  34.                 case 11:LcdSetCursor(8, 1);break;
  35.                 case 12:LcdSetCursor(10, 1);break;
  36.                 case 13:LcdSetCursor(11, 1);break;
  37.                 default:break;
  38.         }
  39. }

  40. /***********************************************************************/
  41. //递增或递减分,秒的BCD码
  42. /*递增一个BCD码的高位*/
  43. unsigned char IncTimeBcdHigh(unsigned char bcd)
  44. {
  45.         if ((bcd&0xf0) < 0x50)
  46.                 bcd += 0x10;
  47.         else
  48.                 bcd &= 0x0f;

  49.         return bcd;
  50. }

  51. /*递减一个BCD码的高位*/
  52. unsigned char DecTimeBcdHigh(unsigned char bcd)
  53. {
  54.         if ((bcd&0xf0) > 0x00)
  55.                 bcd -= 0x10;
  56.         else
  57.                 bcd |= 0x50;

  58.         return bcd;
  59. }

  60. //递增或递减时,分,秒的BCD码
  61. /********************************************************************/

  62. /*递增一个BCD码的高位*/
  63. unsigned char IncBcdHigh(unsigned char bcd)
  64. {
  65.         if ((bcd&0xf0) < 0x90)
  66.                 bcd += 0x10;
  67.         else
  68.                 bcd &= 0x0f;

  69.         return bcd;
  70. }

  71. /*递增一个BCD码的低位*/
  72. unsigned char IncBcdLow(unsigned char bcd)
  73. {
  74.         if ((bcd&0x0f) < 0x09)
  75.                 bcd += 0x01;
  76.         else
  77.                 bcd &= 0xf0;

  78.         return bcd;
  79. }

  80. /*递减一个BCD码的高位*/
  81. unsigned char DecBcdHigh(unsigned char bcd)
  82. {
  83.         if ((bcd&0xf0) > 0x00)
  84.                 bcd -= 0x10;
  85.         else
  86.                 bcd |= 0x90;

  87.         return bcd;
  88. }

  89. /*递减一个BCD码的低位*/
  90. unsigned char DecBcdLow(unsigned char bcd)
  91. {
  92.         if ((bcd&0x0f) > 0x00)
  93.                 bcd -= 0x01;
  94.         else
  95.                 bcd |= 0x09;

  96.         return bcd;
  97. }

  98. /*递增周的BCD码*/
  99. unsigned char IncWeekBcd(unsigned char bcd)
  100. {
  101.         if ((bcd&0x0f) < 0x07)
  102.                 bcd += 0x01;
  103.         else
  104.                 bcd = 0x00;        

  105.         return bcd;
  106. }

  107. /*递减周的BCD码*/
  108. unsigned char DecWeekBcd(unsigned char bcd)
  109. {
  110.         if ((bcd&0x0f) > 0x00)
  111.                 bcd -= 0x01;
  112.         else
  113.                 bcd = 0x07;

  114.         return bcd;
  115. }

  116. /*递增时间当前设置位的值*/
  117. void IncSetTime()
  118. {
  119.         switch(setIndex)
  120.         {
  121.                 case 1:bufTime.year = IncBcdHigh(bufTime.year);break;
  122.                 case 2:bufTime.year = IncBcdLow(bufTime.year);break;
  123.                 case 3:bufTime.mon = IncBcdHigh(bufTime.mon);break;
  124.                 case 4:bufTime.mon = IncBcdLow(bufTime.mon);break;
  125.                 case 5:bufTime.day = IncBcdHigh(bufTime.day);break;
  126.                 case 6:bufTime.day = IncBcdLow(bufTime.day);break;
  127.                 case 7:bufTime.week = IncWeekBcd(bufTime.week);break;
  128.                 case 8:bufTime.hour = IncBcdHigh(bufTime.hour);break;
  129.                 case 9:bufTime.hour = IncBcdLow(bufTime.hour);break;
  130.                 case 10:bufTime.min = IncTimeBcdHigh(bufTime.min);break;
  131.                 case 11:bufTime.min = IncBcdLow(bufTime.min);break;
  132.                 case 12:bufTime.sec = IncTimeBcdHigh(bufTime.sec);break;
  133.                 case 13:bufTime.sec = IncBcdLow(bufTime.sec);break;
  134.                 default:break;
  135.         }
  136.         RefreshTime();
  137.         RefreshSetShow();
  138. }

  139. /*递减时间当前设置位的值*/
  140. void DecSetTime()
  141. {
  142.         switch(setIndex)
  143.         {
  144.                 case 1:bufTime.year = DecBcdHigh(bufTime.year);break;
  145.                 case 2:bufTime.year = DecBcdLow(bufTime.year);break;
  146.                 case 3:bufTime.mon = DecBcdHigh(bufTime.mon);break;
  147.                 case 4:bufTime.mon = DecBcdLow(bufTime.mon);break;
  148.                 case 5:bufTime.day = DecBcdHigh(bufTime.day);break;
  149.                 case 6:bufTime.day = DecBcdLow(bufTime.day);break;
  150.                 case 7:bufTime.week = DecWeekBcd(bufTime.week);break;
  151.                 case 8:bufTime.hour = DecBcdHigh(bufTime.hour);break;
  152.                 case 9:bufTime.hour = DecBcdLow(bufTime.hour);break;
  153.                 case 10:bufTime.min = DecTimeBcdHigh(bufTime.min);break;
  154.                 case 11:bufTime.min = DecBcdLow(bufTime.min);break;
  155.                 case 12:bufTime.sec = DecTimeBcdHigh(bufTime.sec);break;
  156.                 case 13:bufTime.sec = DecBcdLow(bufTime.sec);break;
  157.                 default:break;
  158.         }
  159.         RefreshTime();
  160.         RefreshSetShow();        
  161. }

  162. /*光标左移函数*/
  163. void LeftShift()
  164. {
  165.         if (setIndex != 0)
  166.         {
  167.                 if (setIndex > 1)
  168.                 {
  169.                         setIndex--;
  170.                 }
  171.                 else
  172.                 {
  173.                         setIndex = 13;
  174.                 }
  175.                 RefreshSetShow();
  176.         }
  177. }

  178. /*光标右移函数*/
  179. void RightShift()
  180. {
  181.         if (setIndex != 0)
  182.         {
  183.                 if (setIndex < 13)
  184.                 {
  185.                         setIndex++;
  186.                 }
  187.                 else
  188.                 {
  189.                         setIndex = 1;
  190.                 }
  191.                 RefreshSetShow();
  192.         }
  193. }

  194. /*退出时间设置函数,save-是否保存标志*/
  195. void ExitSetTime(bit save)
  196. {
  197.         setIndex = 0;
  198.         if (save)
  199.         {
  200.                 SetRealTime(&bufTime);
  201.         }
  202.         LcdCloseCursor();
  203. }

  204. /*进入时间设置函数*/
  205. void EnterSetTime()
  206. {
  207.         setIndex = 2;                        //先把设置标志位设为2,再向左移
  208.         LeftShift();
  209.         LcdOpenCursor();
  210. }

  211. /*按键执行函数,keycode-所传递的哪一个按键被按下*/
  212. void KeyAction(unsigned char keycode)
  213. {
  214.         if (keycode >= '0' && keycode <= '9')
  215.         {
  216.         //数字按键不执行任何动作
  217.         }
  218.         else if (keycode == 0x26)          //数字键加
  219.         {
  220.                 IncSetTime();
  221.         }
  222.         else if (keycode == 0x28)          //数字键减
  223.         {
  224.                 DecSetTime();
  225.         }
  226.         else if (keycode == 0x25)          //光标向左移动
  227.         {
  228.                 LeftShift();
  229.         }
  230.         else if (keycode == 0x27)          //光标向右移动
  231.         {
  232.                 RightShift();
  233.         }
  234.         else if (keycode == 0x0d)          //进入/退出时间设置
  235.         {
  236.                 if (setIndex == 0)
  237.                 {
  238.                         EnterSetTime();
  239.                 }
  240.                 else
  241.                 {
  242.                         ExitSetTime(1);          //保存数据并退出
  243.                 }
  244.         }
  245.         else if (keycode == 0x1b)          //取消键
  246.         {
  247.                 ExitSetTime(0);                  //不保存数据
  248.         }
  249. }
五:主程序
  1. #include
  2. //控制小灯的位
  3. ***it led1 = P2^0;
  4. ***it led2 = P2^1;
  5. ***it led3 = P2^2;

  6. //小灯开启时间表
  7. ledstarthour[3] = {0x10, 0x10, 0x10};
  8. ledstartmin[3] = {0x00, 0x02, 0x05};
  9. //小灯关闭时间表
  10. ledclosehour[3] = {0x10, 0x10, 0x10};
  11. ledclosemin[3] = {0x01, 0x04, 0x06};

  12. struct sTime {                                        //定义时间结构体
  13.         unsigned char year;                        //年
  14.         unsigned char mon;                        //月
  15.         unsigned char day;                        //日
  16.         unsigned char hour;                        //时
  17.         unsigned char min;                        //分
  18.         unsigned char sec;                        //秒
  19.         unsigned char week;                        //星期
  20. };

  21. bit flag200ms = 0;                                                //定时标志
  22. extern struct sTime bufTime;                        //时间缓冲区
  23. extern unsigned char setIndex ;                    //设置标志位
  24. unsigned char T0RH = 0;                                        //定时器的高8位
  25. unsigned char T0RL = 0;                                        //定时器的低8位
  26. /*函数声明*/
  27. extern void KeyScan();
  28. void configTimer0(unsigned char ms);
  29. extern void InitLcd1602();
  30. extern void InitDS1302();
  31. extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
  32. extern void KeyDriver();
  33. extern void GetRealTime(struct sTime * time);
  34. void RefreshTime();
  35. void LedStartMonitor();
  36. void LedCloseMonitor();

  37. void main()
  38. {
  39.         unsigned char psec = 0xaa;        //秒备份

  40.         EA = 1;                                                //开总中断
  41.         configTimer0(1);                        //为定时器0配置时间
  42.         InitLcd1602();                                //初始化液晶显示屏
  43.         InitDS1302();                                //初始化时钟
  44.         //显示液晶上固定的位
  45.         LcdShowStr(0, 0, "20  -  -   week ");
  46.         LcdShowStr(4, 1, "  :  :  ");

  47.         while (1)
  48.         {
  49.                 KeyDriver();                                //按键驱动
  50.                 if (flag200ms && (setIndex == 0))
  51.                 {
  52.                         flag200ms = 0;
  53.                         GetRealTime(&bufTime);                 //获取实时时间
  54.                         LedStartMonitor();
  55.                         LedCloseMonitor();
  56.                         if (psec != bufTime.sec)        //如果秒发生变化,就刷新时间
  57.                         {
  58.                                 RefreshTime();
  59.                                 psec = bufTime.sec;
  60.                         }
  61.                 }
  62.         }
  63. }

  64. /*监控时间开启小灯函数,当到达指定时间,小灯亮*/
  65. void LedStartMonitor()
  66. {
  67.         static unsigned char i = 0;
  68.         if ((bufTime.hour == ledstarthour[i])&&(bufTime.min == ledstartmin[i]))
  69.         {
  70.                 led1 = 0;
  71.                 led2 = 0;
  72.                 led3 = 0;
  73.                 i++;
  74.                 if (i >= 3)
  75.                         i = 0;
  76.         }
  77. }

  78. /*监控时间关闭小灯函数,当到达指定时间,小灯灭*/
  79. void LedCloseMonitor()
  80. {
  81.         static unsigned char i = 0;
  82.         if ((bufTime.hour == ledclosehour[i])&&(bufTime.min == ledclosemin[i]))
  83.         {
  84.                 led1 = 1;
  85.                 led2 = 1;
  86.                 led3 = 1;
  87.                 i++;
  88.                 if (i >= 3)
  89.                         i = 0;
  90.         }
  91. }

  92. /*将BCD码转换为字符串*/
  93. void ShowBcdByte(unsigned char x, unsigned char y, unsigned char dat)
  94. {
  95.         unsigned char buf[3];
  96.         if (x == 15)                                 //对“周”的特殊照顾
  97.         {
  98.                 buf[0] = (dat&0x0f)+'0';
  99.                 buf[1] = '\0';
  100.         }
  101.         else
  102.         {
  103.                 buf[0] = (dat>>4)+'0';         
  104.                 buf[1] = (dat&0x0f)+'0';
  105.                 buf[2] = '\0';
  106.         }
  107.         LcdShowStr(x, y, buf);
  108. }

  109. /*刷新时间函数*/
  110. void RefreshTime()
  111. {
  112.         ShowBcdByte(2, 0, bufTime.year);
  113.         ShowBcdByte(5, 0, bufTime.mon);
  114.         ShowBcdByte(8, 0, bufTime.day);
  115.         ShowBcdByte(15, 0, bufTime.week);
  116.         ShowBcdByte(4, 1, bufTime.hour);
  117.         ShowBcdByte(7, 1, bufTime.min);
  118.         ShowBcdByte(10, 1, bufTime.sec);
  119. }

  120. /*配置定时器0*/
  121. void configTimer0(unsigned char ms)
  122. {
  123.         unsigned long temp;

  124.         temp = 11059200 / 12;
  125.         temp = (temp*ms)/1000;
  126.         temp = 65536 - temp;
  127.         T0RH = (unsigned char)(temp >> 8);
  128.         T0RL = (unsigned char)temp;
  129.         TMOD &= 0xf0;
  130.         TMOD |= 0x01;
  131.         TH0 = T0RH;
  132.         TL0 = T0RL;
  133.         TR0 = 1;
  134.         ET0 = 1;                //打开定时器0中断
  135. }

  136. /*中断函数*/
  137. void InterruptTimer0()                        interrupt 1
  138. {
  139.         static unsigned char tmr200ms = 0;

  140.         TH0 = T0RH;
  141.         TL0 = T0RL;
  142.         KeyScan();
  143.         tmr200ms++;
  144.         if (tmr200ms >= 200)
  145.         {
  146.                 tmr200ms = 0;
  147.                 flag200ms = 1;
  148.         }
  149. }



` 控制系统.jpg

更多回帖

发帖
×
20
完善资料,
赚取积分