找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1565|回复: 0
打印 上一主题 下一主题
收起左侧

MCU单片机+DHT11采集温湿度时序图与温湿度数据格式定义与转换

[复制链接]
跳转到指定楼层
楼主
时序图,通信过程就是:

MCU发送起始信号,MCU等待响应,MCU等待DHT11测量完毕,MCU读取测量结果,结束一次通信。

主机发送起始信号:主机发送至少18ms的低电平;

从机等待主机释放总线:主机把总线拉高,延时20~40us;

主机读取响应;

主机读取数据:每一bit数据以5us的低电平开始,数据是0还是1由高电平时长决定;

当最后一bit数据传送完毕后,DHT11拉低总线50us,随后总线由上拉电阻拉高进入空闲状态。

温湿度转换:


单片机代码如下:

.c文件

void DHT11_Init()
{
    delay_ms(1000); //等待1S以越过不稳定状态在此期间不能发送任何指令   
    DHT11_Output(); //主机发开始信号
}

void DHT11_Output()
{
    GPIO_InitTypeDef dht11;  
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

    dht11.GPIO_Mode=GPIO_Mode_Out_PP; //推挽输出
    dht11.GPIO_Pin=GPIO_Pin_6 ;//PB6
    dht11.GPIO_Speed=GPIO_Speed_50MHz; //高速
    GPIO_Init(GPIOB,&dht11);
}

//主机发起始信号
void DHT11_Start()
{   
    GPIO_ResetBits(GPIOB,GPIO_Pin_6); //低电平
    delay_ms(18); //微处理器的 I/O 设置为输出同时输出低电平,低电平保持时间不能小于18ms(最大不得超过 30ms)
    GPIO_SetBits(GPIOB,GPIO_Pin_6); //拉高等待
    delay_us(20); //从机等待主机释放总线:主机把总线拉高,延时20~40us
}

//DHT11发出信号,主机接收信号,切换输入模式
void DHT11_Input()
{
    GPIO_InitTypeDef dht11;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);   
    dht11.GPIO_Mode=GPIO_Mode_IN_FLOATING; //上拉输入  输入上拉:引脚为输入模式,引脚输入状态默认为高电平
    dht11.GPIO_Pin=GPIO_Pin_6 ;
    dht11.GPIO_Speed=GPIO_Speed_50MHz; //高速
    GPIO_Init(GPIOB,&dht11); //根据key配置的参数初始化外设GPIOA寄存器         
}
u8 DHT11_Readbyte()
{
    int i;
    u8 data=0; //读到保存的一个字节
    for(i=0;i<8;i++) //8位
    {
        while(!(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6))); //等待54us低电平时间过去
        delay_us(40); //再延时,判断是否为高电平
        if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)==1) //延时过后,确定为高电平,把1存起来
        {
            while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)); //等待高电平结束
            data |=1<<(7-i);
        }
    }
    return data; //返回读到的字节数据
}

int DHT11_GetTH(u8 buf[])
{
    u8 check=0;
    int n=0;
    DHT11_Output();
    DHT11_Start();
    DHT11_Input();
    //单片机(主机)等待从机响应,单片机读PB6引脚为低电平
    while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)) //等待从机响应低电平
    {
        delay_us(1);
        n++;
        if(n>100)
            return 1; //不响应
    }
    while(!(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6))); //等响应后的低电平时间完全过去
    while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)); //等待80us的高电平过去

    //单片机读取40位数据--8位1个字节
    buf[0]=DHT11_Readbyte(); //湿度的高位字节
    buf[1]=DHT11_Readbyte(); //湿度的低位字节
    buf[2]=DHT11_Readbyte(); //温度的高位字节
    buf[3]=DHT11_Readbyte(); //温度的低位字节
    check=DHT11_Readbyte();  
    //释放总线
    DHT11_Output(); //变成输出模式
    GPIO_SetBits(GPIOB,GPIO_Pin_6);  //拉高--高电平
    if((buf[0]+buf[1]+buf[2]+buf[3])==check)   
    {
        return 0; //采集数据成功
    }
    else
    {
        return 2; //校验不成功
    }
}

main函数
int main(void)  //主函数  
{
    u8 data[4];
    int temp=0;
    float T=0,H=0;
    systick_init(); //系统滴答时钟初始化
    USART1_Init(9600); //串口通信初始化
    DHT11_Init();

    while (1)
    {   
        temp=DHT11_GetTH(data);
        if(temp==0)
        {
            printf("采集校验成功!%d\r\n",temp);
            H=data[0]+(data[1]/100.0);
            T=data[2]+(data[3]/100.0);
            printf("温度:%.2f,湿度:%.2f\r\n",T,H);
        }
        delay_ms(2000)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表