【APM32E030R Micro-EVB开发板评测】读取DHT11
DHT11是一款集温度和湿度测量于一体的数字传感器,采用单总线通信协议,具有体积小、功耗低、性价比高等特点。以下是其主要特性:DHT11模块
DHT11的连接方式
这里我们使用的时PB1引脚。
这里使用的是定时器3实现的定时功能
RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR3);
TMR_TimeBase_T baseConfig;
baseConfig.div = 72-1;
baseConfig.period = 0xFFFF;
baseConfig.clockDivision = TMR_CKD_DIV1;
baseConfig.counterMode = TMR_COUNTER_MODE_UP;
TMR_ConfigTimeBase(TMR3, &baseConfig);
TMR_EnableAUTOReload(TMR3);
TMR_Enable(TMR3);1us定时的实现
TMR3->CNT=0;
TMR_Enable(TMR3);
while(TMR3->CNT < nus);//计数频率6MHz,6次即为1us
TMR_Disable(TMR3);DHT11的读写代码
dht11.c
#include "dht11.h"
#include "delay.h"
void Delay_us(uint16_t time)
{
delay_us(time);
}
void Delay_ms(uint16_t time)
{
delay_ms(time);
}
void DHT11_IO_OUT (void){ //温湿度模块输出函数
GPIO_Config_TconfigStruct;
configStruct.pin = DHT11_IO; //选择端口号(0~15或all)
configStruct.mode = GPIO_MODE_OUT; //推挽输出
configStruct.speed = GPIO_SPEED_50MHz; //设置IO接口速度(2/10/50MHz)
GPIO_Config(DHT11_PORT, &configStruct);
}
void DHT11_IO_IN (void){ //温湿度模块输入函数
GPIO_Config_TconfigStruct;
configStruct.pin = DHT11_IO; //选择端口号(0~15或all)
configStruct.mode = GPIO_MODE_IN; //浮空输入
configStruct.speed = GPIO_SPEED_50MHz; //设置IO接口速度(2/10/50MHz)
GPIO_Config(DHT11_PORT, &configStruct);
}
void DHT11_RST (void){ //DHT11端口复位,发出起始信号(IO发送)
DHT11_IO_OUT(); //端口为输出
DHT11_DQ_OUT_0; //使总线为低电平
Delay_ms(20); //拉低至少18ms
DHT11_DQ_OUT_1; //使总线为高电平
Delay_us(30); //主机拉高20~40us
}
uint8_t DHT11_Check(void){ //等待DHT11回应,返回1:未检测到DHT11,返回0:成功(IO接收)
uint8_t retry=0; //定义临时变量
DHT11_IO_IN(); //IO到输入状态
//GPIO端口输入时,配置为上拉输入或者浮空输入,因为外接上拉电阻,所以默认为高电平
//有负信号输入,GPIO端口为1,当GPIO端口为1且retry小于100,retry自加,否则跳出循环执行下一步
while ((DHT11_DQ_IN == 1) && retry<100) //DHT11会拉低40~80us
{
retry++;
Delay_us(1);
}
if(retry>=100)return 1;
else retry=0;
//DHT11发来高电平信号,GPIO端口为0,当GPIO端口为0且retry小于100,retry自加,否则跳出循环执行下一步
while ((DHT11_DQ_IN == 0) && retry<100)//DHT11拉低后会再次拉高40~80us
{
retry++;
Delay_us(1);
}
if(retry>=100)return 1;
return 0;
}
uint8_t DHT11_Init (void){ //DHT11初始化
RCM_EnableAPB2PeriphClock(DHT11_RCC); //开始DHT11的时钟
DHT11_RST(); //DHT11端口复位,发出起始信号
return DHT11_Check(); //等待DHT11回应
}
//从DHT11读取一个位
//返回值:1/0
uint8_t DHT11_Read_Bit(void)
{
uint8_t retry = 0;
while((DHT11_DQ_IN == 1) && retry < 100) //等待变为低电平
{
retry++;
Delay_us(1);
}
retry = 0;
while((DHT11_DQ_IN == 0) && retry < 100) //等待变高电平
{
retry++;
Delay_us(1);
}
Delay_us(40);//等待40us
if(GPIO_ReadInputBit(DHT11_PORT,DHT11_IO) == 1) //用于判断高低电平,即数据1或0
return 1;
else
return 0;
}
//从DHT11读取一个字节
//返回值:读到的数据
uint8_t DHT11_Read_Byte(void)
{
uint8_t i, dat;
dat = 0;
for (i = 0; i < 8; i++)
{
dat <<= 1; //左移运算符,dat左移1位
dat |= DHT11_Read_Bit(); //"|"表示按位或等于
}
return dat;
}
//从DHT11读取一次数据
//temp:温度值(范围:0~50°)
//humi:湿度值(范围:20%~90%)
//返回值:0,正常;1,读取失败
uint8_t DHT11_Read_Data(uint8_t *temp, uint8_t *humi)
{
uint8_t buf;
uint8_t i;
DHT11_RST(); //DHT11端口复位,发出起始信号
if(DHT11_Check() == 0) //等待DHT11回应,0为成功回应
{
for(i = 0; i < 5; i++) //读取40位数据
{
buf = DHT11_Read_Byte(); //读出数据
}
if((buf + buf + buf + buf) == buf) //数据校验
{
*humi = buf; //将湿度值放入指针humi
*temp = buf; //将温度值放入指针temp
}
}
else return 1;
return 0;
}
dht11.h
#ifndef __DHT11_H
#define __DHT11_H
#include "APM32E030_gpio.h"
#include "APM32E030_rcm.h"
#define DHT11_RCC RCM_AHB_PERIPH_GPIOB //开启引脚RCC,根据具体情况修改
#define DHT11_PORT GPIOB //定义端口,根据具体情况修改
#define DHT11_IO GPIO_PIN_1 //定义IO口,根据具体情况修改
//设置驱动IO端口
#define DHT11_DQ_OUT_1 GPIO_SetBit(DHT11_PORT, DHT11_IO )
#define DHT11_DQ_OUT_0 GPIO_ClearBit(DHT11_PORT, DHT11_IO )
#define DHT11_DQ_IN GPIO_ReadInputBit(DHT11_PORT,DHT11_IO)
void DHT11_IO_OUT (void); //设置IO口为输出模式
void DHT11_IO_IN (void); //设置IO口为输入模式
void DHT11_RST (void); //复位DHT11
uint8_t DHT11_Check (void); //检查DHT11是否正常
uint8_t DHT11_Read_Bit (void); //读取一位数据
uint8_t DHT11_Read_Byte (void); //读取一个字节
uint8_t DHT11_Init (void); //DHT11初始化
uint8_t DHT11_Read_Data (uint8_t *temp, uint8_t *humi); // DHT11读取数据
#endif
main函数
DHT11_Read_Data(&temperature,&humidity); //读取温湿度值
sprintf(s_temp,"温度:%02d'C ",temperature );
OLED_ShowStringCN(0,16,(unsigned char*)s_temp,1);// 显示温度
sprintf(s_temp,"湿度:%02d%% ",humidity);
OLED_ShowStringCN(0,32,(unsigned char*)s_temp,1);// 显示湿度
OLED_Refresh();最终实现的效果
这个单总线通讯,是不是可以考虑使用SPI的通讯方式啊 纯延时处理的话,如果遇到中断,数据传输的稳定性还能保证吗? 这个评测很详细,特别是DHT11的连接和代码实现部分,对于初学者来说很有帮助。
页:
[1]