电子说
前言
本项目主要通过使用STM32F103C8T6作为主控MCU,ESP8266作为数据透传模块,接入机智云AIoT云平台,通过在线智能产品,实现了远程联网、温湿度监测、APP控制等功能。
在上文中,主要介绍了“创建云端产品,烧录Gagent”,以便让设备能够联网,当然其中也备注了ESP8266烧写Gagent固件时的注意事项,说明定义数据点的作用。
在本文中,从原理开始讲解,阐述DHT11驱动的编写。
进入正文
1、DHT11 简要介绍
DHT11 器件采用简化的单总线通信,DATA 引脚用于微处理器与 DHT11 之间的通讯和同步,一次传送 40 位数据,高位先出。

举例:

2、时序分析(附代码)
用户主机(MCU)发送一次开始信号后,DHT11 从低功耗模式转换到高速模式,待主机开始信号结束后,DHT11 发送响应信号,送出 40bit 的数据,信号发送如图所示。

注意: 主机(MCU)从 DHT11 读取的温湿度数据总是前一次的测量值。
总线空闲:
DHT11 的 DATA 数据线由上拉电阻拉高一直保持高电平,此时 DHT11 的DATA 引脚处于输入状态,时刻检测外部信号。
MCU 发出请求信号:
MCU I/O 设置为输出同时输出低电平,且低电平保持时间不能小于 18ms,然后MCU I/O设置为输入状态。由于上拉电阻,MCU I/O 即 DHT11 的 DATA 数据线也随之变高,之后等待 DHT11 作出回答信号。
DHT11 发出应答信号:
当 DHT11 的 DATA 引脚检测到外部信号有低电平时,等待外部信号低电平结束,延迟后 DHT11 的 DATA引脚处于输出状态,输出 80us的低电平作为应答信号,紧接着输出 80us 的高电平通知 MCU 准备接收数据,MCU I/O 此时处于输入状态,检测到 DHT11 回应信号后,等待 80us 的高电平后的数据接收。

MCU 接收 40 位数据
由 DHT11 的 DATA 引脚输出 40 位数据,MCU 根据 I/O 电平的变化来判断是 “0” 还是 “1” 。
位数据 “0” 的格式为:
50us 的低电平和 26-28us的高电平。

位数据 “1” 的格式为:
50us 的低电平加 70us 的高电平。

DHT11 发出结束信号
DHT11 的 DATA 引脚输出 40 位数据后,继续输出低电平 50us 后转为输入状态,由于上拉电阻存在,变为高电平。
// 本驱动采用 HAL 库,us 级延时使用通用定时器实现,对 IO 引脚的状态的改变采用位操作以及直接寄存器操作
// 复位DHT11void DHT11_Rst(void){
DHT11_IO_OUT();
//设置为输出 DHT11_DQ_OUT = 0;
//拉低 HAL_Delay_ms(20);
//拉低至少18ms DHT11_DQ_OUT = 1;
//拉高 HAL_Delay_us(30);
//主机拉高20~40us}
//等待DHT11的回应//返回1:未检测到DHT11的存在//返回0:存在uint8_t DHT11_Check(void)
{
uint8_t retry = 0; DHT11_IO_IN();
//设置为输入
while(DHT11_DQ_IN && retry < 100)
//DHT11会拉低40~80us
{
retry++;
HAL_Delay_us(1);
}
if(retry >= 100)return 1;else
retry = 0;
while(!DHT11_DQ_IN && retry < 100)
//DHT11拉低后会再次拉高40~80us
{
retry++;
HAL_Delay_us(1);
}if(retry >= 100)return 1;
return 0;}
//从DHT11读取一个位//返回值:1/0uint8_t DHT11_Read_Bit(void)
{uint8_t retry = 0;while(DHT11_DQ_IN && retry < 100)//等待变为低电平
{
retry++;
HAL_Delay_us(1);
}
retry = 0;while(!DHT11_DQ_IN && retry < 100)//等待变高电平
{
retry++;
HAL_Delay_us(1);
}
delay_us(40);//等待40usif(DHT11_DQ_IN)return 1;elsereturn 0;
}
//从DHT11读取一个字节//返回值:读到的数据uint8_t DHT11_Read_Byte(void)
{
uint8_t i,dat; dat = 0;for (i=0;i<8;i++)
{
dat <<= 1;
dat |= DHT11_Read_Bit();
}
return dat;}
//从DHT11读取一次数据//temp:温度值(范围:0~50°)//humi:湿度值(范围:20%~90%)//返回值:0,正常;1,读取失败;2,校验和错误uint8_t DHT11_Read_Data(uint8_t *temp, uint8_t *humi)
{
uint8_t buf[5];uint8_t i;
DHT11_Rst();if(DHT11_Check() == 0)
{for(i = 0; i < 5; i++)
//读取40位数据
{
buf[i] = DHT11_Read_Byte(); }if((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4])
{
*humi = buf[0];
*temp = buf[2];
}elsereturn 2;
// 校验和错误
}elsereturn 1;return 0;
}
//初始化DHT11的 IO口, 同时检测DHT11的存在//返回1:不存在//返回0:存在
uint8_t DHT11_Init(void){ DHT11_GPIO_Init();
DHT11_Rst();return DHT11_Check();}
3、使用串口观察数据
将 printf 函数重定向至与 PC 相连的串口上。由于重定向相关函数已经包含在机智云生成的代码中(gizwits_product.c),我们直接使用 printf 进行数据打印即可。
#ifdef __GNUC__/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)#else#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)#endif /* __GNUC__ *//**
* @brief
Retargets the C library printf function to the USART.
* @param None
* @retval None
*/PUTCHAR_PROTOTYPE{/* Place your implementation of fputc here *//* e.g. write a character to the USART1 and Loop until the end of transmission */
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
return ch;}
以下为相关测试代码:
state = DHT11_Read_Data(&temperature, &humidity);if(state == 2){printf("the checksum is error
");}else if(!state){printf("temp = %d , humi = %d
", temperature, humidity);}else{printf("DHT11 is not answer
");}
若采集到的数据没有问题,即可将机智云协议相关代码移植进工程中。
本文结束。
审核编辑 :李倩
全部0条评论
快来发表一下你的评论吧 !