51单片机实训做到的多功能电子时钟用数码管显示的
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- /*
- ************************************ (C) COPYRIGHT 2017 Sourcelink **************************************
- * File Name : main.c
- * Author : Sourcelink
- * Version : V1.0
- * Date : 2017/3/3
- * Description : 2017/3/3: 完成切换功能和设置功能;
- * 2017/3/4: 完成设置闪烁和点码闪烁功能,星期计算功能;
- * 防真发现闪烁时快时慢,初步判断为proteus仿真问题。因为程序中没有阻塞。
- * 完成數字鍵設置時間的功能。
- * 添加退出功能,在不想設置或切換時可以直接退出。
- ********************************************************************************************************
- */
- #include <reg52.H>
- #include "main.h"
- #include "Led_8Seg.h"
- #include "Key.h"
- #include "DS1302.h"
- typedef void (*dispaly_callback)(RealTimeTypeDef*);
- /************************************************************************************************/
- static void display_hour(RealTimeTypeDef *_RealTime);
- static void display_year(RealTimeTypeDef *_RealTime);
- static void display_month(RealTimeTypeDef *_RealTime);
- static void display_day(RealTimeTypeDef *_RealTime);
- static void undisplay(unsigned char time_state);
- void display_switch(dispaly_callback display, RealTimeTypeDef *time, unsigned char next_state);
- void display_set(dispaly_callback display, unsigned char next_state);
- void calculation_week(RealTimeTypeDef *_RealTime);
- void display_switch_state(void);
- void inc_dec_time_handle(unsigned char *val, unsigned char keyval, unsigned char state);
- void num_time_handle(unsigned char *val, unsigned char keyval, unsigned char state);
- void is_exit(void);
- /************************************************************************************************/
- unsigned char globa_state = STATE_STATIC; /* 全局三个状态,静态显示时间,切换显示状态,设置时间状态 */
- unsigned char switch_state = SWITCH_YEAR;
- unsigned char set_state = SET_HOUR;
- unsigned char display_twinkle = 0; /* 500ms 的闪烁信号 */
- unsigned char display_step = DISPLAY; /* 闪烁状态 二值 */
- unsigned char num_bit = num_bitl;
- unsigned char key_continuit = 0; /* key连按信号 */
- RealTimeTypeDef tmp_real_time; /* 实时时间的中间变量 */
- /************************************************************************************************/
- void Delay_ms(unsigned int Cnt)
- {
- unsigned int t;
- while(Cnt--)
- {
- t = 100;
- while(--t);
- }
- }
- void SystemInit()
- {
- TMOD = 0x01;
- TH0 = (65536-2000)/256;
- TL0 = (65536-2000)%256;
- ET0 = 1;
- EA = 1;
- TR0 = 1;
- }
- /************************************************************************************************/
- void main()
- {
- SystemInit();
- DS1302_Init();
- RealTime.YearH = 0x20;
-
- while(1)
- {
- GetTime(&RealTime);
-
- display_switch_state();
-
- switch (globa_state) {
- case STATE_STATIC : {
- display_hour(&RealTime);
-
- if (display_step == UNDISPLAY) {
- Led[1] = (RealTime.Hour & 0x0F);
- Led[3] = (RealTime.Min & 0x0F);
- }
-
-
- /* 检测状态 */
- switch (KeyNum) {
- case SL_SWITCH : {
- /* 等待按键松开 */
- globa_state = STATE_SWITCH;
- while( KeyNum == SL_SWITCH );
-
-
- }
- break;
-
- case SL_SET : {
-
- /* 进行下中间变量存储 */
- tmp_real_time = RealTime;
- globa_state = STATE_SET;
- /* 等待按键松开 */
- while( KeyNum == SL_SET );
-
- }
- break;
- default : break;
- }
- }
- break;
- case STATE_SWITCH : {
- switch (switch_state) {
- case SWITCH_YEAR : {
- display_switch(display_year, &RealTime, SWITCH_MONTH);
- break;
-
- case SWITCH_MONTH : {
- display_switch(display_month, &RealTime, SWITCH_WEEK);
- }
- break;
-
- case SWITCH_WEEK : {
- calculation_week(&RealTime);
- display_switch(display_day, &RealTime, SWITCH_YEAR);
- }
- break;
- default : break;
- }
- }
- is_exit();
- }
- break;
- case STATE_SET : {
- switch (set_state) {
- case SET_HOUR :
- display_set(display_hour, SET_MINUTE);
- break;
- case SET_MINUTE :
- display_set(display_hour, SET_SECOND);
- break;
- case SET_SECOND :
- display_set(display_hour, SET_YEAR);
- break;
-
- case SET_YEAR :
- display_set(display_year, SET_MONTH);
- break;
-
- case SET_MONTH :
- display_set(display_month, SET_DAYTE);
- break;
-
- case SET_DAYTE :
- display_set(display_month, SET_WEEK);
- break;
- case SET_WEEK :
- /* 计算星期 */
- calculation_week(&tmp_real_time);
-
- display_day(&tmp_real_time);
- if (KeyNum == SL_SET) {
- /* 写入到ds1302 */
- globa_state = STATE_STATIC;
- set_state = SET_HOUR;
- SetTime(&tmp_real_time);
- while( KeyNum == SL_SET );
- }
- break;
- default : break;
- }
-
- is_exit();
- }
- break;
- default : break;
- }
- }
- }
- void T0_Int() interrupt 1
- {
- static char KeyTemp,KeyTempOld;
- static unsigned char T0IntCnt;
- static unsigned short is_time500ms;
- static unsigned char is_time200ms;
- if (++is_time500ms >= 249) {
- is_time500ms = 0;
- display_twinkle = 1;
- }
- if ((KeyNum == SL_INC) || (KeyNum == SL_DEC)) {
- if (++is_time200ms >= 69) {
- is_time200ms = 0;
- key_continuit = 1;
- }
- } else {
- is_time200ms = 0;
- }
-
-
- TH0 = (65536-2000)/256;
- TL0 = (65536-2000)%256;
-
- T0IntCnt = (T0IntCnt+1)%10;
-
- if( T0IntCnt<7 ) Dis1bit(T0IntCnt);
- else if( T0IntCnt==9 )
- {
- KeyTempOld = KeyTemp;
- KeyTemp = KeyScan();
- if(KeyTemp==KeyTempOld)
- {
- KeyNum = KeyTemp;
- if(KeyNum==-1)
- {
- KeyDownCnt = 0;
- KeyUpCnt++;
- }
- else
- {
- KeyDownCnt ++ ;
- KeyUpCnt = 0;
- }
- }
- }
- }
- /*
- *********************************************************************************************************
- * 函 数 名: is_exit
- * 功能说明: 退出設置和切換狀態
- * 形 参: _RealTime: 实时时间的实体
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void is_exit(void)
- {
- if (KeyNum == SL_EXIT){
- globa_state = STATE_STATIC;
- switch_state = SWITCH_YEAR;
- set_state = SET_HOUR;
- while( KeyNum == SL_EXIT);
- }
- }
- /*
- *********************************************************************************************************
- * 函 数 名: calculation_week
- * 功能说明: 计算星期功能函数
- * 形 参: _RealTime: 实时时间的实体
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void calculation_week(RealTimeTypeDef *_RealTime)
- {
- unsigned char tmp_month, tmp_date;
- unsigned short tmp_year;
-
- tmp_year = ((_RealTime->YearH >> 4) * 1000) + ((_RealTime->YearH & 0x0F) * 100) + ((_RealTime->YearL >> 4) * 10) + _RealTime->YearL & 0x0F;
- tmp_date = ((_RealTime->Date >> 4) * 10) + (_RealTime->Date & 0x0F);
- tmp_month = ((_RealTime->Month >> 4) * 10) + (_RealTime->Month & 0x0F);
- _RealTime->Day = (tmp_date + 2 * tmp_month + 3 * (tmp_month + 1) / 5 + tmp_year + tmp_year / 4 - tmp_year / 100 + tmp_year / 400) % 7;
- if (_RealTime->Day == 0)
- _RealTime->Day = 7;
- }
- static void display_hour(RealTimeTypeDef *_RealTime)
- {
- Led[0] = _RealTime->Hour >> 4;
- Led[1] = (_RealTime->Hour & 0x0F) + 0x10;
- Led[2] = _RealTime->Min >> 4;
- Led[3] = (_RealTime->Min & 0x0F) + 0x10;
- Led[4] = _RealTime->Sec >> 4;
- Led[5] = _RealTime->Sec & 0x0F;
- }
- static void display_year(RealTimeTypeDef *_RealTime)
- {
- Led[0] = 0x1b;
- Led[1] = 0x1b;
- Led[2] = _RealTime->YearH >> 4;
- Led[3] = _RealTime->YearH & 0x0F;
- Led[4] = _RealTime->YearL >> 4;
- Led[5] = _RealTime->YearL & 0x0F;
- }
- static void display_month(RealTimeTypeDef *_RealTime)
- {
- Led[0] = 0x1b;
- Led[1] = _RealTime->Month >> 4;
- Led[2] = _RealTime->Month & 0x0F;
- Led[3] = 0x1c;
- Led[4] = _RealTime->Date >> 4;
- Led[5] = _RealTime->Date & 0x0F;
- }
- static void display_day(RealTimeTypeDef *_RealTime)
- {
- Led[0] = 0x1b;
- Led[1] = 0x1b;
- Led[2] = 0x1b;
- Led[3] = 0x1b;
- Led[4] = 0x1b;
- Led[5] = _RealTime->Day;
- }
- /*
- *********************************************************************************************************
- * 函 数 名: undisplay
- * 功能说明: 用于设置闪烁
- * 形 参: time_state: 当前要设置的段位
- * 返 回 值: 无
- *********************************************************************************************************
- */
- static void undisplay(unsigned char time_state)
- {
- switch (time_state) {
- case SET_HOUR :
- Led[0] = 0x1b;
- Led[1] = 0x1b;
- break;
- case SET_MINUTE :
- Led[2] = 0x1b;
- Led[3] = 0x1b;
- break;
- case SET_SECOND :
- Led[4] = 0x1b;
- Led[5] = 0x1b;
- break;
- case SET_YEAR :
- Led[4] = 0x1b;
- Led[5] = 0x1b;
- break;
- case SET_MONTH :
- Led[1] = 0x1b;
- Led[2] = 0x1b;
- break;
- case SET_DAYTE:
- Led[4] = 0x1b;
- Led[5] = 0x1b;
- break;
- default : break;
- }
- }
- /*
- *********************************************************************************************************
- * 函 数 名: display_switch_state
- * 功能说明: DISPLAY 和 UNDISPLAY的切换
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void display_switch_state(void)
- {
- if (display_twinkle == 1) {
- display_twinkle = 0;
-
- switch (display_step) {
- case DISPLAY :
- display_step = UNDISPLAY;
- break;
- case UNDISPLAY :
- display_step = DISPLAY;
- break;
-
- default : break;
- }
- }
- }
- /*
- *********************************************************************************************************
- * 函 数 名: display_switch
- * 功能说明: 切换显示时间
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void display_switch(dispaly_callback display, RealTimeTypeDef *time, unsigned char next_state)
- {
- display(time);
- if( KeyNum == SL_SWITCH ) {
- switch_state = next_state;
- if (next_state == SWITCH_YEAR)
- globa_state = STATE_STATIC;
- while( KeyNum == SL_SWITCH );
- }
- }
- /*
- *********************************************************************************************************
- * 函 数 名: display_set
- * 功能说明: 设置时间
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void display_set(dispaly_callback display, unsigned char next_state)
- {
- unsigned char tmp;
- unsigned char tmp_month;
- unsigned short tmp_year;
- unsigned char tmp_keynum;
-
- unsigned char currten_state = next_state - 1;
-
- switch (KeyNum) {
- case SL_ZERO :
- case SL_ONE :
- case SL_TWO :
- case SL_THREE :
- case SL_FOUR :
- case SL_FIVE :
- case SL_SIX :
- case SL_SEVEN :
- case SL_EIGHT :
- case SL_NINE :
- tmp_keynum = KeyNum;
- switch (currten_state) {
- case SET_HOUR :
- num_time_handle(&tmp_real_time.Hour, tmp_keynum, currten_state);
- break;
-
- case SET_MINUTE :
- num_time_handle(&tmp_real_time.Min, tmp_keynum, currten_state);
- break;
-
- case SET_SECOND :
- num_time_handle(&tmp_real_time.Sec, tmp_keynum, currten_state);
- break;
- case SET_YEAR :
- num_time_handle(&tmp_real_time.YearL, tmp_keynum, currten_state);
- break;
-
- case SET_MONTH :
- num_time_handle(&tmp_real_time.Month, tmp_keynum, currten_state);
- break;
-
- case SET_DAYTE :
- num_time_handle(&tmp_real_time.Date, tmp_keynum, currten_state);
- break;
- default : break;
- }
- while (KeyNum == tmp_keynum);
- break;
-
- case SL_INC :
- case SL_DEC :
- if (key_continuit == 1) {
- key_continuit = 0;
- switch (currten_state) {
- case SET_HOUR :
- inc_dec_time_handle(&tmp_real_time.Hour, KeyNum, currten_state);
-
- break;
- case SET_MINUTE :
- inc_dec_time_handle(&tmp_real_time.Min, KeyNum, currten_state);
-
- break;
- case SET_SECOND :
- inc_dec_time_handle(&tmp_real_time.Sec, KeyNum, currten_state);
- break;
- case SET_YEAR :
- inc_dec_time_handle(&tmp_real_time.YearL, KeyNum, currten_state);
- break;
-
- case SET_MONTH :
- inc_dec_time_handle(&tmp_real_time.Month, KeyNum, currten_state);
- break;
- case SET_DAYTE :
- if (KeyNum == SL_INC) {
- /* 日期处理功能 */
- tmp = ((tmp_real_time.Date >> 4) * 10) + (tmp_real_time.Date & 0x0F);
- tmp++;
-
- tmp_month = ((tmp_real_time.Month >> 4) * 10) + (tmp_real_time.Month & 0x0F);
-
- #if 1
- /* 判断月份 */
- switch (tmp_month) {
- case 1 :
- case 3 :
- case 5 :
- case 7 :
- case 8 :
- case 10 :
- case 12 :
- if (tmp > 31) /* 上限处理 */
- tmp = 0;
-
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
多功能电子时钟(数码管显示).rar
(152.08 KB, 下载次数: 108)
|