这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【换取手持数字示波器】+精英板温度采集

共3条 1/1 1 跳转至

【换取手持数字示波器】+精英板温度采集

专家
2024-05-05 18:17:34     打赏

     DS18B20是一款常用的高精度的单总线数字温度测量芯片。具有体积小,硬件开销低,抗干扰能力强,精度高的特点,因此能得到广泛地运用。本次主要分享基于DS18B20的温度精准采集,我们知道DS18B20是美国DSLIAS公司推出的单总线数字温度传感器,具有微型化、低功耗、高性能、抗干扰能力强、易匹配处理器等优点。处理器与DS18B20通信只需要一根数据线即可,同时该数据线还可以向挂接的DS18B20供电。DS18B20内部自带A/D转换器,通过内部的温度采集、A/D转换等一系列过程,将温度值以规定的格式转换为数据并输出,用户可以通过一些简单的算法,将数据还原为温度值。其分辨率可以达到12位,满足一般情况下对温度采集的需要。与模拟温度传感器相比,DS18B20省去了信号调理、A/D转换等通道处理电路,从而使得系统线路简单,成本低廉。

    测温范围为-55℃到+125℃,在-10℃到+85℃范围内误差为±0.4°。返回16位二进制温度数值,主机和从机通信使用单总线,即使用单线进行数据的发送和接收。在使用中不需要任何外围元件,独立芯片即可完成工作。掉电保护功能 DS18B20 内部含有 EEPROM ,通过配置寄存器可以设定数字转换精度和报警温度,在系统掉电以后,它仍可保存分辨率及报警温度的设定值。每个DS18B20都有独立唯一的64位-ID,此特性决定了它可以将任意多的DS18b20挂载到一根总线上,通过ROM搜索读取相应DS18B20的温度值。宽电压供电,电压2.5V~5.5V。

    DS18B20返回的16位二进制数代表此刻探测的温度值,其高五位代表正负。如果高五位全部为1,则代表返回的温度值为负值。如果高五位全部为0,则代表返回的温度值为正值。后面的11位数据代表温度的绝对值,将其转换为十进制数值之后,再乘以0.0625即可获得此时的温度值。

     精英板上针对温湿度传感接入已经设计专门接口,即板上U4位置。

原理图.png

        这里采用一个自购的小模块接入,借助其它废弃的元器件管脚,插入圆形的插座上,然后杜邦线引入。如果有单独的DS18B20元器件,则无需转接。我们知道DS18B20是一款l-wire总线接口的器件,即与外部的处理器通信只有一根线,因此,通信流程就显得稍微复杂,需要用MCU的I/O口软件模拟l-wire的时序。

时序图.png一线式通讯部分代参考如下:

static uint8_t ds18b20_read_bit(void)
{
    uint8_t data = 0;
    DS18B20_DQ_OUT(0);
    delay_us(2);
    DS18B20_DQ_OUT(1);
    delay_us(12);

    if (DS18B20_DQ_IN)
    {
        data = 1;
    }

    delay_us(50);
    return data;
}

/**
 * @brief       从DS18B20读取一个字节
 * @param       无
 * @retval      读到的数据
 */
static uint8_t ds18b20_read_byte(void)
{
    uint8_t i, b, data = 0;

    for (i = 0; i < 8; i++)
    {
        b = ds18b20_read_bit(); /* DS18B20先输出低位数据 ,高位数据后输出 */
        
        data |= b << i;         /* 填充data的每一位 */ 
    }

    return data;
}

/**
 * @brief       写一个字节到DS18B20
 * @param       data: 要写入的字节
 * @retval      无
 */
static void ds18b20_write_byte(uint8_t data)
{
    uint8_t j;

    for (j = 1; j <= 8; j++)
    {
        if (data & 0x01)
        {
            DS18B20_DQ_OUT(0);  /*  Write 1 */
            delay_us(2);
            DS18B20_DQ_OUT(1);
            delay_us(60);
        }
        else
        {
            DS18B20_DQ_OUT(0);  /*  Write 0 */
            delay_us(60);
            DS18B20_DQ_OUT(1);
            delay_us(2);
        }

        data >>= 1;             /* 右移,获取高一位数据 */
    }
}

/**
 * @brief       开始温度转换
 * @param       无
 * @retval      无
 */
static void ds18b20_start(void)
{
    ds18b20_reset();
    ds18b20_check();
    ds18b20_write_byte(0xcc);   /*  skip rom */
    ds18b20_write_byte(0x44);   /*  convert */
}

/**
 * @brief       初始化DS18B20的IO口 DQ 同时检测DS18B20的存在
 * @param       无
 * @retval      0, 正常
 *              1, 不存在/不正常
 */
uint8_t ds18b20_init(void)
{
    GPIO_InitTypeDef gpio_init_struct;
    
    DS18B20_DQ_GPIO_CLK_ENABLE();   /* 开启DQ引脚时钟 */

    gpio_init_struct.Pin = DS18B20_DQ_GPIO_PIN;
    gpio_init_struct.Mode = GPIO_MODE_OUTPUT_OD;            /* 开漏输出 */
    gpio_init_struct.Pull = GPIO_PULLUP;                    /* 上拉 */
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;          /* 高速 */
    HAL_GPIO_Init(DS18B20_DQ_GPIO_PORT, &gpio_init_struct); /* 初始化DS18B20_DQ引脚 */
    /* DS18B20_DQ引脚模式设置,开漏输出,上拉, 这样就不用再设置IO方向了, 开漏输出的时候(=1), 也可以读取外部信号的高低电平 */

    ds18b20_reset();
    return ds18b20_check();
}

/**
 * @brief       从ds18b20得到温度值(精度:0.1C)
 * @param       无
 * @retval      温度值 (-550~1250)
 *   [url=home.php?mod=space&uid=1902110]@NOTE[/url]      返回的温度值放大了10倍.
 *              实际使用的时候,要除以10才是实际温度.
 */
short ds18b20_get_temperature(void)
{
    uint8_t flag = 1;           /* 默认温度为正数 */
    uint8_t TL, TH;
    short temp;
    
    ds18b20_start();            /*  ds1820 start convert */
    ds18b20_reset();
    ds18b20_check();
    ds18b20_write_byte(0xcc);   /*  skip rom */
    ds18b20_write_byte(0xbe);   /*  convert */
    TL = ds18b20_read_byte();   /*  LSB */
    TH = ds18b20_read_byte();   /*  MSB */

    if (TH > 7)
    {/* 温度为负,查看DS18B20的温度表示法与计算机存储正负数据的原理一致:
        正数补码为寄存器存储的数据自身,负数补码为寄存器存储值按位取反后+1
        所以我们直接取它实际的负数部分,但负数的补码为取反后加一,但考虑到低位可能+1后有进位和代码冗余,
        我们这里先暂时没有作+1的处理,这里需要留意 */
        TH = ~TH; 
        TL = ~TL;
        flag = 0;   /* 温度为负 */
    }

    temp = TH;      /* 获得高八位 */
    temp <<= 8;
    temp += TL;     /* 获得底八位 */
    
    /* 转换成实际温度 */
    if (flag == 0)
    {   /* 将温度转换成负温度,这里的+1参考前面的说明 */
        temp = (double)(temp+1) * 0.625;
        temp = -temp;   
    }
    else
    {
        temp = (double)temp * 0.625;
    }
    
    return temp;
}
int main(void)
{
    uint8_t t = 0;
    float temp,float_num;
    short temperature;

    HAL_Init();                         /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
    delay_init(72);                     /* 延时初始化 */
    usart_init(115200);                 /* 串口初始化为115200 */
    led_init();                         /* 初始化LED */

    while (ds18b20_init()) /* DS18B20初始化 */
    {
        printf("DS18B20 Init Error\\r\\n");
        delay_ms(200);
    }
    printf("DS18B20 OK\\r\\n");

    while (1)
    {
        if (t % 50 == 0) /* 每200ms读取一次 */
        {
            temperature = ds18b20_get_temperature();
	    temp = (float)temperature  * 0.0625;
            if (temperature < 0)
            {
		printf("采集的温度为:-%.2f\\r\\n",temp);
            }
	    printf("采集的温度为:%.2f\\r\\n",temp);
        }
        delay_ms(4);
        t++;
        if (t == 100)
        {
            t = 0;
            LED0_TOGGLE(); /* LED0闪烁 */
        }
    }
}

       编译完成后,接入JLink调试器,选择JLink调试下载方式,并勾选下载完成后自动重启复位,检查下载算法是否ok。

识别调试器.png下载算法.png板上实物接线如下图所示:

板上接线.jpg       连接DS18B20时千万要注意电源的正负极方向,连接后小模块的红色指示灯会被点亮,然后打开串口调试助手,波特率设置115200,打开串口,然后将手指紧贴DS18B20的元器件上,串口打印出的采集温度值则会随之改变。实测采集的温度比较稳定,干扰少,很精准。效果如下视频文件所示:

DS18B20温度采集.zip




关键词: 换取手持数字示波器     DS18B20温度采集    

专家
2024-05-06 08:19:03     打赏
2楼

谢谢分享!


高工
2024-05-06 14:27:11     打赏
3楼

这个小板有点年头了


共3条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]