大家好!我自己動手做了一個數(shù)字溫度計(jì)。用的是STC12C2052AD單片機(jī),而溫度傳感器用的是DS18B20,12M晶振,用C語言寫(移植)的程序,但是現(xiàn)在溫度可以測出來,只是顯示有時是對的,有是錯的。規(guī)律是:顯示正確溫度2-3秒,跳成850約一秒,然后又顯示正確溫度。對這個現(xiàn)象,我真是百思不得其解,如果是時序的問題,那為什么可以測得正確的溫度?
還有,資料上說STC12系列的單片機(jī)是不分頻的,那是不是說比如我用12M的晶振,那么執(zhí)行一條指令的時間不再是1us,而是1/12 us?
DS18B20是數(shù)字傳感器,讀出的是一個16bit的數(shù)據(jù),前5bit表示符號,中間八位表示溫度的整數(shù)部分,我是把中間8位取出來,然后用分離出百、十、個位,送到數(shù)碼管顯示,剛開始用定時器中斷掃描數(shù)碼管,但因這個傳感器對時序要求很嚴(yán)格,便改用了軟件延時,可是用定時器與用軟件延時效果是一樣的都是對錯對錯循還。以下是我的程序,請論壇高手多多指點(diǎn),在下感激不盡!
附件是原理圖。
(程序可以顯示正確的溫度,只是會跳動)
#include <reg2051.h> #include<intrins.h> #define uchar unsigned char #define uint unsigned int void ow_reset(void); void delay(uint t); void write_byte(uchar val); uint read_temp(); uchar read_byte(void); work_temp(uint tem); void chuli(uchar wd); void delayms(uint ms); void displays(); uchar wei=0; uint temp=0; uchar wendu=0; uchar b,s,g,x; //百位,十位,個位,小數(shù) sbit d4=P3^2; //位選信號端 sbit d3=P3^4; sbit d2=P3^3; sbit d1=P3^5; sbit DQ=P3^7; //接傳感 器 uchar code disdu[12]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf}; //段選列表 //共陽LED段碼表 "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "不亮" "-" uchar data temp_data[2]={0x00,0x00}; //讀出溫度暫放 uchar code ditab[16]= {0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09}; //小數(shù)部分直接查表 void main() { ow_reset(); write_byte(0xcc); //Skip ROM write_byte(0x44); //發(fā)轉(zhuǎn)換命令 while(1) { work_temp(read_temp()); displays(); } } void ow_reset(void) //復(fù)位 { char presence=1; while(presence) { while(presence) { DQ=1;_nop_();_nop_();//從高拉倒低 DQ=0; delay(50); //550 us DQ=1; delay(6); //66 us presence=DQ; //presence=0 復(fù)位成功,繼續(xù)下一步 } delay(45); //延時500 us presence=~DQ; } DQ=1; //拉高電平 } /****************DS18B20寫命令函數(shù)************************/ //向1-WIRE 總線上寫1個字節(jié) void write_byte(uchar val) { uchar i; for(i=8;i>0;i--) { DQ=1;_nop_();_nop_(); //從高拉倒低 DQ=0;_nop_();_nop_();_nop_();_nop_(); //5 us DQ=val&0x01; //最低位移出 delay(6); //66 us val=val/2; //右移1位 } DQ=1; delay(1); } /****************DS18B20讀1字節(jié)函數(shù)************************/ //從總線上取1個字節(jié) uchar read_byte(void) { uchar i; uchar value=0; for(i=8;i>0;i--) { DQ=1;_nop_();_nop_(); value>>=1; DQ=0;_nop_();_nop_();_nop_();_nop_(); //4 us DQ=1;_nop_();_nop_();_nop_();_nop_(); //4 us if(DQ)value|=0x80; delay(6); //66 us } DQ=1; return(value); } uint read_temp() { ow_reset(); //總線復(fù)位 delay(200); write_byte(0xcc); //發(fā)命令 write_byte(0x44); //發(fā)轉(zhuǎn)換命令 ow_reset(); delay(1); write_byte(0xcc); //發(fā)命令 write_byte(0xbe); temp_data[0]=read_byte(); //讀溫度值的第字節(jié) delay(3); temp_data[1]=read_byte(); //讀溫度值的高字節(jié) temp=temp_data[1]; temp<<=8; temp=temp|temp_data[0]; // 兩字節(jié)合成一個整型變量。 return(temp); //返回溫度值 } /****************溫度數(shù)據(jù)處理函數(shù)************************/ //二進(jìn)制高字節(jié)的低半字節(jié)和低字節(jié)的高半字節(jié)組成一字節(jié),這個 //字節(jié)的二進(jìn)制轉(zhuǎn)換為十進(jìn)制后,就是溫度值的百、十、個位值,而剩 //下的低字節(jié)的低半字節(jié)轉(zhuǎn)化成十進(jìn)制后,就是溫度值的小數(shù)部分 /********************************************************/ work_temp(uint tem) { uchar n=0; if(tem>6348) // 溫度值正負(fù)判斷 { tem=65536-tem; n=1; } x=tem&0x0f; // 取小數(shù)部分的值 wendu=tem>>4; // 取中間八位,即整數(shù)部分的值 chuli(wendu); if(n) b=0x0b; //負(fù)溫度時最高位顯示"-" } void delay(uint t) { t=t*12; //stc12系列單片機(jī)不分頻,乘以8-12時,延時約10us for (;t>0;t--); } void delayms(uint ms) { ms=120*2*ms; //取這個參數(shù)顯示比較穩(wěn)定(數(shù)碼管不閃爍,也有較高亮度) for(;ms>0;ms--) ; } void displays() //顯示溫度 { P1=disdu[ditab[x]]; d1=0; delayms(5); d1=1; P1=disdu[g]; P1^7=0; //點(diǎn)亮小數(shù)點(diǎn) d2=0; delayms(5); d2=1; P1=disdu; d3=0; delayms(5); d3=1; P1=disdu; d4=0; delayms(5); d4=1; } void chuli(uchar wd) { b=wd/100; s=wd%100/10; g=wd%100%10; if(b==0) b=10; if(s==0) s=10; }
也不是是1/12 us ,實(shí)際的速度你得把c語言反匯編以后再對照stc的指令周期表 才知道了.
歡迎光臨 (http://www.torrancerestoration.com/bbs/) | Powered by Discuz! X3.1 |