118 lines
3.0 KiB
C
118 lines
3.0 KiB
C
#include "dht11.h"
|
|
#include "bitband.h"
|
|
#include "systick.h"
|
|
|
|
#define DATA_OUT PCOut(10)
|
|
#define DATA_IN PCIn(10)
|
|
|
|
// 将连接 DHT11 的管脚设置为浮空输入(变为输入模式)
|
|
static void dht11_set_input(void)
|
|
{
|
|
GPIO_InitTypeDef GPIO_InitStruct;
|
|
|
|
// 浮空输入模式
|
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
|
|
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
|
|
GPIO_Init(GPIOC, &GPIO_InitStruct);
|
|
}
|
|
|
|
// 将连接 DHT11 的管脚设置为推挽输出或开漏输出(变为输出模式)
|
|
static void dht11_set_output(void)
|
|
{
|
|
GPIO_InitTypeDef GPIO_InitStruct;
|
|
|
|
// 开漏输出模式
|
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;
|
|
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
|
|
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
|
|
GPIO_Init(GPIOC, &GPIO_InitStruct);
|
|
}
|
|
|
|
// 将连接 DHT11 的管脚设置位输出状态为 s(0, 1)
|
|
static void dht11_set_output_status(int s)
|
|
{
|
|
dht11_set_output();
|
|
DATA_OUT = s ? 1 : 0;
|
|
|
|
}
|
|
|
|
|
|
// 将连接 DHT11 的管脚设置位输出状态为 s(0, 1)
|
|
static int dht11_get_input_status()
|
|
{
|
|
dht11_set_input();
|
|
|
|
return DATA_IN;
|
|
}
|
|
|
|
// 初始化 DHT11 控制器
|
|
void dht11_init(void)
|
|
{
|
|
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
|
|
// 设置位浮空输入
|
|
dht11_set_input();
|
|
// 初始化时钟(防止主函数内忘记初始化)
|
|
systick_init();
|
|
}
|
|
|
|
// 获取 DHT11 传感器的 40位 数据,放入buf中
|
|
// 成功返回 1. 失败返回 0
|
|
int dht11_get_values(u8 buf[5])
|
|
{
|
|
u8 status = 0;
|
|
u8 time = 0;
|
|
// 用于记录缓冲区地址
|
|
int i;
|
|
|
|
int bit;
|
|
u8 temp = 0;
|
|
// 发送起始信号
|
|
// 先保证数据线位高电平
|
|
dht11_set_output_status(1);
|
|
// 发送起始信号
|
|
dht11_set_output_status(0);
|
|
delay_ms(20);
|
|
// 拉高
|
|
dht11_set_output_status(1);
|
|
delay_us(20);
|
|
// 等待 40us,如果有数据线没被拉低,则说明设备不存在
|
|
do
|
|
{
|
|
// 获取输入的状态
|
|
status = dht11_get_input_status();
|
|
delay_us(2);
|
|
time++;
|
|
} while (status == 1 && time < 20);
|
|
if (temp >= 20)
|
|
{
|
|
return 0;
|
|
}
|
|
// 等待转为高电平
|
|
while (!dht11_get_input_status());
|
|
|
|
// 读取 40bit 数据
|
|
// i 表示字节的缩影
|
|
for (i = 0; i < 5; i++)
|
|
{
|
|
// temp 表示正在读取的一个字节
|
|
temp = 0;
|
|
for (bit = 0; bit < 8; bit++)
|
|
{
|
|
// 等待转为低电平
|
|
while(dht11_get_input_status());
|
|
// 等待转为高电平
|
|
while(!dht11_get_input_status());
|
|
delay_us(40);
|
|
// 将 40us 后的电平状态放入 temp 的最低位
|
|
temp <<= 1;
|
|
temp |= dht11_get_input_status();
|
|
}
|
|
// 将获取到的一个字节填入数组中
|
|
buf[i] = temp;
|
|
}
|
|
// 主机拉高
|
|
dht11_set_output_status(1);
|
|
|
|
return 1;
|
|
}
|