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
相关产品推荐
相关产品推荐

