电子时钟仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- #include "reg52.H"
- #include "stdio.h"
- #include "intrins.h"
- sbit K1 = P3^4;//设置键
- sbit K2 = P3^5;//加键
- sbit K3 = P3^6;//减键
- sbit K4 = P3^7;//日期时间切换键
- unsigned char pre_key = 0x0f;//记录按键状态
- unsigned char key_value;//获取到按键的值
- #define DIG_SEG P0 //段选
- #define DIG_PLA P2 //位选
- unsigned char code dig_tab[18] =//共阴数码管码表
- {
- 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,//0、1、2、3、4、5、6、7、
- 0x7f,0x6f,0x77,0x00,0x39,0x5e,0x79,0x71,//8、9、A、B、C、D、E、F、
- 0x40,0x00//-
- };
- unsigned char dig_show_fir;//数码管第一位显示值
- unsigned char dig_show_two;//数码管第二位显示值
- unsigned char dig_show_thr;//数码管第三位显示值
- unsigned char dig_show_fou;//数码管第四位显示值
- unsigned char dig_show_fiv;//数码管第五位显示值
- unsigned char dig_show_six;//数码管第六位显示值
- unsigned char dig_show_sev;//数码管第七位显示值
- unsigned char dig_show_eig;//数码管第八位显示值
- unsigned char dig_show_tmp = 0;//显示临时变量
- unsigned char now_window;//当前显示窗口
- unsigned char now_win_sta;//当前显示状态
- unsigned char win_sta_tmp;//显示状态临时变量
- unsigned char tim_flg;//倒计时标志1S一次
- unsigned char nian,yue,ri,shi,fen,miao;//定义时分秒年月日
- signed char tim_temp[3] = {0};//时分秒设置临时变量
- #define FLIOPE 200//数码管闪烁时间常量
- #define FLICLO 400//数码管闪烁时间常量
- unsigned char part;//数码管闪烁标志设置的时候
- unsigned int sci_count;//数码管闪烁时间
- unsigned char curr_menu;
- unsigned char alm_tim_cnt;//报警时间计数
- unsigned char alm_flag;//报警标志
- unsigned char dist_yel_alm;//东西南北黄灯闪烁区分变量
- void init_all_hardware(void);//初始化硬件
- void delay_ms(unsigned int cnt);//延时函数
- void time_init(void);//定时器初始化
- void key_scan(void);//按键扫描
- void key_service(void);//按键处理函数
- void dis_dri(void);//动态数码管扫描
- void display_service(void);//数码显示处理
- void timing_service(void);//倒计时函数
- void main(void)
- {
- init_all_hardware();//初始化硬件,IO和定时器
- while(1)
- {
- key_scan();//按键扫描
- key_service();//按键服务处理函数
- display_service();//数码显示处理
- timing_service();//倒计时函数
- }
- }
- /******************************************************
- ** 函数名:init_all_hardware
- ** 描述 :初始化所有硬件,及其变量参数。
- ** 输入 :无
- ** 输出 :无
- ** 调用 :主程序
- ******************************************************/
- void init_all_hardware(void)
- {
- delay_ms(100);
- time_init();//定时器初始化
- key_value = 0;
- dig_show_fir = 17;//开机不显示
- dig_show_two = 17;//开机不显示
- dig_show_thr = 17;//开机不显示
- dig_show_fou = 17;//开机不显示
- dig_show_fiv = 17;//开机不显示
- dig_show_six = 17;//开机不显示
- dig_show_sev = 17;//开机不显示
- dig_show_eig = 17;//开机不显示
- shi = 8; //初始化时分秒
- fen = 12;
- miao = 35;
- nian = 16;//初始化年月日
- yue = 1;
- ri = 4;
- part = 0;
- sci_count = 0;
- curr_menu = 0;
- now_window = 1;
- now_win_sta = 1;
- EA=1;
- delay_ms(1000);//延时1S
- }
- /*******************************************************************************
- * 函 数 名 : delay_ms
- * 函数功能 : 延时函数,延时1ms
- * 输 入 : cnt
- * 输 出 : 无
- * 说 名 : 该函数是在12MHZ晶振下,12分频单片机的延时。
- *******************************************************************************/
- void delay_ms(unsigned int cnt) //
- {
- unsigned int x;
- for( ; cnt>0; cnt--)
- {
- for(x=110; x>0; x--);//软件延时为1MS
- }
- }
- /******************************************************
- ** 函数名:time_init
- ** 描述 :定时器初始化
- ** 输入 :无
- ** 输出 :无
- ******************************************************/
- void time_init(void)
- {
- TMOD |= 0x01;//time0 工作方式为1
- TH0 = 0xf8;//装载初值
- TL0 = 0x2f;//装载初值,为2ms(65535-63535)
- TR0 = 1;//开启定时器
- ET0 = 1;//打开中断
- ES = 1;
- }
- /******************************************************
- ** 函数名:key_scan
- ** 描述 :按键扫描
- ** 输入 :无
- ** 输出 :无
- ******************************************************/
- void key_scan(void)
- {
- P3 |=0xf0;//P3高四位置高
- if (pre_key==(P3&0xf0))return;//按键状态未改变时继续
- pre_key = P3&0xf0;//保存当前最新按键状态
- if (!K1)//特殊模式按键
- {
- delay_ms(10);//延时10ms
- if(!K1)//还判断为按下
- {
- key_value = 1;//触发按键值
- }
- }
- if (!K2)//特殊模式按键
- {
- delay_ms(10);//延时10ms
- if(!K2)//还判断为按下
- {
- key_value = 2;//触发按键值
- }
- }
- if (!K3)//特殊模式按键
- {
- delay_ms(10);//延时10ms
- if(!K3)//还判断为按下
- {
- key_value = 3;//触发按键值
- }
- }
- if (!K4)//特殊模式按键
- {
- delay_ms(10);//延时10ms
- if(!K4)//还判断为按下
- {
- key_value = 4;//触发按键值
- }
- }
- }
- /******************************************************
- ** 函数名:key_service
- ** 描述 :按键服务函数
- ** 输入 :无
- ** 输出 :无
- ** 调用 :主程序
- ******************************************************/
- void key_service(void)
- {
- switch(now_window)//选择不同窗口
- {
- case 1:
- {
- switch(key_value)
- {
- case 1://切换到设置日期
- {
- now_window = 3;
- now_win_sta = 31;
- tim_temp[0] = shi;
- tim_temp[1] = fen;
- tim_temp[2] = miao;
- part = 1;
- curr_menu = 1;
- }
- key_value = 0;
- break;
- case 4://切换到显示日期
- {
- now_window = 2;
- now_win_sta = 2;
- }
- key_value = 0;
- break;
- }
- }
- break;
- case 2:
- {
- switch(key_value)
- {
- case 4://切换到显示时间
- {
- now_window = 1;
- now_win_sta = 1;
- }
- key_value = 0;
- break;
- }
- }
- break;
- case 3:
- {
- switch(key_value)
- {
- case 1://设置日期
- {
- if (curr_menu<4)
- curr_menu++;
- if (curr_menu == 2)
- {
- part = 2;
- now_win_sta = 31;
- }
- else if(curr_menu == 3)
- {
- part = 3;
- now_win_sta = 31;
- }
- else if (curr_menu == 4)
- {
- curr_menu = 0;
- now_window = 1;
- now_win_sta = 1;
- }
- }
- key_value = 0;
- break;
- case 2://日期加
- {
- if(curr_menu == 1)
- {
- if (++tim_temp[2]>59)
- {
- tim_temp[2] = 0;
- }
- miao = tim_temp[2];
- }
- else if (curr_menu == 2)
- {
- if (++tim_temp[1]>59)
- {
- tim_temp[1] = 0;
- }
- fen = tim_temp[1];
- }
- else if (curr_menu == 3)
- {
- if (++tim_temp[0]>23)
- {
- tim_temp[0] = 0;
- }
- shi = tim_temp[0];
- }
- }
- key_value = 0;
- break;
- case 3://日期减
- {
- if(curr_menu == 1)
- {
- if (--tim_temp[2]<0)
- {
- tim_temp[2] = 59;
- }
- miao = tim_temp[2];
- }
- else if (curr_menu == 2)
- {
- if (--tim_temp[1]<0)
- {
- tim_temp[1] = 59;
- }
- fen = tim_temp[1];
- }
- else if (curr_menu == 3)
- {
- if (--tim_temp[0]<0)
- {
- tim_temp[0] = 23;
- }
- shi = tim_temp[0];
- }
- }
- key_value = 0;
- break;
- }
- }
- break;
- }
- }
- /*******************************************************************************
- * 函 数 名 : dis_dri
- * 函数功能 : 数码管扫描函数
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- void dis_dri(void)
- {
- static unsigned char dis_step = 1;
- DIG_SEG = 0x00;
- switch(dis_step)
- {
- case 1: //显示第1位
- {
- dig_show_tmp=dig_tab[dig_show_fir];
- DIG_SEG = dig_show_tmp;
- DIG_PLA = 0xfe;
- }
- break;
- case 2: //显示第2位
- {
- dig_show_tmp=dig_tab[dig_show_two];
- DIG_SEG = dig_show_tmp;
- DIG_PLA = 0xfd;
- }
- break;
- case 3: //显示第3位
- {
- dig_show_tmp=dig_tab[dig_show_thr];
- DIG_SEG = dig_show_tmp;
- DIG_PLA = 0xfb;
- }
- break;
- case 4: //显示第4位
- {
- dig_show_tmp=dig_tab[dig_show_fou];
- DIG_SEG = dig_show_tmp;
- DIG_PLA = 0xf7;
- }
- break;
- case 5: //显示第5位
- {
- dig_show_tmp=dig_tab[dig_show_fiv];
- DIG_SEG = dig_show_tmp;
- DIG_PLA = 0xef;
- }
- break;
- case 6: //显示第6位
- {
- dig_show_tmp=dig_tab[dig_show_six];
- DIG_SEG = dig_show_tmp;
- DIG_PLA = 0xdf;
- }
- break;
- case 7: //显示第7位
- {
- dig_show_tmp=dig_tab[dig_show_sev];
- DIG_SEG = dig_show_tmp;
- DIG_PLA = 0xbf;
- }
- break;
- case 8: //显示第8位
- {
- dig_show_tmp=dig_tab[dig_show_eig];
- DIG_SEG = dig_show_tmp;
- DIG_PLA = 0x7f;
- }
- break;
- }
- dis_step++;
- if(dis_step>8) //扫描完4个数码管后,重新从第一个开始扫描
- {
- dis_step=1;
- }
- }
- /*******************************************************************************
- * 函 数 名 : display_service()
- * 函数功能 : 显示服务函数
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- void display_service(void)
- {
- switch(now_window)
- {
- case 1://显示时间
- {
- if (now_win_sta == 1)//刷新显示
- {
- now_win_sta = 0;
- dig_show_fir = miao/10;//显示秒
- dig_show_two = miao%10;//显示秒
- dig_show_fou = 16;//显示-
- dig_show_six = fen/10;//显示分
- dig_show_thr = fen%10;//显示分
- dig_show_fiv = 16;//显示-
- dig_show_sev = shi/10;//显示时
- dig_show_eig = shi%10;//显示时
- }
- }
- break;
- case 2://显示日期
- {
- if (now_win_sta == 2)//刷新显示
- {
- now_win_sta = 0;
- dig_show_fir = ri/10;//显示秒
- dig_show_two = ri%10;//显示秒
- dig_show_fou = 16;//显示-
- dig_show_six = yue/10;//显示分
- dig_show_thr = yue%10;//显示分
- dig_show_fiv = 16;//显示-
- dig_show_sev = nian/10;//显示时
- dig_show_eig = nian%10;//显示时
- }
- }
- break;
- case 3:
- {
- if(now_win_sta ==31)
- {
- now_win_sta = 0;
- dig_show_fir = tim_temp[2]/10;//显示秒
- dig_show_two = tim_temp[2]%10;//显示秒
- dig_show_fou = 16;//显示-
- dig_show_six = tim_temp[1]/10;//显示分
- dig_show_thr = tim_temp[1]%10;//显示分
- dig_show_fiv = 16;//显示-
- dig_show_sev = tim_temp[0]/10;//显示时
- dig_show_eig = tim_temp[0]%10;//显示时
- }
- switch (part)//设置时候闪烁
- {
- case 1://秒闪烁
- {
- if (sci_count == FLIOPE)
- {
- dig_show_fir = tim_temp[2] / 10;
- dig_show_two = tim_temp[2] % 10;
- }
- else if (sci_count > FLICLO)
- {
- sci_count = 0;
- dig_show_fir = 17;
- dig_show_two = 17;
- }
- }
- break;
- case 2://分闪烁
- {
- if (sci_count == FLIOPE)
- {
- dig_show_six = tim_temp[1] / 10;
- dig_show_thr = tim_temp[1] % 10;
- }
- else if (sci_count > FLICLO)
- {
- sci_count = 0;
- dig_show_six = 17;
- dig_show_thr = 17;
- }
- }
- break;
- case 3://时闪烁
- {
- if (sci_count == FLIOPE)
- {
- dig_show_sev = tim_temp[0] / 10;
- dig_show_eig = tim_temp[0] % 10;
- }
- else if (sci_count > FLICLO)
- {
- sci_count = 0;
- dig_show_sev = 17;
- dig_show_eig = 17;
- }
- }
- break;
- }
- }
- break;
- }
- }
- /******************************************************
- ** 函数名:timing_service
- ** 描述 :定时1秒函数
- ** 输入 : 无
- ** 输出 :无
- ** 调用 :中断调用
- ******************************************************/
- void timing_service(void)//倒计时函数
- {
- if (tim_flg == 1)
- {
- tim_flg = 0;
- now_win_sta = 1;
- miao++;
- if(miao==60)//六十秒到了吗
- {
- fen++;//分加加
- miao=0;
- if(fen==60)//六十分到了吗
- {
- shi++;
- fen=0;
- if(shi==24)//24小时到了吗
- {
- shi=0; //时清零
- fen=0;
- miao=0;
- ri++;
- if (ri==30)
- {
- ri = 1;
- }
- }
- }
- }
- }
- }
- /******************************************************
- ** 函数名:time0_interrupt
- ** 描述 :按键扫描函数
- ** 输入 :无
- ** 输出 :无
- ******************************************************/
- void time0_interrupt() interrupt 1
- {
- static unsigned int base_2ms_buff;
- static unsigned int samping_cnt = 0;//1//1S钟计时
- TF0 = 0;//清除标志
- TR0 = 0;
- dis_dri();//动态扫描数码管
- if (++samping_cnt > 500)
- {
- samping_cnt = 0;
- if (now_window!=3)
- {
- tim_flg = 1;
- }
- }
- if (++base_2ms_buff==50)
- {
- base_2ms_buff = 0;
- if (alm_tim_cnt)
- alm_tim_cnt--;
- }
- if (++sci_count > 2000)
- {
- sci_count = 0;
- }
- TR0 = 1;
- TH0 = 0xf8;
- TL0 = 0x2f;//装载初值2ms(65535-63535)
- }
复制代码
所有资料51hei提供下载:
电子钟程序程序及电路.zip
(63.26 KB, 下载次数: 54)
|