#include <reg52.h>
struct sTime { //日期时间结构体定义
unsigned int year;
unsigned char mon;
unsigned char day;
unsigned char hour;
unsigned char min;
unsigned char sec;
unsigned char week;
};
bit flag1s = 0; //1s定时标志
bit flag200ms = 1; //200ms定时标志
struct sTime bufTime; //日期时间缓冲区
unsigned char setIndex = 0; //时间设置索引
unsigned char T0RH = 0; //T0重载值的高字节
unsigned char T0RL = 0; //T0重载值的低字节
void ConfigTimer0(unsigned int ms);
void RefreshTimeShow();
void GetShowTemp();
extern void InitDS1302();
extern void GetRealTime(struct sTime *time);
extern void SetRealTime(struct sTime *time);
extern void KeyScan();
extern void KeyDriver();
extern void InitLcd1602();
extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
extern void LcdSetCursor(unsigned char x, unsigned char y);
extern void LcdOpenCursor();
extern void LcdCloseCursor();
extern bit Start18B20();
extern bit Get18B20Temp(int *temp);
void main()
{
unsigned char psec=0xAA; //秒备份,初值AA确保首次读取时间后会刷新显示
EA = 1; //开总中断
ConfigTimer0(1); //T0定时1ms
Start18B20(); //启动DS18B20
InitDS1302(); //初始化实时时钟
InitLcd1602(); //初始化液晶
//初始化屏幕上固定不变的内容
LcdShowStr(3, 0, "20 - - ");
LcdShowStr(1, 1, " : : --`C");
while (1)
{
KeyDriver(); //调用按键驱动
if (flag200ms && (setIndex == 0))
{ //每隔200ms且未处于设置状态时,
flag200ms = 0;
GetRealTime(&bufTime); //获取当前时间
if (psec != bufTime.sec) //检测到时间有变化时刷新显示
{
RefreshTimeShow();
psec = bufTime.sec; //用当前值更新上次秒数
}
}
if (flag1s && (setIndex == 0)) //每隔1s读取并显示温度
{
flag1s = 0;
GetShowTemp();
}
}
}
/* 将一个BCD码字节显示到屏幕上,(x,y)-屏幕起始坐标,bcd-待显示BCD码 */
void ShowBcdByte(unsigned char x, unsigned char y, unsigned char bcd)
{
unsigned char str[4];
str[0] = (bcd >> 4) + '0';
str[1] = (bcd&0x0F) + '0';
str[2] = '\0';
LcdShowStr(x, y, str);
}
/* 获取并显示温度 */
void GetShowTemp()
{
int temp;
unsigned char str[4];
if (Get18B20Temp(&temp)) //读取当前温度并判断是否成功
{ //读取成功时,刷新当前温度显示
temp >>= 4; //右移4位以舍弃小数位
str[0] = temp/10 + '0'; //显示为两位十进制数字
str[1] = temp%10 + '0';
str[2] = '\0';
LcdShowStr(11, 1, str);
}
else
{ //读取失败时,提示错误信息
LcdShowStr(11, 1, "--");
}
Start18B20(); //重新启动下一次转换
}
/* 刷新日期时间的显示 */
void RefreshTimeShow()
{
ShowBcdByte(5, 0, bufTime.year);
ShowBcdByte(8, 0, bufTime.mon);
ShowBcdByte(11, 0, bufTime.day);
ShowBcdByte(1, 1, bufTime.hour);
ShowBcdByte(4, 1, bufTime.min);
ShowBcdByte(7, 1, bufTime.sec);
}
/* 刷新当前设置位的光标指示 */
void RefreshSetShow()
{
switch (setIndex)
{
case 1: LcdSetCursor(5, 0); break;
case 2: LcdSetCursor(6, 0); break;
case 3: LcdSetCursor(8, 0); break;
case 4: LcdSetCursor(9, 0); break;
case 5: LcdSetCursor(11, 0); break;
case 6: LcdSetCursor(12, 0); break;
case 7: LcdSetCursor(1, 1); break;
case 8: LcdSetCursor(2, 1); break;
case 9: LcdSetCursor(4, 1); break;
case 10: LcdSetCursor(5, 1); break;
case 11: LcdSetCursor(7, 1); break;
case 12: LcdSetCursor(8, 1); break;
default: break;
}
}
/* 递增一个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;
}
/* 递增时间当前设置位的值 */
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.hour = IncBcdHigh(bufTime.hour); break;
case 8: bufTime.hour = IncBcdLow(bufTime.hour); break;
case 9: bufTime.min = IncBcdHigh(bufTime.min); break;
case 10: bufTime.min = IncBcdLow(bufTime.min); break;
case 11: bufTime.sec = IncBcdHigh(bufTime.sec); break;
case 12: bufTime.sec = IncBcdLow(bufTime.sec); break;
default: break;
}
RefreshTimeShow();
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.hour = DecBcdHigh(bufTime.hour); break;
case 8: bufTime.hour = DecBcdLow(bufTime.hour); break;
case 9: bufTime.min = DecBcdHigh(bufTime.min); break;
case 10: bufTime.min = DecBcdLow(bufTime.min); break;
case 11: bufTime.sec = DecBcdHigh(bufTime.sec); break;
case 12: bufTime.sec = DecBcdLow(bufTime.sec); break;
default: break;
}
RefreshTimeShow();
RefreshSetShow();
}
/* 右移时间设置位 */
void RightShiftTimeSet()
{
if (setIndex != 0)
{
if (setIndex < 12)
setIndex++;
else
setIndex = 1;
RefreshSetShow();
}
}
/* 左移时间设置位 */
void LeftShiftTimeSet()
{
if (setIndex != 0)
{
if (setIndex > 1)
setIndex--;
else
setIndex = 12;
RefreshSetShow();
}
}
/* 进入时间设置状态 */
void EnterTimeSet()
{
setIndex = 2; //把设置索引设置为2,即可进入设置状态
LeftShiftTimeSet(); //再利用现成的左移操作移到位置1并完成显示刷新
LcdOpenCursor(); //打开光标闪烁效果
}
/* 退出时间设置状态,save-是否保存当前设置的时间值 */
void ExitTimeSet(bit save)
{
setIndex = 0; //把设置索引设置为0,即可退出设置状态
if (save) //需保存时即把当前设置时间写入DS1302
{
SetRealTime(&bufTime);
}
LcdCloseCursor(); //关闭光标显示
}
/* 按键动作函数,根据键码执行相应的操作,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) //向左键,向左切换设置位
{
LeftShiftTimeSet();
}
else if (keycode == 0x27) //向右键,向右切换设置位
{
RightShiftTimeSet();
}
else