STC8H开发(十一): GPIO单线驱动多个DS18B20数字温度计
目录
- STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解)
 - STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解)
 - STC8H开发(三): 基于FwLib_STC8的模数转换ADC介绍和演示用例说明
 - STC8H开发(四): FwLib_STC8 封装库的介绍和使用注意事项
 - STC8H开发(五): SPI驱动nRF24L01无线模块
 - STC8H开发(六): SPI驱动ADXL345三轴加速度检测模块
 - STC8H开发(七): I2C驱动MPU6050三轴加速度+三轴角速度检测模块
 - STC8H开发(八): NRF24L01无线传输音频(对讲机原型)
 - STC8H开发(九): STC8H8K64U模拟USB HID外设
 - STC8H开发(十): SPI驱动Nokia5110 LCD(PCD8544)
 - STC8H开发(十一): GPIO单线驱动多个DS18B20数字温度计
 - STC8H开发(十二): I2C驱动AT24C08,AT24C32系列EEPROM存储
 
DS18B20
关于DS18B20的详细介绍说明已经转移到这组文章下
- DS18B20数字温度计 (一) 电气特性, 寄生供电模式和远距离接线
 - DS18B20数字温度计 (二) 测温, ROM和CRC算法
 - DS18B20数字温度计 (三) 1-WIRE总线 ROM搜索算法和实际测试
 
使用STC8H驱动DS18B20
接线
普通模式
GND  -> GND
P35  -> DQ
3.3V -> VDD
寄生供电模式
这个模式下
- VDD和GND都要接地
 - DQ 需要用5K电阻上拉. STC8H可以通过寄存器进行设置.
 - 建议使用5V电压供电, 使用3.3V供电时, 可能会出现测温读数不更新的情况
 
GND  -> GND -> VDD
P35  -> DQ
5V
寄生模式下, 发起温度转换后不能查询完成情况, 如果查询, 会导致测温不成功, 读数不变, 需要等待一个合理的时间, 例如1000毫秒, 然后直接读出温度值.
代码
代码可以从GitHub或者Gitee下载
定义 IO
只需要一个Pin, 在STC8H中, 注意要将其设置为上拉, 否则读出来的全是0
#define DS18B20_DQ           P35
#define DS18B20_DQ_PULLUP()  GPIO_SetPullUp(GPIO_Port_3, GPIO_Pin_5, HAL_State_ON)
#define DS18B20_DQ_INPUT()   GPIO_P3_SetMode(GPIO_Pin_5, GPIO_Mode_Input_HIP)
#define DS18B20_DQ_OUTPUT()  GPIO_P3_SetMode(GPIO_Pin_5, GPIO_Mode_InOut_OD)
#define DS18B20_DQ_LOW()     DS18B20_DQ=RESET
#define DS18B20_DQ_HIGH()    DS18B20_DQ=SET
IO 读写
读一个bit和一个byte
__BIT DS18B20_ReadBit(void)
{
    __BIT b = RESET;
    /* Line low */
    DS18B20_DQ = RESET;
    DS18B20_DQ_OUTPUT();
    SYS_DelayUs(2);
    /* Release line */
    DS18B20_DQ_INPUT();
    SYS_DelayUs(10);
    /* Read line value */
    if (DS18B20_DQ) {
        /* Bit is HIGH */
        b = SET;
    }
    /* Wait 50us to complete 60us period */
    SYS_DelayUs(50);
    
    /* Return bit value */
    return b;
}
uint8_t DS18B20_ReadByte(void)
{
    uint8_t i = 8, byte = 0;
    while (i--) 
    {
        byte >>= 1;
        byte |= (DS18B20_ReadBit() << 7);
    }
    return byte;
}
写一个bit和一个byte
void DS18B20_WriteBit(__BIT b)
{
    if (b)
    {
        /* Set line low */
        DS18B20_DQ = RESET;
        DS18B20_DQ_OUTPUT();
        SYS_DelayUs(10);
        /* Bit high */
        DS18B20_DQ_INPUT();
        
        /* Wait for 55 us and release the line */
        SYS_DelayUs(55);
        DS18B20_DQ_INPUT();
    } 
    else 
    {
        /* Set line low */
        DS18B20_DQ = RESET;
        DS18B20_DQ_OUTPUT();
        SYS_DelayUs(65);
        
        /* Bit high */
        DS18B20_DQ_INPUT();
        
        /* Wait for 5 us and release the line */
        SYS_DelayUs(5);
        DS18B20_DQ_INPUT();
    }
}
void DS18B20_WriteByte(uint8_t byte)
{
    uint8_t i = 8;
    /* Write 8 bits */
    while (i--) 
    {
        /* LSB bit is first */
        DS18B20_WriteBit(byte & 0x01);
        byte >>= 1;
    }
}
单个 DS18B20 的场景
初始化, 注意设置上拉, 以及输入和输出模式的切换
void DS18B20_Init(void)
{
    DS18B20_DQ_PULLUP();
    DS18B20_DQ_OUTPUT();
    DS18B20_DQ = SET;
    SYS_DelayUs(1000);
    DS18B20_DQ = RESET;
    SYS_DelayUs(1000);
    DS18B20_DQ = SET;
    SYS_DelayUs(2000);
}
读取温度, 这样读出的值并非温度值, 需要根据上面的温度转换, 乘以对应的温度单元值(默认为0.0625摄氏度)
// 发起转换
DS18B20_StartAll();
// 读取总线, 当转换完成时会变为高电平
while (!DS18B20_AllDone())
{
    UART1_TxChar('.');
    SYS_Delay(1);
}
// 重置总线
DS18B20_Reset();
// 跳过ROM选择
DS18B20_WriteByte(ONEWIRE_CMD_SKIPROM);
// 写入读取暂存器指令
DS18B20_WriteByte(ONEWIRE_CMD_RSCRATCHPAD);
// 读出9个字节的数据
for (i = 0; i < 9; i++) 
{
    /* Read byte by byte */
    data[i] = DS18B20_ReadByte();
}
// 温度值位于第1和第2个字节
temperature = data[1];
temperature = temperature << 8 | data[0];
读取ROM
// 重置总线
DS18B20_Reset();
// 写入读取ROM指令, 注意这个命令不能用于连接多个设备的总线, 否则结果读数是无意义的
DS18B20_WriteByte(ONEWIRE_CMD_READROM);
// 读出数据
for (i = 0; i < 8; i++) 
{
    *buf++ = DS18B20_ReadByte();
}
多个 DS18B20 的场景
指定设备地址, 读取温度
// 重置总线
DS18B20_Reset();
// 根据地址选择设备
DS18B20_Select(addr);
// 对选中的设备, 发起转换
DS18B20_WriteByte(DS18B20_CMD_CONVERTTEMP);
// 等待转换结束
// 重置总线
DS18B20_Reset();
// 根据地址选择设备
DS18B20_Select(addr);
// 写入读取暂存器指令
DS18B20_WriteByte(ONEWIRE_CMD_RSCRATCHPAD);
// 读取数据
for (i = 0; i < 9; i++) 
{
    *buf++ = DS18B20_ReadByte();
}
参考
- 单线总线搜索算法 1-WIRE SEARCH ALGORITHM https://www.maximintegrated.com/en/design/technical-documents/app-notes/1/187.html
 - 寄生供电模式 https://learn.openenergymonitor.org/electricity-monitoring/temperature/DS18B20-temperature-sensing
 - 寄生供电模式 https://e-radionica.com/en/blog/hum-how-to-use-the-ds18b20-with-parasitic-power-supply/
 
                    
                
                
            
        
浙公网安备 33010602011771号