第七章、DHT11: 单总线协!议
1、DHT11是什么 ?有什么特性 ?
2、单总线协议是什么 ?原理 ?DHT11的单总线协议的组成 ?
## 1、DHT11定义 单总线协议是一种用于在多个设备之间进行通信的协议,所有设备共享同一条数据线(总线),通过特定的时序和信号来区分不同设备的通信。原理:
单总线协议通过在同一条数据线上发送和接收数据,利用时序控制和信号电平来实现设备之间的通信。每个设备在总线上都有唯一的地址,主设备通过发送特定的命令来选择与之通信的从设备。
DHT11温湿度传感器使用单总线协议进行数据传输,其协议主要包括以下几个部分:
起始信号:主设备向DHT11发送一个起始信号,持续约18毫秒,表示开始通信。
应答信号:DHT11在接收到起始信号后,发送一个应答信号,持续约20-40微秒,表示准备好发送数据。
数据传输:DHT11通过单总线发送40位数据,包括湿度和温度信息。每位数据由一个高电平和一个低电平组成,具体时长决定了数据位的值(0或1)。
校验位:最后,DHT11发送一个校验位,用于验证数据的完整性。
2、微秒延时在其中的作用 ?
时序控制:在数据传输过程中,微秒级的延时确保了主设备和从设备之间的时序同步,避免数据丢失或错误。
信号稳定:在发送和接收信号之间的延时可以确保信号在总线上稳定,避免由于信号抖动导致的误读。
数据完整性:通过精确控制延时,可以确保每一位数据的发送和接收都在预定的时间窗口内完成,从而提高数据的完整性和可靠性。
3、如何实现微秒延时 ?
1.使用循环延时
通过空循环来实现延时,适用于简单的延时需求,但不够精确。
void delay_us(unsigned int us) {
for (unsigned int i = 0; i < us; i++) {
// 根据具体的系统时钟频率调整循环次数
for (volatile int j = 0; j < 10; j++);
}
}
2. 使用定时器
使用硬件定时器可以实现更精确的延时。
void delay_us(unsigned int us) { // 配置定时器
TIM2->PSC = 72 - 1; // 预分频,假设系统时钟为72MHz
TIM2->ARR = us; // 设置自动重装载寄存器
TIM2->CNT = 0; // 清零计数器
TIM2->CR1 |= TIM_CR1_CEN; // 启动定时器
while (!(TIM2->SR & TIM_SR_UIF)); // 等待更新中断标志位
TIM2->SR &= ~TIM_SR_UIF; // 清除更新中断标志位
}
3. 使用系统时钟
如果系统支持,使用系统时钟的延时函数(如 HAL_Delay())可以实现毫秒级延时,结合其他方法实现微秒级延时。
4. 使用专用延时库
一些嵌入式开发环境提供了专用的延时库,可以直接调用。
注意事项:
精度:使用循环延时时,延时的精度受编译器优化和系统时钟频率影响,可能不够准确。
中断:在延时期间,可能会影响中断的响应,特别是使用循环延时时。
系统负载:在高负载情况下,延时可能会受到影响,使用定时器通常更可靠。
4、DHT11
(本质也是一个滑动变阻器,把外界的环境信息转化成电压值,内部的一个高级一点的芯片把电压值转化成ADC,又通过内部的计算,把这个转化成十进制)
检测外部温度/湿度信号,当有数据后,
会通过某种通讯协议,发送给主设备,G030拿到数据后自己分析,通过公式转化得到温度和湿度。这是一种传感器;;另一种传感器是DHT11内部直接转化,得到当前的温度和湿度,再传给G030,节省了一步计算(也就是节省了一部分性能)
三根引脚,第一根是VCC,3.3V/5V 第三根是GND(0V),中间的一根是Data数据线,默认使用单总线协议,这是一种通讯方式;
5、通讯的分类
单工/全双工/半双工 串行/并行 同步/异步
单总线协议的一般形式:
主机:发送开始信号(18ms的低电平)
从机:给出一个反馈(响应信号是一个低电平,低电平的时间是30us)
从机:发送数据给主机(温度/湿度)
正常数据都由0/1组成,而这里0:由一段电平组成,就是20us的低电平和50us的高电平认定为0; 1由一段电平组成—50us的低电平,50us的高电平-----单总线只有一根线,不参考GND的数据的发送,核心点在于高低电平的时长
主机:停止信号
**
6、实验
**
移植步骤
1、写项目框架: printf移植框架
2、 移植 dht11 的 .c/.h 到项目中
3、 在keil中 添加 dht11.c 文件
4、 增加定时器14,写微秒延时函数
5、确定GPIO_CLK时钟被打开(开启PA8 输出模式)
6、 DTH11单总线协议
开始+响应+4字节数据+1字节校验
毫秒级延时 —》 tim14
// DHT11代码移植
void delay_us(uint16_t nus){
// DHT11 微秒延时
__HAL_TIM_SetCounter(&htim14,0);
__HAL_TIM_ENABLE(&htim14);
while( __HAL_TIM_GetCounter(&htim14)< nus);
__HAL_TIM_DISABLE(&htim14);
}
// 核心代码
FS_DHT11_Init();
uint8_t humiH,humiL,tempH,tempL;
while (1)
{
DHT11_Read_Data(&humiH,&humiL,&tempH,&tempL);
printf("湿度:%d.%d 温度:%d.%d \r\n",humiH,humiL,tempH,tempL);
HAL_Delay(1000);
}