温湿度传感器
硬件使用
- STM32F103 RCT6
- DHT11 (温湿度传感器)
软件使用
- keil5 MDK环境
- 串口调试助手
实现说明
根据 DHT11 温湿度传感器手册
1. 初始化 DHT11
复位 DHT11 ,根据时序图写出设置
```
void dht_Rst(void)
{
dht_output(); //设置 dht11 为普通推挽输出
dht_low_input(); //设置 dht11 为低电平
delay_ms(20); //延时20ms 时间根据时序图应该定义为18ms到30ms之间
dht_high_input(); //设置 dht11 为高电平
delay_us(30); //延时30us,少量延时,不易出错
}
```
**==注意:==** 部分代码为博主自己编写的函数,都很==简单!== 例如设置引脚模式,设置引脚高低电平等。由于温湿度传感器 DHT11 对时间要求比较高,**所以延时函数,我这边采用的是==大佬正点原子编写的==** 。
根据时序图可知
应答信号为:低电平 83 us,高电平 87 us。
所以代码编写为:
```
u8 dht_Check(void)
{
u8 k = 0; //设置 参数 k,防止程序卡死
dht_input(); //定义 dht11 为输入
while(dht_read_input && k < 100) //判断是否有低电平输入(dht11回应信号),或是 超出 83 us
{
k++; //延时等待
delay_us(1);
}
if(k >= 100 )return 1; //超时退出
else k = 0;
while(!dht_read_input && k<100 ) //同理,87us 高电平退出while循环
{
k++;
delay_us(100); //延时等待
}
if(k>=100)return 1; //超时退出
return 0; //成功监测应答信号,返回0
}
```
所以 DHT11 初始化代码为:
u8 dht_Init(void)
{
dht_output();
dht_Rst();
return dht_Check();
}
2. DHT11 读取数据信息
由 DHT11手册 可以得到,DHT11 会输出40位数据
每位数据 格式如下图所示:
所以每位数据获取代码为:
u8 dht_ReadBit(void)
{
u8 k = 0; //定义 参数k ,防止超时
while(dht_read_input && k<100) //一检测出低电平跳出循环 或 超时跳出
{
k++;
delay_us(1); //延时等待
}
k = 0;
while(!dht_read_input && k<100) //一检测出高电平跳出循环 或 超时跳出
{
k++;
delay_us(1); //延时等待
}
delay_us(40); //这时候为刚检测出高电平,由于数据格式 数据为 和数据位 只在高电平的时间不同,所以延时 40us ,如果还为高电平,则为 数据位 1
if(dht_read_input) return 1;
else return 0;
}
由于手册下关于数据位描述为下图:
可知:应该把代码分为8位一组,并且先测出的为 高位
代码为:
u8 dht_ReadByte(void)
{
u8 i,dat;
dat = 0;
for(i=0;i<8;i++)
{
dat<<=1; //数据左移 不够补0
dat|=dht_ReadBit(); // | 字符 与0相或,结果为 后面的那个,即只取决于dht_ReadBit() 得到的数据
}
return dat; //返回数据
}
3. DHT11 具体读取数据代码
u8 dht_ReadData(u8 *t,u8 *h)
{
u8 temp[5]; //存放40位数据,每8位一组,总共5组
u8 i;
dht_Rst(); //复位 DHT11,防止传感器处在其他状态
if(dht_Check() == 0) //判断是否应答成功
{
for(i=0;i<5;i++)
{
temp[i] = dht_ReadByte(); //取出数值
}
if(temp[0]+temp[1]+temp[2]+temp[3] == temp[4]) //判断检验和
{
*h = temp[0]; //传出参数,只传整数值,0和2为整数值,1和3位小数值
*t = temp[2];
}
}else return 1;
return 0;
}
4.通过串口发送到串口调试助手
(1)初始化串口
GPIO_InitTypeDef GPIO_InitStrue;
USART_InitTypeDef USART_InitStrue;
NVIC_InitTypeDef NVIC_InitStrue;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //使能 USART1
GPIO_InitStrue.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 //USART1_Tx USB Rx STM32中为 Tx,需要接到 USB转TTL串口中的 Rx
GPIO_InitStrue.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStrue.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_InitStrue);
//USART1_Rx USB Tx
GPIO_InitStrue.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_InitStrue.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStrue.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_InitStrue);
USART_InitStrue.USART_BaudRate = 115200;
USART_InitStrue.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStrue.USART_Mode = USART_Mode_Tx|USART_Mode_Rx;
USART_InitStrue.USART_Parity = USART_Parity_No;
USART_InitStrue.USART_StopBits = USART_StopBits_1;
USART_InitStrue.USART_WordLength = USART_WordLength_8b;
USART_Init(USART1,&USART_InitStrue);
USART_Cmd(USART1,ENABLE);
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
NVIC_InitStrue.NVIC_IRQChannel = USART1_IRQn;//设置中断
NVIC_InitStrue.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级1
NVIC_InitStrue.NVIC_IRQChannelSubPriority = 1; //子优先级1
NVIC_Init(&NVIC_InitStrue);
(2)中断发送数据
void USART1_IRQHandler(void)
{
u8 s;
while(*s!='\0')
{
while(USART_GetFlagStatus(USART1,USART_FLAG_TC )==RESET);
USART_SendData(USART1,*s);
s++;
}
}
最后
第一次尝试编写博客,若是有什么建议,欢迎批评指出。
后续会逐步分块更新,并会在最后一篇文章上传源代码。
若是该文章对你有作用或是觉得文章写得还行,帮忙点点赞,三连,求求了!