51单片机实现Ds18b20的温度采集

Ds18b20有3根引脚,供电、接地、单总线。

在往单片机发送数据的时候18b20发送的是数字量,结构的优势让18b20可以避免进行手动的ADC转换。将模拟温度转换成数字。

 采集的流程分为:

   采集流程:
        复位        //18b20的复位
        主机发送0xcc;  //从寄存器0xcc开始读取
        主机发送0x44;  //温度变化,内部ADC开始转换
        延时,18b20将转换的值写入寄存器中
        复位
        发送0xcc;
        发送0xBE    //开始读取温度
        读取2个字节

问题:由于P37接通之后,如果51和18b20一个想拉高电平,另外一个想拉低电平,会出现怎样的抉择

        双方都要拉高时,上拉电阻的作用就体现了
        在加上拉电阻,双方都拉高的时候,上拉电阻可以上高电平更准确,相当于再使一把劲。
        如果有任何一方要拉低,那么就直接相当于接地,无论有没有上拉电阻,都会使该引脚成为低电平。


    如何保证该总线是高电平
    :通过在总线上添加上拉电阻。
    51单片机的引脚的高电平很弱,所以需要上拉电阻来保证引脚的高电平。

   复位:
    //在复位的过程中, 如何检测引脚确实发生如下变化,证明18b20的存在

 int t;
 while (t <= 24 && (P3 & (1 << 7) != 0))  // 检测引脚是否为高电平
    {
        Delay10us(1);
        t++;
    }
    if (t > 24)
    {
        return 0;
    }

    while (t <= 24 && (P3 & (1 << 7) == 0))  // 检测引脚是否为低电平
    {
        Delay10us(1);
        t++;
    }
    if (t > 24)
    {
        return 0;
    }
    return 1;

 cpu和18b20之间的通信

  #define DS18B20CLR  (P3 &= ~(1 << 7))   //P3_7 = 0
    #define DS18B20SET  (P3 |= (1 << 7))    //P3_7 = 1;
    #define DS18B20TST  ((P3 &= (1 << 7)) != 0)
    void sendChar(unsigned char n)
    {
        int i;
        for (i = 0; i < 8; ++i)
        {
            if (n & 0x01 != 0)
            {
                //根据手册
                DS18B20CLR;
                Delay10us(1);
                DS18B20SET;
                Delay10us(3);
            }
            else
            {
                DS18B20CLR;
                Delay10us(5);
                DS18B20SET;
            }

        }
    }

    unsigned char readChar(void)
    {
        unsigned char i, n = 0;
        for(i = 0; i < 8; i++)
        {
            DS18B20CLR;
            _nop();
            _nop();
            DS18B20SET;
            _nop();
            _nop();
            _nop();
            _nop();

            n |= DS18B20TST << i;   // read bit并保存至n
            Delay10us(5);
        }

        return n;
    }    

    ret = t2 << 8 | t1;
    return ret * 0.0625;

上位机与上位机的通信
 modbus协议框架:
        帧:                        
        起始字节    地址码      功能码    数据长度    数据码    数据码    校验码    结束码
        0xAA        0x01         03        02        xx        xx       CRC      0x0D
        地址码:modbus并未规定
            
            功能码: 01     读温度
                    02     读秒数
                    03     设秒数 

        举例:
        上位机(读温度命令): AA 01 01 00 XX 0D
        下位机(回复给上位): AA 81 01 04 XX XX XX XX ** 0D

        上位机(02):AA 01 02 00 XX 0D
        下位机(回复给上位):AA 81 02 XX XX ** 0D


       

 校验:int parse(const unsigned char *buffer, int len)
            {
                if (buffer[1] != 0x01)
                {
                    return 0;
                }
                if (buffer[0] != (unsigned char)0xAA || buffer[len-1] != (unsigned char)0x0D)
                {
                    return 0;
                }
                if (校验条件)
                {
                    return 0;
                }
                return buffer[2];
            }

            int main(void)
            {
                int ret = 0;
                ret = parse(recvBuffer, pos);
                if (ret != 0)
                {
                    switch(ret)
                    {

                    }
                }
            }

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值