简介:单片机开源项目之按键可调时电子钟(矩阵按键+红外遥控按键进行调时)
此程序是基于51hei单片机开发板上面写的,如需要移植到自己的电路上,修改相应的端口即可。
/**
************************************************************************
* @file : main.c
* @author : xr
* @date : 2014年4月21日 22:23:12 - 2014年4月26日21:22:29
* @version : V1.2.3
* @brief : 按键可调时电子钟(矩阵按键+红外遥控按键进行调时) 单片机STC89C52RC MCU 晶振 11.0592MHZ
************************************************************************
*/
#include #include "main.h" /*定义结构体来封装从DS1302中读取的时间和日期和设置到DS1302中的时间和日期*/ struct Time { unsigned char year; //DS1302中只存放的是年的低两位字节 unsigned char month; unsigned char day; unsigned char hour; unsigned char min; unsigned char sec; unsigned char week; }; /*定义结构体时间变量来保存时间和日期*/ struct Time timeBuf; //此处必须用结构体变量,不能用结构体指针否则写入失败! unsigned char setTimeIndex = 0; //设置时间状态及设置光标位置及设置时间位置的索引值(0时正常运行,1-12为设置时间状态,1-12是设置的位置) bit flag200ms = 0; unsigned char thr0, tlr0; //红外通信解码的键码和标准PC机编码映射表 unsigned char code IrdCodeMap[] = {0x45, 0x46, 0x47, //开关,Mode, 静音 0x44, 0x40, 0x43, //播放/暂停 快退, 快进 0x07, 0x15, 0x09, //EQ, 减, 加 0x16, 0x19, 0x0D, //0, 返回, U/SD 0x0C, 0x18, 0x5E, //1, 2, 3 0x08, 0x1C, 0x5A, //4, 5, 6 0x42, 0x52, 0x4A};//7, 8, 9 //外部变量声明 extern bit flagIrd; //红外数据码值接收完毕标志位 extern unsigned char irdCode[4]; //保存NEC协议解码的四个字节的数据码(用户码+用户反码,键码+键码反码) extern void InitLCD1602(); extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char * str); extern void LcdSetCoursor(unsigned char x, unsigned char y); extern void LcdOpenCoursor(); extern void InitDS1302(); extern void GetTimeFromDS1302(struct Time * time); extern void SetTimeToDS1302(struct Time * time); extern void KeyDriver(); extern void KeyScan(); extern void LcdCoursorRight(); extern void LcdCoursorLeft(); void ConfgiTimer0(unsigned int xms); void RefreshLcdShowTime(); extern void ConfigIrdByTimer1(); void IrdDrive(); void IrdKeyAction(); extern void SetTimeBcdByte(unsigned char keyNum); /*主程序main()*/ void main() { unsigned char psec = 0xFF;//用于检测sec秒是否变化,若变化则刷新时间显示 ConfgiTimer0(1); //定时1ms ConfigIrdByTimer1();//配置红外通信 InitLCD1602(); InitDS1302(); /*液晶初始化显示*/ LcdShowStr(1, 0, "*"); LcdShowStr(2, 0, "20 - - "); LcdShowStr(12, 0, "*"); LcdShowStr(14, 0, "--"); LcdShowStr(0, 1, "time: --:--:--"); while (1) { KeyDriver();//检测按键动作 if (flagIrd) { flagIrd = 0; IrdKeyAction();//检测红外按键动作 } if (flag200ms == 1 && (setTimeIndex == 0)) //每200ms且setTimeIndex==0处于非设定时间状态时刷新一次时间显示 { flag200ms = 0; GetTimeFromDS1302(&timeBuf); //从DS1302中获取时间到timeBuf结构体指针变量的成员中 if (timeBuf.sec != psec) //当前秒值和上一次的秒值不相等 { RefreshLcdShowTime();//刷新时间显示 psec = timeBuf.sec;//备份当前的秒值(秒寄存器值) } } } } /*定时器T0配置*/ void ConfgiTimer0(unsigned int xms) { unsigned long tmp; tmp = 11059200/12;//周期频率 tmp = (tmp * xms) / 1000;//定时xms需要的计数值 tmp = 65536-tmp;//定时装入的初值 thr0 = (unsigned char)(tmp >> 8); tlr0 = (unsigned char)tmp; TMOD &= 0xF0;//清零T0控制位 TMOD |= 0x01;//T0方式1,16位可设定时模式 TH0 = thr0; TL0 = tlr0; TR0 = 1; ET0 = 1; EA = 1; } /*将一个BCD码字节数据分解显示到LCD1602的(x, y)坐标上*/ void LcdShowBCDByte(unsigned char x, unsigned char y, unsigned char bcdbyte) { unsigned char str[4]; str[0] = (bcdbyte >> 4) + '0';//取BCD码的高四位字节 str[1] = (bcdbyte & 0x0F) + '0';//取BCD码的第四位字节 str[2] = '