![]() |
發(fā)布時間: 2019-6-26 10:26
正文摘要:#include<reg51.h> #include<intrins.h> #include <ctype.h> #include <stdlib.h> #define LCD_DATA P0 sbit LCD_RS = P2^0; sbi ... |
仿真是以AT8051的12T指令運行的 STC89C52是6T指令 所有用到延時的延時時間要*2,定時器可以不用改 |
現(xiàn)在仿真可以了,但是同樣代碼在硬件上不行 |
青青梓衿 發(fā)表于 2019-6-26 14:32 仿真可以讀出來溫度,但是一燒到單片機上就不行了,單片機是STC89C52 |
DS18B20 讀時序要求特別高,用實際硬件來調(diào)調(diào)吧,否則都用定時器 |
先占個位置學習 |
如果你用的是12M的晶振就把復位里的低電平延時30改成70以上 |
我這個例程是使用過的,沒有問題。 有程序main.c: /******************************************************************************* * 實驗名 :溫度顯示實驗 * 使用的IO : * 實驗效果 :1602顯示溫度 * 注意 : *******************************************************************************/ #include<reg51.h> #include"temp.h" //數(shù)碼管IO #define DIG P0 sbit LSA=P2^2; sbit LSB=P2^3; sbit LSC=P2^4; unsigned char code DIG_CODE[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; unsigned char Num=0; unsigned int disp[8]={0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f}; void LcdDisplay(int); void Timer0Configuration(); /******************************************************************************* * 函數(shù)名 : main * 函數(shù)功能 : 主函數(shù) * 輸入 : 無 * 輸出 : 無 *******************************************************************************/ void main() { Timer0Configuration(); while(1) { LcdDisplay(Ds18b20ReadTemp()); } } /******************************************************************************* * 函數(shù)名 : LcdDisplay() * 函數(shù)功能 : LCD顯示讀取到的溫度 * 輸入 : v * 輸出 : 無 *******************************************************************************/ void LcdDisplay(int temp) //lcd顯示 { unsigned char datas[] = {0, 0, 0, 0, 0}; //定義數(shù)組 float tp; if(temp< 0) //當溫度值為負數(shù) { disp[2] = 0x40; //因為讀取的溫度是實際溫度的補碼,所以減1,再取反求出原碼 temp=temp-1; temp=~temp; tp=temp; temp=tp*0.0625*100+0.5; //留兩個小數(shù)點就*100,+0.5是四舍五入,因為C語言浮點數(shù)轉(zhuǎn)換為整型的時候把小數(shù)點 //后面的數(shù)自動去掉,不管是否大于0.5,而+0.5之后大于0.5的就是進1了,小于0.5的就 //算加上.5,還是在小數(shù)點后面。 } else { disp[2] = 0; tp=temp;//因為數(shù)據(jù)處理有小數(shù)點所以將溫度賦給一個浮點型變量 //如果溫度是正的那么,那么正數(shù)的原碼就是補碼它本身 temp=tp*0.0625*100+0.5; //留兩個小數(shù)點就*100,+0.5是四舍五入,因為C語言浮點數(shù)轉(zhuǎn)換為整型的時候把小數(shù)點 //后面的數(shù)自動去掉,不管是否大于0.5,而+0.5之后大于0.5的就是進1了,小于0.5的就 //算加上0.5,還是在小數(shù)點后面。 } // disp[0] = 0; // disp[1] = 0; // disp[3] = DIG_CODE[temp / 10000]; disp[4] = DIG_CODE[temp % 10000 / 1000]; disp[5] = DIG_CODE[temp % 1000 / 100] | 0x80; disp[6] = DIG_CODE[temp % 100 / 10]; disp[7] = DIG_CODE[temp % 10]; } /******************************************************************************* * 函數(shù)名 : Timer0Configuration() * 函數(shù)功能 : 設置計時器 * 輸入 : 無 * 輸出 : 無 *******************************************************************************/ void Timer0Configuration() { TMOD=0X02;//選擇為定時器模式,工作方式2,僅用TRX打開啟動。 TH0=0X9C; //給定時器賦初值,定時100us TL0=0X9C; ET0=1;//打開定時器0中斷允許 EA=1;//打開總中斷 TR0=1;//打開定時器 } /******************************************************************************* * 函數(shù)名 : DigDisplay() interrupt 1 * 函數(shù)功能 : 中斷數(shù)碼管顯示 * 輸入 : 無 * 輸出 : 無 *******************************************************************************/ void DigDisplay() interrupt 1 { //定時器在工作方式二會自動重裝初,所以不用在賦值。 // TH0=0X9c;//給定時器賦初值,定時1ms // TL0=0X00; DIG=0; //消隱 switch(Num) //位選,選擇點亮的數(shù)碼管, { case(7): LSA=0;LSB=0;LSC=0; break; case(6): LSA=1;LSB=0;LSC=0; break; case(5): LSA=0;LSB=1;LSC=0; break; case(4): LSA=1;LSB=1;LSC=0; break; // case(3): // LSA=0;LSB=0;LSC=1; break; // case(2): // LSA=1;LSB=0;LSC=1; break; // case(1): // LSA=0;LSB=1;LSC=1; break; // case(0): // LSA=1;LSB=1;LSC=1; break; } DIG=disp[Num]; //段選,選擇顯示的數(shù)字。 Num++; if(Num>7) Num=4; } 溫度讀取程序temp.c: #include"temp.h" /******************************************************************************* * 函數(shù)名 : Delay1ms * 函數(shù)功能 : 延時函數(shù) * 輸入 : 無 * 輸出 : 無 *******************************************************************************/ void Delay1ms(unsigned int y) { unsigned int x; for(y;y>0;y--) for(x=110;x>0;x--); } /******************************************************************************* * 函數(shù)名 : Ds18b20Init * 函數(shù)功能 : 初始化 * 輸入 : 無 * 輸出 : 初始化成功返回1,失敗返回0 *******************************************************************************/ unsigned char Ds18b20Init() { unsigned int i; EA = 0; DSPORT=0; //將總線拉低480us~960us i=70; while(i--);//延時642us DSPORT=1; //然后拉高總線,如果DS18B20做出反應會將在15us~60us后總線拉低 i=0; EA = 1; while(DSPORT) //等待DS18B20拉低總線 { i++; if(i>5000)//等待>5MS return 0;//初始化失敗 } return 1;//初始化成功 } /******************************************************************************* * 函數(shù)名 : Ds18b20WriteByte * 函數(shù)功能 : 向18B20寫入一個字節(jié) * 輸入 : com * 輸出 : 無 *******************************************************************************/ void Ds18b20WriteByte(unsigned char dat) { unsigned int i,j; EA = 0; for(j=0;j<8;j++) { DSPORT=0; //每寫入一位數(shù)據(jù)之前先把總線拉低1us i++; DSPORT=dat&0x01; //然后寫入一個數(shù)據(jù),從最低位開始 i=6; while(i--); //延時68us,持續(xù)時間最少60us DSPORT=1; //然后釋放總線,至少1us給總線恢復時間才能接著寫入第二個數(shù)值 dat>>=1; } EA = 1; } /******************************************************************************* * 函數(shù)名 : Ds18b20ReadByte * 函數(shù)功能 : 讀取一個字節(jié) * 輸入 : com * 輸出 : 無 *******************************************************************************/ unsigned char Ds18b20ReadByte() { unsigned char byte,bi; unsigned int i,j; EA = 0; for(j=8;j>0;j--) { DSPORT=0;//先將總線拉低1us i++; DSPORT=1;//然后釋放總線 i++; i++;//延時6us等待數(shù)據(jù)穩(wěn)定 bi=DSPORT; //讀取數(shù)據(jù),從最低位開始讀取 /*將byte左移一位,然后與上右移7位后的bi,注意移動之后移掉那位補0。*/ byte=(byte>>1)|(bi<<7); // i=4; //讀取完之后等待48us再接著讀取下一個數(shù) // while(i--); } EA = 1; return byte; } /******************************************************************************* * 函數(shù)名 : Ds18b20ChangTemp * 函數(shù)功能 : 讓18b20開始轉(zhuǎn)換溫度 * 輸入 : com * 輸出 : 無 *******************************************************************************/ void Ds18b20ChangTemp() { Ds18b20Init(); Delay1ms(1); Ds18b20WriteByte(0xcc); //跳過ROM操作命令 Ds18b20WriteByte(0x44); //溫度轉(zhuǎn)換命令 // Delay1ms(100); //等待轉(zhuǎn)換成功,而如果你是一直刷著的話,就不用這個延時了 } /******************************************************************************* * 函數(shù)名 : Ds18b20ReadTempCom * 函數(shù)功能 : 發(fā)送讀取溫度命令 * 輸入 : com * 輸出 : 無 *******************************************************************************/ void Ds18b20ReadTempCom() { Ds18b20Init(); Delay1ms(1); Ds18b20WriteByte(0xcc); //跳過ROM操作命令 Ds18b20WriteByte(0xbe); //發(fā)送讀取溫度命令 } /******************************************************************************* * 函數(shù)名 : Ds18b20ReadTemp * 函數(shù)功能 : 讀取溫度 * 輸入 : com * 輸出 : 無 *******************************************************************************/ int Ds18b20ReadTemp() { int temp=0; unsigned char tmh,tml; Ds18b20ChangTemp(); //先寫入轉(zhuǎn)換命令 Ds18b20ReadTempCom(); //然后等待轉(zhuǎn)換完后發(fā)送讀取溫度命令 tml=Ds18b20ReadByte(); //讀取溫度值共16位,先讀低字節(jié) tmh=Ds18b20ReadByte(); //再讀高字節(jié) temp=tmh; temp<<=8; temp|=tml; return temp; } 溫度讀取頭文件temo.h: #ifndef __TEMP_H_ #define __TEMP_H_ #include<reg51.h> sbit DSPORT=P3^7; void Delay1ms(unsigned int ); unsigned char Ds18b20Init(); void Ds18b20WriteByte(unsigned char com); unsigned char Ds18b20ReadByte(); void Ds18b20ChangTemp(); void Ds18b20ReadTempCom(); int Ds18b20ReadTemp(); #endif 適用電路: ![]() ![]() ![]() |
Powered by 單片機教程網(wǎng)