熱門: 51單片機(jī) | 24小時(shí)必答區(qū) | 單片機(jī)教程 | 單片機(jī)DIY制作 | STM32 | Cortex M3 | 模數(shù)電子 | 電子DIY制作 | 音響/功放 | 拆機(jī)樂園 | Arduino | 嵌入式OS | 程序設(shè)計(jì)
![]() |
發(fā)布時(shí)間: 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指令運(yùn)行的 STC89C52是6T指令 所有用到延時(shí)的延時(shí)時(shí)間要*2,定時(shí)器可以不用改 |
現(xiàn)在仿真可以了,但是同樣代碼在硬件上不行 |
青青梓衿 發(fā)表于 2019-6-26 14:32 仿真可以讀出來溫度,但是一燒到單片機(jī)上就不行了,單片機(jī)是STC89C52 |
DS18B20 讀時(shí)序要求特別高,用實(shí)際硬件來調(diào)調(diào)吧,否則都用定時(shí)器 |
先占個(gè)位置學(xué)習(xí) |
如果你用的是12M的晶振就把復(fù)位里的低電平延時(shí)30改成70以上 |
我這個(gè)例程是使用過的,沒有問題。 有程序main.c: /******************************************************************************* * 實(shí)驗(yàn)名 :溫度顯示實(shí)驗(yàn) * 使用的IO : * 實(shí)驗(yàn)效果 :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) //當(dāng)溫度值為負(fù)數(shù) { disp[2] = 0x40; //因?yàn)樽x取的溫度是實(shí)際溫度的補(bǔ)碼,所以減1,再取反求出原碼 temp=temp-1; temp=~temp; tp=temp; temp=tp*0.0625*100+0.5; //留兩個(gè)小數(shù)點(diǎn)就*100,+0.5是四舍五入,因?yàn)镃語(yǔ)言浮點(diǎn)數(shù)轉(zhuǎn)換為整型的時(shí)候把小數(shù)點(diǎn) //后面的數(shù)自動(dòng)去掉,不管是否大于0.5,而+0.5之后大于0.5的就是進(jìn)1了,小于0.5的就 //算加上.5,還是在小數(shù)點(diǎn)后面。 } else { disp[2] = 0; tp=temp;//因?yàn)閿?shù)據(jù)處理有小數(shù)點(diǎn)所以將溫度賦給一個(gè)浮點(diǎn)型變量 //如果溫度是正的那么,那么正數(shù)的原碼就是補(bǔ)碼它本身 temp=tp*0.0625*100+0.5; //留兩個(gè)小數(shù)點(diǎn)就*100,+0.5是四舍五入,因?yàn)镃語(yǔ)言浮點(diǎn)數(shù)轉(zhuǎn)換為整型的時(shí)候把小數(shù)點(diǎn) //后面的數(shù)自動(dòng)去掉,不管是否大于0.5,而+0.5之后大于0.5的就是進(jìn)1了,小于0.5的就 //算加上0.5,還是在小數(shù)點(diǎn)后面。 } // 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ù)功能 : 設(shè)置計(jì)時(shí)器 * 輸入 : 無 * 輸出 : 無 *******************************************************************************/ void Timer0Configuration() { TMOD=0X02;//選擇為定時(shí)器模式,工作方式2,僅用TRX打開啟動(dòng)。 TH0=0X9C; //給定時(shí)器賦初值,定時(shí)100us TL0=0X9C; ET0=1;//打開定時(shí)器0中斷允許 EA=1;//打開總中斷 TR0=1;//打開定時(shí)器 } /******************************************************************************* * 函數(shù)名 : DigDisplay() interrupt 1 * 函數(shù)功能 : 中斷數(shù)碼管顯示 * 輸入 : 無 * 輸出 : 無 *******************************************************************************/ void DigDisplay() interrupt 1 { //定時(shí)器在工作方式二會(huì)自動(dòng)重裝初,所以不用在賦值。 // TH0=0X9c;//給定時(shí)器賦初值,定時(shí)1ms // TL0=0X00; DIG=0; //消隱 switch(Num) //位選,選擇點(diǎn)亮的數(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í)函數(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--);//延時(shí)642us DSPORT=1; //然后拉高總線,如果DS18B20做出反應(yīng)會(huì)將在15us~60us后總線拉低 i=0; EA = 1; while(DSPORT) //等待DS18B20拉低總線 { i++; if(i>5000)//等待>5MS return 0;//初始化失敗 } return 1;//初始化成功 } /******************************************************************************* * 函數(shù)名 : Ds18b20WriteByte * 函數(shù)功能 : 向18B20寫入一個(gè)字節(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; //然后寫入一個(gè)數(shù)據(jù),從最低位開始 i=6; while(i--); //延時(shí)68us,持續(xù)時(shí)間最少60us DSPORT=1; //然后釋放總線,至少1us給總線恢復(fù)時(shí)間才能接著寫入第二個(gè)數(shù)值 dat>>=1; } EA = 1; } /******************************************************************************* * 函數(shù)名 : Ds18b20ReadByte * 函數(shù)功能 : 讀取一個(gè)字節(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++;//延時(shí)6us等待數(shù)據(jù)穩(wěn)定 bi=DSPORT; //讀取數(shù)據(jù),從最低位開始讀取 /*將byte左移一位,然后與上右移7位后的bi,注意移動(dòng)之后移掉那位補(bǔ)0。*/ byte=(byte>>1)|(bi<<7); // i=4; //讀取完之后等待48us再接著讀取下一個(gè)數(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)換成功,而如果你是一直刷著的話,就不用這個(gè)延時(shí)了 } /******************************************************************************* * 函數(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 單片機(jī)教程網(wǎng)