51单片机调时电子钟

xiaoxiao2021-02-28  97

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

               程序功能:在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)&×[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&×[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&×[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&×[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&×[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&×[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&×[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]++; } }
转载请注明原文地址: https://www.6miu.com/read-24846.html

最新回复(0)