dht11如何才能精确到小数点后两位啊,还有这里为什么写的是<<8啊
2条回答 默认 最新
关注 不知道你这个问题是否已经解决, 如果还没有解决的话:- 给你找了一篇非常好的博客,你可以看看是否有帮助,链接:STM32利用滴答定时器实现高精度延时(在DHT11温湿度传感器中的应用)
- 除此之外, 这篇博客: stm32实现DHT11读取温湿度中的 数据传输的数据 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:
一次完整的数据传输为40bits,也就是32位机的5个字节(byte),假如数据为buf[0]~buf[4],每个buf为一个unsigned char,或者其他8位的数据类型,buf[0]就是湿度的整数数据,buf[1]就是其湿度的小数部分,然后buf[2]就是温度的整数部分,buf[3]就是其温度的小数部分,buf[4]是校验和,也就是前面4个buf加起来的和。如果前面四个加起来等于校验和,说明数据传输成功,否则说明数据传输有问题。
- 以下回答来自chatgpt:
解决方案: 在stm32中实现对dht11读取温湿度值的精确控制,需要对DHT11输出的波形进行解码,从而获取到温湿度数据。在解码波形的过程中,需要计算出低电平持续时间和高电平持续时间,用于将波形转换为二进制数。根据DHT11手册,温湿度数据分为整数和小数两部分,因此需要分别计算出整数和小数部分,再将它们组合成一个完整的数值。
以下是代码示例:
// 解码DHT11输出的波形,获取温湿度数据 // 参数:data 保存温湿度数据的数组,长度为5 // 返回值:成功返回0,失败返回负数 int decode_dht11(uint8_t* data) { // 发送开始信号 // 设置引脚为输出模式,并输出低电平 GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = GPIO_PIN_0; // 选择引脚 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 输出模式 GPIO_InitStruct.Pull = GPIO_PULLUP; // 上拉 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; // 低速 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); // 输出低电平 HAL_Delay(20); // 低电平持续时间至少18ms HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET); // 输出高电平 HAL_Delay(40); // 高电平持续时间20-40us // 切换引脚为输入模式,接收DHT11响应信号 GPIO_InitStruct.Mode = GPIO_MODE_INPUT; // 输入模式 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); uint32_t t = 0; while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET) { HAL_Delay(1); ++t; if (t > 80) { return -1; // 响应信号持续时间大于80us,通信失败 } } t = 0; while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET) { HAL_Delay(1); ++t; if (t > 80) { return -2; // 响应信号持续时间大于80us,通信失败 } } t = 0; while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET) { HAL_Delay(1); ++t; if (t > 80) { return -3; // 响应信号持续时间大于80us,通信失败 } } // 解码温湿度数据 uint8_t buffer[5]; for (int j = 0; j < 5; ++j) { uint8_t d = 0; for (int i = 7; i >= 0; --i) { // 测量低电平持续时间 t = 0; while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET) { HAL_Delay(1); ++t; if (t > 100) { return -4; } } HAL_Delay(40); // 判断是否有高电平产生 if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET) { d |= 1 << i; // 测量高电平持续时间 t = 0; while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET) { HAL_Delay(1); ++t; if (t > 100) { return -5; } } } } buffer[j] = d; } // 数据校验 uint8_t sum = buffer[0] + buffer[1] + buffer[2] + buffer[3]; if (sum != buffer[4]) { return -6; // 校验和错误 } // 计算温度和湿度值 int temp_int = (int)buffer[2]; int temp_dec = (int)buffer[3]; int humidity_int = (int)buffer[0]; int humidity_dec = (int)buffer[1]; data[0] = (uint8_t)(humidity_int * 10 + humidity_dec); data[1] = 0; data[2] = (uint8_t)(temp_int * 10 + temp_dec); data[3] = 0; data[4] = sum; return 0; }
关于参考资料中的 <<8 操作,它是将一个8位的数左移8位,相当于将该数乘以256。在温湿度数据传输过程中,第1个字节表示湿度的整数部分,第2个字节表示湿度的小数部分,而温度的整数部分和小数部分分别在第3个和第4个字节中。为了将整数部分和小数部分组合成一个带小数的数值,需要将小数部分左移8位,相当于将它乘以256,再与整数部分相加。因此,代码中需要进行左移位运算,将小数部分左移8位,再与整数部分相加得到完整的温湿度数值。
如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 1无用
悬赏问题
- ¥30 YOLO检测微调结果p为1
- ¥20 求快手直播间榜单匿名采集ID用户名简单能学会的
- ¥15 DS18B20内部ADC模数转换器
- ¥15 做个有关计算的小程序
- ¥15 MPI读取tif文件无法正常给各进程分配路径
- ¥15 如何用MATLAB实现以下三个公式(有相互嵌套)
- ¥30 关于#算法#的问题:运用EViews第九版本进行一系列计量经济学的时间数列数据回归分析预测问题 求各位帮我解答一下
- ¥15 setInterval 页面闪烁,怎么解决
- ¥15 如何让企业微信机器人实现消息汇总整合
- ¥50 关于#ui#的问题:做yolov8的ui界面出现的问题