GPIO 发表于 2018-11-15 23:05:02

DS18B20测温程序/读序列号STC-Y3系列+软串口发送 支持负温度测量+摄氏度/华氏度转换




#include "reg51.h"
#include "intrins.h"
#include "stdio.h"
sbit LED=P3^4;      //LED端口
sbit DQ=P3^5;      //18B20数据线
sbit txd=P3^1;         //数据发送口
sbit key=P3^2;      //摄氏度与华氏度选择位 (高电平摄氏度,低电平华氏度)
#define U8 unsigned char
#define U16 unsigned int
#define U32 unsigned long
U8 asciitemp;
U8 ds18b20_id;                //DS18B20序列号
union N16 {
      U8 c;
      int i;

};

void delay_uart(){      //11.0592Mhz@9600Bps
    U8 a,b;
    for(b=3;b>0;b--)
      for(a=94;a>0;a--);
}
      void txd_data(U8 i){                  //串口发字节
      U8 j=1,k=8;
      delay_uart();
      txd=0;
      while(k--){
      delay_uart();
      txd=(i&j)/j;
      j<<=1;
      }
      delay_uart();
      txd=1;
      }


void send_text(U8 *text){               //发送字符串
      for(;*text!=0;text++){          //遇到停止符0结束发送
                txd_data(*text);         //发送数据
      }
}

void send_hex(U8 c,bit u){                //串口发16进制字节 参数1:待发字节 参数2:1大写0小写
      U8 d,i;
      for(i=0;i<2;i++){
                d= i ? c&15 : c>>4;
                txd_data((d >= 0 && d <=9?48:u?55:87)+d);
      }

}

void delay15us()                //@11.0592MHz
{
      U8 i;

      _nop_();
      _nop_();
      i = 38;
      while (--i);
}

void delayx15us(U8 t){      //延时N个15us
      while(--t) delay15us();

}

void delay1ms()                //@11.0592MHz
{
      U8 i, j;

      _nop_();
      i = 11;
      j = 190;
      do
      {
                while (--j);
      } while (--i);
}

void delayxms(U16 t){      //延时N个1ms
      while(--t) delay1ms();

}
      bit ds18b20_init(){                //DS18B20初始化 检测DS18B20是否接入 成功返回1失败返回0
                bit dat=0;
                DQ=1;      //置高电平
                _nop_();_nop_();      //延时4个NOP
                _nop_();_nop_();
                DQ=0;      //置低电平
                delayx15us(40);      //延时600us 范围480~960us

                DQ=1;
                delayx15us(4);      
                dat=DQ;
                delayx15us(48);      //延时720us
                return !dat;
      }
      
      U8 ds18b20_r8(){                //DS18B20读字节
                U8 i,dat=0;
                for(i=8;i>0;i--){
                        DQ=0;
                        dat>>=1;
                        _nop_();
                        DQ=1;
                        if(DQ) dat|=0x80;
                        delayx15us(4);
                }
                return dat;
      }


      void ds18b20_w8(U8 dat){      //DS18B20写字节
                U8 i;
               for (i=8; i>0; i--){
                        DQ = 0;
                        delay15us();
                        DQ= dat&1;
                        delayx15us(3);
                        DQ=1;
                        dat >>=1;
                }
      }

      void ds18b20_rid(){                //DS18B20读ID(序列号)
                U8 i;
                ds18b20_init();
                ds18b20_w8(0x33);
                for(i=0;i<8;i++) {
                        ds18b20_id=ds18b20_r8();
                }

      }

      
      U8 ds18b20_crc8(){                //DS18B20序列号CRC8校验 (返回0为正确)
                U8 i,j,x,k=0;
                for(x=0;x<8;x++){
                        j=ds18b20_id;
                        for(i=0;i<8;i++){
                        k= (k^j)&1 ? (k^0x18)>>1|0x80 : k>>1;
                              j >>=1;
                        }
                        
                }

                return k;
      }
      

      float ds18b20_rt(){                //DS18B20读温度 失败返回-100
                union N16 r;
                if(!ds18b20_init()) return -100;
                ds18b20_w8(0xCC);         // 跳过读序号列号的操作
                ds18b20_w8(0x44);         // 启动温度转换
                delayxms(10);
                        if(!ds18b20_init()) return -100;
                        ds18b20_w8(0xCC);
                        ds18b20_w8(0xBE);
                        r.c=ds18b20_r8();                //低位
                        r.c=ds18b20_r8();                //高位
                        return (float)(r.i*0.0625);

      }

      float c2f(float c){      //摄氏度转华氏度
                return 1.8*c+32;

      }
      void ds18b20_sendid(){      //发送DS18B20序列号
                U8 i;
                send_text("DS18B20 ID:");
                        for(i=0;i<8;i++){
                        send_hex(ds18b20_id,1);
                        }
                send_text("\r\n");
      }

      void main(){
      float rt=0;                //温度摄氏度
      ds18b20_rid();
      ds18b20_sendid();
      if(ds18b20_crc8()){
      send_text("DS18B20 CRC8 Error! \r\n");
      while(1);
      }
                while(1){
                        rt=ds18b20_rt();      //查询DS18B20温度
                        if(rt == -100){      //返回-100表示未接入
                        send_text("Read DS18B20 Error! \r\n");
                        } else {
                        LED = !(rt>=30);      //大于30摄氏度 LED点亮
                        if(key){
                        sprintf(asciitemp,"%7.4f °C\r\n",rt);
                        } else {
                        sprintf(asciitemp,"%7.4f °F\r\n",c2f(rt));
                        }
                        send_text(asciitemp);                        //从内存发送字符串
                        }
                delayxms(100);
                }

      }

1心1亿 发表于 2018-11-16 08:26:38

谢谢分享

222 发表于 2018-11-17 12:11:38

楼上回答正解

小莉今年7岁 发表于 2018-11-17 19:00:03

222 发表于 2018-11-17 12:11
楼上回答正解

你这是发错了吧

demon 发表于 2018-12-23 10:52:38

谢谢分享
页: [1]
查看完整版本: DS18B20测温程序/读序列号STC-Y3系列+软串口发送 支持负温度测量+摄氏度/华氏度转换