51单片机调时电子钟

来源:互联网 发布:苹果手机监视软件 编辑:程序博客网 时间:2024/06/13 07:35

/**************************************************************************************

              
程序功能:在8个数码管上显示时间(24小时制),包含时、分、秒各2位,共6位,时分秒之间
用短横隔开,可以使用按键对各位进行调时校准,被调整的那位所对应的数码管会闪烁,被调整的
位循环方向可以左移也可以右移,调整的数值可加可减。  
***************************************************************************************/


#include "reg52.h"
typedef unsigned int u16;  //对数据类型进行声明定义
typedef unsigned char u8;


#define GPIO_KEY P1


sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;


u8 KeyValue; //用来存放按键扫描读取到的键值


//预设时间各位数值,这里设置23:59:55是为了尽快观察进制变化是否正常
////u8 a=2;     //小时,十位
////u8 b=3;     //小时,个位
////u8 c=5; //分钟,十位
////u8 d=9; //分钟,个位
////u8 e=5; //秒,十位
////u8 f=5; //秒,个位


u16 smgwei[8]={2,3,10,5,9,10,5,5};//8位数码管对应的段码,10在smgduan数组中对应smgduan[10]=0x40,显示到数码管上是中间的一短横


u8 setwei=0; //调整时间各位的位置参数,默认为0,即不调整任何位。
u16 times[8];//循环次数累计,累计指令条数,粗略估算时间,控制被调整位闪烁频率。


u8 code smgduan[11]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,//数码管段选,显示0~9的值
0x40};//0x40数码管显示是短横


void delay(u16 i)  //延时子函数
{
while(i--);
}




void sub()      //调整时间数值,数值减小
{
switch(setwei)  //先判断调整时间中的哪一位,然后被选中位的数值自减
{ //减法可能越界,所以需要根据不同各位的进制来控制越界
case(1):smgwei[0]--;if(smgwei[0]==-1) smgwei[0]=2;break;
case(2):smgwei[1]--;if(smgwei[0]==0&&smgwei[1]==-1) 
{smgwei[1]=3;smgwei[0]=2;}
else if(smgwei[1]==-1)  
{smgwei[1]=9;smgwei[0]--; }
break;
case(3):;break;
case(4):smgwei[3]--;if(smgwei[3]==-1) {smgwei[3]=5;smgwei[1]--;}break;
case(5):smgwei[4]--;if(smgwei[4]==-1) {smgwei[4]=9;smgwei[3]--;}break;
case(6):;break;
case(7):smgwei[6]--;if(smgwei[6]==-1) {smgwei[6]=5;smgwei[4]--;}break;
case(8):smgwei[7]--;if(smgwei[7]==-1) {smgwei[7]=9;smgwei[6]--;}break;
}
}


void add()      //调整时间数值,数值增大
{
switch(setwei)//和减法类似,也是先判断被选中的位。再修改其值。
{ //不过加法的越界问题在main秒数递增进位过程中处理了
case(1):smgwei[0]++;break;
case(2):smgwei[1]++;break;
case(3):;break;
case(4):smgwei[3]++;break;
case(5):smgwei[4]++;break;
case(6):;break;
case(7):smgwei[6]++;break;
case(8):smgwei[7]++;break;
}
}


//4*4矩阵键盘按键扫描,因为需用到4个按键,所以让每一列的按键控制同一功能
void KEY_Scan()
{
char k=0;
GPIO_KEY=0x0f;
if(GPIO_KEY!=0x0f)//读取按键是否按下
{
delay(1000);//延时10ms进行消抖
if(GPIO_KEY!=0x0f)//再次检测键盘是否按下
{
//测试列
GPIO_KEY=0X0F;
switch(GPIO_KEY)
{
case(0X07): KeyValue=0;break;
case(0X0b): KeyValue=1;break;
case(0X0d): KeyValue=2;break;
case(0X0e): KeyValue=3;break;
}


while((k<50)&&(GPIO_KEY!=0x0f))//按键松手检测
{
delay(10000);
k++;
}


switch(KeyValue)
{ //被调整位的值也需要控制越界
case(0):setwei--;if(setwei==-1)  setwei=8; break;
case(1):setwei++;if(setwei==9) setwei=0;   break;
case(2):sub();break;
case(3):add();break;
}
}
}
}


void Timer0Init()
{
TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。
TH0=0XFC; //给定时器赋初值,定时1ms
TL0=0X18;
ET0=1;//打开定时器0中断允许
EA=1;//打开总中断
TR0=1;//打开定时器
}


//数码管动态显示函数
void show()   //修改后数码管显示函数
{
u8 j;
P2|=0x1c;   //8个数码管 ,使用for循环,轮流选通这8个数码管并传送不同的数据给P0
for (j=0;j<8;j++)
{ //同时根据条件,选择数码管常亮或者闪烁
P2+=4;
P0=(setwei==(j+1)&&times[j]>500)?0x00:smgduan[smgwei[j]];
times[j]++; 
if (times[j]>1000) times[j]=0;    
delay(10);P0=0x00;
}
}
// void show()   //修改前的数码管显示子函数
// {
// LSA=0;LSB=0;LSC=0;  
// P0=(setwei==1&&times[0]>500)?0x00:smgduan[a];
// times[0]++; 
// if (times[0]>1000) times[0]=0;    
// delay(10);P0=0x00;
// LSA=1;LSB=0;LSC=0;  
// P0=(setwei==2&&times[1]>500)?0x00:smgduan[b];
// times[1]++; 
// if (times[1]>1000) times[1]=0;
// delay(10);P0=0x00;
// LSA=0;LSB=1;LSC=0;   
// P0=0X40;
// delay(10);P0=0x00;
// LSA=1;LSB=1;LSC=0;  
// P0=(setwei==3&&times[2]>300)?0x00:smgduan[c];
// times[2]++; 
// if (times[2]>600) times[2]=0;
// delay(10);P0=0x00; 
// LSA=0;LSB=0;LSC=1;   
// P0=(setwei==4&&times[3]>300)?0x00:smgduan[d];
// times[3]++; 
// if (times[3]>600) times[3]=0;
// delay(10);P0=0x00;
// LSA=1;LSB=0;LSC=1;  
// P0=0X40;
// delay(10);P0=0x00;
// LSA=0;LSB=1;LSC=1;  
// P0=(setwei==5&&times[4]>100)?0x00:smgduan[e];
// times[4]++; 
// if (times[4]>200) times[4]=0;
// delay(10);P0=0x00;
// LSA=1;LSB=1;LSC=1;  
// P0=(setwei==6&&times[5]>100)?0x00:smgduan[f];
// times[5]++; 
// if (times[5]>200) times[5]=0;
// delay(10);P0=0x00;
// }


void main()
{
Timer0Init();  //定时器0初始化
while(1)
{ KEY_Scan();//扫描是否有调时按键按下 
//由于秒数自加,需根据进制不同选择判断条件和对应操作
if(smgwei[7]==10) {smgwei[7]=0;smgwei[6]+=1;}
if(smgwei[6]==6) {smgwei[6]=0;smgwei[4]+=1;}
if(smgwei[4]==10) {smgwei[4]=0;smgwei[3]+=1;}
if(smgwei[3]==6) {smgwei[3]=0;smgwei[1]+=1;}
if(smgwei[1]==10) {smgwei[1]=0;smgwei[0]+=1;}
if((smgwei[0]*10+smgwei[1])>=24) {smgwei[0]=0;smgwei[1]=0;} 
show();
}
}


void Timer0() interrupt 1
{
static u16 i;
TH0=0XFC; //给定时器赋初值,定时1ms
TL0=0X18;
i++;
if(i==1000)
{
i=0;
smgwei[7]++;
}
}
原创粉丝点击