標題:
單片機實訓做的多功能電子時鐘用(數碼管顯示)有proteus仿真
[打印本頁]
作者:
平凡32
時間:
2017-10-10 14:26
標題:
單片機實訓做的多功能電子時鐘用(數碼管顯示)有proteus仿真
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: 完成設置閃爍和點碼閃爍功能,星期計算功能;
* 防真發(fā)現(xiàn)閃爍時快時慢,初步判斷為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; /* 全局三個狀態(tài),靜態(tài)顯示時間,切換顯示狀態(tài),設置時間狀態(tài) */
unsigned char switch_state = SWITCH_YEAR;
unsigned char set_state = SET_HOUR;
unsigned char display_twinkle = 0; /* 500ms 的閃爍信號 */
unsigned char display_step = DISPLAY; /* 閃爍狀態(tài) 二值 */
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);
}
/* 檢測狀態(tài) */
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
* 功能說明: 退出設置和切換狀態(tài)
* 形 參: _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
作者:
qwthh
時間:
2018-7-10 21:20
請問一下有沒有功能備注啥的啊 設定是改時間還是?鬧鐘啊
作者:
5563003
時間:
2019-12-24 15:43
程序中怎么去實現(xiàn)報時功能啊
作者:
zhao0015
時間:
2021-2-8 20:22
剛開始學,感覺好難的樣子。
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1