zoukankan      html  css  js  c++  java
  • STM32获取DHT11温度传感器数据

    准备物件

    • STM32F103C8T6核心板
    • ST-LINK V2
    • DHT11
    • 杜邦线若干

    连接线

    STM32F103C8T6芯片管脚图

    管脚说明

    连接仿真器

    STM32 ST-LINKV2
    VCC VCC
    GND GND
    SWCLK SWCLK
    SWDIO SWDIO

    创建工程

    参考STM32F103X 开发环境搭建
    可将其模板复制一份

    添加延时功能

    DRIVER/inc中添加timer.h

    #ifndef __TIMER_H__
    #define __TIMER_H__
    
    #include "stm32f10x.h"
    
    void systick_init(void);
    void timing_delay_decrement(void);
    void delay_us(__IO uint32_t n);
    
    #endif
    

    对应的在DRIVER/src中添加timer.c

    #include "timer.h"
    
    __IO uint32_t gTimingDelay;
    
    /* SystemCoreClock / 1000    --> 1ms */
    /* SystemCoreClock / 10000   --> 100us */
    /* SystemCoreClock / 100000  --> 10us */
    /* SystemCoreClock / 1000000 --> 1us */
    
    void systick_init(void)
    {
        while (SysTick_Config(SystemCoreClock / 1000000) == 1);
    }
    
    void timing_delay_decrement(void)
    {
        if (gTimingDelay != 0x0)
        {
            gTimingDelay--;
        }
    }
    
    void SysTick_Handler(void)
    {
        timing_delay_decrement();
    }
    
    void delay_us(__IO uint32_t n)
    {
        gTimingDelay = n;
        while(gTimingDelay != 0);
    }
    

    点亮LED

    可以看到核心板上有两个LED灯,PWR(电源)和PC13
    修改USER/main.c

    #include "stm32f10x.h"
    #include "timer.h"
    
    #define Led_On   GPIO_SetBits(GPIOC, GPIO_Pin_13)
    #define Led_Off GPIO_ResetBits(GPIOC, GPIO_Pin_13)
    
    void LED_Init()
    {
        GPIO_InitTypeDef s;
        
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
        
        s.GPIO_Pin = GPIO_Pin_13;
        s.GPIO_Mode = GPIO_Mode_Out_PP;
        s.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOC, &s);
    }
    
    int main()
    {
        SystemInit();
        systick_init();
    
        LED_Init();
        while (1)
        {
            Led_On;
            delay_us(500000);
            Led_Off;
            delay_us(500000);
        }
    }
    

    <1> 由于timer.c已经实现SysTick_handler中断实现,需要编辑USER/stm32f10x_it.c,将SysTick_handler函数注释

    <2> 右击工程名 -> Options -> C/C++ Compiler -> Preprocessor
    在"Additional include directories:"中添加$PROJ_DIR$USERinc

    <3> 右击工程名 -> Options -> Debugger -> Setup
    在Driver中选择ST-LINK

    <4> 右击工程名 -> Options -> ST-LINK -> Setup
    在Reset选择Connect during reset
    在Interface中选择SWD

    <5> 点击编译,然后Download and Debug -> Go

    便可以看到PC13 LED灯均匀的闪烁。

    串口发送数据

    用于显示DHT11读取的数据

    连线方式

    USB-TTL STM32
    VCC VCC
    GND GND
    RXD PA9(TXD)
    TXD PA10(RXD)

    如果是树莓派,可以查看GPIO管脚说明,按照上述连接即可。

    添加DRIVER/inc/usart.h

    #ifndef __USART_H_
    #define __USART_H_
    
    
    #include "stm32f10x.h"
    #include "stm32f10x_rcc.h"
    #include "stm32f10x_usart.h"
    #include <stdarg.h>
    
    #define WAIT_TC while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
    
    void usart_config(void);
    void usart_gpio_init(void);
    void usart_param_config(void);
    
    void usart_send_string(char *data);
    void usart_printf(const char *fmt, ...);
    
    #endif
    

    添加DRIVER/src/usart.c

    #include "usart.h"
    
    void usart_config(void)
    {
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
        
        usart_gpio_init();
        usart_param_config();
    }
    
    void usart_gpio_init(void)
    {
        GPIO_InitTypeDef g;
        g.GPIO_Speed = GPIO_Speed_50MHz;
        
        g.GPIO_Pin = GPIO_Pin_9;
        g.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
        GPIO_Init(GPIOA, &g);
        
        g.GPIO_Pin = GPIO_Pin_10;
        g.GPIO_Mode = GPIO_Mode_IN_FLOATING; //开漏输入
        GPIO_Init(GPIOA, &g);
    }
    
    void usart_param_config(void)
    {
        USART_InitTypeDef u;
        
        u.USART_BaudRate = 9600;
        u.USART_WordLength = USART_WordLength_8b;   //数据位8位
        u.USART_StopBits = USART_StopBits_1;    //停止位1位
        u.USART_Parity = USART_Parity_No;   //无校验位
        u.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
        u.USART_Mode = USART_Mode_Tx;
        
        USART_Init(USART1, &u);
        
        USART_Cmd(USART1, ENABLE);
    }
    
    void usart_send_string(char *data)
    {
        char *p = data;
        while (p < data + strlen(data))
        {
            WAIT_TC;
            USART_SendData(USART1, *p++);
        }
    }
    
    void usart_printf(const char *fmt, ...)
    {
        va_list ap;
        char string[64];
        
        va_start(ap, fmt);
        vsprintf(string, fmt, ap);
        va_end(ap);
        usart_send_string(string);
    }
    

    main.c添加如下细节

    #include "usart.h"
    
    int main()
    {
        SystemInit();
        systick_init();
    
        usart_config();
        
        LED_Init();
        while (1)
        {
            Led_On;
            usart_printf("test usart
    ");
            delay_us(2000000);
            Led_Off;
            delay_us(2000000);
        }
    }
    

    打开串口工具,linux下是minicom

    minicom -b 9600 -D /dev/ttyUSB0
    

    可以看到test usart字符,说明串口通信正常。

    驱动DHT11

    连线方式

    DHT11 STM32
    VCC VCC
    GND GND
    DATA PB11

    添加DRIVER/inc/dht11.h

    #ifndef __DHT11_H__
    #define __DHT11_H__
    
    #include "timer.h"
    #include "stm32f10x_gpio.h"
    
    #define DHT11_GPIO_TYPE  GPIOB
    #define DHT11_GPIO_PIN   GPIO_Pin_11
    #define DHT11_RCC        RCC_APB2Periph_GPIOB
    
    
    #define DHT11_OUT_H GPIO_SetBits(DHT11_GPIO_TYPE, DHT11_GPIO_PIN)
    #define DHT11_OUT_L GPIO_ResetBits(DHT11_GPIO_TYPE, DHT11_GPIO_PIN)
    #define DHT11_IN    GPIO_ReadInputDataBit(DHT11_GPIO_TYPE, DHT11_GPIO_PIN)
    
    
    void dht11_gpio_input(void);
    void dht11_gpio_output(void);
    u16 dht11_scan(void);
    u16 dht11_read_bit(void);
    u16 dht11_read_byte(void);
    u16 dht11_read_data(u8 buffer[4]);
    
    #endif
    

    添加DRIVER/src/dht11.c

    #include "dht11.h"
    
    void dht11_gpio_input(void)
    {
        GPIO_InitTypeDef g;
        
        RCC_APB2PeriphClockCmd(DHT11_RCC, ENABLE);
        
        g.GPIO_Pin = DHT11_GPIO_PIN;
        g.GPIO_Speed = GPIO_Speed_50MHz;
        g.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
        
        GPIO_Init(DHT11_GPIO_TYPE, &g);
    }
    
    void dht11_gpio_output(void)
    {
        GPIO_InitTypeDef g;
        
        RCC_APB2PeriphClockCmd(DHT11_RCC, ENABLE);
        
        g.GPIO_Pin = DHT11_GPIO_PIN;
        g.GPIO_Speed = GPIO_Speed_50MHz;
        g.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
    
        GPIO_Init(DHT11_GPIO_TYPE, &g);
    }
    
    void dht11_reset(void)
    {
        // 按照DHT11手册步骤
        dht11_gpio_output();
        DHT11_OUT_L;
        delay_us(19000);
        DHT11_OUT_H;
        delay_us(30);
        dht11_gpio_input();
    }
    
    u16 dht11_scan(void)
    {
        return DHT11_IN;
    }
    
    u16 dht11_read_bit(void)
    {
        while (DHT11_IN == RESET);
        delay_us(40);
        if (DHT11_IN == SET)
        {
            while (DHT11_IN == SET);
            return 1;
        }
        else
        {
            return 0;
        }
    }
    
    u16 dht11_read_byte(void)
    {
        u16 i;
        u16 data = 0;
        for (i = 0; i < 8; i++)
        {
            data <<= 1;
            data |= dht11_read_bit();
        }
        return data;
    }
    
    u16 dht11_read_data(u8 buffer[5])
    {
        u16 i = 0;
        
        dht11_reset();
        if (dht11_scan() == RESET)
        {
            //检测到DHT11响应
            while (dht11_scan() == RESET);
            while (dht11_scan() == SET);
            for (i = 0; i < 5; i++)
            {
                buffer[i] = dht11_read_byte();
            }
            
            while (dht11_scan() == RESET);
            dht11_gpio_output();
            DHT11_OUT_H;
            
            u8 checksum = buffer[0] + buffer[1] + buffer[2] + buffer[3];
            if (checksum != buffer[4])
            {
                // checksum error
                return 1;
            }
        }
        
        return 0;
    }
    

    修改USER/main.c

    #include "dht11.h"
    
    int main()
    {
        SystemInit();
        systick_init();
    
        usart_config();
        
        LED_Init();
        while (1)
        {
            Led_On;
            u8 buffer[5];
            double hum;
            double temp;
            if (dht11_read_data(buffer) == 0)
            {
                hum = buffer[0] + buffer[1] / 10.0;
                temp = buffer[2] + buffer[3] / 10.0;
            }
            usart_printf("___{"temperature": %.2f, "humidness": %.2f}___
    ", temp, hum);
            delay_us(2000000);
            Led_Off;
            delay_us(2000000);
        }
    }
    

    编译、运行,发现串口可以收到温度信息。

    minicom -b 9600 -D /dev/ttyUSB0
    

  • 相关阅读:
    k8s 使用 Init Container 确保依赖的服务已经启动
    asp.net core 从 3.0 到 3.1
    Github原生CI/CD,初尝Github Actions
    [nginx]编译安装及安全优化
    [nginx]盗链和防盗链场景模拟实现
    [nginx]location语法
    [nginx]站点目录及文件访问控制
    [svc]nginx限制客户端上传附件的大小
    [sql]mysql指引(整理中...)-对db的分类
    [sql]mysql参数(配置)手册
  • 原文地址:https://www.cnblogs.com/rainmote/p/7591256.html
Copyright © 2011-2022 走看看