完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
本帖最后由 wosen886 于 2019-6-14 12:09 编辑
ds18b20和ds1302分别单独在1602上显示都能够显示出来,当我将两个程序结合起来时就会出现温度显示乱码的情况,这是一个什么问题引起的呢? 代码: #include "reg52.h" #include "lcd.h" #include "ds1302.h" #include "bluetooth.h" #include "temp.h" typedef unsigned int u16; //对数据类型进行声明定义 typedef unsigned char u8; bit flag200ms = 0; u8 T0RH = 0; u8 T0RL = 0; u8 datas[5]; u8 idata strb[17] = {"TEP: . C "}; char num=0; u8 DisplayData[8]; u8 code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; ***it K1=P3^1; ***it K2=P3^0; ***it K3=P3^2; ***it K4=P3^3; ***it led=P2^0; ***it IFR=P1^0; ***it LSA=P2^2; ***it LSB=P2^3; ***it LSC=P2^4; void delay(u16 i); void Configtimer0(unsigned int ms); void strtemp(int temp); void UsartConfiguration(); void LcdDisplay(int temp); void datapros(int temp); void DigDisplay(); void main() { u8 psec = 0xAA; u8 i; u16 n; u8 flag = 0; u8 c0,c1,c2,c3; u8 d0,d1,d2,d3,d4,d5; u8 e0,e1,e2,e3; u8 IFRchoice = 0; u8 setplace = 0; u8 idata stra[17] = {" : / / "}; u8 idata strc[17] = {" : SETTIME"}; u8 idata strd[17] = {"K3:BACK K4:OK"}; u8 idata stre[17] = {" / / SETDATE"}; u8 idata strf[17] = {"K3:SETDATE K4:OK"}; u8 idata strg[17] = {" s TIMING"}; u8 idata strh[17] = {"K3:0K K4:RESET"}; u8 idata stri[17] = {"TOUCH:ON SET"}; u8 idata strj[17] = {"K3:BACK "}; u16 count = 0; u16 reg0 = 0; // u8 count0,count1,count2,count3; EA = 1; ConfigTimer0(1); Ds1302Init(); //初始化DS1302 LcdInit(); //初始化lcd BlueToothInit(); //初始化蓝牙 while(1) { datapros(Ds18b20ReadTemp()); //数据处理函数 DigDisplay();//数码管显示函数 if(flag200ms) //每200ms读取一次时间 { flag200ms = 0; Ds1302ReadTime(); //把1302中的数据读取到TIME[]中 if(psec != TIME[0]) //判断ds1302有没有更新 { //lcd第一层 count++; stra[0] = (TIME[2]>>4) + '0'; stra[1] = (TIME[2]&0X0F) + '0'; //时 stra[3] = (TIME[1]>>4) + '0'; stra[4] = (TIME[1]&0X0F) + '0'; //分 // stra[6] = (TIME[0]>>4) + '0'; // stra[7] = (TIME[0]&0X0F) + '0'; //秒 stra[8] = (TIME[6]>>4) + '0'; stra[9] = (TIME[6]&0X0F) + '0'; //年 stra[11] = (TIME[4]>>4) + '0'; stra[12] = (TIME[4]&0X0F) + '0'; //月 stra[14] = (TIME[3]>>4) + '0'; stra[15] = (TIME[3]&0X0F) + '0'; //日 psec = TIME[0]; } } if(flag == 0) { LcdWriteCom(0x80); for(i=0;i<16;i++) { LcdWriteData(stra); } } if (K3 == 0) //K3进入设置 { flag++; if(flag == 3) { flag = 0; } setplace = 0; while(K3==0) // 检测是否被按下 { delay(10); } } if(flag == 0) { LcdDisplay(Ds18b20ReadTemp()); LcdWriteCom(0x80+0x40); strb[5] = '0' + datas[0]; strb[6] = '0' + datas[1]; strb[7] = '0' + datas[2]; strb[9] = '0' + datas[3]; strb[10] = '0' + datas[4]; for (i = 0; i < 16; i++) { LcdWriteData(strb); //strb[17] = {"K3:SET "}; } } else if (flag == 1) //如果K3被按下,进入设置 { if (K2 == 0) //K2用于选择位 { setplace++; //setplace初值为0 if (setplace == 4) { setplace = 0; } } if (K1 == 0) { switch(setplace) { case 0:c0++; if (c0 == 3) { c0 = 0; }break; case 1:c1++; if(c0 == 2 && c1 == 4) { c1 = 0; } if (c0<2 && c1 == 10) { c1 = 0; }break; case 2:c2++; if (c2 == 6) { c2 = 0; }break; case 3:c3++; if (c3 == 10) { c3 = 0; }break; } } LcdWriteCom(0x80); strc[0] = c0 + '0'; //时 strc[1] = c1 + '0'; strc[3] = c2 + '0'; //分 strc[4] = c3 + '0'; // strc[6] = c4 + '0'; //秒 // strc[7] = c5 + '0'; for (i = 0; i < 16; i++) { LcdWriteData(strc); } LcdWriteCom(0x80+0x40); for (i = 0; i < 16; i++) { LcdWriteData(strf); // strd[17] = {"K3:BACK K4:OK"}; } TIME[2] = (c0*10+c1)+(c0*10+c1)/10*6; //时 TIME[1] = (c2*10+c3)+(c2*10+c3)/10*6; //分 // TIME[0] = (c4*10+c5)+(c4*10+c5)/10*6; //秒 if(K4 == 0) { Ds1302Write(0x8E,0X00); //关闭写保护功能 for (n=0; n<7; n++) //写入7个字节的时钟信号:分秒时日月周年 { Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]); } Ds1302Write(0x8E,0x80); //打开写保护功能 flag = 0; setplace = 0; } } //设置时间DATA if(flag == 2) { if (K2 == 0) //K2用于选择位 { setplace++; //setplace初值为0 if (setplace == 6) { setplace = 0; } } if (K1 == 0) //K1用于加1 { switch(setplace) { case 0:d0++; if (d0 == 10) { d0 = 0; }break; case 1:d1++; if(d1 == 10) { d1 = 0; }break; case 2:d2++; if (d2 == 2) { d2 = 0; }break; case 3:d3++; if (d2 == 0 && d3 == 10) { d3 = 0; } if(d2 == 1 && d3 == 3 ) { d3 = 0; }break; case 4:d4++; if (d4 == 4) { d4 = 0; }break; case 5:d5++; if(d4<=2 && d5 == 10) { d5 = 0; } if(d4==3 && d5 == 2) { d5 = 0; }break; } } LcdWriteCom(0x80); stre[0] = d0 + '0'; //年 stre[1] = d1 + '0'; stre[3] = d2 + '0'; //月 stre[4] = d3 + '0'; stre[6] = d4 + '0'; //日 stre[7] = d5 + '0'; for (i = 0; i < 16; i++) { LcdWriteData(stre); } LcdWriteCom(0x80+0x40); for (i = 0; i < 16; i++) { LcdWriteData(strd); // strd[17] = {"K3:BACK K4:OK"}; } TIME[6] = (d0*10+d1)+(d0*10+d1)/10*6; //年 TIME[4] = (d2*10+d3)+(d2*10+d3)/10*6; //月 TIME[3] = (d4*10+d5)+(d4*10+d5)/10*6; //日 if(K4 == 0) { Ds1302Write(0x8E,0X00); //关闭写保护功能 for (n=0; n<7; n++) //写入7个字节的时钟信号:分秒时日月周年 { Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]); } Ds1302Write(0x8E,0x80); //打开写保护功能 flag = 0; setplace = 0; } } //设置定时 if (K2 == 0 && flag == 0) { flag = 3; while(K2 == 0) { delay(10); } } if (flag == 3) { if (K1 == 0) { n++; } if (K2 == 0) { n--; } if (K4 == 0) //清零 { n = 0; } if(n > 9999) { n = 0; } e0 = n/1000; e1 = n/100%10; e2 = n/10%10; e3 = n%10; strg[0] = e0 + '0'; strg[1] = e1 + '0'; strg[2] = e2 + '0'; strg[3] = e3 + '0'; LcdWriteCom(0x80); for(i=0;i<16;i++) { LcdWriteData(strg); //strg[17] = {" s TIMING"}; } LcdWriteCom(0x80 + 0x40); for(i=0;i<16;i++) { LcdWriteData(strh); //strh[17] = {"K3:0K K4:RESET"}; } if (K3 == 0) //确认(返回) { flag = 0; count = 0; reg0 = n; n = 0; while(K3 == 0) { delay(10); } } } if (flag == 0 && K1 == 0) { flag = 4; while(K1 == 0) { delay(10); } } if (flag == 4) { if (K1 == 0) { IFRchoice = 1; } if (K2 == 0) { IFRchoice = 0; } switch(IFRchoice) { case 1: stri[6] = 'O'; stri[7] = 'N'; stri[8] = ' ';break; case 0: stri[6] = 'O'; stri[7] = 'F'; stri[8] = 'F';break; } LcdWriteCom(0x80); for(i=0;i<16;i++) { LcdWriteData(stri); } LcdWriteCom(0x80+0x40); for(i=0;i<16;i++) { LcdWriteData(strj); } if (K3 == 0) { flag = 0; while(K3 == 0) { delay(10); } } } if(reg0>=1) { if(reg0 == count) { led = 0; } } if(flag == 0) //按K4关被控对象 { if(K4 == 0) { led = 1; } } } } void LcdDisplay(int temp) { float tp; if(temp< 0) //当温度值为负数 { strb[4]='-'; //因为读取的温度是实际温度的补码,所以减1,再取反求出原码 temp=temp-1; temp=~temp; tp=temp; temp=tp*0.0625*100+0.5; } else { strb[4]='+'; tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量 //如果温度是正的那么,那么正数的原码就是补码它本身 temp=tp*0.0625*100+0.5; //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点 //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就 //算加上0.5,还是在小数点后面。 } datas[0] = temp / 10000; datas[1] = temp % 10000 / 1000; datas[2] = temp % 1000 / 100; datas[3] = temp % 100 / 10; datas[4] = temp % 10; } /*配置并启动T0,ms-T0定时时间*/ void ConfigTimer0(unsigned int ms) { unsigned long tmp; tmp = 11059200/12; tmp = (tmp*ms)/1000; tmp = 65536 - tmp; tmp = tmp + 12; T0RH = (unsigned char)(tmp>>8); T0RL = (unsigned char)tmp; TMOD&=0XF0; TMOD|=0X01; TH0 = T0RH; TL0 = T0RL; ET0 = 1; TR0 = 1; } void InterruptTimer0() interrupt 1 { static unsigned char tmr200ms = 0; TH0 = T0RH; TL0 = T0RL; tmr200ms++; if (tmr200ms >= 200) { tmr200ms = 0; flag200ms = 1; } } void delay(u16 i) { while(i--); } void DigDisplay() { u8 i; for(i=0;i<6;i++) { switch(i) //位选,选择点亮的数码管, { case(0): LSA=0;LSB=0;LSC=0; break;//显示第0位 case(1): LSA=1;LSB=0;LSC=0; break;//显示第1位 case(2): LSA=0;LSB=1;LSC=0; break;//显示第2位 case(3): LSA=1;LSB=1;LSC=0; break;//显示第3位 case(4): LSA=0;LSB=0;LSC=1; break;//显示第4位 case(5): LSA=1;LSB=0;LSC=1; break;//显示第5位 } P0=DisplayData[5-i];//发送数据 delay(100); //间隔一段时间扫描 P0=0x00;//消隐 } } void datapros(int temp) { float tp; if(temp< 0) //当温度值为负数 { DisplayData[0] = 0x40; // - //因为读取的温度是实际温度的补码,所以减1,再取反求出原码 temp=temp-1; temp=~temp; tp=temp; temp=tp*0.0625*100+0.5; //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点 //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就 //算加上0.5,还是在小数点后面。 } else { DisplayData[0] = 0x00; tp=temp; temp=tp*0.0625*100+0.5; } DisplayData[1] = smgduan[temp / 10000]; DisplayData[2] = smgduan[temp % 10000 / 1000]; DisplayData[3] = smgduan[temp % 1000 / 100] | 0x80; DisplayData[4] = smgduan[temp % 100 / 10]; DisplayData[5] = smgduan[temp % 10]; } #include"ds1302.h" //---DS1302写入和读取时分秒的地址命令---// //---秒分时日月周年 最低位读写位;-------// uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d}; uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c}; //---DS1302时钟初始化2019年8月26日星期一13点00分00秒。---// //---存储顺序是秒分时日月周年,存储格式是用BCD码---// uchar TIME[7] = {0, 0, 0x13, 0x26, 0x08, 0x01, 0x19}; /******************************************************************************* * 函 数 名 : Ds1302Write * 函数功能 : 向DS1302命令(地址+数据) * 输 入 : addr,dat * 输 出 : 无 *******************************************************************************/ void Ds1302Write(uchar addr, uchar dat) { uchar n; RST = 0; _nop_(); SCLK = 0;//先将SCLK置低电平。 _nop_(); RST = 1; //然后将RST(CE)置高电平。 _nop_(); for (n=0; n<8; n++)//开始传送八位地址命令 { DSIO = addr & 0x01;//数据从低位开始传送 addr >>= 1; SCLK = 1;//数据在上升沿时,DS1302读取数据 _nop_(); SCLK = 0; _nop_(); } for (n=0; n<8; n++)//写入8位数据 { DSIO = dat & 0x01; dat >>= 1; SCLK = 1;//数据在上升沿时,DS1302读取数据 _nop_(); SCLK = 0; _nop_(); } RST = 0;//传送数据结束 _nop_(); } /******************************************************************************* * 函 数 名 : Ds1302Read * 函数功能 : 读取一个地址的数据 * 输 入 : addr * 输 出 : dat *******************************************************************************/ uchar Ds1302Read(uchar addr) { uchar n,dat,dat1; RST = 0; _nop_(); SCLK = 0;//先将SCLK置低电平。 _nop_(); RST = 1;//然后将RST(CE)置高电平。 _nop_(); for(n=0; n<8; n++)//开始传送八位地址命令 { DSIO = addr & 0x01;//数据从低位开始传送 addr >>= 1; SCLK = 1;//数据在上升沿时,DS1302读取数据 _nop_(); SCLK = 0;//DS1302下降沿时,放置数据 _nop_(); } _nop_(); for(n=0; n<8; n++)//读取8位数据 { dat1 = DSIO;//从最低位开始接收 dat = (dat>>1) | (dat1<<7); SCLK = 1; _nop_(); SCLK = 0;//DS1302下降沿时,放置数据 _nop_(); } //RST = 0; _nop_(); //以下为DS1302复位的稳定时间,必须的。 SCLK = 1; _nop_(); DSIO = 0; _nop_(); DSIO = 1; _nop_(); return dat; } /******************************************************************************* * 函 数 名 : Ds1302Init * 函数功能 : 初始化DS1302. * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void Ds1302Init() { uchar n; Ds1302Write(0x8E,0X00); //禁止写保护,就是关闭写保护功能 for (n=0; n<7; n++)//写入7个字节的时钟信号:分秒时日月周年 { Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]); } Ds1302Write(0x8E,0x80); //打开写保护功能 } /******************************************************************************* * 函 数 名 : Ds1302ReadTime * 函数功能 : 读取时钟信息 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void Ds1302ReadTime() { uchar n; for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年 { TIME[n] = Ds1302Read(READ_RTC_ADDR[n]); } } #include"temp.h" /******************************************************************************* * 函 数 名 : Delay1ms * 函数功能 : 延时函数 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void Delay1ms(uint y) { uint x; for( ; y>0; y--) { for(x=110; x>0; x--); } } /******************************************************************************* * 函 数 名 : Ds18b20Init * 函数功能 : 初始化 * 输 入 : 无 * 输 出 : 初始化成功返回1,失败返回0 *******************************************************************************/ uchar Ds18b20Init() { uchar i; DSPORT = 0; //将总线拉低480us~960us i = 70; while(i--);//延时642us DSPORT = 1; //然后拉高总线,如果DS18B20做出反应会将在15us~60us后总线拉低 i = 0; while(DSPORT) //等待DS18B20拉低总线 { Delay1ms(1); i++; if(i>5)//等待>5MS { return 0;//初始化失败 } } return 1;//初始化成功 } /******************************************************************************* * 函 数 名 : Ds18b20WriteByte * 函数功能 : 向18B20写入一个字节 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void Ds18b20WriteByte(uchar dat) { uint i, j; for(j=0; j<8; j++) { DSPORT = 0; //每写入一位数据之前先把总线拉低1us i++; DSPORT = dat & 0x01; //然后写入一个数据,从最低位开始 i=6; while(i--); //延时68us,持续时间最少60us DSPORT = 1; //然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值 dat >>= 1; } } /******************************************************************************* * 函 数 名 : Ds18b20ReadByte * 函数功能 : 读取一个字节 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ uchar Ds18b20ReadByte() { uchar byte, bi; uint i, j; for(j=8; j>0; j--) { DSPORT = 0;//先将总线拉低1us i++; DSPORT = 1;//然后释放总线 i++; i++;//延时6us等待数据稳定 bi = DSPORT; //读取数据,从最低位开始读取 /*将byte左移一位,然后与上右移7位后的bi,注意移动之后移掉那位补0。*/ byte = (byte >> 1) | (bi << 7); i = 4; //读取完之后等待48us再接着读取下一个数 while(i--); } return byte; } /******************************************************************************* * 函 数 名 : Ds18b20ChangTemp * 函数功能 : 让18b20开始转换温度 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void Ds18b20ChangTemp() { Ds18b20Init(); Delay1ms(1); Ds18b20WriteByte(0xcc); //跳过ROM操作命令 Ds18b20WriteByte(0x44); //温度转换命令 //Delay1ms(100); //等待转换成功,而如果你是一直刷着的话,就不用这个延时了 } /******************************************************************************* * 函 数 名 : Ds18b20ReadTempCom * 函数功能 : 发送读取温度命令 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void Ds18b20ReadTempCom() { Ds18b20Init(); Delay1ms(1); Ds18b20WriteByte(0xcc); //跳过ROM操作命令 Ds18b20WriteByte(0xbe); //发送读取温度命令 } /******************************************************************************* * 函 数 名 : Ds18b20ReadTemp * 函数功能 : 读取温度 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ int Ds18b20ReadTemp() { int temp = 0; uchar tmh, tml; Ds18b20ChangTemp(); //先写入转换命令 Ds18b20ReadTempCom(); //然后等待转换完后发送读取温度命令 tml = Ds18b20ReadByte(); //读取温度值共16位,先读低字节 tmh = Ds18b20ReadByte(); //再读高字节 temp = tmh; temp <<= 8; temp |= tml; return temp; } |
|
相关推荐
2 条评论
3个回答
|
|
你需要把程序的模块化做好一些,主程序里的按键处理最好能做成一个子程序,主程序里过多的使用同一个标志flag,不论是按键,还是显示判断都是这个标志,会容易混乱的。既然1302和18b20单独显示都没问题,那么问题就在主程序的合并上了,最好先去除按键处理,只做1302和18b20两部分的显示
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
【每周推荐】采用11代Intel CPU,基于youyeetoo X1开发板搭建少儿AI智能STEAM积木平台
776 浏览 0 评论
2265 浏览 2 评论
【youyeetoo X1 windows 开发板体验】+ 影音处理和AI模型移植
2124 浏览 5 评论
I.MX6ULL-飞凌 ElfBoard ELF1板卡- 移植zbar的方法
1682 浏览 0 评论
2786 浏览 3 评论
【youyeetoo X1 windows 开发板体验】少儿AI智能STEAM积木平台
5539 浏览 31 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-4-20 04:48 , Processed in 1.035609 second(s), Total 72, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号