51單片機實訓做到的多功能電子時鐘用數碼管顯示的
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
0.png (29.25 KB, 下載次數: 51)
下載附件
2017-10-11 02:43 上傳
0.png (42.56 KB, 下載次數: 57)
下載附件
2017-10-11 02:42 上傳
單片機源程序如下:
- /*
- ************************************ (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)
2017-10-10 14:23 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|