标题:
单片机电子时钟设计
[打印本页]
作者:
rqwyyuuyew
时间:
2019-3-28 15:27
标题:
单片机电子时钟设计
单片机源程序如下:
#include<stc15.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
uint bdata key; //定义变量,键状态
uint bdata edgk; //定义变量,键状态变化前沿
uchar data kcode; //定义变量,键编号
sbit ESET=edgk^4; //重定义KC键为设置键(触发型)
sbit EINC=edgk^6; //定义K17键为加1键(触发型)
sbit EDEC=edgk^7; //定义K18键为减1键(触发型)
sbit SETK=key^4; //重定义KC键为设置键(开关型)
sbit ALA=key^5;
sbit ALARM=edgk^5;
sbit EKF=edgk^7;
sbit EKE=edgk^6;
sbit K17=P3^2;
sbit K18=P3^3;
uchar data state; //定义变量,工作状态
uchar data timer; //定义变量,0.5秒计时器
uchar data KeyOnTmr; //定义变量,调整键长键计时
uchar data Keytmr;
uchar data hour=0x0c; //定义变量,时变量,二进制
uchar data min=0x00; //定义变量,分变量,二进制
uchar data sec=0x00; //定义变量,秒变量,二进制
uchar data set_num; //定义变量,当前调整位,0~"时"十位,3~"分"个位
uchar data clock_flag;
uchar beeftmr;
uchar data ktmr;
sbit BEEF=P2^7;
sbit LED7=P1^7;
sbit LED8=P1^6;
sbit P_HC595_SER=P4^0;
sbit P_HC595_RCLK=P5^4;
sbit P_HC595_SRCLK=P4^3;
uchar code SEG7[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x00};
uchar code Scon_bit[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
uchar data dis_buf[]={16,16,16,16,16,16,16,16};
uchar data alarm_clock[]={0,0,0,0,0,0,0,0};
void Delay1ms(){
uchar i,j;
_nop_();
_nop_();
_nop_();
i=11;
j=190;
do{
while(--j);
}while(--i);
}
void F_Send_595(uchar x){
uchar i;
for(i=0;i<8;i++){
x=x<<1;
P_HC595_SER=CY;
P_HC595_SRCLK=1;
P_HC595_SRCLK=0;
}
}
void display(void){
uchar i;
for(i=2;i<8;i++){
F_Send_595(Scon_bit[i]);
if((state==1||state==2)&&i==set_num&&(sec&1)==1)
F_Send_595(SEG7[16]);
else
F_Send_595(SEG7[dis_buf[i]]);
P_HC595_RCLK=1;
P_HC595_RCLK=0;
//Delay1ms();
}
}
void readkey()
{ uchar i;
P0=0x7f;
for(i=0;i<20;i++);
edgk=(~P0<<4)&0xf0;
P0=0xbf;
for(i=0;i<20;i++);
edgk|=(~P0)&0x0f;
edgk<<=8;
P0=0xdf;
for(i=0;i<20;i++);
edgk|=(~P0<<4)&0xf0;
P0=0xef;
for(i=0;i<20;i++);
edgk|=(~P0)&0x0f;
EKE=0;EKF=0; //放弃矩阵键盘的KE、KF键状态
if(!K17)EKE=1; //K17键状态存入edgk^6,或K17取代KE
if(!K18)EKF=1; //K18键状态存入edgk^7,或K18取代KF
}
void keytrim()
{ uint temp;
if(edgk==0)ktmr=0;
else
{ if(ktmr<255)ktmr++;
if(ktmr<8)edgk=0;
}
temp=edgk;
edgk=(key^edgk)&edgk;
key=temp;
if(edgk!=0)
{ temp=edgk;
for(kcode=0;(temp&0x1)==0;kcode++)temp>>=1;
}
else kcode=0x10;
}
void keysound()
{ if(edgk!=0)beeftmr=40;
if(beeftmr!=0){beeftmr--;BEEF=0;}
else BEEF=1;
}
void Timer0Init(void) //2500ms@11.0592MHz
{
AUXR |= 0x80;
TMOD &= 0xF0;
TL0 = 0x00;
TH0 = 0x94;
TF0 = 0;
TR0 = 1;
}
void clock() //时钟走时函数
{ timer++; //计时,500ms回0
if(timer>=200) //0.5秒到则
{ timer=0;sec++; //走秒
if(sec>=120){sec=0;min++;} //60秒到则秒回0、走分
if(min>=60){min=0;hour++;} //60分到则分回0、走时
if(hour>=24)hour=0; //24时到则时回0
}
}
void wrdisb() //设置显示缓冲器函数
{ dis_buf[2]=hour/10; //数码左第1位显示时"十"位
dis_buf[3]=hour%10; //数码左第2位显示时"个"位
dis_buf[4]=min/10; //数码左第3位显示分"十"位
dis_buf[5]=min%10; //数码左第4位显示分"个"位
dis_buf[6]=sec/20;
dis_buf[7]=(sec/2)%10;
}
void inputcheck() //时分秒数值合理性检查
{
if(dis_buf[7]==255)dis_buf[7]=9; //秒个位-1
if(dis_buf[7]==10)dis_buf[7]=0; //秒个位+1
if(dis_buf[6]==255)dis_buf[6]=5; //秒十位-1
if(dis_buf[6]==6)dis_buf[6]=0; //秒十位+1
if(dis_buf[5]==255)dis_buf[5]=9; //分个位由0减1则回9
if(dis_buf[5]==10)dis_buf[5]=0; //分个位由9加1则回0
if(dis_buf[4]==255)dis_buf[4]=5; //分十位由0减1则回5
if(dis_buf[4]==6)dis_buf[4]=0; //分十位由5加1则回0
if(dis_buf[3]==255) //时个位由0减1则
{ if(dis_buf[2]==2)dis_buf[3]=3; //如时十位为2则时个位为3
else dis_buf[3]=9; //否则时个位为9
}
if(dis_buf[3]==10)dis_buf[3]=0; //时个位由9加1则回0
if(dis_buf[2]==255)dis_buf[2]=2; //时十位由0减1则回2
if(dis_buf[2]==2&&dis_buf[3]>=4)dis_buf[3]=0; //时十位为2,个位超3则回0
if(dis_buf[2]==3)dis_buf[2]=0; //时十位由2加1则回0
}
void compare(){
uchar i;
uchar flag=0;
for(i=2;i<8;i++){
if(dis_buf[i]!=alarm_clock[i]){
flag=1; break;
}
}
if(!flag) clock_flag=0x01;
if(!LED7&&clock_flag==0x01){
beeftmr=10;
}else
beeftmr=0;
}
void gpio(){
P0M1=0; P0M0=0;
P1M1=0; P1M0=0;
P2M1=0; P2M0=0;
P3M1=0; P3M0=0;
P4M1=0; P4M0=0;
P5M1=0; P5M0=0;
}
void main(void)
{ uchar i;
BEEF=0; //初始化,上电时P3.0(BEEF)为高电平
state=0; //默认待机态
set_num=2;
clock_flag=0x00;
Timer0Init(); //调用T0定时器初始化函数
gpio();
while(1)
{ while(!TF0); //2.5mS定时未到则等待
TF0=0; //清定时器溢出标志
readkey(); //调用扫描键盘存键状态函数
display(); //调用显示扫描函数
keytrim(); //调用键状态消抖等处理函数
keysound(); //调用有键发出"嘀"声响函数
clock(); //时钟走时
compare();
switch(state) //根据状态转移
{ case 0: //时钟显示态
{
LED8=1;
wrdisb(); //显示时分秒
if(clock_flag==0x01&&(ESET||EINC||EDEC||ALARM)) clock_flag=0x00;
if(!SETK)KeyOnTmr=0; //无SETK则键计时器清0
else if(timer==0)KeyOnTmr++; //有SETK则键计时(时基0.5秒)
if(KeyOnTmr==10) //判断长键达5秒?
{ KeyOnTmr=0;state=1;set_num=2; //长键计时复位,转时间调整态
}
if(!ALA) Keytmr=0;
else if(timer==0)Keytmr++;
if(Keytmr==10){
Keytmr=0; state=2; set_num=2;
}
if(ALARM)LED7=!LED7;
break;
}
case 1: //时间调整态
{ LED8=0; //LED8指示常亮
if(ESET) //点按SET键则
{ set_num++; //调整位后移
if(set_num==8) //4位都调整完则结束
{
min=dis_buf[4]*10+dis_buf[5];
hour=dis_buf[2]*10+dis_buf[3];
sec=dis_buf[6]*10+dis_buf[7];
set_num=2;timer=0;state=0; //转时钟显示态
}
}
if(EINC) //点按加1键则调整位+1,检查合理性
{ dis_buf[set_num]++;inputcheck();
}
if(EDEC) //点按减1键则调整位-1,检查合理性
{ dis_buf[set_num]--;inputcheck();
}
break;
}
case 2:
{
if(timer==0) LED8=!LED8;
if(ALARM)
{
set_num++;
if(set_num==6)
{
for(i=2;i<6;i++)
alarm_clock[i]=dis_buf[i];
wrdisb();
LED7=0;
set_num=2; state=0;
}
}
if(EINC) //点按加1键则调整位+1,检查合理性
{ dis_buf[set_num]++;inputcheck();
}
if(EDEC) //点按减1键则调整位-1,检查合理性
{ dis_buf[set_num]--;inputcheck();
}
break;
}
}
}
}
复制代码
所有资料51hei提供下载:
shiyan5.zip
(72.78 KB, 下载次数: 14)
2019-3-28 15:26 上传
点击文件名下载附件
下载积分: 黑币 -5
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1