在本论坛看到的一个数码管时钟程序,稍作修改后,自己用洞洞板焊了一块板子,用了两个四位共阳数码管做的,取消了锁存器,实现的功能完全正常,后来又加入了DS18B20测温程序,温度显示也正常,时间显示4秒多然后显示温度1秒的样子,交替显示,现在遇到的问题是,在没加温度程序的时候,调整时间的时候时分秒年月日都会闪烁,并且调整加减的时候都实时显示,现在加了温度程序以后,按下调整键的时候,时分秒不会闪烁,按加减的时候,数据也不能实时变化,但是数据的加减在调整退出后是有变化的,只是没能实时的显示,而年月日的调整是正常的,就是说调整的时候年月日会闪烁,且数据也是随加减键实时变化的,下面是我的程序,大神帮我看看程序哪里有问题?已经折腾好几天了,没能解决
- #include <reg52.h> //头文件
- #define uchar unsigned char //宏定义
- #define uint unsigned int //宏定义
- sbit TRST = P1^0; /* DS1302实时时钟的复位/片选线引脚(第5脚RST低电平复位高电平时芯片正常工作)*/
- sbit TIO = P1^1; /* DS1302实时时钟的数据输入/输出引脚(第6脚I/O)*/
- sbit SCLK = P1^2; /* DS1302实时时钟的串行时钟引脚(第7脚SCLK)*/
- sbit S2 = P1^3; //定义调整按键
- sbit S3 = P1^4; //定义减数据按键,正常走时情况下按下显示年月日,延时6秒后转回时间显示
- sbit S4 = P1^5; //定义加数据按键
- sbit DQ = P1^6; //定义DS18B20的数据输入/输出口
- unsigned char code duan[]=
- {0xc0,0xf9,0xa4,0xb0,
- 0x99,0x92,0x82,0xf8,
- 0x80,0x90,0xbf,0xff,0x9c,0xc6}; //共阳数码管段选码0-9
- /*****************************************************/
- /***********ds18b20子程序模块*************************/
- /*****************************************************/
- unsigned char temp_value,temp1_value; //temp_value温度值整数部分 temp1_value温度值小数部分
- bit fg=1; //温度正负标志 1为正0为负
- /***********ds18b20延迟子函数(晶振12MHz )*******/
- void delay_18B20(unsigned int i)
- {
- while(i--);
- }
- /**********ds18b20初始化函数**********************/
- void Init_DS18B20(void)
- {
- unsigned char x=0;
- DQ = 1; //DQ复位,不要也行
- delay_18B20(8); //稍做延时
- DQ = 0; //单片机将DQ拉低
- delay_18B20(40); //精确延时维持至少480us当总线停留在低电平超过480us,总线上所以器件都将被复位
- DQ = 1; //释放总线即拉高总线,产生复位脉冲后,微处理器释放总线,让总线处于空闲状态
- delay_18B20(7); //稍作延时,释放总线后,以便从机18b20通过拉低总线来指示其是否在线
- x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
- delay_18B20(10); //稍作延时
- }
- /***********ds18b20读一个字节**************/
- unsigned char ReadOneChar(void)
- {
- unsigned char i=0;
- unsigned char dat = 0; //一定别忘了给初值
- for (i=8;i>0;i--) //读取数据时,数据以字节的最低有效位先从总线移出
- {
- DQ = 0; // 给脉冲信号,单片机(微处理器)将DS18B20总线拉低
- dat>>=1;
- DQ = 1; // 给脉冲信号,拉低总线后接着释放总线,让从机18b20能够接管总线,输出有效数据
- if(DQ)
- dat|=0x80;
- delay_18B20(4); //所有读"时间隙"必须60~120us
- }
- return(dat); //返回一个字节的数据
- }
- /*************ds18b20写一个字节****************/
- void WriteOneChar(unsigned char dat)
- {
- unsigned char i=0;
- for (i=8; i>0; i--)
- {
- DQ = 0;
- DQ = dat&0x01;
- delay_18B20(5);
- DQ = 1;
- dat>>=1;
- }
- }
- /**************读取ds18b20当前温度************/
- void ReadTemp(void)
- {
- unsigned char L=0;
- unsigned char H=0;
- unsigned char t=0;
- Init_DS18B20(); //ds18b20初始化
- WriteOneChar(0xCC); // 跳过读序号列号的操作
- WriteOneChar(0x44); // 启动温度转换
- delay_18B20(100); // this message is wery important
- Init_DS18B20(); //ds18b20初始化
- WriteOneChar(0xCC); //跳过读序号列号的操作
- WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
- delay_18B20(50); //延时
- L=ReadOneChar(); //读取温度值低8位
- H=ReadOneChar(); //读取温度值高8位
- t=H&0xf8; //把读取到的温度值高8位跟11111000做与运算判断温度正负,若高5位全部为1即为负否则为正
- if(t)
- {
- fg=0; //给出温度为负的标志
- temp_value=H<<4;
- temp_value+=(L&0xf0)>>4;
- temp_value=~temp_value+1; //负温度值整数部分-取反加1
- temp1_value=~L&0x0f; //负温度值小数部分
- }
- else
- {
- temp_value=H<<4;
- temp_value+=(L&0xf0)>>4; //正温度值整数部分
- temp1_value=L&0x0f; //正温度值小数部分
- }
- }
- //*********************************************************************************************
- /*******************************时钟芯片DS1302的数据时序子程序********************************/
- //*********************************************************************************************
- #include <intrins.h> //包含_nop_函数的头文件
- #define sce timedate[1] //秒钟寄存器1读WRITE 0x80写READ 0x81(bit7CH是时钟停止标志位0是正常工作若为1说明芯片掉电没有备用电池未运行剩下7位高3位是秒的十位,低4位是秒的个位)
- #define min timedate[2] //分钟寄存器2读WRITE 0x82写READ 0x83(bit7没意义,剩下的7位高3位是分钟的十位,低4位是分钟的个位)
- #define hour timedate[3] //小时寄存器3读WRITE 0x84写READ 0x85(bit7是1代表12小时制,0代表24小时制bit6固定是0,bit5在12小时制下0代表上午1代表下午在24小时制下和bit4一起代表了小时的十位低4位代表的是小时的个位)
- #define date timedate[4] //日期寄存器4读WRITE 0x86写READ 0x87(高2位固定是0,bit5和bit4是日期的十位,低4位是日期的个位)
- #define month timedate[5] //月份寄存器5读WRITE 0x88写READ 0x89(高3位固定是0 bit4是月的十位,低4位是月的个位)
- #define week timedate[6] //星期寄存器6读WRITE 0x8a写READ 0x8b(高5位固定是0,低3位代表了星期)
- #define year timedate[7] //年份寄存器7读WRITE 0x8c写READ 0x8d(高4位代表了年的十位,低4位代表了年的个位,这里特别注意,这里的00到99年指的是2000年到2099)
- //寄存器8读WRITE 0x8e写READ 0x8f(bit7是一个保护位,如果这一位是1,那么是禁止给任何其他的寄存器或者那31个字节的RAM写数据的,因此在写数据之前,这一位必须先写成0,剩下7位都是0)
- unsigned char displaychar1[8]={0,1,2,3,4,5,6,7},a,ya,ja ; //a结尾的字符都用来专门延时,a通用,ya日期延时程序用
- unsigned char commandchar[9]={0,0x80,0x82,0x84,0x86,0x88,0x8a,0x8c,0x8e}; //与timedate对应,分别控制每个寄存器的写,读时数组+1,第8个数是控制写保护位
- unsigned char timedate[8],sdat,seta,b,fen,tz; //fen用来给分钟计数,tz用来计算分钟数自动补偿差错
- unsigned char LD = 1; //************数码管,亮度调节,0最小,10最高,越亮越闪 因会影响开始信号查询时间,建议最高设置为3**************
- char m;
- bit s,s2,s3,s4,K,setbit,sk;
- /******************延时子程序***********************/
- void timeout(unsigned char a)
- {
- unsigned char b;
- for(;a>0;a--)
- for(b=10;b>0;b--);//本来b=114会闪烁
- }
- /*********延时5微秒子程序************/
- // void timeout5us()
- // {
- // _nop_();
- // }
- /**************写控制和一个字节***********************/
- void sendchar(unsigned char csdat,unsigned char sdat)
- {
- SCLK = 0; //串行时钟置低//拉低SCLK,为脉冲上升沿写入数据做好准备
- TRST = 1; //启动数据传输 打开片选 DS1302实时时钟的复位/片选线引脚(第5脚RST低电平复位高电平时芯片正常工作)
- for(a=0;a<8;a++) //连续写8个二进制位数据
- {
- SCLK = 0;//确保写数据前SCLK被拉低
- TIO = (csdat%2);
- SCLK = 1;//上升沿写入数据
- csdat >>=1; //将csdat的各数据位右移1位,准备写入下一个数据位
- }
- for(a=0;a<8;a++) //连续写8个二进制位数据
- {
- SCLK = 0;//确保写数据前SCLK被拉低
- TIO = (sdat%2);
- SCLK = 1;//上升沿写入数据
- sdat >>=1;
- }
- SCLK = 0; //重新拉低SCLK,形成脉冲
- TRST = 0; //禁止数据传递 关闭片选 DS1302实时时钟的复位/片选线引脚(第5脚RST低电平复位高电平时芯片正常工作)
- }
- /**************************读一个字节**************************************************************/
- unsigned char receviechar(unsigned char crdat)
- {
- unsigned char rdat;
- TRST = 1; //打开片选 DS1302实时时钟的复位/片选线引脚(第5脚RST低电平复位高电平时芯片正常工作)
- //TRST = 1;
- for(a=0;a<8;a++)
- {
- SCLK = 0;
- TIO = (crdat%2);
- SCLK = 1;
- crdat >>=1;
- }
- for(a=0;a<8;a++)
- {
- SCLK = 1;
- rdat >>= 1;
- SCLK = 0;
-
- if(TIO)
- rdat = rdat|0x80;
- }
- SCLK = 0;
- TRST = 0;
- return rdat ; //返回读出的rdat的值
- }
- /*************************读取时分秒子程序**************************************/
- void readtime()
- {
- sendchar(0x8e,0); //去DS1302写保护
- hour = receviechar(0x85); //读小时数据
- min = receviechar(0x83); //读分钟数据
- sce = receviechar(0x81); //读秒针数据
- sendchar(0x8e,0x80); //DS1302加写保护
- }
- /************************读取年月日子程序***************************************/
- void readyear()
- {
- sendchar(0x8e,0); //去DS1302写保护
- date = receviechar(0x87); //读日期
- month = receviechar(0x89); //读月份
- year = receviechar(0x8d); //读年份
- sendchar(0x8e,0x80); //DS1302加写保护
- }
- /**********************键盘扫描子程序,用定时器延时******************************/
- bit jianpan(K)
- {
- if((!K)&TF0) //如果S2或S3或S4被按下且计时器0溢出
- {
- TF0 = 0; //定时器0溢出标志清0(溢出时TF0被硬件置1,并且申请中断,软件查询到该位置1后需用软件清零)
- ja++;
- if(ja>=2)
- {
- TR0 = 0; //关闭定时器0,每次按下后都会关闭定时器,后面的程序会检测松手,松开按键后会重新打开定时器,可以保护每次按下只起作用一次
- ja = 0;
- s = 1;
- }
- return s; //返回s的值给K
- }
- //return s; //返回s的值给K
- }
- //**********************************************设置时间日期子程序*******************************************/
- void settime()
- {
- setbit=1; //设置控制标识,进本函数后先就让标识打开,在下面延时跳出前都会一直跳入设置功能函数
- if(TF1&(s2==s3==s4==0)) //没有按键按下时用定时器1来延时跳出
- {
- TF1=0; //定时器1溢出标志清0(溢出时TF1被硬件置1,并且申请中断,软件查询到该位置1后需用软件清零)
- seta ++;
- }
- if(!(s2==s3==s4==0)) //松手检测
- seta = 0; //延时时间超过一定值,或者有按键被按下(注意!这个符号)时,时间会被延长
- if(seta>=70) //延时
- {
- setbit=0; //关闭设置
- sdat = 0;
- }
- if(sk!=s2) //sk用来做s2的中间暂存数据,用来用来识别S2是否变化过
- {
- sk = s2;
- if(s2)
- sdat ++; //每次进行一次S2动作时才自加一次sdat
- if(sdat ==6)sdat=7; //跳过星期,本程序不显示星期
- }
- m = timedate[sdat]/16*10+timedate[sdat]%16; //m用10进制存下以供写入DS1302
- if(s3) m--;
- switch (sdat) //每次进入设置的对应操作判断
- {
- case 1:
- if(m==-1) //调整秒钟
- m = 59;
- break;
-
- case 2:
- if(m==-1) //调整分钟
- m = 59;
- break;
-
- case 3:
- if(m==-1) //调整小时
- m =23;
- break;
-
- case 4: //调整日期***因为月份不同所以每个月的天数是不同的
- if(timedate[5]==4|timedate[5]==6|timedate[5]==9|timedate[5]==11) //小月,
- {
- if(m<=0)
- m = 30;
- break; //4月6月9月和11月是小月份,只有30天,所以到了30后转到1日
- }
- if(timedate[5]==2&(timedate[7]%4==0)) //闰年2月
- {
- if(m<=0)
- m=29;
- break; //闰年2月有29天
- }
- if(timedate[5]==2&(timedate[7]%4!=0)) //平年2月
- {
- if(m<=0)
- m=28;
- break; //平年2月只有28天
- }
- if(m<=0)
- m =31;
- break; //其它月分情况
- /********************************************************************************************************
- 怎么判断一个年份是不是闰年:1:普通情况求闰年只需除以4可除尽即可 年/4余数为0
- 2:如果是100的倍数但不是400的倍数,那就不是闰年了,即末两位都是零的整除400才行
- 判断闰年条件①:非整百年数除以4,无余为闰,有余为平;②整百年数除以400,无余为闰有余为平。
- *********************************************************************************************************/
- case 5: //调整月份
- if(m==0)
- m = 12;
- break;
-
- case 6:
- sdat++; //跳过星期本程序不显示星期
- if(m<=0)
- m = 7;
- break;
-
- case 7: //调整年份17-99
- if(m<=16)
- m = 99;
- break;
-
- default : /****不在判断范围的进行初始化处理*/
- sdat = 0; //S2按键计数清0
- sk = 0; //s2的中间暂存数据清0
- setbit = 0; //设置控制标识清0
- s2 = 0; //s2=0是优化点,在按下S2后按键标识不会清零,松手时程序已重复运行了很多遍,所以会重新跳回设置的第一位.加本命令可以让设置判断失效,不进设置页。
- break;
- }
- if(s4) m++;
- switch (sdat) //每次进入设置的对应操作判断
- {
- case 1: //调整秒钟
- if(m>59)
- m = 0;
- break;
-
- case 2: //调整分钟
- if(m>59)
- m = 0;
- break;
-
- case 3: //调整小时
- if(m>23)
- m = 0;
- break;
-
- case 4: //调整日期***因为月份不同所以每个月的天数是不同的
- if(timedate[5]==4|timedate[5]==6|timedate[5]==9|timedate[5]==11) //小月,
- {
- if(m>=31)
- m = 1;
- break;//4月6月9月和11月是小月份,只有30天,所以到了30后转到1日
- }
- if(timedate[5]==2&(timedate[7]%4==0)) //闰年2月
- {
- if(m>=30)
- m = 1;
- break; //闰年2月有29天
- }
- if(timedate[5]==2&(timedate[7]%4!=0)) //平年2月
- {
- if(m>=29)
- m = 1;
- break; //平年2月只有28天
- }
- if(m>=32)
- m = 1;
- break; //其它月分情况
-
- case 5: //调整月份
- if(m>=13)
- m = 1;
- break;
-
- case 6:
- sdat++; //跳过星期本程序不显示星期
- if(m>=8)
- m = 1;
- break;
-
- case 7: //调整年份17-99
- if(m>=100)
- m = 17;
- break;
-
- default : /****不在判断范围的进行初始化处理*/
- sdat = 0; //S2按键计数清0
- sk = 0; //s2的中间暂存数据清0
- setbit = 0; //设置控制标识清0
- s2 = 0; //s2=0是优化点,在按下S2后按键标识不会清零,松手时程序已重复运行了很多遍,所以会重新跳回设置的第一位.加本命令可以让设置判断失效,不进设置页。
- break;
- }
- if(setbit) //如果设置控制标识setbit为1则说明以上有成立的条件,需要发送修改数据
- {
- sendchar(0x8e,0); //去DS1302写保护
- sendchar(commandchar[sdat],m/10*16+m%10); //将改好的数据写入DS1302(sdat的值决定写时分秒或年月日星期,m的值转换成BCD写入)
- sendchar(0x8e,0x80); //加写保护
-
- if(seta%5>2&seta<50) //设置延时操作期间控制闪烁时间
- timedate[sdat] = 0xbb; //显示空,对应段选的两位11;0xbb/16=11,0xbb%16=11,而上面段选数组中第12个数是显示空
- }
- }
- /***************************************************************************************
- 显示子程序 两个数,分别记录键值和重复码个数
- *****************************************************************************************/
- void display()
- {
- P2 = 0x7f; //送位选数据0111 1111
- P0 = (displaychar1[0]); //送段选数据
- timeout(LD); //延时
- P0 =0xff; //消隐,很重要,不然会闪烁,共阴数码管用P0=0x00
-
- P2 = 0xbf; //送位选数据1011 1111
- P0 = displaychar1[1];
- timeout(LD); //延时
- P0 =0xff;
-
- P2 = 0xdf; //送位选数据1101 1111
- P0 = displaychar1[2];
- timeout(LD);//延时
- P0 =0xff;
-
- P2 = 0xef; //送位选数据1110 1111
- P0 = displaychar1[3];
- timeout(LD); //延时
- P0 =0xff;
-
- P2 = 0xf7; //送位选数据1111 0111
- P0 = displaychar1[4];
- timeout(LD); //延时
- P0 =0xff;
-
- P2 = 0xfb; //送位选数据1111 1011
- P0 = displaychar1[5];
- timeout(LD); //延时
- P0 =0xff;
-
- P2 = 0xfd; //送位选数据1111 1101
- P0 = displaychar1[6];
- timeout(LD); //延时
- P0 =0xff;
-
- P2 = 0xfe; //送位选数据1111 1110
- P0 = displaychar1[7];
- timeout(LD); //延时
- P0 =0xff;
- }
- /************************************温度显示子程序*****************************************/
- DS18b20display()
- {
- if(fg==1) //温度为正时显示的数据
- {
- if((temp_value/100)>=1) //若温度高于100度时--即温度百位数大于或等于1的时候
- {
- displaychar1[0] = duan[11]; //不显示
- displaychar1[1] = duan[temp_value/100]; //显示温度百位
- displaychar1[2] = duan[temp_value%100/10]; //显示温度十位
- displaychar1[3] = duan[temp_value%10]&0x7f; //显示温度个位和小数点
- displaychar1[4] = duan[temp1_value*625/1000%10];//显示温度小数点后第一位
- displaychar1[5] = duan[11]; //不显示
- displaychar1[6] = duan[12]; //温度显示"0"
- displaychar1[7] = duan[13]; //温度显示"C"
- }
- if((temp_value%100/10)>=1&(temp_value/100)<1) //若温度高于10度与温度低于100度时--即温度十位数大于或等于1并且温度百位数小于1的时候
- {
- displaychar1[0] = duan[11]; //不显示
- displaychar1[1] = duan[11]; //不显示
- displaychar1[2] = duan[temp_value%100/10]; //显示温度十位
- displaychar1[3] = duan[temp_value%10]&0x7f; //显示温度个位和小数点
- displaychar1[4] = duan[temp1_value*625/1000%10];//显示温度小数点后第一位
- displaychar1[5] = duan[11]; //不显示
- displaychar1[6] = duan[12]; //温度显示"0"
- displaychar1[7] = duan[13]; //温度显示"C"
- }
- if((temp_value%100/10)<1&(temp_value/100)<1) //若温度低于10度时--即温度十位数小于1并且百位数小于1的时候
- {
- displaychar1[0] = duan[11]; //不显示
- displaychar1[1] = duan[11]; //不显示
- displaychar1[2] = duan[temp_value%10]&0x7f; //显示温度个位和小数点
- displaychar1[3] = duan[temp1_value*625/1000%10];//显示温度小数点后第一位
- displaychar1[4] = duan[11]; //不显示
- displaychar1[5] = duan[12]; //温度显示"0"
- displaychar1[6] = duan[13]; //温度显示"C"
- displaychar1[7] = duan[11]; //不显示
- }
- }
- if(fg==0) //温度为负时显示的数据
- {
- if(((temp_value-1)%100/10)>=1) //如果为负10度以下时
- {
- displaychar1[0] = duan[11]; //不显示
- displaychar1[1] = duan[10]; //显示"-"
- displaychar1[2] = duan[(temp_value-1)%100/10]; //显示负温度十位
- displaychar1[3] = duan[(temp_value-1)%10]&0x7f; //显示负温度个位和小数点
- displaychar1[4] = duan[temp1_value*625/1000%10];//显示负温度小数点后第一位
- displaychar1[5] = duan[11]; //不显示
- displaychar1[6] = duan[12]; //温度显示"0"
- displaychar1[7] = duan[13]; //温度显示"C"
-
- fg=1; //清负温度标志
- }
- else //负十度以上时
- {
- displaychar1[0] = duan[11]; //不显示
- displaychar1[1] = duan[11]; //不显示
- displaychar1[2] = duan[10]; //显示"-"
- displaychar1[3] = duan[(temp_value-1)%10]&0x7f; //显示负温度个位和小数点
- displaychar1[4] = duan[temp1_value*625/1000%10];//显示负温度小数点后第一位
- displaychar1[5] = duan[11]; //不显示
- displaychar1[6] = duan[12]; //温度显示"0"//小数点后第二位temp1_value*625/100%10
- displaychar1[7] = duan[13]; //温度显示"C" //小数点后第三位temp1_value*625/10%10
- fg=1; //清负温度标志
- }
- }//温度为负时显示的数据包含的大括号
- }//显示温度数据包含的大括号
- /***************************************主函数**************************************************/
- main()
- {
- SCLK = 0 ; /* DS1302实时时钟的串行时钟引脚(第7脚SCLK)*/
- TRST = 0 ; /* DS1302实时时钟的复位/片选线引脚(第5脚RST低电平复位高电平时芯片正常工作)*///复位DS1302实时时钟
- readtime(); //先读一下时间然后再判断自动补偿程序
- fen=min; //fen用来判断min是否到了1分钟
- if(S2==0) //上电检测 如果调整键S2被按下就初始化1302 给初值是17年12月26日,16:30:00星期二
- { //这里是给系统送初始值的,使用的方法是断电之后,按住S2调整键,然后上电,S2键按住1~3s,松开即设置完成
- sendchar(0x8e,0); //去DS1302写保护
- sendchar(0x80,0x00); //写入秒数据00
- sendchar(0x82,0x30); //写入分数据30
- sendchar(0x84,0x16); //写入小时数据16
- sendchar(0x8a,0x02); //写入星期数据2
- sendchar(0x86,0x26); //写入日期数据26
- sendchar(0x88,0x12); //写入月份数据12
- sendchar(0x8c,0x17); //写入年份数据17
- sendchar(0x8e,0x80); //DS1302加写保护
- }
- TMOD = 0x12; //设置定时器工作模式0001 0010(T1为方式1-16位定时器/计数器 T2为方式2-8位初值自动重装的8位定时器/计数器)
- TR1 = 1; //启动定时器/计数器1
- TR0 = 1; //启动定时器/计数器0
- while(1) //大循环
- {
- readtime(); //先读一下时间然后再判断自动补偿程序
- if(fen!=min) //如果fen不等于min证明过了1分钟了
- {
- fen=min; //那么再让fen等于min
- tz++; //tz自加1
- }
- if((tz==38)&(sce>=01)) //如果计时到了38分钟和秒钟过了1秒的时候
- {
- tz=0; //tz清零
- sendchar(0x8e,0); //去DS1302写保护
- sendchar(0x80,0x00); //秒清0--即减去1秒或者加1秒再这里修改
- sendchar(0x8e,0x80); //加写保护
- }
- if(!S2) //检测设置按键S2是否按下
- s2 = jianpan(S2); //若S2被按下则扫描键盘扫描程序S2
- if(!S3) //检测减数据按键S3是否被按下
- s3 = jianpan(S3); //若S3被按下则扫描键盘扫描程序S3
- if(!S4) //检测加数据按键S4是否被按下
- s4 = jianpan(S4); //若S4被按下则扫描键盘扫描程序S4
- TRST = 0; /* DS1302实时时钟的复位/片选线引脚(第5脚RST低电平复位高电平时芯片正常工作)*/
- /*以下是开始年月日自动归零的问题修改,问题产生原因是开始没有加!setbit这个条件,程序在运行到设置年月日时依然会进
- 入下面这个判断,然后再进入设置,但是年月日在这里还没有读数,所以这里的设置就会进入M=0然后加或减,从而让设置值
- 出现错误
- */
- if((!ya&(!setbit)&(!s3))|(setbit&(sdat<4)))//如果S2没有被按下且不在显示年月日的延时范围,而且设置标识为0时,或者在标识为1但是设置值在123中时,则正常显示时间格式
- {
- readtime(); //先读一下时间然后再判断设置程序,这样的主要目的是让初m的值由1302决定。
- ReadTemp(); //读取DS18B20当前温度
- if(s2|setbit) //按下S2或设置标识打开时会进入本判断
- {
- ya = 0; //进设置后会关闭日期显示延时
- settime(); //设置时间日期子程序
- }
- else //正常显示时间和温度
- {
- if((sce%5)!=0) //如果秒对5求余不等于0的时候显示时间--即温度和时间间歇显示,时间显示比温度显示长
- {
- displaychar1[0] = duan[hour/16]; //正常显示小时十位
- displaychar1[1] = duan[hour%16]; //正常显示小时个位
- displaychar1[2] = duan[10]; //正常显示"-"
- displaychar1[3] = duan[min/16]; //正常显示分钟十位
- displaychar1[4] = duan[min%16]; //正常显示分钟个位
- displaychar1[5] = duan[10]; //正常显示"-"
- displaychar1[6] = duan[sce/16]; //正常显示秒钟十位
- displaychar1[7] = duan[sce%16]; //正常显示秒钟个位
- }
- else //否则显示温度
- {
- DS18b20display(); //温度显示子程序
- }
- }//正常显示时间和温度数据包含的大括号
- }//如果S2没有被按下且不在显示年月日的延时范围,而且设置标识为0时,或者在标识为1但是设置值在123中时,则正常显示时间格式包含的大括号
- if(((!setbit)&s3)|ya>0|(setbit&sdat>3))
- {
- if(TF1&!setbit) //如果定时器1计满溢出或设置标识打开时会进入本判断
- {
- ya++; //非设置页面才进去日期延时
- TF1 = 0; //定时器1溢出标志清0(溢出时TF1被硬件置1,并且申请中断,软件查询到该位置1后需用软件清零)
- }
- readyear(); //读取年月日数据
- if(s2|setbit) //如果按下S2或设置标识打开时会进入本判断
- {
- ya = 0; //进设置后会关闭日期显示延时
- settime(); //设置时间日期子程序
- }
- displaychar1[0] = duan[2]; //显示年月日 固定显示2
- displaychar1[1] = duan[0]; //显示年月日 固定显示0
- displaychar1[2] = duan[year/16]; //显示年份十位
- displaychar1[3] = duan[year%16]&0x7f; //显示年份个位****&0x7f是让这一位显示出小数点,共阴数码管就是或0x80或者是+0x80
- displaychar1[4] = duan[month/16]; //显示月份十位
- displaychar1[5] = duan[month%16]&0x7f; //显示月份个位****&0x7f是让这一位显示出小数点,共阴数码管就是或0x80或者是+0x80
- displaychar1[6] = duan[date/16]; //显示日期十位
- displaychar1[7] = duan[date%16]; //显示日期个位
- if(ya>70) ya =0; //日期延时约6秒,大约时间,与计时器和程序的运行有关
- }
- s3 = s4 =0;
- if(S2==S3==S4==1) //松手检测 如果三个按键都没有被按下
- {
- ja = 0;
- TR0 = 1; //启动定时器0
- s2= s3= s4= 0; //松开按键后恢复计时器并清零按键值
- //s=0; //为快速跳时,s清零放在松手检测中,s3和s4在按下不放后会重复跳值,想要每次按下只起作用一次,请将s放在本循环外面这个循环后面
- } //
- s = 0;
- for(a=0; a<50;a++) //一个循环显示50次数码管
- display();
- }//while包含的大括号
- }
复制代码
|