STM32 入门 + 传感器采集 + 显示 综合实验

STM32 入门 + 传感器采集 + 显示 综合实验,基于 STM32F103C8T6(蓝桥杯/最小系统板)。


一、系统总体方案

复制代码
温湿度传感器  →  USART1(RX)  →  STM32F103
                                       │
                                       ├── USART2(TX) → PC串口助手(调试)
                                       └── GPIO → 74HC595 → 4位数码管

硬件选型(最常见组合)

模块 型号 说明
MCU STM32F103C8T6 72MHz,3.3V
温湿度 DHT11 单总线(简单)
数码管 4位共阳/共阴 带 74HC595 移位寄存器
下载 ST-Link V2 SWD 接口

推荐 :如果你不想自己写 DHT11 驱动,也可以用 SHT30(I2C),稳定性更好。


二、硬件连接表(重点)

1、DHT11 → STM32

DHT11 STM32F103 说明
VCC 3.3V
GND GND
DATA PA0 推挽输出 / 输入切换

2、数码管(74HC595) → STM32

74HC595 STM32 说明
SER PB12 数据
RCLK PB13 锁存
SRCLK PB14 时钟
OE GND 使能
VCC 5V 数码管供电

数码管类型一定要确认

  • 共阳:段码取反
  • 共阴:段码原样

三、核心源码

1、DHT11 驱动(单总线)

c 复制代码
// dht11.h
#ifndef __DHT11_H
#define __DHT11_H

#include "stm32f10x.h"

uint8_t DHT11_Read(uint8_t *temp, uint8_t *humi);

#endif
c 复制代码
// dht11.c
#include "dht11.h"
#include "delay.h"

#define DHT11_PIN GPIO_Pin_0
#define DHT11_PORT GPIOA

static void DHT11_Mode_OUT(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = DHT11_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(DHT11_PORT, &GPIO_InitStructure);
}

static void DHT11_Mode_IN(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = DHT11_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(DHT11_PORT, &GPIO_InitStructure);
}

uint8_t DHT11_Read(uint8_t *temp, uint8_t *humi)
{
    uint8_t buf[5] = {0};
    uint8_t i, j;

    DHT11_Mode_OUT();
    GPIO_ResetBits(DHT11_PORT, DHT11_PIN);
    Delay_ms(18);
    GPIO_SetBits(DHT11_PORT, DHT11_PIN);
    Delay_us(30);
    DHT11_Mode_IN();

    if(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) != 0)
        return 1;

    while(!GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN));
    while(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN));

    for(i=0;i<5;i++)
    {
        for(j=0;j<8;j++)
        {
            while(!GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN));
            Delay_us(40);
            buf[i] <<= 1;
            if(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN))
                buf[i] |= 1;
            while(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN));
        }
    }

    if(buf[0]+buf[1]+buf[2]+buf[3] != buf[4])
        return 2;

    *humi = buf[0];
    *temp = buf[2];
    return 0;
}

2、74HC595 驱动数码管

c 复制代码
// seg.c
#include "seg.h"
#include "stm32f10x_gpio.h"

#define SER_H()   GPIO_SetBits(GPIOB, GPIO_Pin_12)
#define SER_L()   GPIO_ResetBits(GPIOB, GPIO_Pin_12)
#define RCLK_H()  GPIO_SetBits(GPIOB, GPIO_Pin_13)
#define RCLK_L()  GPIO_ResetBits(GPIOB, GPIO_Pin_13)
#define SRCLK_H() GPIO_SetBits(GPIOB, GPIO_Pin_14)
#define SRCLK_L() GPIO_ResetBits(GPIOB, GPIO_Pin_14)

// 共阳数码管段码(0~9)
const uint8_t SegCode[10] = {
    0xC0,0xF9,0xA4,0xB0,0x99,
    0x92,0x82,0xF8,0x80,0x90
};

void Seg_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
}

void Seg_SendByte(uint8_t dat)
{
    for(uint8_t i=0;i<8;i++)
    {
        (dat & 0x80) ? SER_H() : SER_L();
        SRCLK_H(); SRCLK_L();
        dat <<= 1;
    }
}

void Seg_Display(uint16_t num)
{
    Seg_SendByte(SegCode[num/1000]);
    Seg_SendByte(SegCode[num%1000/100]);
    Seg_SendByte(SegCode[num%100/10]);
    Seg_SendByte(SegCode[num%10]);
    RCLK_H(); RCLK_L();
}

3、串口打印(调试用)

c 复制代码
// usart.c
void USART1_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Tx;

    USART_Init(USART1, &USART_InitStructure);
    USART_Cmd(USART1, ENABLE);
}

4、Main 主逻辑

c 复制代码
int main(void)
{
    uint8_t temp = 0, humi = 0;

    Delay_Init();
    Seg_Init();
    USART1_Init();

    while(1)
    {
        if(DHT11_Read(&temp, &humi) == 0)
        {
            // 显示温度(例如 25°C → 显示 25)
            Seg_Display(temp);

            // 串口打印
            printf("Temp:%dC Humi:%d%%\r\n", temp, humi);
        }
        Delay_ms(1000);
    }
}

四、串口上位机显示效果

复制代码
Temp:26C Humi:58%
Temp:26C Humi:57%
Temp:27C Humi:56%

参考代码 STM32F103-串口控制数码管显示温湿度数据 www.youwenfan.com/contentcsv/103447.html

五、常见问题排查

现象 原因
数码管不亮 共阳/共阴段码搞反
DHT11 一直 0 延时不准(必须精准 µs)
数值跳动 未加延时 / 电源不稳
串口乱码 晶振频率 ≠ 72MHz
相关推荐
FreakStudio4 天前
W55MH32L-EVB 上手测评:硬件 TCP/IP 加持的以太网单片机,MicroPython 零门槛开发
python·单片机·嵌入式·大学生·面向对象·并行计算·电子diy·电子计算机
✎ ﹏梦醒͜ღ҉繁华落℘9 天前
单片机基础知识---stm32单片机的优先级
stm32·单片机·mongodb
u152109648499 天前
S.S.Audio PRO A2音频隔离器
嵌入式硬件·音视频·实时音视频·视频编解码·视频
zd8451015009 天前
RS485 总线详解
单片机·嵌入式硬件
半条-咸鱼9 天前
【STM32】I2C协议原理、HAL读写与OLED显示操作
嵌入式硬件·c·信息与通信
牛根生同志9 天前
SPI数据收发的时候 TXE与RXNE标志位置位的时机
stm32·spi·transfer
wohoo_wangzi9 天前
苏州晟雅泰电子:关于W25Q128JVSIQ这个芯片物料的参数,规格及应用领域
嵌入式硬件
goldenrolan9 天前
学习型红外控制系统稳定性挂测工装专项总结
软件测试·python·stm32·嵌入式·红外
✎ ﹏梦醒͜ღ҉繁华落℘9 天前
编程基础 --高内聚,低耦合
c语言·单片机
科芯创展9 天前
1A,1MHz,30VIN,XZ4115,降压恒流LED驱动芯片
单片机·嵌入式硬件