一、硬件介绍
我选用的板卡型号是FRDM-MCXN947,温湿度传感器型号是DHT22,实物如下图


FRDM-MCXN947板卡参数如下
内核:有两个ARM Cortex-M33内核,每个内核的主频均为150MHz
加速器:神经处理单元、PowerQuad、Smart DMA等
连接:
以太网PHY和连接器
HS USB Type-C连接器
SPI/I2C/UART连接器(PMOD/mikroBUS、DNP)
CAN-FD收发器
调试:带有CMSIS-DAP的板载MCU-Link调试器,JTAG/SWD连接器
传感器:P3T1755 I3C/I2C温度传感器,触摸板
扩展选项:Arduino接头(带FRDM扩展行)、FRDM接头、FlexIO/LCD接头、SmartDMA摄像头接头
DHT22产品参数:
供电电压:3.3V到5V
温度范围:-40到80℃,分辨率0.1℃,误差±0.5℃
湿度范围:0到100%RH,分辨率0.1%RH,误差±2%RH
接口线序:VCC,GND,digital
模块尺寸:38×20mm
二、接线方式
DHT22的引脚图如下

总共有三根引脚,分别是GND、VCC和S(数据引脚)。接线方式如下

三、流程图

四、驱动程序
DHT22的数据引脚输出的是数字信号,需要通过引脚实现启动信号和数据接收等功能。具体的源码如下
#include "dht22.h"
#include <zephyr/drivers/gpio.h>
#include <zephyr/sys/printk.h>
#define DHT22_GPIO_PIN 12
static const struct device *dht_gpio_dev;
static inline void delay_us(uint32_t us)
{
k_busy_wait(us);
}
int dht22_init(void)
{
dht_gpio_dev = DEVICE_DT_GET(DT_NODELABEL(gpio0));
if (!device_is_ready(dht_gpio_dev)) {
printk("DHT22 GPIO 未就绪!\n");
return -ENODEV;
}
gpio_pin_configure(dht_gpio_dev, DHT22_GPIO_PIN, GPIO_OUTPUT_HIGH);
printk("DHT22 初始化成功\n");
k_msleep(100);
return 0;
}
static void dht22_set_output(int value)
{
gpio_pin_configure(dht_gpio_dev, DHT22_GPIO_PIN, GPIO_OUTPUT);
gpio_pin_set(dht_gpio_dev, DHT22_GPIO_PIN, value);
}
static void dht22_set_input(void)
{
gpio_pin_configure(dht_gpio_dev, DHT22_GPIO_PIN, GPIO_INPUT);
}
static uint8_t dht22_read_byte(void)
{
uint8_t byte = 0;
for (int i = 0; i < 8; i++) {
while (!gpio_pin_get(dht_gpio_dev, DHT22_GPIO_PIN));
delay_us(40);
byte <<= 1;
if (gpio_pin_get(dht_gpio_dev, DHT22_GPIO_PIN)) {
byte |= 1;
}
while (gpio_pin_get(dht_gpio_dev, DHT22_GPIO_PIN));
}
return byte;
}
int dht22_read(struct dht22_data *data)
{
uint8_t buf[5] = {0};
// 启动信号
dht22_set_output(0);
k_msleep(18);
dht22_set_output(1);
delay_us(20);
dht22_set_input();
delay_us(30);
// 响应
if (gpio_pin_get(dht_gpio_dev, DHT22_GPIO_PIN)) return -EIO;
while (!gpio_pin_get(dht_gpio_dev, DHT22_GPIO_PIN));
while (gpio_pin_get(dht_gpio_dev, DHT22_GPIO_PIN));
// 读5字节
for (int i = 0; i < 5; i++) {
buf[i] = dht22_read_byte();
}
printk("[原始数据] %02x %02x %02x %02x %02x\n",
buf[0], buf[1], buf[2], buf[3], buf[4]);
// ====================== 校验和======================
uint16_t check = buf[0] + buf[1] + buf[2] + buf[3];
if ((uint8_t)check != buf[4]) {
printk("[校验错误]\n");
return -EINVAL;
}
// 转换数据
data->humidity = (buf[0] << 8 | buf[1]) / 10.0f;
data->temperature = ((buf[2] & 0x7F) << 8 | buf[3]) / 10.0f;
if (buf[2] & 0x80) data->temperature = -data->temperature;
return 0;
}其中gpio0和DHT22_GPIO_PIN对应DHT22的数据引脚端口。
五、效果展示
程序编译成功后下载到板卡上,通过串口软件打开就可以看到获取的温湿度数据值

六、问题总结
程序编写完成后串口一直没有打印,刚开始通过仿真发现传感器一直没有响应。通过AI定位要求数据端口有上拉电阻才行。而板卡的端口并不是为这个传感器而设定的,但是考虑到传感器应该会在数据端口加上拉电阻的,所以特地的查看了下传感器手册,发现在数据端口处有上拉电阻

后来发现在端口初始化时需要配置成默认高电平才可以。
之后也遇到温湿度数据获取完成后校验一直失败的问题,通过串口打印获取的原始数据和逻辑分析仪获取的数据对比,发现没有问题。自己计算这些数据值也是没有问题。所以只能是程序的校验方式有问题。最后是修改校验变量的数据类型才解决的。
七、相关文件
工程文件:MCXN947+DHT22.zip
我要赚赏金
