dth11.c文件①
#include "dht11.h"
#include "delay.h"// 1、温湿度模块初始化(PG9)
void Dht11_Init(void)
{// 0、GPIO外设信息结构体GPIO_InitTypeDef GPIO_InitStruct;// 1、使能硬件时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);// 2、配置GPIOB外设 (TRIG)GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; // 引脚:第9根引脚GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; // 模式:输出模式(现在是初始化,后面再转换)GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; // 输出类型:推挽模式GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; // 是否上下拉:上拉GPIO_InitStruct.GPIO_Speed = GPIO_High_Speed; // 速度:高速GPIO_Init(GPIOG, &GPIO_InitStruct); // 将配置好的外设信息,通过此函数写到其相应的外设寄存器中// 3、根据温湿度时序图,引脚一开始为高电平 DHT11_OUT = 1; }// 2、转换温湿度引脚的输入输出模式
void Dht11_ConvertMode(GPIOMode_TypeDef GPIO_Mode)
{GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; // 引脚:第9根引脚if(GPIO_Mode == GPIO_Mode_OUT){GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; // 模式:输出模式(现在是初始化,后面再转换)GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; // 输出类型:推挽模式GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; // 是否上下拉:上拉 // 你的开发板电路有上拉电阻,这里就不需要GPIO_InitStruct.GPIO_Speed = GPIO_High_Speed; // 速度:高速}else{GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN; // 模式:输入模式GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; // 是否上下拉:上拉 }GPIO_Init(GPIOG, &GPIO_InitStruct); // 将配置好的外设信息,通过此函数写到其相应的外设寄存器中
}// 3、获取温湿度的数据
int8_t Dht11_GetVal(uint8_t pbuf[5])
{uint16_t t_count = 0;int8_t i,j = 0;uint8_t data = 0;uint8_t check_num = 0;// 一、stm32单片机发送信号dht11模块 // 方老板:小坤啊,起来下蛋啦// 1、将PG9引脚设置为输出模式Dht11_ConvertMode(GPIO_Mode_OUT);// 2、将PG9引脚置为低电平DHT11_OUT = 0; // 3、至少延时18ms以上(20ms即可)delay_ms(20);// 4、将PG9引脚置为高电平DHT11_OUT = 1; // 5、至少延时20us-40us(30us即可)delay_us(30);// 二、dht11模块发送响应信号给stm32单片机 // 小坤: 好的,方老板,我马上下// 1、将PG9引脚设置为输入模式Dht11_ConvertMode(GPIO_Mode_IN);// 2、等待PG9引脚是否变为低电平(看其从高电平变为低电平时是否超时(4ms))t_count = 0;while(DHT11_IN == 1) {t_count++;delay_us(1);if(t_count > 4000)return -1;}// 3、等待PG9引脚在低电平是否超时(80us,建议100us)t_count = 0;while(DHT11_IN == 0) {t_count++;delay_us(1);if(t_count > 100)return -2;}// 4、等待PG9引脚在高电平是否超时(80us,建议100us)t_count = 0;while(DHT11_IN == 1) {t_count++;delay_us(1);if(t_count > 100)return -3;}// 三、dht11模块发送40个bit数据给stm32单片机,stm32单片机接受并验证 // 小坤努力下40个蛋给方老板,方老板根据这些是公还是母(公比较重,母比较轻)给钱// 1、将40个数据一次性存到有5个字节的数组中(uint8_t pbuf[5])for(i=0; i<5; i++) // 一共有5个数据(每个数据是1个字节,8位){data = 0;for(j=7; j>=0; j--) // 高位先出,因此从7开始,并需要进行移位操作{// a、等待发送数据的高电平的到来(看其变成低电平是否超时50us(建议60us))t_count = 0;while(DHT11_IN == 0) {t_count++;delay_us(1);if(t_count > 70)return -4;}// b、开始延时一段时间(建议40us)delay_us(40);// c、判断引脚是否为高电平(1的话进行移位操作)if(DHT11_IN == 1){data |= 1<<j;// 将70us剩余的高电平时间,给略过t_count = 0;while(DHT11_IN == 1) {t_count++;delay_us(1);if(t_count > 50)return -5;}} }pbuf[i] = data;}// 2、进行数据校验check_num = (pbuf[0] + pbuf[1] +pbuf[2] +pbuf[3]) & 0xff; // 得出末8位if(check_num != pbuf[4]){return -6;}// 四、通信的结束delay_us(60);// 1、将PG9引脚设置为输出模式Dht11_ConvertMode(GPIO_Mode_OUT);// 2、将PG9引脚置为高电平DHT11_OUT = 1;return 0;}
dth11.c版本②
#include <stm32f4xx.h>
#include "delay.h"
#define PFout(n) (*(volatile uint32_t *)(0x42000000+(GPIOF_BASE+0x14-0x40000000)*32+(n)*4))
#define PAin(n) (*(volatile uint32_t *)(0x42000000+(GPIOA_BASE+0x10-0x40000000)*32+(n)*4))
#define PEout(n) (*(volatile uint32_t *)(0x42000000+(GPIOE_BASE+0x14-0x40000000)*32+(n)*4))
#define PEin(n) (*(volatile uint32_t *)(0x42000000+(GPIOE_BASE+0x10-0x40000000)*32+(n)*4))
#define PBout(n) (*(volatile uint32_t *)(0x42000000+(GPIOB_BASE+0x14-0x40000000)*32+(n)*4))
#define PBin(n) (*(volatile uint32_t *)(0x42000000+(GPIOB_BASE+0x10-0x40000000)*32+(n)*4))
#define PCin(n) (*(volatile uint32_t *)(0x42000000+(GPIOC_BASE+0x10-0x40000000)*32+(n)*4))
#define PCout(n) (*(volatile uint32_t *)(0x42000000+(GPIOC_BASE+0x14-0x40000000)*32+(n)*4))
#define PGout(n) (*(volatile uint32_t *)(0x42000000+(GPIOG_BASE+0x14-0x40000000)*32+(n)*4))
#define PGin(n) (*(volatile uint32_t *)(0x42000000+(GPIOG_BASE+0x10-0x40000000)*32+(n)*4))
static GPIO_InitTypeDef GPIO_InitStructure;
void dht11_init(void)
{//打开端口G的硬件时钟,就是供电RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG,ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //9号引脚GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //输出模式GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; //开漏GPIO_InitStructure.GPIO_Speed = GPIO_High_Speed;//高速,速度越高,响应越快,但是功耗会更高GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//不使能上下拉电阻GPIO_Init(GPIOG,&GPIO_InitStructure);//只要有输出模式,肯定会有初始电平的状态,看连接设备的说明书PGout(9)=1;}int32_t dht11_read(uint8_t *buf)
{uint32_t t=0;int32_t i=0,j=0;uint8_t d=0;uint8_t *p=buf;uint8_t check_sum=0;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //9号引脚GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //输出模式GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; //开漏GPIO_InitStructure.GPIO_Speed = GPIO_High_Speed;//高速,速度越高,响应越快,但是功耗会更高GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//不使能上下拉电阻GPIO_Init(GPIOG,&GPIO_InitStructure); PGout(9)=0;delay_ms(18);PGout(9)=1;delay_us(30);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //9号引脚GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; //输入模式GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; //开漏GPIO_InitStructure.GPIO_Speed = GPIO_High_Speed;//高速,速度越高,响应越快,但是功耗会更高GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//不使能上下拉电阻GPIO_Init(GPIOG,&GPIO_InitStructure);//等待低电平出现t=0;while(PGin(9)){t++;delay_us(1);if(t >= 4000)return -1;}//用超时检测的方法测量低电平的合法性t=0;while(PGin(9)==0){t++;delay_us(1);if(t >= 100)return -2;} //用超时检测的方法测量高电平的合法性t=0;while(PGin(9)){t++;delay_us(1);if(t >= 100)return -3;} for(j=0; j<5; j++){//接收一个字节的数据for(d=0,i=7; i>=0; i--){//用超时检测的方法测量低电平的合法性t=0;while(PGin(9)==0){t++;delay_us(1);if(t >= 100)return -4;}//延时40us (延时时间在28us ~ 70us)delay_us(40);if(PGin(9)){d|=1<<i; //将d变量对应的bit置1//等待高电平持续完毕t=0;while(PGin(9)){t++;delay_us(1);if(t >= 100)return -5;} }} p[j]=d;}//延时50us,可以忽略通讯结束的低电平delay_us(50);//计算校验和,检查接收到的数据是否准确check_sum = (p[0]+p[1]+p[2]+p[3])&0xFF;if(check_sum == p[4])return 0;return -6;
}
主函数main.c
int main(void)
{uint8_t buf[5];int32_t rt;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//抢占优先级0~3,支持4级!//响应优先级0~3,支持4级!key_init();Led_init();usart1_init(115200);dht11_init();printf("this is dht11 test\r\n");printf("1<<6=%X \r\n",1<<6); printf("1<<3=%X \r\n",1<<3); while(1){rt = dht11_read(buf);if( rt == 0){printf("温度:%d.%d 湿度:%d.%d\r\n",buf[2],buf[3],buf[0],buf[1]);}else{printf("dht11 read error code is %d\r\n",rt);}//官方要求,每6秒delay_ms(6000);}
}