//------------------------------------------------------------------------ // // DS18B20温度计C程序 // 2008.12.8通过调试 //------------------------------------------------------------------------ //使用AT89C2051单片机,12MHZ晶振,用共阳LED数码管 //P1口输出段码,P3口扫描 // #include "reg51.h" #include "intrins.h" //_nop_();延时函数用
#define Disdata P0 //段码输出口 #define discan P2 //扫描口 #define uchar unsigned char #define uint unsigned int
sbit DQ=P3^7; //温度输入口 sbit DIN=P0^7; //LED小数点控制 int TH; //上限报警温度
//共阴LED段码表 "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "_" uchar code dis_7[16]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x08}; uchar code scan_con[4]={0xf7,0xfb,0xfd,0xfe}; //列扫描控制字 uchar data temp0,temp1; // 读出温度暂放 uchar data display[4]={0x00,0x00,0x00,0x00};//显示单元数据,共4个数据,一个运算暂存用
//------------------------------------------------------------------------ //函数的声明 // void delay15us(uint t); //延时15us void scan(void); //动态扫描数码管 void Reset_DQ(void); //DS18B20复位函数 void write_bit(uchar w_bit); //写一bit数据函数 void write_byte(uchar w_byte); //写一byte数据函数 int read_bit(void); //读出一bit数据 int read_byte(void); //读出一byte数据 void read_temp(void); //读出温度 void process_temp(void); //处理温度显示 void initTS(void); //初始化DS18B20 void dlms(void); //延时约10ms void set_temp(void); //温度设置函数
//------------------------------------------------------------------------ //delay 15 us. // void delay15us(uint t) { for(;t>0;t--) { //_nop_()函数少一个,或者多一个都会使占用CPU的资源增多。 _nop_();_nop_();_nop_();_nop_(); } }
//------------------------------------------------------------------------ //Display And Scan module // void scan(void) { char loop; for(loop=0;loop<4;loop++) //四位LED扫描控制 { Disdata=dis_7[display][loop]]; if(loop==2) {DIN=1;} else DIN=0; discan=scan_con[loop]; delay15us(100); discan=0xff; } }
//------------------------------------------------------------------------ //Reset DS18B20 // void Reset_DQ(void) { DQ=1;_nop_();_nop_(); DQ=0; delay15us(38); DQ=1; delay15us(3); DQ=0; delay15us(15); DQ=1; } //------------------------------------------------------------------------ //Send a 1-wire write bit.Probide 10us recovery time // void write_bit(uchar w_bit) {
if(w_bit) { //Write '1' bit DQ=0; _nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); DQ=1; delay15us(4); } else { //Write '0' bit DQ=0; delay15us(4); DQ=1; _nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_(); } }
//------------------------------------------------------------------------ //Write 1-Wire data byte // void write_byte(uchar w_byte) { int loop; //Loop to write each int bit in the byte,Ls_bit first for(loop=0;loop<8;loop++) { write_bit(w_byte&0x01); //shift the data byte for the next bit w_byte>>=1; }
} //------------------------------------------------------------------------ //Read a bit from the 1-Wire bus and return it.Probide 10us recovery time. // int read_bit(void) { int result; DQ=0; //Drives DQ low _nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); DQ=1; //Rleases the bus _nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_(); result=DQ; //Samples the bit value from the slave delay15us(4); //Complete the time slot and 10us recovery
return result; } //------------------------------------------------------------------------ //Read 1-Wire data byte and return it. // int read_byte(void) { int loop,result=0; for(loop=0;loop<8;loop++) { result>>=1; if(read_bit()) result|=0x80; } return result; }
//------------------------------------------------------------------------ //Read temperature // void read_temp(void) { Reset_DQ(); //总线复位 write_byte(0xCC); //由于只使用了一片DS18B20,发Skip ROM命令 write_byte(0xBE); //发读命令 temp0=read_byte(); //温度低8位 temp1=read_byte(); //温度高8位 // TH=read_byte(); //读出上限告警温度 Reset_DQ(); write_byte(0xCC); // Skip ROM write_byte(0x44); // 发转换命令,温度转换以后750ms可以读出温度。
} //------------------------------------------------------------------------ //Process temperature.Display temperature in the LEDs. //数码管只有四位,常用测温范围为0-100,不考虑温度为负数和大于100情况,测温精 //度为0.5,分辨率是0.0625,如果温度出现负数,将会读出负的温度值,不过没有显示‘-’ void process_temp(void) { int tempL,tempH; int n; tempH=((temp0&0xf0)>>4)|((temp1&0x0f)<<4); //温度的整数部分 //取测得温度的bit4~bit11位与TH和TL分别比较,如果大于TH或者小于TL,则S=1,即tempH>127 if(tempH>127) { tempH=256-tempH; n=1; } display[3]=tempH/10; //温度十位 display[2]=tempH%10; //温度个位 tempL=temp0&0x0f; tempL=tempL*6.25; //温度的小数部分 display[1]=tempL/10; //温度小数第一位 display[0]=tempL%10; //温度小数第二位
//Compare with the TH if((tempH+(temp0&0x0f)*0.0625)>TH) {P3&=0X80; delay15us(1000);}
if(!display[3]){display[3]=0x0A;} //最高位为0时不显示 }
//------------------------------------------------------------------------ //Initialize the DS18B20 // void initTS(void) { Reset_DQ(); write_byte(0xcc); write_byte(0x4e); //写温度限制指令 write_byte(0x64); //TH为100℃ write_byte(0x80); //TL为-10℃ write_byte(0x7f); //设置转换为12位,分辨率达到0.0625 // Reset_DQ(); }
//------------------------------------------------------------------------ //Main Function // main() { int h; Disdata=0xff; //初始化端口 discan=0xff;
initTS(); //初始化DS18B20,开机时显示85.00℃ while(1) { read_temp(); //读出18B20温度数据 process_temp(); //处理温度数据 for(h=0;h<250;h++) {scan();} //显示温度值约1.5秒,温度显示时间较长,对变化不是很敏感,但可 //以减少占用CPU的资源。 } }
//*********************结束**************************//
|