stm32-时序图学习-温度传感器-DHT11
目录
温度传感器-DHT11
1. 单总线协议:只有一条数据线,数据只能以比特流的方式传输,所以就会涉及到MSB(高位先出)还是LSB(低位先出),传输方向是半双工通信
2. 时序图
主从机应答信号时序图
第一步主机发送启动信号
点击查看代码
//向DHT11发送开始信号
void DHT11_SendStart(void)
{
//1.配置引脚为输出模式
DHT11_PinOutputModeConfig();
//2.把引脚电平拉低并持续20ms
GPIO_ResetBits(GPIOG,GPIO_Pin_9);
delay_ms(20);
//3.把引脚电平拉高并持续30us
GPIO_SetBits(GPIOG,GPIO_Pin_9);
delay_us(30);
}
第二步从机发送响应信号
点击查看代码
//判断DHT11是否响应
bool DHT11_IsACK(void)
{
uint32_t cnt = 0; //作为计数器
//1.配置引脚为输入模式
DHT11_PinInputModeConfig();
//2.判断PG9引脚是否检测到低电平 为了提高程序可靠性,所以人为添加超时机制,超时时间假设为100us
while( GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_9) == 1 && cnt < 100)
{
delay_us(1);
cnt++;
}
if(cnt >= 100)
return false;
cnt = 0;
//3.判断PG9引脚检测的低电平是否持续80us
while( GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_9) == 0 && cnt < 100)
{
delay_us(1);
cnt++;
}
if( cnt >= 100 )
return false;
else
return true;
}
** 注意:拉低时间可能不够80us,最好只判断不超过上限 **
DHT11发送的数据 0 的形式
DHT11发送的数据 1 的形式
第三步判断DHT11发送的bit的值,并存储到一个字节的bit0位置中
点击查看代码
//判断DHT11发送的bit的值,并存储到一个字节的bit0位置中
uint8_t DHT11_ReadBit(void)
{
//1.等待低电平出现
while( GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_9) == 1 );
//1.等待低电平结束
while( GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_9) == 0 );
//2.此时高电平出现,则延时 28us < n < 70us
delay_us(40);
//3.延时结束之后,判断PG9引脚的电平状态,如果电平还是高电平,则说明是bit = 1
if( GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_9) == 1 )
return 1;
else
return 0;
}
第四步DHT11读取1字节 DHT11提供的40bit是以MSB
点击查看代码
//DHT11读取1字节 DHT11提供的40bit是以MSB
uint8_t DHT11_ReadByte(void)
{
int i = 0;
//1.定义变量并初始化
uint8_t data = 0; // 0000 0000
//2.循环8次,接收一个字节
for(i = 0;i < 8;i++)
{
data <<= 1;
data |= DHT11_ReadBit();
}
return data;
}
第五步读取DHT11温湿度传感器的数据
点击查看代码
//读取DHT11温湿度传感器的数据
bool DHT11_ReadData(uint8_t buf[5])
{
int i = 0;
//1.MCU发送开始信号
DHT11_SendStart();
//2.MCU等待DHT进行响应
if( true == DHT11_IsACK() )
{
//3.循环读取40bit
for(i=0;i<5;i++)
{
buf[i] = DHT11_ReadByte();
}
//4.对数据进行校验
if( buf[4] == buf[0] + buf[1] + buf[2] + buf[3] )
{
return true;
}
else
return false; //说明读取数据失败,原因是校验未通过
}
else
{
return false; //说明读取数据失败,原因是DHT未响应
}
}
第六步显示数据
点击查看代码
int main()
{
uint8_t dhtbuf[5] = {0};
USART1_Config(9600);
while(1)
{
DHT11_ReadData(dhtbuf); //获取了一次温湿度数据
printf("temp = %d ℃, humi = %d %%RH\r\n",dhtbuf[2],dhtbuf[0]);
delay_ms(2000);
}
}
注意:时序图对时间要求严格,不要在代码段中打印,一打印就出错
参考李明轩老师笔记