STM32 Study Note

层级 方式 示例 难度 适合人群
高级 HAL 库(CubeMX 默认) HAL_GPIO_WritePin() 新手入门
中级 LL 库(Low Layer) LL_GPIO_SetOutputPin() ⭐⭐ 进阶者
底层 直接寄存器 GPIOA->ODR = (1 << 5); ⭐⭐⭐ 高级用户

名称 含义
GPIOA 代表 GPIOA 端口
ODR Output Data Register,输出数据寄存器
1 << 5 把第 5 位(PA5)置 1
` = `
HAL_Init();
SystemClock_Config();   // 已由 CubeMX 自动生成 72MHz 配置
MX_GPIO_Init();
while (1)
{
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);   // 设置高电平
  HAL_Delay(500);
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); // 设置低电平
  HAL_Delay(500);
}

GPIO 初始化MX_GPIO_Init()

系统时钟SystemClock_Config()

CubeMX 中配置外部时钟 + GPIO 步骤
image

项目 当前设置值 含义 & 作用
GPIO output level High 初始化时的默认输出电平,上电时默认输出高电平(VDD)
GPIO mode Output Push Pull 输出推挽模式(标准输出)
GPIO Pull-up/Pull-down Pull-up 内部上拉电阻,使引脚在悬空时为高电平(对输出口其实不起作用)
Maximum output speed Medium GPIO 切换速度为中等(约 10 MHz)
User Label LED 给这个引脚设置标签(可读性提升)

官方定义说明(STM32 HAL 中):

#define GPIO_PIN_0                 ((uint16_t)0x0001)  // 1 << 0
#define GPIO_PIN_1                 ((uint16_t)0x0002)  // 1 << 1
...
#define GPIO_PIN_15                ((uint16_t)0x8000)  // 1 << 15
注意这些宏是 uint16_t 类型,所以最多只能表达 16 位(即 PIN_0~15)。
GPIOA->ODR |= (1 << pin) 置高,或 GPIOA->ODR &= ~(1 << pin) 置低
31 … 16 15 … 0
复位位 Reset Bits 设置位 Set Bits

低 16 位(0~15 bit):将对应引脚 置高电平(写 1 有效)
高 16 位(16~31 bit):将对应引脚 置低电平(写 1 有效)

操作 写入值 说明
设置 PA5 为高电平 GPIOA->BSRR = (1<<5) 低 16 位 Bit5 写 1
设置 PA5 为低电平 GPIOA->BSRR = (1<<21) 高 16 位 Bit5 写 1(5+16)
GPIOx->BSRR = GPIO_PIN_0;  // 置 GPIOx 的第 0 引脚为高电平
GPIOx->BSRR = (uint32_t)GPIO_Pin << 16u;

ODR 修改需要 读 → 改 → 写,中断过程中可能打断写入操作。
BSRR 写入是 一次完成、原子操作,不会影响其他引脚,适合高实时场景(如中断、RTOS)

while (1)
{
    GPIOA->BSRR = (1 << 5);           // PA5 = 高
    HAL_Delay(500);                   // 延时 500ms
    GPIOA->BSRR = (1 << (5 + 16));    // PA5 = 低
    HAL_Delay(500);                   // 延时 500ms
}

for i in range(16):
    led_high = 1 << i
    led_low  = 1 << (i + 16)
    print(f"GPIO_PIN_{i:>2}:  SET=0x{led_high:08X}  RESET=0x{led_low:08X}")

Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_gpio.h

宏定义名 说明
GPIO_MODE_INPUT 输入模式(默认悬浮)
GPIO_MODE_OUTPUT_PP 推挽输出(能主动拉高+拉低)
GPIO_MODE_OUTPUT_OD 开漏输出(只能拉低)
GPIO_MODE_AF_PP 推挽复用功能(如 UART TX)
GPIO_MODE_AF_OD 开漏复用功能(如 I2C)
GPIO_MODE_ANALOG 模拟模式(ADC)
GPIO_MODE_IT_RISING 上升沿中断输入
GPIO_MODE_IT_FALLING 下降沿中断输入
GPIO_MODE_IT_RISING_FALLING 双边沿中断输入

MX_GPIO_Init() 函数

GPIO_InitTypeDef GPIO_InitStruct = {0};

__HAL_RCC_GPIOA_CLK_ENABLE();  //使能 GPIOA 时钟

GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;  //推挽输出模式
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);      //初始化 PA5

开漏模式:LED 长脚(正极)连 GPIO 短脚(负极)连电阻 → GND

GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;   // 开漏输出模式
GPIO_InitStruct.Pull = GPIO_PULLUP;           // 内部上拉电阻启用
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

image

时钟选项

选项 含义 用于哪些功能 是否必须
HSE (High Speed Clock) 高速外部时钟,通常为外接 8MHz 晶振 主系统时钟(SYSCLK)、串口、USB、定时器等较精准时钟 ✅ 推荐开启(大部分板子通常带 8MHz 晶振)
LSE (Low Speed Clock) 低速外部时钟,常为 32.768KHz 晶体 用于 RTC 实时时钟、低功耗定时、日历功能等 ❌ 通常不需要(除非你用到 RTC)

光敏电阻模块引脚

引脚名 功能
A0 模拟输出(可选)
GND 地线
D0 数字输出(高/低电平)
VCC 电源(一般 3.3V 或 5V)

有源蜂鸣器模块引脚

蜂鸣器引脚 说明 连接到 STM32 小板
VCC 电源(3.3V 或 5V) 3.3V 或 5V(建议用 5V)
GND GND
I/O 控制引脚(低电平触发) 比如 PA0(GPIO 输出)

有源蜂鸣器模块接线(低电平触发型)

蜂鸣器模块引脚 说明 接 STM32 小板
VCC 电源 5V(或 3.3V)
GND GND
I/O 控制输入 PA0(输出)

光敏电阻模块接线(数字输出 DO)

光敏模块引脚 说明 接 STM32 小板
VCC 电源(建议 5V) 5V
GND GND
D0 数字信号输出(高/低) PA1(输入)
A0 模拟输出(可忽略) 不接或接 ADC
#include "main.h"

void SystemClock_Config(void);
static void MX_GPIO_Init(void);

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();

  while (1)
  {
    // 如果检测到低电平,说明环境变暗
    if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_RESET)
    {
      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); // 蜂鸣器响
    }
    else
    {
      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET); // 蜂鸣器关闭
    }

    HAL_Delay(100); // 稍作延时
  }
}

继电器吸合:

#define RELAY_ON()  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET) // 低电平吸合
#define RELAY_OFF() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET)   // 高电平断开

RELAY_ON();   // 吸合
HAL_Delay(1000);
RELAY_OFF();  // 断开
HAL_Delay(1000);
posted @ 2025-08-12 12:58  huh&uh  阅读(17)  评论(0)    收藏  举报