单片机源程序如下:
- /*
- *******************************************************************************
- * 《手把手教你学51单片机(C语言版)》
- * 配套 KST-51 单片机开发板 示例源代码
- *
- * 文件名:main.c
- * 描 述:第16章 作业题4 带温度显示的电子钟
- * 版本号:v1.0.0
- * 备 注:在lesson15_3基础上添加温度,温度显示在第二行右端,原时间位置相应左移
- *******************************************************************************
- */
- #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 if (keycode == 0x0D) //回车键,进入设置模式/启用当前设置值
- {
- if (setIndex == 0) //不处于设置状态时,进入设置状态
- {
- EnterTimeSet();
- }
- else //已处于设置状态时,保存时间并退出设置状态
- {
- ExitTimeSet(1);
- }
- }
- else if (keycode == 0x1B) //Esc键,取消当前设置
- {
- ExitTimeSet(0);
- }
- }
- /* 配置并启动T0,ms-T0定时时间 */
- void ConfigTimer0(unsigned int ms)
- {
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
温度检测.rar
(41.24 KB, 下载次数: 72)
|