仿真的实验现象图已经放在后面了,大佬帮我看看问题啊 现在就是LCD显示的温度和实际模拟温度不一致, /**************************************************/ #include<reg51.h> #include<intrins.h> #define uchar unsigned char #define uint unsigned int #define delayNop(); {_nop_();_nop_();_nop_();_nop_();}; uchar code table[]=" ERROR!!! "; uchar code table1[]="xianzaiwendu "; uchar code table2[]="Temp= . Cent"; uchar code table3[10]="0123456789"; sbit lcd_rs=P1^0; //sbit lcd_rw=P1^1; sbit lcd_en=P2^5; sbit DQ=P2^2; uchar num,time; void delay(uint t) { unsigned char n; while(t--) { for(n = 0; n<250; n++) { _nop_(); _nop_(); _nop_(); _nop_(); } } } void write_com(uchar com) //写命令 { ////lcd_rw=0; //delay(5); lcd_rs=0; lcd_en=0; _nop_(); _nop_(); P0=com; delayNop(); lcd_en=1; delay(1); lcd_en=0; } void write_date(uchar date) //写数据 { //lcd_rw=0; // delay(5); lcd_rs=1; lcd_en=0; _nop_(); _nop_(); P0=date; delayNop(); lcd_en=1; delay(1); lcd_en=0; } void init() //初始化函数 { // dula=0; // wela=0; lcd_en=0; //可以试试不加这一句看结果怎样 write_com(0x38); write_com(0x0c); write_com(0x06); write_com(0x01); } uchar init_DS18bB20() { bit flag; DQ=1; //人为拉高 for(time=0;time<2;time++); //稍微延时6US; DQ=0; //认为拉低 for(time=0;time<200;time++); //延时600US给单片机检测 DQ=1; //被上拉电阻拉高 (仿真里面没有上拉,有没有都需要人为拉高) for(time=0;time<20;time++); // 延时60US检测 flag=DQ; //这时又被DS18B20拉低, for(time=0;time<200;time++); //延时600US检测时间 return flag; //返回0表示存在 } void Write_Byte(uchar dat) //写一个字节,单片机向DS18B20写命令,确定DS18B20的工作方法之类的 { unsigned char i=0; for (i=0; i<8; i++) { DQ =1; // 先将数据线拉高 _nop_(); //等待一个机器周期 DQ=0; //将数据线从高拉低时即启动写时序 DQ=dat&0x01; //利用与运算取出要写的某位二进制数据, //并将其送到数据线上等待DS18B20采样 for(time=0;time<10;time++) ;//延时约30us,DS18B20在拉低后的约15~60us期间从数据线上采样 DQ=1; //释放数据线,也就是被上拉电阻拉高,反正就是要把这个口释放,然后来执行下一个命令 for(time=0;time<1;time++) ;//延时3us,两个写时序间至少需要1us的恢复期 dat>>=1; //将dat中的各二进制位数据右移1位 } for(time=0;time<4;time++) ; //稍作延时,给硬件一点反应时间 } uchar Read_Byte() { uchar i=0; uchar dat;//用来储存读出的一个字节,默认为0 for(i=0;i<8;i++) { DQ=1; _nop_(); DQ=0; //读命令一定得是低电平 dat>>=1; //读取数据是从高位开始读,dat默认是0,也就是0000 0000, // 这是下标是指向最高位的,所以得先右移一位让出一个位置 _nop_(); //需要>1US; DQ=1; //又被上拉电阻拉高 for(time=0;time<2;time++); if(DQ==1) //由DQ发送的信号来决定,发送的是高电平还是低电平 dat|=0x80; //高电平就或0x80,1000 0000 else dat|=0x00; //低电平就或,0x00 for(time=0;time<5;time++);//延时10US左右,因为需要在15US内完成读取 } return dat; } void Readyread()//做好读温度准备。。。。可以加在主函数里面,但是分出来比较清晰明了 { init_DS18bB20(); Write_Byte(0xcc); //跳过读序号 Write_Byte(0x44); //启动温度转换 for(time=0;time<100;time++); init_DS18bB20(); //再初始化一下 Write_Byte(0xcc); //跳过读序号 Write_Byte(0xbe); //都温度寄存器,前两个分别是温度的,低,高位 } void display() //显示第一行说明 { write_com(0x80); for(num=0;num<16;num++) { write_date(table[num]); // delay(1); } while(1); } void display1() //显示第二行说明 { write_com(0x80); for(num=0;num<16;num++) { write_date(table1[num]); // delay(1); } } void display2() { write_com(0x80+0x40); for(num=0;num<16;num++) { write_date(table2[num]); //delay(1); } } void display_temp(uchar x) //显示温度整数部分 { uchar bai,shi,ge; bai=x/100; shi=(x%100)/10; ge=x%10; write_com(0x80+0x46); write_date(table3[bai]); write_date(table3[shi]); write_date(table3[ge]); } void display1_temp(uchar x) //显示温度小数部分 { write_com(0x80+0x4a); write_date(table3[x]); } void main() { uchar TL;//储存暂存器的温度最高位 uchar TH;//储存暂存器的温度最低位 uchar TN; //储存温度整数部分 uchar TD; //储存温度小数部分 init(); if(init_DS18bB20()==1) display(); display1(); display2(); while(1) { Readyread(); TL=Read_Byte(); TH=Read_Byte(); TN=TH*16+TL/16; //实际温度值=(TH*256+TL)/16,即:TH*16+TL/16 //这样得出的是温度的整数部分,小数部分被丢弃了 TD=(TL%16)*10/16; //计算温度的小数部分,将余数乘以10再除以16取整, //这样得到的是温度小数部分的第一位数字(保留1位小数) display_temp(TN); display1_temp(TD); _nop_(); _nop_(); } } |
51hei图片_20191227184425.png (57.36 KB, 下载次数: 75)
欢迎光临 (http://www.51hei.com/bbs/) | Powered by Discuz! X3.1 |