给大家分享一个单片机课程设计,已经调试成功而且做出实物了如下图
红外遥控万年历的实物图:
设计要求: 1 具备在液晶上显示年、月、日、星期、时、分、秒的功能; 2 具备年、月、日、时、分、秒校准功能(星期可以自动调整,用函数算出来) 3 具有与即时时间同步的功能红外按键调时; 4 具有显示温度的功能,可设置闹钟;
红外遥控万年历课程设计proteus仿真图(51hei附件中可下载proteus仿真工程文件):
课程设计ppt文档:
¤难度系数:100
¤设计要求:
用LCD1602显示,红外遥控器输入,扬声器报警,DS18B20测量温度,DS1302计时
设计程序实现如下功能:
- 实时显示当前日期时间温度信息
- 用遥控器设置日期时间和闹钟
¤需要器件:
51hei单片机开发板
LCD1602,红外遥控器,DS18B20
完成硬件设计,焊接,调试
编写软件,完成题目要求的功能
实物演示,答辩验收
完成设计报告
周一:12讲解题目,34查阅资料,56定题并给出设计方案,元件清单。
周二:上午检查硬件电路,领取元器件,下午完成硬件电路制作。
周三:程序设计,调试。
周四:程序设计,调试。
周五:上午完成设计报告,下午提交作品和设计报告。(实物、照片、录像)
万年历的单片机源程序:
- /*
- *************************************************************************************************************
- * clock.c
- * 说 明:时钟
- * 作 者:Jonelec
- * 首发:51黑电子论坛
- * 修改者: 修改内容: 修改日期:
- * Jonelec 第一版 2017-04-20
- * Copyright(c) 2015-2025 skytech.org Inc.
- *************************************************************************************************************
- */
- #include "clock.h"
- #include "display.h"
- /* 时钟计时闪烁设置 */
- bit FlashTimeFlag = 0; /*闪烁冒号*/
- #define FlashTimeTMR_ID 0 /*冒号闪烁定时器ID*/
- #define FlashTimeTIME 1000 /*冒号闪烁定时时间*/
- /* 切换界面参数设置*/
- bit SwitchDisplayFlag = 0;
- #define SwitchDispTMR_ID 1 /*切换显示方式定时器ID*/
- #define SwitchDispTIME 3000 /*切换显示方式定时时间*/
- extern float idata CurTemp; /*获取温度值,3s采集一次*/
- uint8_t idata DispSetIndex = 0; /*光标索引*/
- uint8_t idata AlarmSetIndex = 0;
- AlarmSetInitTypeDef RingTime,SetRing;
- RealTimeInitTypeDef CurTime,SetTime;
- void DispNormalClock(void);
- /*
- *************************************************************************************************************
- * main()
- *函数功能:主函数,执行程序入口
- *函数参数:无
- *返 回 值:无
- *************************************************************************************************************
- */
- int main(void)
- {
- bsp_Init();
- RingTime = SetRing;
- while(1)
- {
- DispNormalClock();
- }
- }
- /*
- *************************************************************************************************************
- * RefreshTime()
- *函数功能:时间显示刷新
- *函数参数:_ucFlag 【为0时正常显示时间,为1时显示闹铃时间,不影响日期温度等显示】
- *返 回 值:无
- *************************************************************************************************************
- */
- void RefreshTime(uint8_t _ucFlag)
- {
- if(_ucFlag != 1) /*正常显示时间*/
- {
- bsp_GetTime(&CurTime);
-
- if(bsp_CheckTimer(FlashTimeTMR_ID))
- {
- FlashTimeFlag = !FlashTimeFlag; /*冒号闪烁*/
- }
- Lcd1602_DispNum(1,0,CurTime.Hour>>4);
- Lcd1602_DispNum(1,1,CurTime.Hour&0xF);
- Lcd1602_DispNum(1,3,CurTime.Minute>>4);
- Lcd1602_DispNum(1,4,CurTime.Minute&0xF);
- Lcd1602_DispNum(1,6,CurTime.Second>>4);
- Lcd1602_DispNum(1,7,CurTime.Second&0xF);
-
- Lcd1602_DispStr(1,8," ");
- if(FlashTimeFlag)
- {
- Lcd1602_DispChar(1,2,':');
- Lcd1602_DispChar(1,5,':');
- }
- else
- {
- Lcd1602_DispChar(1,2,' ');
- Lcd1602_DispChar(1,5,' ');
- }
- }
- else /*显示闹铃时间*/
- {
- if(RingTime.OpenFlag != 1)
- {
- Lcd1602_DispStr(1,0,"OFF");
- }
- else
- {
- Lcd1602_DispStr(1,0,"ON ");
- }
- Lcd1602_DispChar(1,3,' ');
- Lcd1602_DispNum(1,4,RingTime.Hour>>4);
- Lcd1602_DispNum(1,5,RingTime.Hour&0xF);
- Lcd1602_DispChar(1,6,':');
- Lcd1602_DispNum(1,7,RingTime.Minute>>4);
- Lcd1602_DispNum(1,8,RingTime.Minute&0xF);
- Lcd1602_DispChar(1,9,' ');
- }
- }
- /*
- *************************************************************************************************************
- * RefreshDate()
- *函数功能:日期显示刷新
- *函数参数:_ucFlag 【为0时如果日期有变化则会刷新,为1时则立即刷新】
- *返 回 值:无
- *************************************************************************************************************
- */
- void RefreshDate(uint8_t _ucFlag)
- {
- uint8_t pdata week;
- static uint8_t day_backup = 0;
-
- week = bsp_CulateDate(CurTime); /*计算星期*/
-
- if(day_backup != CurTime.Day || _ucFlag != 0)
- {
- Lcd1602_DispNum(0,0,CurTime.YearH>>4);
- Lcd1602_DispNum(0,1,CurTime.YearH&0xF);
- Lcd1602_DispNum(0,2,CurTime.YearL>>4);
- Lcd1602_DispNum(0,3,CurTime.YearL&0xF);
- Lcd1602_DispChar(0,4,'-');
- Lcd1602_DispNum(0,5,CurTime.Month>>4);
- Lcd1602_DispNum(0,6,CurTime.Month&0xF);
- Lcd1602_DispChar(0,7,'-');
- Lcd1602_DispNum(0,8,CurTime.Day>>4);
- Lcd1602_DispNum(0,9,CurTime.Day&0xF);
-
- Lcd1602_DispStr(0,12,"W:");
- Lcd1602_DispNum(0,14,week>>4);
- Lcd1602_DispNum(0,15,week&0xF);
- day_backup = CurTime.Day;
- }
- }
- /*
- *************************************************************************************************************
- * RefreshTemp()
- *函数功能:温度显示刷新
- *函数参数:_ucFlag 【为0时如果温度有变化则会刷新,为1时则立即刷新】
- *返 回 值:无
- *************************************************************************************************************
- */
- void RefreshTemp(uint8_t _ucFlag)
- {
- int16_t pdata temp;
- static int16_t tmp_backup = 0;
-
- temp = CurTemp*10;
- temp >>= 4; /*保留整数部分*/
-
- if((tmp_backup != temp) || (_ucFlag != 0))
- {
- Lcd1602_DispStr(1,10,"T:");
- if(temp < 0)
- {
- Lcd1602_DispChar(1,12,'-');
- }
- else
- {
- Lcd1602_DispChar(1,12,'+');
- }
- Lcd1602_DispNum(1,13,temp/10);
- Lcd1602_DispNum(1,14,temp%10);
- Lcd1602_WriteGram();
- Lcd1602_DispChar(1,15,0x00);
- tmp_backup = temp;
- }
- }
- /*
- *************************************************************************************************************
- * DispNormalClock()
- *函数功能:正常显示时钟
- *函数参数:无
- *返 回 值:无
- *************************************************************************************************************
- */
- void DispNormalClock(void)
- {
- uint8_t ucKeyCode;
-
- Lcd1602_ClearScreen(); /*清屏*/
- Lcd1602_OpenCursor(0); /*关闭光标闪烁*/
- RefreshDate(1); /*立即更新日期和温度*/
- RefreshTemp(1);
- bsp_StartAutoTimer(FlashTimeTMR_ID,FlashTimeTIME); /*秒闪烁定时器*/
- bsp_StartAutoTimer(SwitchDispTMR_ID,SwitchDispTIME);/*切换显示定时器*/
- while(1)
- {
- ucKeyCode = bsp_GetIRKey();
-
- if(bsp_CheckTimer(SwitchDispTMR_ID))
- {
- SwitchDisplayFlag = !SwitchDisplayFlag;
- }
- RefreshTime(SwitchDisplayFlag);/*时间显示,即刻刷新,每秒更新*/
- RefreshDate(0);/*年份及日期显示,只有当日期变化的时候才会刷新*/
- RefreshTemp(0);/*温度显示,只有当温度变化的时候才会刷新*/
-
- if(ucKeyCode != IR_KEY_NONE)
- {
- switch(ucKeyCode)
- { case IR_KEY_POWER:
- {
- RingTime.OpenFlag = !RingTime.OpenFlag;
- }break;
- case IR_KEY_MENU:
- {
- bsp_StopTimer(SwitchDispTMR_ID);
- bsp_StopTimer(FlashTimeTMR_ID);
- LCD_ChangeMenu();
- }break;
- default :break;
- }
- }
- }
- }
- /*
- *************************************************************************************************************
- * ShiftRightCursor()
- *函数功能:光标索引右移
- *函数参数:_ucFlag : 0【设置闹钟】 1【设置时钟】
- *返 回 值:无
- *************************************************************************************************************
- */
- void ShiftRightCursor(uint8_t _ucFlag)
- {
- if(_ucFlag != 0) //设置时钟
- {
- switch(DispSetIndex)
- {
- case 0: DispSetIndex = 1;Lcd1602_SetPos(0,1);break;
- case 1: DispSetIndex = 2;Lcd1602_SetPos(0,2);break;
- case 2: DispSetIndex = 3;Lcd1602_SetPos(0,3);break;
- case 3: DispSetIndex = 4;Lcd1602_SetPos(0,5);break;
- case 4: DispSetIndex = 5;Lcd1602_SetPos(0,6);break;
- case 5: DispSetIndex = 6;Lcd1602_SetPos(0,8);break;
- case 6: DispSetIndex = 7;Lcd1602_SetPos(0,9);break;
- case 7: DispSetIndex = 8;Lcd1602_SetPos(1,0);break;
- case 8: DispSetIndex = 9; Lcd1602_SetPos(1,1);break;
- case 9: DispSetIndex = 10;Lcd1602_SetPos(1,3);break;
- case 10: DispSetIndex = 11;Lcd1602_SetPos(1,4);break;
- case 11: DispSetIndex = 12;Lcd1602_SetPos(1,6);break;
- case 12: DispSetIndex = 13;Lcd1602_SetPos(1,7);break;
- default :DispSetIndex = 0;Lcd1602_SetPos(0,0);break;
- }
- }
- else /*设置闹钟*/
- {
- switch(AlarmSetIndex)
- {
- case 0:AlarmSetIndex = 1;Lcd1602_SetPos(1,1);break;
- case 1:AlarmSetIndex = 2;Lcd1602_SetPos(1,3);break;
- case 2:AlarmSetIndex = 3;Lcd1602_SetPos(1,4);break;
- case 3:AlarmSetIndex = 4;Lcd1602_SetPos(1,10);break;
- default :AlarmSetIndex = 0;Lcd1602_SetPos(1,0);break;
- }
- }
- }
- /*
- *************************************************************************************************************
- * ShiftLeftCursor()
- *函数功能:光标索引左移
- *函数参数:_ucFlag : 0【设置闹钟】 1【设置时钟】
- *返 回 值:无
- *************************************************************************************************************
- */
- void ShiftLeftCursor(uint8_t _ucFlag)
- {
- if(_ucFlag != 0) //设置时钟
- {
- switch(DispSetIndex)
- {
- case 0: DispSetIndex = 13;Lcd1602_SetPos(1,7);break;
-
- case 1: DispSetIndex = 0;Lcd1602_SetPos(0,0);break;
- case 2: DispSetIndex = 1;Lcd1602_SetPos(0,1);break;
- case 3: DispSetIndex = 2;Lcd1602_SetPos(0,2);break;
- case 4: DispSetIndex = 3;Lcd1602_SetPos(0,3);break;
-
- case 5: DispSetIndex = 4;Lcd1602_SetPos(0,5);break;
- case 6: DispSetIndex = 5;Lcd1602_SetPos(0,6);break;
-
- case 7: DispSetIndex = 6;Lcd1602_SetPos(0,8);break;
- case 8: DispSetIndex = 7;Lcd1602_SetPos(0,9);break;
-
- case 9: DispSetIndex = 8;Lcd1602_SetPos(1,0);break;
- case 10: DispSetIndex = 9;Lcd1602_SetPos(1,1);break;
-
- case 11: DispSetIndex = 10;Lcd1602_SetPos(1,3);break;
- case 12: DispSetIndex = 11;Lcd1602_SetPos(1,4);break;
- default :DispSetIndex = 12;Lcd1602_SetPos(1,6);break;
- }
- }
- else
- {
- switch(AlarmSetIndex)
- {
- case 0:AlarmSetIndex = 4;Lcd1602_SetPos(1,10);break;
- case 1:AlarmSetIndex = 0;Lcd1602_SetPos(1,0);break;
- case 2:AlarmSetIndex = 1;Lcd1602_SetPos(1,1);break;
- case 3:AlarmSetIndex = 2;Lcd1602_SetPos(1,3);break;
- default :AlarmSetIndex = 3;Lcd1602_SetPos(1,4);break;
- }
- }
- }
- /*
- *************************************************************************************************************
- * InputSetNumber()
- *函数功能:将输入数字进行判断赋值
- *函数参数:_ucFlag : 0【设置闹钟】 1【设置时钟】
- *返 回 值:无
- *************************************************************************************************************
- */
- void InputSetNumber(uint8_t _ucFlag,uint8_t _ucNum)
- {
- if(_ucFlag != 0)
- {
- switch(DispSetIndex)
- {
- case 0: /*设置年份的最高位*/
- {
- SetTime.YearH = (SetTime.YearH&0x0F)|(_ucNum<<4);
- Lcd1602_DispNum(0,0,_ucNum);
- }break;
- case 1:
- {
- SetTime.YearH = (SetTime.YearH&0xF0)|_ucNum; /*年份第三位数字*/
- Lcd1602_DispNum(0,1,_ucNum);
- }break;
- case 2:
- {
- SetTime.YearL = (SetTime.YearL&0x0F)|(_ucNum<<4); /*年份第二位数字*/
- Lcd1602_DispNum(0,2,_ucNum);
- }break;
- case 3:
- {
- SetTime.YearL = (SetTime.YearL&0xF0)|_ucNum; /*年份第一位数字*/
- Lcd1602_DispNum(0,3,_ucNum);
- }break;
- case 4:
- {
- if(_ucNum > 1)
- {
- Lcd1602_DispChar(0,5,'E'); /*月份输入有误*/
- }
- else
- {
- SetTime.Month = (SetTime.Month&0x0F)|(_ucNum<<4); /*设置月份*/
- Lcd1602_DispNum(0,5,_ucNum);
- }
-
- }break;
- case 5:
- {
- if((SetTime.Month>>4) == 1)
- {
- if(_ucNum > 2)
- {
- Lcd1602_DispChar(0,6,'E');
- }
- else
- {
- SetTime.Month = (SetTime.Month&0xF0)|_ucNum;
- Lcd1602_DispNum(0,6,_ucNum);
- }
- }
- else
- {
- SetTime.Month = (SetTime.Month&0xF0)|_ucNum;
- Lcd1602_DispNum(0,6,_ucNum);
- }
- }
- case 6: /*设置 天数*/
- {
- if(_ucNum > 3)
- {
- Lcd1602_DispChar(0,8,'E');
- }
- else
- {
- SetTime.Day = (SetTime.Day&0x0F)|(_ucNum<<4);
- Lcd1602_DispNum(0,8,_ucNum);
- }
- }break;
- case 7:
- {
- if((SetTime.Day>>4)==3) /*判断是否为3,最多只有31天*/
- {
- if(_ucNum > 1)
- {
- Lcd1602_DispChar(0,9,'E');
- }
- else
- {
- SetTime.Day = (SetTime.Day&0xF0)|_ucNum;
- Lcd1602_DispNum(0,9,_ucNum);
- }
- }
- else
- {
- SetTime.Day = (SetTime.Day&0xF0)|_ucNum;
- Lcd1602_DispNum(0,9,_ucNum);
- }
- }break;
- case 8: /*设置小时*/
- {
- if(_ucNum > 2)
- {
- Lcd1602_DispChar(1,0,'E');
- }
- else
- {
- SetTime.Hour = (SetTime.Hour&0x0F)|(_ucNum<<4);
- Lcd1602_DispNum(1,0,_ucNum);
- }
- }break;
- case 9:
- {
- if((SetTime.Hour>>4) == 2)
- {
- if(_ucNum > 3)
- {
- Lcd1602_DispChar(1,1,'E');
- }
- else
- {
- SetTime.Hour = (SetTime.Hour&0xF0)|_ucNum;
- Lcd1602_DispNum(1,1,_ucNum);
- }
- }
- else
- {
- SetTime.Hour = (SetTime.Hour&0xF0)|_ucNum;
- Lcd1602_DispNum(1,1,_ucNum);
- }
- }break;
- case 10: /*设置分钟*/
- {
- if(_ucNum > 5)
- {
- Lcd1602_DispChar(1,3,'E');
- }
- else
- {
- SetTime.Minute = (SetTime.Minute&0x0F)|(_ucNum<<4);
- Lcd1602_DispNum(1,3,_ucNum);
- }
- }break;
- case 11:
- {
- SetTime.Minute = (SetTime.Minute&0xF0)|_ucNum;
- Lcd1602_DispNum(1,4,_ucNum);
- }break;
- case 12: /*设置秒钟*/
- {
- if(_ucNum > 5)
- {
- Lcd1602_DispChar(1,6,'E');
- }
- else
- {
- SetTime.Second = (SetTime.Second&0x0F)|(_ucNum<<4);
- Lcd1602_DispNum(1,6,_ucNum);
- }
- }break;
- default :
- {
- SetTime.Second = (SetTime.Second&0xF0)|_ucNum;
- Lcd1602_DispNum(1,7,_ucNum);
- }break;
- }
- ShiftRightCursor(1);
- }
- else /*设置闹钟*/
- {
- switch(AlarmSetIndex)
- {
- case 0:
- {
- if(_ucNum > 2)
- {
- Lcd1602_DispChar(1,0,'E');
- }
- else
- {
- SetRing.Hour = (SetRing.Hour&0x0F)|(_ucNum<<4);
- Lcd1602_DispNum(1,0,_ucNum);
- }
- }break;
- case 1:
- {
- if((SetRing.Hour>>4) == 2)
- {
- if(_ucNum >3)
- {
- Lcd1602_DispChar(1,1,'E');
- }
- else
- {
- SetRing.Hour = (SetRing.Hour&0xF0)|_ucNum;
- Lcd1602_DispNum(1,1,_ucNum);
- }
- }
- else
- {
- SetRing.Hour = (SetRing.Hour&0xF0)|_ucNum;
- Lcd1602_DispNum(1,1,_ucNum);
- }
- }break;
- case 2:
- {
- if(_ucNum > 5)
- {
- Lcd1602_DispChar(1,3,'E');
- }
- else
- {
- SetRing.Minute = (SetRing.Minute&0x0F)|(_ucNum<<4);
- Lcd1602_DispNum(1,3,_ucNum);
- }
- }break;
- case 3:
- {
- SetRing.Minute = (SetRing.Minute&0xF0)|_ucNum;
- Lcd1602_DispNum(1,4,_ucNum);
- }break;
- default :
- {
- if(_ucNum == IR_KEY_POWER) /*按下开关按键*/
- {
- SetRing.OpenFlag = !SetRing.OpenFlag;
-
- if(SetRing.OpenFlag != 0) /*开启闹钟*/
- Lcd1602_DispStr(1,10,"ON ");
- else
- Lcd1602_DispStr(1,10,"OFF");
- }
- }break;
- }
- ShiftRightCursor(0); /*光标自加*/
- }
- }
- /*
- *************************************************************************************************************
- * DisplaySetTime()
- *函数功能:将当前的时间加载到设置菜单当中
- *函数参数:无
- *返 回 值:无
- *************************************************************************************************************
- */
- void DisplaySetTime(void)
- {
- bsp_GetTime(&CurTime);
-
- SetTime = CurTime ;
-
- Lcd1602_DispNum(1,0,CurTime.Hour>>4);
- Lcd1602_DispNum(1,1,CurTime.Hour&0xF);
- Lcd1602_DispNum(1,3,CurTime.Minute>>4);
- Lcd1602_DispNum(1,4,CurTime.Minute&0xF);
- Lcd1602_DispNum(1,6,CurTime.Second>>4);
- Lcd1602_DispNum(1,7,CurTime.Second&0xF);
- Lcd1602_DispChar(1,2,':');
- Lcd1602_DispChar(1,5,':');
-
- Lcd1602_DispNum(0,0,CurTime.YearH>>4);
- Lcd1602_DispNum(0,1,CurTime.YearH&0xF);
- Lcd1602_DispNum(0,2,CurTime.YearL>>4);
- Lcd1602_DispNum(0,3,CurTime.YearL&0xF);
- Lcd1602_DispChar(0,4,'-');
- Lcd1602_DispNum(0,5,CurTime.Month>>4);
- Lcd1602_DispNum(0,6,CurTime.Month&0xF);
- Lcd1602_DispChar(0,7,'-');
- Lcd1602_DispNum(0,8,CurTime.Day>>4);
- Lcd1602_DispNum(0,9,CurTime.Day&0xF);
- }
- /*
- *************************************************************************************************************
- * SetClockTime()
- *函数功能:设置时间
- *函数参数:无
- *返 回 值:无
- *************************************************************************************************************
- */
- void SetClockTime(void)
- {
- uint8_t pdata ucKeyCode;
-
- Lcd1602_ClearScreen();
-
- DisplaySetTime();
-
- Lcd1602_SetPos(0,0);
- Lcd1602_OpenCursor(1);
-
- while(1)
- {
- ucKeyCode = bsp_GetIRKey();
-
- if(ucKeyCode != IR_KEY_NONE)
- {
- switch(ucKeyCode)
- {
- case IR_KEY_LEFT : ShiftLeftCursor(1);break;
- case IR_KEY_RIGHT: ShiftRightCursor(1);break;
- case IR_KEY_0: InputSetNumber(1,0);break;
- case IR_KEY_1: InputSetNumber(1,1);break;
- case IR_KEY_2: InputSetNumber(1,2);break;
- case IR_KEY_3: InputSetNumber(1,3);break;
- case IR_KEY_4: InputSetNumber(1,4);break;
- case IR_KEY_5: InputSetNumber(1,5);break;
- case IR_KEY_6: InputSetNumber(1,6);break;
- case IR_KEY_7: InputSetNumber(1,7);break;
- case IR_KEY_8: InputSetNumber(1,8);break;
- case IR_KEY_9: InputSetNumber(1,9);break;
- case IR_KEY_RETURN :
- {
- DispSetIndex = 0;
- LCD_ChangeMenu();
- }break;
- case IR_KEY_OK :
- {
- CurTime = SetTime;
- bsp_SetTime(&CurTime);
- DispNormalClock();
- }break;
- default : break;
- }
- }
- }
- }
- /*
- *************************************************************************************************************
- * SetClockTime()
- *函数功能:设置闹钟
- …………限于本文篇幅 余下代码请从51电子黑下载附件…………
复制代码
下载:
基于单片机的多功能遥控万年历设计.rar
(2.54 MB, 下载次数: 48)
|