|
樓主的程序基本沒有問題,關(guān)鍵是參考的程序MCU時鐘與樓主選用的不同導(dǎo)致時序誤差而產(chǎn)生讀取錯誤。
無標(biāo)題.jpg (94.81 KB, 下載次數(shù): 57)
下載附件
2019-12-31 10:58 上傳
- #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 DelayUs2x(uchar t)
- {
- while(--t);
- }
- 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) //寫數(shù)據(jù)
- {
- //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() //初始化函數(shù)
- {
- // dula=0;
- // wela=0;
- lcd_en=0; //可以試試不加這一句看結(jié)果怎樣
- write_com(0x38);
- write_com(0x0c);
- write_com(0x06);
- write_com(0x01);
- }
- uchar init_DS18bB20()
- {
- bit flag;
- DQ=1; //人為拉高
- DelayUs2x(5); //稍做延時 //稍微延時6US;
- DQ=0; //認為拉低
- DelayUs2x(200); //精確延時 大于 480us 小于960us
- DelayUs2x(200);
- DQ=1; //被上拉電阻拉高 (仿真里面沒有上拉,有沒有都需要人為拉高)
- DelayUs2x(50); //15~60us 后 接收60-240us的存在脈沖 // 延時60US檢測
- flag=DQ; //這時又被DS18B20拉低,
- DelayUs2x(25); //稍作延時返回 //延時600US檢測時間
- return flag; //返回0表示存在
- }
- void Write_Byte(uchar dat) //寫一個字節(jié),單片機向DS18B20寫命令,確定DS18B20的工作方法之類的
- {
- unsigned char i=0;
- for (i=0; i<8; i++)
- {
- DQ =1; // 先將數(shù)據(jù)線拉高
- _nop_(); //等待一個機器周期
- DQ=0; //將數(shù)據(jù)線從高拉低時即啟動寫時序
- DQ=dat&0x01; //利用與運算取出要寫的某位二進制數(shù)據(jù),
- //并將其送到數(shù)據(jù)線上等待DS18B20采樣
- DelayUs2x(25);
- //延時約30us,DS18B20在拉低后的約15~60us期間從數(shù)據(jù)線上采樣
- DQ=1; //釋放數(shù)據(jù)線,也就是被上拉電阻拉高,反正就是要把這個口釋放,然后來執(zhí)行下一個命令
- // for(time=0;time<1;time++)
- // ;//延時3us,兩個寫時序間至少需要1us的恢復(fù)期
- dat>>=1; //將dat中的各二進制位數(shù)據(jù)右移1位
- }
- DelayUs2x(25);
- //稍作延時,給硬件一點反應(yīng)時間
- }
- uchar Read_Byte()
- {
- uchar i=0;
- uchar dat;//用來儲存讀出的一個字節(jié),默認為0
- for(i=0;i<8;i++)
- {
- DQ=1;
- _nop_();
- DQ=0; //讀命令一定得是低電平
- dat>>=1; //讀取數(shù)據(jù)是從高位開始讀,dat默認是0,也就是0000 0000,
- // 這是下標(biāo)是指向最高位的,所以得先右移一位讓出一個位置
- _nop_(); //需要>1US;
- DQ=1; //又被上拉電阻拉高
- // for(time=0;time<2;time++);
- if(DQ==1) //由DQ發(fā)送的信號來決定,發(fā)送的是高電平還是低電平
- dat|=0x80; //高電平就或0x80,1000 0000
- else
- dat|=0x00; //低電平就或,0x00
- DelayUs2x(25);//延時10US左右,因為需要在15US內(nèi)完成讀取
- }
- return dat;
- }
- void Readyread()//做好讀溫度準(zhǔn)備。。。。可以加在主函數(shù)里面,但是分出來比較清晰明了
- {
- init_DS18bB20();
- Write_Byte(0xcc); //跳過讀序號
- Write_Byte(0x44); //啟動溫度轉(zhuǎn)換
- 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) //顯示溫度整數(shù)部分
- {
- 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) //顯示溫度小數(shù)部分
- {
- write_com(0x80+0x4a);
- write_date(table3[x]);
- }
- void main()
- {
- uchar TL;//儲存暫存器的溫度最高位
- uchar TH;//儲存暫存器的溫度最低位
- uchar TN; //儲存溫度整數(shù)部分
- uchar TD; //儲存溫度小數(shù)部分
- 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
- //這樣得出的是溫度的整數(shù)部分,小數(shù)部分被丟棄了
- TD=(TL%16)*10/16; //計算溫度的小數(shù)部分,將余數(shù)乘以10再除以16取整,
- //這樣得到的是溫度小數(shù)部分的第一位數(shù)字(保留1位小數(shù))
-
- display_temp(TN);
- display1_temp(TD);
- _nop_(); _nop_();
- }
- }
復(fù)制代碼
|
|