|
/script> //實驗目的:熟悉DS18B20的使用 //六位數碼管顯示溫度結果,其中整數部分2位,小數部分4位 //每次按下RB0鍵后進行一次溫度轉換。 //硬件要求:把DS18B20插在18B20插座上 // 撥碼開關S10第1位置ON,其他位置OFF // 撥碼開關S5、S6全部置ON,其他撥碼開關全部置OFF #i nclude<pic.h> //__CONFIG(0x1832); //芯片配置字,看門狗關,上電延時開,掉電檢測關,低壓編程關,加密,4M晶體HS振蕩 #define uch unsigned char //給unsigned char起別名 uch # define DQ RA0 //定義18B20數據端口 # define DQ_DIR TRISA0 //定義18B20D口方向寄存器 # define DQ_HIGH() DQ_DIR =1 //設置數據口為輸入 # define DQ_LOW() DQ = 0; DQ_DIR = 0 //設置數據口為輸出 unsigned char TLV=0 ; //采集到的溫度高8位 unsigned char THV=0; //采集到的溫度低8位 unsigned char TZ=0; //轉換后的溫度值整數部分 unsigned char TX=0; //轉換后的溫度值小數部分 unsigned int wd; //轉換后的溫度值BCD碼形式 unsigned char shi; //整數十位 unsigned char ge; //整數個位 unsigned char shifen; //十分位 unsigned char baifen; //百分位 unsigned char qianfen; //千分位 unsigned char wanfen; //萬分位 unsigned char table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //0-9的顯示代碼 //------------------------------------------------ //延時函數 void delay(char x,char y) { char z; do{ z=y; do{;}while(--z); }while(--x); } //其指令時間為:7+(3*(Y-1)+7)*(X-1)如果再加上函數調用的call 指令、頁面設定、傳遞參數花掉的7 個指令。 //則是:14+(3*(Y-1)+7)*(X-1)。 //-------------------------------------------------- //結果顯示函數 void display() { TRISA=0X00; delay(5,100); //設置A口全為輸出 PORTD=table[shi]; //顯示整數十位 PORTA=0x3e; delay(10,100); PORTD=table[ge]&0X7F; //顯示整數個位,并點亮小數點 PORTA=0x3d; delay(10,100); PORTD=table[shifen]; //顯示小數十分位 PORTA=0x3b; delay(10,100); PORTD=table[baifen]; //顯示小數百分位 PORTA=0x37; delay(10,100); PORTD=table[qianfen]; //顯示小數千分位 PORTA=0x2f; delay(10,100); PORTD=table[wanfen]; //顯示小數萬分位 PORTA=0x1f; delay(10,100); } //------------------------------------------------ //系統初始化函數 void init() { ADCON1=0X07; //設置A口為普通數字口 TRISA=0X00; //設置A口方向為輸出 TRISD=0X00; //設置D口方向為輸出 } //----------------------------------------------- //復位DS18B20函數 reset(void) { char presence=1; while(presence) { DQ_LOW() ; //主機拉至低電平 delay(2,70); //延時503us DQ_HIGH(); //釋放總線等電阻拉高總線,并保持15~60us delay(2,8); //延時70us if(DQ==1) presence=1; //沒有接收到應答信號,繼續復位 else presence=0; //接收到應答信號 delay(2,60); //延時430us } } //----------------------------------------------- //寫18b20寫字節函數 void write_byte(uch val) { uch i; uch temp; for(i=8;i>0;i--) { temp=val&0x01; //最低位移出 DQ_LOW(); NOP(); NOP(); NOP(); NOP(); NOP(); //從高拉至低電平,產生寫時間隙 if(temp==1) DQ_HIGH(); //如果寫1,拉高電平 delay(2,7); //延時63us DQ_HIGH(); NOP(); NOP(); val=val>>1; //右移一位 } } //------------------------------------------------ //18b20讀字節函數 uch read_byte(void) { uch i; uch value=0; //讀出溫度 static bit j; for(i=8;i>0;i--) { value>>=1; DQ_LOW(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); //6us DQ_HIGH(); //拉至高電平 NOP(); NOP(); NOP(); NOP(); NOP(); //4us j=DQ; if(j) value|=0x80; delay(2,7); //63us } return(value); } //------------------------------------------------- //啟動溫度轉換函數 void get_temp() { int i; DQ_HIGH(); reset(); //復位等待從機應答 write_byte(0XCC); //忽略ROM匹配 write_byte(0X44); //發送溫度轉化命令 for(i=50;i>0;i--) { display(); //調用多次顯示函數,確保溫度轉換完成所需要的時間 } reset(); //再次復位,等待從機應答 write_byte(0XCC); //忽略ROM匹配 write_byte(0XBE); //發送讀溫度命令 TLV=read_byte(); //讀出溫度低8 THV=read_byte(); //讀出溫度高8位 DQ_HIGH(); //釋放總線 TZ=(TLV>>4)|(THV<<4)&0X3f; //溫度整數部分 TX=TLV<<4; //溫度小數部分 if(TZ>100) TZ/100; //不顯示百位 ge=TZ%10;//個位 //整數部分個位 shi=TZ/10;//十位 //整數十位 wd=0; if (TX & 0x80) wd=wd+5000; if (TX & 0x40) wd=wd+2500; if (TX & 0x20) wd=wd+1250; if (TX & 0x10) wd=wd+625; //以上4條指令把小數部分轉換為BCD碼形式 shifen=wd/1000; //十分位 baifen=(wd%1000)/100; //百分位 qianfen=(wd%100)/10; //千分位 wanfen=wd%10; //萬分位 NOP(); NOP(); } //-------------------------------------------------- //主函數 void main() { init(); //調用系統初始化函數 while(1) { get_temp(); //調用溫度轉換函數 // delay(5,50); display(); //調用結果顯示函數 } } |