|
基于DS18B20的温度传感器设计,有程序详细解释,适合初学者。
- /*******************************************************************
- 基于DS18B20的温度传感器设计
- 版本号: V1.0;2016.9.19
- 温度传感器:DS18B20
- 显示方式: LCD1602
- ********************************************************************/
- #include<reg52.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit DQ=P1^6;//ds18b20与单片机连接口
- sbit RS=P1^0;
- sbit RW=P1^1;
- sbit EN=P1^2;
- sbit BEEP = P1^7;
- uchar code str1[]={" Temperature is "};
- uchar code str2[]={" designer: "};
- uchar code str3[]={" xzf586" };
- uchar data disdata[5];
- uchar p=0;
- uint tvalue;//温度值
- uchar tflag;//温度正负标志
- /*******************************************************************
- lcd1602程序
- 1:延时
- 2:读数据(因为没有忙检测,本程序没有)
- 3:忙检测(本程序没有)
- 4: 写指令
- 5:写数据
- 6: 初始化
- ********************************************************************/
- void delay1ms(uint ms)//延时1毫秒
- {
- uint i,j;
- for(i=0;i<ms;i++)
- for(j=0;j<114;j++);
- }
- void wr_com(uchar com)//写指令//
- {
- delay1ms(1);
- RS=0;
- RW=0;
- EN=0;
- P0=com;
- delay1ms(1);
- EN=1;
- delay1ms(1);
- EN=0;
- }
- void wr_dat(uchar dat)//写数据//
- {
- delay1ms(1);
- RS=1;
- RW=0;
- EN=0;
- P0=dat;
- delay1ms(1);
- EN=1;
- delay1ms(1);
- EN=0;
- }
- void lcd_init()//初始化设置//
- {
- wr_com(0x38);delay1ms(5);
- wr_com(0x08);delay1ms(5);
- wr_com(0x01);delay1ms(5);
- wr_com(0x06);delay1ms(5);
- wr_com(0x0c);delay1ms(5);
- }
- /***************************************************
- 报警程序
- ****************************************************/
- void baojing(void)
- {
- unsigned int j;
- BEEP=0;
- for (j = 49; j > 0; j--)//响30ms
- {
- BEEP = ~BEEP; //输出频率800Hz
- delay1ms(10); //延时310us
- }
- BEEP=0;
- }
- void display(uchar *p)//显示//
- {
- while(*p!='\0')
- {
- wr_dat(*p);
- p++;
- delay1ms(1);
- }
- }
- void init_play()//初始化显示
- {
- lcd_init();
- wr_com(0x80);
- display(str2);
- wr_com(0xc0);
- display(str3);
- delay1ms(3000);
- lcd_init();
- wr_com(0x80);
- display(str1);
- }
- /*******************************************************************
- ds18b20程序
- 1:延时
- 2:复位
- 3:读数据
- 4: 写数据
- 5:读取温度值并转换(正负)
- ********************************************************************/
- void delay_18B20(uint i)//延时1微秒
- {
- while(i--);
- }
- void ds1820rst()/*ds1820复位*/
- {
- DQ = 1; //DQ复位
- delay_18B20(4); //延时
- DQ = 0; //DQ拉低
- delay_18B20(100); //精确延时大于480us
- DQ = 1; //拉高
- delay_18B20(40);
- }
- uchar ds1820rd()/*读数据*/
- {
- uchar i=0;
- uchar dat = 0;
- for (i=8;i>0;i--)
- {
- DQ = 0; //给脉冲信号
- dat>>=1; //相当于0输入最高位
- DQ = 1; //给脉冲信号
- if(DQ)
- dat|=0x80; // 等价于dat=dat|0x80,dat和0x80做“或”的运算,意思是最高位置1,其它位保持不变,即1输入最高位
- delay_18B20(10);
- }
- return(dat);
- }
- void ds1820wr(uchar wdata)/*写数据*/
- {
- uchar i=0;
- for (i=8; i>0; i--)
- {
- DQ = 0;
- DQ = wdata&0x01; //前7位置0,最后一位保持不变,输出
- delay_18B20(10);
- DQ = 1;
- wdata>>=1; //倒数第二位到最后一位,继续上面过程,输出
- }
- }
- /*******************************************************************
- ds18b20温度值规则
- 1:b=0000 0111 1101 0000=64+32+16+8+4+1=125度 最大
- 2:b=0000 0001 1101 0001=16+8+4+1+2^(-4)=29.0625度
- 3:b=0000 0000 0000 0000=0度
- 4: b=1111 1111 1111 1000转换 前五位=1,说明负值,其绝对值为取反加1,即0000 0000 0111+1=0000 0000 1000=2^(-1)=0.5
- 5:b=1111 1100 1001 0000转换 绝对值为取反加1,即0011 0110 1111+1=0011 0111 0000=-55 最小
- 6:15~11是符号位,都为1就是零下;都0就是零上,后10~0 这11位,是温度的实际数据,这个数据乘0.0625就得到温度了(正温度算法)
- ********************************************************************/
- read_temp()/*读取温度值并转换*/
- {
- uint a,b;
- ds1820rst(); //复位
- ds1820wr(0xcc);//*跳过读序列号*/
- ds1820wr(0x44);//*启动温度转换*/
- ds1820rst();
- ds1820wr(0xcc);//*跳过读序列号*/
- ds1820wr(0xbe);//*读取温度*/
- a=ds1820rd(); //第一次读的低八位,例如125度,则 a=0000 0000 1101 0000
- b=ds1820rd(); //第二次读的高八位,例如125度,则 b=0000 0000 0000 0111
- tvalue=b; //下面三句是将这两次读的合起来
- tvalue<<=8; //若是125,则tvalue<<=8,即tvalue=0000 0111 0000 0000
- tvalue=tvalue|a; //tvalue|a=0000 0111 0000 0000 | 0000 0000 1101 0000=0000 0111 1101 0000
- if(tvalue<0x08ff) //若tvalue是正的,则tvalue<0000 0111 1111 1111,前五位符号都是0
- tflag=0;
- else
- {
- tvalue=~tvalue+1; //负值,取反加1
- tflag=1;
- }
- tvalue=tvalue*(0.0625)*10;//温度值扩大10倍,精确到1位小数,注意到负温度已经转换了,因此可以这样算
- return(tvalue);
- }
- /*******************************************************************/
- void ds1820disp()//温度值显示
- {
- uchar flagdat;
- disdata[0]=tvalue/1000+0x30;//百位数,0的ASCII码是0x30,以此类推
- disdata[1]=tvalue%1000/100+0x30;//十位数
- disdata[2]=tvalue%100/10+0x30;//个位数
- disdata[3]=tvalue%10+0x30;//小数位
- if(tflag==0)
- //flagdat=0x20;//正温度不显示符号,空格的ASCII码是0x20
- flagdat=0x2b;//正温度显示正号,正号的ASCII码是0x2b
- else
- flagdat=0x2d;//负温度显示负号:-
- if(disdata[0]==0x30) //注意0的ASCII码是0x30,空格的ASCII码是0x20
- {
- disdata[0]=0x20;//如果百位为0,不显示
- if(disdata[1]==0x30)
- {
- disdata[1]=0x20;//如果百位为0,十位为0也不显示
- }
- }
- wr_com(0xc0+4); //LCD第二行,空4格
- wr_dat(flagdat);//显示符号位
- wr_com(0xc1+4);
- wr_dat(disdata[0]);//显示百位
- wr_com(0xc2+4);
- wr_dat(disdata[1]);//显示十位
- wr_com(0xc3+4);
- wr_dat(disdata[2]);//显示个位
- wr_com(0xc4+4);
- wr_dat(0x2e);//显示小数点
- wr_com(0xc5+4);
- wr_dat(disdata[3]);//显示小数位
- wr_com(0xc6+4);
- wr_dat(0x43); //C的ASCII码是0x43
- }
- //********************主程序***********************************//
- void main()
- {
- BEEP=0;
- init_play();//初始化显示
- while(1)
- {
- read_temp();//读取温度
- ds1820disp();//显示
- if(read_temp()>950||read_temp()<860) //报警温度 86~95之间,因为前面乘以10
- {
- baojing() ;
- }
- delay1ms(1) ;
- }
- }
复制代码
|
评分
-
查看全部评分
|