You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SiLabs BGM220开发板替代Arduino analogRead()的函数及DHT11读取方法

在SiLabs BGM220上读取DHT11温湿度传感器数据

首先纠正你对GPIO_PinOutGet(gpioPortB, 0)的误解:这个函数只能返回引脚的逻辑电平(0代表低电平,1代表高电平),根本不是读取电压值,而且DHT11用的是单总线通信协议,不是直接读引脚电平就能拿到数据的,必须严格按照它的时序来交互。

下面是在BGM220上实现DHT11读取的具体步骤和核心代码:

1. GPIO引脚配置

DHT11的DATA引脚需要配置为开漏输出+输入模式(单总线需要双向切换),以PB0为例:

// 配置PB0为开漏输出,初始高电平
GPIO_PinModeSet(gpioPortB, 0, gpioModeWiredAndPullUp, 1);

2. 实现DHT11的通信时序

DHT11的通信流程是:主机发起始信号 → 传感器响应 → 传感器发送40位数据(湿度整数+湿度小数+温度整数+温度小数+校验位)

核心函数实现

微秒级延时函数(需根据BGM220时钟校准)

BGM220默认时钟为38MHz,这里写一个简单的微秒延时(追求精准度可改用定时器实现):

void dht11_delay_us(uint32_t us) {
  while (us--) {
    // 38MHz时钟下,约1us对应的循环次数,可自行校准
    for (uint32_t i = 0; i < 38; i++) {
      __NOP();
    }
  }
}

发送起始信号并等待传感器响应

bool dht11_start(void) {
  // 主机拉低总线至少18ms
  GPIO_PinOutClear(gpioPortB, 0);
  dht11_delay_us(18000);
  
  // 主机释放总线,等待传感器响应
  GPIO_PinOutSet(gpioPortB, 0);
  dht11_delay_us(20);
  
  // 切换为输入模式,读取传感器响应
  GPIO_PinModeSet(gpioPortB, 0, gpioModeInputPullUp, 1);
  dht11_delay_us(40);
  
  // 检查传感器是否拉低总线
  if (!GPIO_PinInGet(gpioPortB, 0)) {
    // 等待传感器释放总线
    while (!GPIO_PinInGet(gpioPortB, 0));
    return true;
  }
  return false;
}

读取一位数据

uint8_t dht11_read_bit(void) {
  uint8_t bit = 0;
  // 等待传感器拉低总线(起始位)
  while (GPIO_PinInGet(gpioPortB, 0));
  // 等待传感器释放总线
  while (!GPIO_PinInGet(gpioPortB, 0));
  // 延时40us,判断电平:高电平持续>26us为1,否则为0
  dht11_delay_us(40);
  if (GPIO_PinInGet(gpioPortB, 0)) {
    bit = 1;
    // 等待高电平结束
    while (GPIO_PinInGet(gpioPortB, 0));
  }
  return bit;
}

读取一个字节

uint8_t dht11_read_byte(void) {
  uint8_t byte = 0;
  for (int i = 7; i >= 0; i--) {
    byte |= (dht11_read_bit() << i);
  }
  return byte;
}

读取完整温湿度数据

bool dht11_read_data(uint8_t *humidity_int, uint8_t *humidity_dec, uint8_t *temp_int, uint8_t *temp_dec) {
  if (!dht11_start()) {
    return false;
  }
  
  uint8_t humi_int = dht11_read_byte();
  uint8_t humi_dec = dht11_read_byte();
  uint8_t temp_int_val = dht11_read_byte();
  uint8_t temp_dec_val = dht11_read_byte();
  uint8_t checksum = dht11_read_byte();
  
  // 切换回输出模式,保持总线高电平
  GPIO_PinModeSet(gpioPortB, 0, gpioModeWiredAndPullUp, 1);
  
  // 校验数据
  if ((humi_int + humi_dec + temp_int_val + temp_dec_val) == checksum) {
    *humidity_int = humi_int;
    *humidity_dec = humi_dec;
    *temp_int = temp_int_val;
    *temp_dec = temp_dec_val;
    return true;
  }
  return false;
}

3. 使用示例

在主循环中调用:

uint8_t humi_int, humi_dec, temp_int, temp_dec;
if (dht11_read_data(&humi_int, &humi_dec, &temp_int, &temp_dec)) {
  // 可通过串口输出数据,格式示例:湿度X.X%,温度Y.Y℃
} else {
  // 读取失败,处理错误(如重试)
}

注意事项

  • 延时函数需根据BGM220实际时钟频率校准,时序错误会直接导致读取失败
  • DHT11采样周期至少1秒,不要频繁发起读取请求
  • 确保传感器VCC接3.3V(BGM220为3.3V系统),GND接开发板GND,DATA引脚连接正确

内容的提问来源于stack exchange,提问作者TA L 1223nij

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 15:15:54