标题:
单片机实训做的多功能电子时钟用(数码管显示)有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: 完成设置闪烁和点码闪烁功能,星期计算功能;
* 防真发现闪烁时快时慢,初步判断为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
作者:
qwthh
时间:
2018-7-10 21:20
请问一下有没有功能备注啥的啊 设定是改时间还是?闹钟啊
作者:
5563003
时间:
2019-12-24 15:43
程序中怎么去实现报时功能啊
作者:
zhao0015
时间:
2021-2-8 20:22
刚开始学,感觉好难的样子。
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1