单片机源程序如下(代码注释非常详细):
#include "dht11.h" //导入头文件dht11.h
static void DHT11_Input(void); //声明static函数DHT11_Input,用于配置DHT11的引脚为输入模式
static void DHT11_Output(void); //声明static函数DHT11_Output,用于配置DHT11的引脚为输出模式
/*定义全局变量,分别用于统计湿度高位;湿度低位;温度高位;温度低位*/
u8 DHT11_hem_high,DHT11_hem_low,DHT11_temp_high,DHT11_temp_low;
static void DHT11_Input(void) //设置DHT11数据引脚的输入模式的配置
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(DHT11_RCC,ENABLE); //开启GPIOD的时钟
GPIO_InitStructure.GPIO_Pin = DHT11_PIN; //设置引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速率50MHz
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //配置输入模式为上拉输入模式
GPIO_Init(DHT11_GPIO, &GPIO_InitStructure);//把上面的配置初始化
}
static void DHT11_Output(void)//设置DHT11数据引脚的输出模式的配置
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(DHT11_RCC,ENABLE);//开启GPIOD时钟
GPIO_InitStructure.GPIO_Pin = DHT11_PIN;//设置引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//配置为推挽输出
GPIO_Init(DHT11_GPIO, &GPIO_InitStructure);//初始化
}
/*从这里开始就根据DHT11使用说明的流程进行,确保万无一失*/
void DHT11_Start(void)//DHT11的开始程序
{
delay_init();//调用Systick,开启
DHT11_Output();//设置为输出模式
DHT11_hem_high = 0;
DHT11_hem_low = 0;
DHT11_temp_high = 0;
DHT11_temp_low = 0;
}
u16 DHT11_ReadByte(void)//读取DHT11每个字节的函数
{
u8 temp=0,i,cout;//三个变量的含义(1)temp用于储存数据(2)i表示字节的位数(3)cout用于保证执行条件或函数
DHT11_Input();
for(i=0;i<8;i++)//这个for循环的意义就是依次读8位字节,所以只执行8次,
{
cout=1;//确保执行while
while(!DHT11_ReadBit() && cout++);//当 [读取到PB3的电平不为1 且 cout++都为真] 的条件下执行循环,否则跳出循环
delay_us(30);//延时30us,再读取PB3的状态
temp = temp << 1;//表示把上次的temp的值左移一位,因为DHT11读取的数据是先出高值再出低值,
if(DHT11_ReadBit() == Bit_SET)//如果 [ 读取到PB3的电平等于Bit_SET的值 为真 ] ,则执行表达式
{
temp |=1; //temp=temp|1,进行或运算,有1得1
}
//等待输出的电平为低电平,进入下一位数据接收
cout=1;
while(DHT11_ReadBit() && cout++);
}
return temp;//返回接收到的temp
}
u16 DHT11_ReadData(int *shidu,int *wendu)//读取DHT11的数据,把读取到的自己整合
{
u16 cout = 1;//用于保证语句执行的变量
u16 temp_high,temp_low,hem_high,hem_low,Check;//用于整合字节的变量,分别是温度高位,温度低位,湿度高位,湿度低位,校验和
DHT11_Output();//把引脚切换为输出模式
DHT11_ResetBit();//拉低引脚电平,就是输出高电平
delay_ms(20);//持续20ms,数据手册上说要至少拉低18ms,保证DHT11能够检测到起始信号
DHT11_SetBit();//抬高引脚的电平;也就是输出低电平
delay_us(40);//持续30us,数据手册上说的区间是20-40us
DHT11_Input();//设置PB3为输入模式
/* 如果MCU采集到PE13的数据输入是低电平的话则执行表达式 */
if(DHT11_ReadBit() == Bit_RESET)
{
cout = 1;//低电平响应信号,等待DHT11响应完毕
while(!DHT11_ReadBit() && cout++);
cout = 1;//高电平传输数据,等待DHT11传输完毕,持续26us - 28us表示的是0;持续70us表示的是1
while(DHT11_ReadBit() && cout++);
/*开始按顺序接收DHT11的回传数据*/
/*根据DHT11的使用说明一共会接收5个字节的数据*/
hem_high = DHT11_ReadByte();//第一个接收到的是湿度的高八位,温度整数数据
hem_low = DHT11_ReadByte();//第二个接收到的是湿度的低八位,温度小数数据
temp_high = DHT11_ReadByte();//第三个接受到的是温度的高八位,湿度整数数据
temp_low = DHT11_ReadByte();//第四个接收到的是温度的低八位,湿度小数数据
Check = DHT11_ReadByte();//最后接收到的是前四位的和,用于校验,确保精度
if(Check == ( temp_high + temp_low + hem_high + hem_low ))//校验和.如果前4个字节加起来的和等于Check
{
*shidu= hem_high;//写入湿度整数变量
// DHT11_hem_low = hem_low;//写入湿度小数变量
*wendu= temp_high;//写入温度整数变量
// DHT11_temp_low = temp_low;//写入温度小数变量
return 1;//返回1,确保有效,表示成功采集一次数据
}
else
{
return 0;//若不正确,否则返回0,表示未成功采集数据
}
}
return 0;
}
u16 DHT11_GetTemp(void) //获取温度值
{
/* 这句话的意思是 */
/* [把DHT11_temp_high左移8位] 再与[DHT11_temp_low]进行 或运算,有1得1 */
/* 因为DHT11只能采集整数数据,所以做了或运算后还是原先采集到的整数数据 */
return(DHT11_temp_high <<8 | DHT11_temp_low);
}
u16 DHT11_GetHem(void)//获取湿度值
{
/* [把DHT11_hem_high左移8位] 再与[DHT11_hem_low]进行 或运算,有1得1 */
return(DHT11_hem_high <<8 | DHT11_hem_low);
}
全部代码51hei下载地址:
STM32F103C8T6.7z
(200.94 KB, 下载次数: 457)
|