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);
}
}