标题:
单片机C51电子时钟按键式程序及仿真
[打印本页]
作者:
雨季莫忧黎
时间:
2018-12-4 17:50
标题:
单片机C51电子时钟按键式程序及仿真
电子时钟仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
0.png
(15.55 KB, 下载次数: 35)
下载附件
2018-12-5 03:47 上传
单片机源程序如下:
#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)
2018-12-4 17:49 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
jztddxrcqq
时间:
2021-6-18 15:54
谢了,下载就能用。就是程序说明有点少。
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1