两只袜子 发表于 2021-8-23 11:33

时钟控制器(电子时钟)

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

一:LCD1602液晶模块





[*]#include <reg52.h>
[*]//控制LCD1602的位
[*]#define LCD1602_DB P0      //数据位
[*]sbit LCD1602_RS = P2^6;      //指令/数据选择信号
[*]sbit LCD1602_RW = P2^5;      //读写选择信号
[*]sbit LCD1602_E = P2^7;      //使能信号
[*]
[*]/*LCD1602状态检测函数DB7为忙标志位,为1时禁止,为0是工作*/
[*]void LcdWaitReady()
[*]{
[*]      unsigned char sta;                //用来缓存LCD1602_DB的值
[*]
[*]      LCD1602_DB = 0xff;                //赋初值
[*]      LCD1602_RS = 0;
[*]      LCD1602_RW = 1;
[*]      do {
[*]                LCD1602_E = 1;
[*]                sta = LCD1602_DB;
[*]                LCD1602_E = 0;
[*]      }while (sta&0x80);         //当DB7为0时结束循环
[*]}
[*]
[*]/*LCD1602写指令函数,形参cmd-要输入的指令*/
[*]void LcdWriteCmd(unsigned char cmd)
[*]{
[*]      LcdWaitReady();                //检测状态函数
[*]      LCD1602_RS = 0;                //根据LCD1602时序图所写
[*]      LCD1602_RW = 0;
[*]      LCD1602_DB = cmd;
[*]      LCD1602_E = 1;
[*]      LCD1602_E = 0;
[*]}
[*]
[*]/*LCD1602设置坐标函数,形参(x,y)-书写坐标*/
[*]void LcdSetCursor(unsigned char x, unsigned char y)
[*]{
[*]      unsigned char addr;                        //书写地址
[*]
[*]      if (y == 0)
[*]                addr = x + 0x00;
[*]      else
[*]                addr = x + 0x40;
[*]      LcdWriteCmd(addr | 0x80);//写入书写的地址
[*]}
[*]
[*]/*LCD1602写入数据函数,形参dat-要写入的数据*/
[*]void LcdWriteDat(unsigned char dat)
[*]{
[*]      LcdWaitReady();                              //状态检测函数
[*]      LCD1602_RS = 1;
[*]      LCD1602_RW = 0;
[*]      LCD1602_DB = dat;
[*]      LCD1602_E = 1;
[*]      LCD1602_E = 0;
[*]}
[*]
[*]/*LCD1602开光标函数*/
[*]void LcdOpenCursor()
[*]{
[*]      LcdWriteCmd(0x0f);
[*]}
[*]
[*]/*LCD1602关闭光标函数*/
[*]void LcdCloseCursor()
[*]{
[*]      LcdWriteCmd(0x0c);
[*]}
[*]
[*]/*LCD1602显示字符函数,形参(x,y)-代表书写坐标,str-所写字符串的指针*/
[*]void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str)
[*]{
[*]      LcdSetCursor(x, y);                        //设置坐标函数
[*]      while (*str != '\0')
[*]      {
[*]                LcdWriteDat(*str++);         //写数据函数
[*]      }
[*]}
[*]
[*]/*LCD1602液晶初始化函数*/
[*]void InitLcd1602()
[*]{
[*]      LcdWriteCmd(0x38);      //写指令函数。功能设置,8位数据总线,两行显示,5*7点阵
[*]      LcdWriteCmd(0x0c);      //显示开关控制,开显示,游标不显示
[*]      LcdWriteCmd(0x06);      //完成一个字符码传送后,光标右移,地址自动加1
[*]      LcdWriteCmd(0x01);      //清显示
[*]}


复制代码



二:矩阵按键模块





[*]#include <reg52.h>
[*]//控制按键的位
[*]sbit keyout1 = P1^7;
[*]sbit keyout2 = P1^6;
[*]sbit keyout3 = P1^5;
[*]sbit keyout4 = P1^4;
[*]sbit keyin1 = P1^3;
[*]sbit keyin2 = P1^2;
[*]sbit keyin3 = P1^1;
[*]sbit keyin4 = P1^0;
[*]
[*]unsigned char code KeyCodeMap = {         //矩阵按键编号到标准键盘键码的印射表
[*]      {'1', '2', '3', 0x26},                                 //数字键1,数字键2,数字键3,向上键
[*]      {'4', '5', '6', 0x25},                                 //数字键4,数字键5,数字键6,向左键
[*]      {'7', '8', '9', 0x28},                                 //数字键7,数字键8,数字键9,向下键
[*]      {'0', 0x1b, 0x0d, 0x27}                                 //数字键0,ESC键,回车键,向右键
[*]};
[*]//用来保存按键的状态
[*]unsigned char keysta = {
[*]      {1, 1, 1, 1},{1, 1, 1, 1},{1, 1, 1, 1},{1, 1, 1, 1}
[*]};
[*]
[*]extern void KeyAction(unsigned char keycode);
[*]
[*]/*按键驱动函数,用来调用按键*/
[*]void KeyDriver()
[*]{      //用来保存上一次按键的状态
[*]      static unsigned char backup = {
[*]                {1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}
[*]      };
[*]      unsigned char i;
[*]      unsigned char j;
[*]
[*]      for (i = 0; i < 4; i++)      //构建两层循环来完成对矩阵按键的扫描
[*]      {
[*]                for (j = 0; j < 4; j++)
[*]                {
[*]                        if (keysta != backup)
[*]                        {
[*]                              if (backup != 0)
[*]                              {
[*]                                        KeyAction(KeyCodeMap); //通过按键位置来执行相应的程序
[*]                              }
[*]                              backup = keysta;
[*]                        }
[*]                }
[*]      }
[*]}
[*]
[*]/*按键扫描函数,通过定时器0中断来完成1ms扫描一次*/
[*]void KeyScan()
[*]{
[*]      static unsigned char keyout = 0;
[*]      static unsigned char keybuff = {      //用来消抖
[*]                {0xff, 0xff, 0xff, 0xff},{0xff, 0xff, 0xff, 0xff},
[*]                {0xff, 0xff, 0xff, 0xff},{0xff, 0xff, 0xff, 0xff}
[*]      };
[*]      unsigned char i;
[*]
[*]      //将一行的4个按键值移入缓冲区
[*]      keybuff = (keybuff << 1)|keyin1;
[*]      keybuff = (keybuff << 1)|keyin2;
[*]      keybuff = (keybuff << 1)|keyin3;
[*]      keybuff = (keybuff << 1)|keyin4;
[*]      //消抖后更新按键状态
[*]      for (i = 0; i < 4; i++)
[*]      {
[*]                if ((keybuff&0x0f) == 0x0f)
[*]                {//连续4次扫描值为1,即4*4ms内都是弹起状态时,可以认为按键已稳定弹起
[*]                        keysta = 1;
[*]                }
[*]                else if ((keybuff&0x0f) == 0x00)
[*]                {//连续4次扫描值为0,即4*4ms内都是按下状态时,可以认为按键已稳定按下
[*]                        keysta = 0;
[*]                }
[*]      }
[*]      keyout++;
[*]      if (keyout >= 4)
[*]                keyout = 0;
[*]      switch (keyout)
[*]      {//每次拉低一个按键的值
[*]                case 0:keyout1=0;keyout2=1;keyout3=1;keyout4=1;break;
[*]                case 1:keyout1=1;keyout2=0;keyout3=1;keyout4=1;break;
[*]                case 2:keyout1=1;keyout2=1;keyout3=0;keyout4=1;break;
[*]                case 3:keyout1=1;keyout2=1;keyout3=1;keyout4=0;break;
[*]                default:break;
[*]      }
[*]}



复制代码

三:DS1302时钟芯片模块(单字节读出函数未使用)





[*]#include <reg52.h>
[*]#include <intrins.h>
[*]//控制DS1302时钟的位
[*]sbit DS1302_SK = P3^6;                        //时钟信号端,通过控制其高低电平来输入/输出数据
[*]sbit DS1302_IO = P3^4;                        //输入输出数据端
[*]sbit DS1302_CE = P3^5;                        //使能端,高电平时有效
[*]
[*]struct sTime {                                           //定义时间结构体
[*]      unsigned char year;                        //年
[*]      unsigned char mon;                        //月
[*]      unsigned char day;                        //日
[*]      unsigned char hour;                        //时
[*]      unsigned char min;                        //分
[*]      unsigned char sec;                        //秒
[*]      unsigned char week;                        //星期
[*]};
[*]
[*]/*DS1302读出函数,根据时序图编写,返回值为读出的数据*/
[*]unsigned char DS1302ByteRead()
[*]{
[*]      unsigned char dat = 0;
[*]      unsigned char mask;
[*]
[*]      for (mask=0x01; mask!=0; mask<<=1)
[*]      {
[*]                if (DS1302_IO != 0)
[*]                        dat |= mask;
[*]                DS1302_SK = 1;      //先准备好数据,然后拉高SK
[*]                _nop_();
[*]                DS1302_SK = 0;      //拉低SK
[*]                _nop_();
[*]      }
[*]
[*]      return dat;
[*]}
[*]
[*]/*DS1302写入函数,根据时序图编写,dat-写入的数据*/
[*]void DS1302ByteWrite(unsigned char dat)
[*]{
[*]      unsigned char mask;
[*]
[*]      for (mask=0x01; mask!=0; mask<<=1)
[*]      {
[*]                if ((mask&dat) != 0) //将输入数据的位从最低位依次输入
[*]                        DS1302_IO = 1;
[*]                else
[*]                        DS1302_IO = 0;
[*]                DS1302_SK = 1;               //先准备好数据,拉高SK,数据采样
[*]                _nop_();
[*]                DS1302_SK = 0;               //拉低SK,数据输出
[*]                _nop_();
[*]      }
[*]      DS1302_IO = 1;                            //释放IO引脚
[*]}
[*]
[*]/*DS1302单字节读出函数,addr-写入要读字节的寄存器地址,返回值为读出的数据*/
[*]unsigned char DS1302SingleRead(unsigned char addr)
[*]{
[*]      unsigned char dat;
[*]
[*]      DS1302_CE = 1;
[*]      _nop_();
[*]      DS1302ByteWrite(addr);
[*]      dat = DS1302ByteRead();
[*]      DS1302_CE = 0;
[*]      _nop_();
[*]
[*]      return dat;
[*]}
[*]
[*]/*DS1302单字节写入函数,addr-写入字节的寄存器地址,dat-写入数据*/
[*]void DS1302SingleWrite(unsigned addr, unsigned dat)
[*]{
[*]      DS1302_CE = 1;
[*]      _nop_();
[*]      DS1302ByteWrite(addr);
[*]      DS1302ByteWrite(dat);
[*]      DS1302_CE = 0;
[*]      _nop_();
[*]}
[*]
[*]/*DS1302burst写入模式,一次写入8个字节,dat-写入数据的指针*/
[*]void DS1302BurstWrite(unsigned char *dat)
[*]{
[*]      unsigned char i;
[*]
[*]      DS1302_CE = 1;
[*]      _nop_();
[*]      DS1302ByteWrite(0xbe);
[*]      for (i = 0; i < 8; i++)
[*]      {
[*]                DS1302ByteWrite(*dat++);
[*]      }
[*]      DS1302_CE = 0;
[*]      _nop_();
[*]}
[*]
[*]/*DS1302Burst读出模式,一次读出8个字节,dat-存储读出数据的指针*/
[*]void DS1302BurstRead(unsigned char * dat)
[*]{
[*]      unsigned char i;
[*]
[*]      DS1302_CE = 1;
[*]      _nop_();
[*]      DS1302ByteWrite(0xbf);
[*]      for (i = 0; i < 8; i++)
[*]      {
[*]                *dat++ = DS1302ByteRead();
[*]      }
[*]      DS1302_CE = 0;
[*]      _nop_();
[*]}
[*]
[*]/*获取实时时间,time-存储时间的结构体*/
[*]void GetRealTime(struct sTime * time)
[*]{
[*]      unsigned char buf;
[*]
[*]      DS1302BurstRead(buf);
[*]      time->year = buf + 0x2000;
[*]      time->week = buf;
[*]      time->mon = buf;
[*]      time->day = buf;
[*]      time->hour = buf;
[*]      time->min = buf;
[*]      time->sec = buf;
[*]}
[*]
[*]/*设置实时时间,dat-要写入的数据的结构体*/
[*]void SetRealTime(struct sTime * dat)
[*]{
[*]      unsigned char buf;
[*]
[*]      buf = 0x00;
[*]      buf = dat->year;
[*]      buf = dat->week;
[*]      buf = dat->mon;
[*]      buf = dat->day;
[*]      buf = dat->hour;
[*]      buf = dat->min;
[*]      buf = dat->sec;
[*]      DS1302BurstWrite(buf);
[*]}
[*]
[*]/*初始化DS1302函数*/
[*]void InitDS1302()
[*]{
[*]      struct sTime code InitTime[] = {0x2019, 0x10, 0x11, 0x09, 0x59, 0x50, 0x05};
[*]
[*]      DS1302_CE = 0;
[*]      _nop_();                                       //延时一个机器周期
[*]      DS1302_SK = 0;
[*]      _nop_();
[*]      DS1302SingleWrite(0x8e, 0x00); //撤销写保护,0x8e-写保护位的地址,0x00-撤销写保护
[*]      SetRealTime(InitTime);                   //设置初始时间
[*]      DS1302SingleWrite(0x8e, 0x80); //添加写保护
[*]}


复制代码


四:设置时间函数





[*]#include <reg52.h>
[*]
[*]struct sTime {                                        //定义时间结构体
[*]      unsigned char year;                        //年
[*]      unsigned char mon;                  //月
[*]      unsigned char day;                        //日
[*]      unsigned char hour;                        //时
[*]      unsigned char min;                        //分
[*]      unsigned char sec;                        //秒
[*]      unsigned char week;                        //星期
[*]};
[*]
[*]struct sTime bufTime;                        //时间缓冲区
[*]unsigned char setIndex = 0;                //设置标志位
[*]/*函数声明*/
[*]extern void RefreshTime();
[*]extern void LcdSetCursor(unsigned char x, unsigned char y);
[*]extern void SetRealTime(struct sTime * dat);
[*]extern void LcdCloseCursor();
[*]extern void LcdOpenCursor();
[*]
[*]/*刷新当前设置位的光标指示*/
[*]void RefreshSetShow()
[*]{
[*]      switch(setIndex)
[*]      {
[*]                case 1:LcdSetCursor(2, 0);break;
[*]                case 2:LcdSetCursor(3, 0);break;
[*]                case 3:LcdSetCursor(5, 0);break;
[*]                case 4:LcdSetCursor(6, 0);break;
[*]                case 5:LcdSetCursor(8, 0);break;
[*]                case 6:LcdSetCursor(9, 0);break;
[*]                case 7:LcdSetCursor(15, 0);break;
[*]                case 8:LcdSetCursor(4, 1);break;
[*]                case 9:LcdSetCursor(5, 1);break;
[*]                case 10:LcdSetCursor(7, 1);break;
[*]                case 11:LcdSetCursor(8, 1);break;
[*]                case 12:LcdSetCursor(10, 1);break;
[*]                case 13:LcdSetCursor(11, 1);break;
[*]                default:break;
[*]      }
[*]}
[*]
[*]/***********************************************************************/
[*]//递增或递减分,秒的BCD码
[*]/*递增一个BCD码的高位*/
[*]unsigned char IncTimeBcdHigh(unsigned char bcd)
[*]{
[*]      if ((bcd&0xf0) < 0x50)
[*]                bcd += 0x10;
[*]      else
[*]                bcd &= 0x0f;
[*]
[*]      return bcd;
[*]}
[*]
[*]/*递减一个BCD码的高位*/
[*]unsigned char DecTimeBcdHigh(unsigned char bcd)
[*]{
[*]      if ((bcd&0xf0) > 0x00)
[*]                bcd -= 0x10;
[*]      else
[*]                bcd |= 0x50;
[*]
[*]      return bcd;
[*]}
[*]
[*]//递增或递减时,分,秒的BCD码
[*]/********************************************************************/
[*]
[*]/*递增一个BCD码的高位*/
[*]unsigned char IncBcdHigh(unsigned char bcd)
[*]{
[*]      if ((bcd&0xf0) < 0x90)
[*]                bcd += 0x10;
[*]      else
[*]                bcd &= 0x0f;
[*]
[*]      return bcd;
[*]}
[*]
[*]/*递增一个BCD码的低位*/
[*]unsigned char IncBcdLow(unsigned char bcd)
[*]{
[*]      if ((bcd&0x0f) < 0x09)
[*]                bcd += 0x01;
[*]      else
[*]                bcd &= 0xf0;
[*]
[*]      return bcd;
[*]}
[*]
[*]/*递减一个BCD码的高位*/
[*]unsigned char DecBcdHigh(unsigned char bcd)
[*]{
[*]      if ((bcd&0xf0) > 0x00)
[*]                bcd -= 0x10;
[*]      else
[*]                bcd |= 0x90;
[*]
[*]      return bcd;
[*]}
[*]
[*]/*递减一个BCD码的低位*/
[*]unsigned char DecBcdLow(unsigned char bcd)
[*]{
[*]      if ((bcd&0x0f) > 0x00)
[*]                bcd -= 0x01;
[*]      else
[*]                bcd |= 0x09;
[*]
[*]      return bcd;
[*]}
[*]
[*]/*递增周的BCD码*/
[*]unsigned char IncWeekBcd(unsigned char bcd)
[*]{
[*]      if ((bcd&0x0f) < 0x07)
[*]                bcd += 0x01;
[*]      else
[*]                bcd = 0x00;
[*]
[*]      return bcd;
[*]}
[*]
[*]/*递减周的BCD码*/
[*]unsigned char DecWeekBcd(unsigned char bcd)
[*]{
[*]      if ((bcd&0x0f) > 0x00)
[*]                bcd -= 0x01;
[*]      else
[*]                bcd = 0x07;
[*]
[*]      return bcd;
[*]}
[*]
[*]/*递增时间当前设置位的值*/
[*]void IncSetTime()
[*]{
[*]      switch(setIndex)
[*]      {
[*]                case 1:bufTime.year = IncBcdHigh(bufTime.year);break;
[*]                case 2:bufTime.year = IncBcdLow(bufTime.year);break;
[*]                case 3:bufTime.mon = IncBcdHigh(bufTime.mon);break;
[*]                case 4:bufTime.mon = IncBcdLow(bufTime.mon);break;
[*]                case 5:bufTime.day = IncBcdHigh(bufTime.day);break;
[*]                case 6:bufTime.day = IncBcdLow(bufTime.day);break;
[*]                case 7:bufTime.week = IncWeekBcd(bufTime.week);break;
[*]                case 8:bufTime.hour = IncBcdHigh(bufTime.hour);break;
[*]                case 9:bufTime.hour = IncBcdLow(bufTime.hour);break;
[*]                case 10:bufTime.min = IncTimeBcdHigh(bufTime.min);break;
[*]                case 11:bufTime.min = IncBcdLow(bufTime.min);break;
[*]                case 12:bufTime.sec = IncTimeBcdHigh(bufTime.sec);break;
[*]                case 13:bufTime.sec = IncBcdLow(bufTime.sec);break;
[*]                default:break;
[*]      }
[*]      RefreshTime();
[*]      RefreshSetShow();
[*]}
[*]
[*]/*递减时间当前设置位的值*/
[*]void DecSetTime()
[*]{
[*]      switch(setIndex)
[*]      {
[*]                case 1:bufTime.year = DecBcdHigh(bufTime.year);break;
[*]                case 2:bufTime.year = DecBcdLow(bufTime.year);break;
[*]                case 3:bufTime.mon = DecBcdHigh(bufTime.mon);break;
[*]                case 4:bufTime.mon = DecBcdLow(bufTime.mon);break;
[*]                case 5:bufTime.day = DecBcdHigh(bufTime.day);break;
[*]                case 6:bufTime.day = DecBcdLow(bufTime.day);break;
[*]                case 7:bufTime.week = DecWeekBcd(bufTime.week);break;
[*]                case 8:bufTime.hour = DecBcdHigh(bufTime.hour);break;
[*]                case 9:bufTime.hour = DecBcdLow(bufTime.hour);break;
[*]                case 10:bufTime.min = DecTimeBcdHigh(bufTime.min);break;
[*]                case 11:bufTime.min = DecBcdLow(bufTime.min);break;
[*]                case 12:bufTime.sec = DecTimeBcdHigh(bufTime.sec);break;
[*]                case 13:bufTime.sec = DecBcdLow(bufTime.sec);break;
[*]                default:break;
[*]      }
[*]      RefreshTime();
[*]      RefreshSetShow();
[*]}
[*]
[*]/*光标左移函数*/
[*]void LeftShift()
[*]{
[*]      if (setIndex != 0)
[*]      {
[*]                if (setIndex > 1)
[*]                {
[*]                        setIndex--;
[*]                }
[*]                else
[*]                {
[*]                        setIndex = 13;
[*]                }
[*]                RefreshSetShow();
[*]      }
[*]}
[*]
[*]/*光标右移函数*/
[*]void RightShift()
[*]{
[*]      if (setIndex != 0)
[*]      {
[*]                if (setIndex < 13)
[*]                {
[*]                        setIndex++;
[*]                }
[*]                else
[*]                {
[*]                        setIndex = 1;
[*]                }
[*]                RefreshSetShow();
[*]      }
[*]}
[*]
[*]/*退出时间设置函数,save-是否保存标志*/
[*]void ExitSetTime(bit save)
[*]{
[*]      setIndex = 0;
[*]      if (save)
[*]      {
[*]                SetRealTime(&bufTime);
[*]      }
[*]      LcdCloseCursor();
[*]}
[*]
[*]/*进入时间设置函数*/
[*]void EnterSetTime()
[*]{
[*]      setIndex = 2;                        //先把设置标志位设为2,再向左移
[*]      LeftShift();
[*]      LcdOpenCursor();
[*]}
[*]
[*]/*按键执行函数,keycode-所传递的哪一个按键被按下*/
[*]void KeyAction(unsigned char keycode)
[*]{
[*]      if (keycode >= '0' && keycode <= '9')
[*]      {
[*]      //数字按键不执行任何动作
[*]      }
[*]      else if (keycode == 0x26)          //数字键加
[*]      {
[*]                IncSetTime();
[*]      }
[*]      else if (keycode == 0x28)          //数字键减
[*]      {
[*]                DecSetTime();
[*]      }
[*]      else if (keycode == 0x25)          //光标向左移动
[*]      {
[*]                LeftShift();
[*]      }
[*]      else if (keycode == 0x27)          //光标向右移动
[*]      {
[*]                RightShift();
[*]      }
[*]      else if (keycode == 0x0d)          //进入/退出时间设置
[*]      {
[*]                if (setIndex == 0)
[*]                {
[*]                        EnterSetTime();
[*]                }
[*]                else
[*]                {
[*]                        ExitSetTime(1);          //保存数据并退出
[*]                }
[*]      }
[*]      else if (keycode == 0x1b)          //取消键
[*]      {
[*]                ExitSetTime(0);                  //不保存数据
[*]      }
[*]}


复制代码


五:主程序





[*]#include <reg52.h>
[*]//控制小灯的位
[*]sbit led1 = P2^0;
[*]sbit led2 = P2^1;
[*]sbit led3 = P2^2;
[*]
[*]//小灯开启时间表
[*]ledstarthour = {0x10, 0x10, 0x10};
[*]ledstartmin = {0x00, 0x02, 0x05};
[*]//小灯关闭时间表
[*]ledclosehour = {0x10, 0x10, 0x10};
[*]ledclosemin = {0x01, 0x04, 0x06};
[*]
[*]struct sTime {                                        //定义时间结构体
[*]      unsigned char year;                        //年
[*]      unsigned char mon;                        //月
[*]      unsigned char day;                        //日
[*]      unsigned char hour;                        //时
[*]      unsigned char min;                        //分
[*]      unsigned char sec;                        //秒
[*]      unsigned char week;                        //星期
[*]};
[*]
[*]bit flag200ms = 0;                                                //定时标志
[*]extern struct sTime bufTime;                        //时间缓冲区
[*]extern unsigned char setIndex ;                  //设置标志位
[*]unsigned char T0RH = 0;                                        //定时器的高8位
[*]unsigned char T0RL = 0;                                        //定时器的低8位
[*]/*函数声明*/
[*]extern void KeyScan();
[*]void configTimer0(unsigned char ms);
[*]extern void InitLcd1602();
[*]extern void InitDS1302();
[*]extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
[*]extern void KeyDriver();
[*]extern void GetRealTime(struct sTime * time);
[*]void RefreshTime();
[*]void LedStartMonitor();
[*]void LedCloseMonitor();
[*]
[*]void main()
[*]{
[*]      unsigned char psec = 0xaa;      //秒备份
[*]
[*]      EA = 1;                                                //开总中断
[*]      configTimer0(1);                        //为定时器0配置时间
[*]      InitLcd1602();                              //初始化液晶显示屏
[*]      InitDS1302();                              //初始化时钟
[*]      //显示液晶上固定的位
[*]      LcdShowStr(0, 0, "20--   week ");
[*]      LcdShowStr(4, 1, "::");
[*]
[*]      while (1)
[*]      {
[*]                KeyDriver();                              //按键驱动
[*]                if (flag200ms && (setIndex == 0))
[*]                {
[*]                        flag200ms = 0;
[*]                        GetRealTime(&bufTime);               //获取实时时间
[*]                        LedStartMonitor();
[*]                        LedCloseMonitor();
[*]                        if (psec != bufTime.sec)      //如果秒发生变化,就刷新时间
[*]                        {
[*]                              RefreshTime();
[*]                              psec = bufTime.sec;
[*]                        }
[*]                }
[*]      }
[*]}
[*]
[*]/*监控时间开启小灯函数,当到达指定时间,小灯亮*/
[*]void LedStartMonitor()
[*]{
[*]      static unsigned char i = 0;
[*]      if ((bufTime.hour == ledstarthour)&&(bufTime.min == ledstartmin))
[*]      {
[*]                led1 = 0;
[*]                led2 = 0;
[*]                led3 = 0;
[*]                i++;
[*]                if (i >= 3)
[*]                        i = 0;
[*]      }
[*]}
[*]
[*]/*监控时间关闭小灯函数,当到达指定时间,小灯灭*/
[*]void LedCloseMonitor()
[*]{
[*]      static unsigned char i = 0;
[*]      if ((bufTime.hour == ledclosehour)&&(bufTime.min == ledclosemin))
[*]      {
[*]                led1 = 1;
[*]                led2 = 1;
[*]                led3 = 1;
[*]                i++;
[*]                if (i >= 3)
[*]                        i = 0;
[*]      }
[*]}
[*]
[*]/*将BCD码转换为字符串*/
[*]void ShowBcdByte(unsigned char x, unsigned char y, unsigned char dat)
[*]{
[*]      unsigned char buf;
[*]      if (x == 15)                                 //对“周”的特殊照顾
[*]      {
[*]                buf = (dat&0x0f)+'0';
[*]                buf = '\0';
[*]      }
[*]      else
[*]      {
[*]                buf = (dat>>4)+'0';
[*]                buf = (dat&0x0f)+'0';
[*]                buf = '\0';
[*]      }
[*]      LcdShowStr(x, y, buf);
[*]}
[*]
[*]/*刷新时间函数*/
[*]void RefreshTime()
[*]{
[*]      ShowBcdByte(2, 0, bufTime.year);
[*]      ShowBcdByte(5, 0, bufTime.mon);
[*]      ShowBcdByte(8, 0, bufTime.day);
[*]      ShowBcdByte(15, 0, bufTime.week);
[*]      ShowBcdByte(4, 1, bufTime.hour);
[*]      ShowBcdByte(7, 1, bufTime.min);
[*]      ShowBcdByte(10, 1, bufTime.sec);
[*]}
[*]
[*]/*配置定时器0*/
[*]void configTimer0(unsigned char ms)
[*]{
[*]      unsigned long temp;
[*]
[*]      temp = 11059200 / 12;
[*]      temp = (temp*ms)/1000;
[*]      temp = 65536 - temp;
[*]      T0RH = (unsigned char)(temp >> 8);
[*]      T0RL = (unsigned char)temp;
[*]      TMOD &= 0xf0;
[*]      TMOD |= 0x01;
[*]      TH0 = T0RH;
[*]      TL0 = T0RL;
[*]      TR0 = 1;
[*]      ET0 = 1;                //打开定时器0中断
[*]}
[*]
[*]/*中断函数*/
[*]void InterruptTimer0()                        interrupt 1
[*]{
[*]      static unsigned char tmr200ms = 0;
[*]
[*]      TH0 = T0RH;
[*]      TL0 = T0RL;
[*]      KeyScan();
[*]      tmr200ms++;
[*]      if (tmr200ms >= 200)
[*]      {
[*]                tmr200ms = 0;
[*]                flag200ms = 1;
[*]      }
[*]}



复制代码
页: [1]
查看完整版本: 时钟控制器(电子时钟)