STM32寄存器开发练习(二):GPIO的工作模式

📅 2026/7/2 1:07:47
STM32寄存器开发练习(二):GPIO的工作模式
前言上篇文章我们点亮了LED用的是推挽输出模式。当我们去查STM32的参考手册时会发现GPIO有8种工作模式那这么多模式什么时候该用哪个这篇文章我们就来梳理一下GPIO的8种工作模式以及它们的应用场景。为什么要了解GPIO的工作模式你可能会问我只想点亮一个LED为什么要了解这么多模式原因是不同的外设需要不同的GPIO模式按键输入、PWM输出、I2C通信、ADC采集……每种应用场景都有对应的最佳GPIO模式如果模式选错了外设可能不工作或者工作不稳定所以了解GPIO的工作模式是STM32开发的基础。STM32 GPIO的8种工作模式STM32的GPIO可以分为两大类输出模式和输入模式每类各有4种。输出模式4种模式说明典型应用推挽输出(Push-Pull)能主动输出高、低电平LED控制、普通数字信号输出、驱动芯片使能脚开漏输出(Open-Drain)只能输出低电平高电平需要外接上拉电阻I2C总线、电平转换复用推挽输出GPIO 被外设接管引脚功能由片上外设决定如PWM、串口TXPWM输出、USART_TX复用开漏输出GPIO 被外设接管引脚功能由片上外设决定如I2CI2C_SDA、I2C_SCL输入模式4种模式说明典型应用浮空输入(Floating)引脚电平不确定易受干扰外部信号输入外部已有明确电平驱动上拉输入(Pull-up)内部上拉电阻无外部信号时为高电平按键输入按键另一端接GND、I²C 总线输入下拉输入(Pull-down)内部下拉电阻无外部信号时为低电平按键输入按键另一端接VCC、检测高电平有效的触发信号模拟输入(Analog)关闭数字缓冲器直接连接ADC或比较器电压采集、传感器信号采集输出模式详解1. 推挽输出Push-Pull原理引脚可以主动输出高电平3.3V或低电平0V内部有两个MOS管PMOS NMOS一个接VCC一个接GND输出高电平时上管导通输出低电平时下管导通特点✅ 驱动能力强能输出20mA左右✅ 高低电平切换快✅ 不需要外接上拉电阻应用场景LED控制、继电器控制、蜂鸣器控制普通数字信号输出驱动芯片使能脚配置方法寄存器编程c// 配置PA0为推挽输出、50MHz GPIOA-CRL ~(0xF 0); // 清除CNF0和MODE0位 GPIOA-CRL | (0x3 0); // CNF000推挽输出MODE01150MHz2. 开漏输出Open-Drain原理引脚只能主动输出低电平高电平需要外接上拉电阻输出低电平时内部MOS管导通引脚被拉到低电平输出高电平时MOS管截止引脚靠外部上拉电阻拉到高电平特点✅ 可以实现电平匹配比如用5V上拉就能输出5V电平✅ 支持线与多个开漏输出接在一起任意一个输出低电平总线就是低电平❌ 高电平切换速度慢受上拉电阻影响应用场景I2C总线SDA和SCL都是开漏输出电平匹配3.3V MCU控制5V设备多个设备共享一根信号线配置方法寄存器编程c// 配置PA0为开漏输出、50MHz GPIOA-CRL ~(0xF 0); // 清除CNF0和MODE0位 GPIOA-CRL | (0x7 0); // CNF001开漏输出MODE01150MHz3. 复用推挽输出 / 复用开漏输出原理和普通的推挽/开漏输出一样但输出信号来自外设不是来自GPIOx_ODR寄存器比如PWM信号来自定时器串口TX信号来自USART模块应用场景PWM输出TIMx_CHx串口发送USARTx_TXSPI时钟和数据SPIx_SCK、SPIx_MOSI配置方法寄存器编程c// 配置PA8为复用推挽输出、50MHzTIM1_CH1 GPIOA-CRH ~(0xF 0); // 清除CNF8和MODE8位 GPIOA-CRH | (0xB 0); // CNF810复用推挽输出MODE81150MHz输入模式详解1. 浮空输入Floating原理引脚内部既不上拉也不下拉引脚电平完全由外部电路决定如果外部没有接任何东西电平是不确定的可能是高也可能是低特点✅ 外部可以灵活控制电平❌ 如果外部信号不稳定容易误触发应用场景外部有上拉/下拉电阻的场合用于读取数字传感器的输出如DHT11配置方法寄存器编程c// 配置PA0为浮空输入 GPIOA-CRL ~(0xF 0); // 清除CNF0和MODE0位 GPIOA-CRL | (0x4 0); // CNF001浮空输入MODE000输入模式2. 上拉输入Pull-up原理引脚内部有一个上拉电阻约40kΩ把引脚拉到高电平如果外部把引脚拉到低电平引脚就读到低电平特点✅ 默认高电平适合按键接GND的场合✅ 抗干扰能力强应用场景按键输入按键另一端接GND读取开关状态配置方法寄存器编程c// 配置PA0为上拉输入 GPIOA-CRL ~(0xF 0); // 清除CNF0和MODE0位 GPIOA-CRL | (0x8 0); // CNF010上拉/下拉输入MODE000输入模式 GPIOA-ODR | (1 0); // ODR01选择上拉或者c// 配置PA0为上拉输入 GPIOA-CRL ~(0xF 0); // 清除CNF0和MODE0位 GPIOA-CRL | (0x8 0); // CNF010上拉/下拉输入MODE000输入模式 GPIOA-BSRR (1 0); // 置位 ODRODR写 1选择上拉更推荐第二种的写法因为操作ODR的过程是读-改-写在中断或多任务中可能被打断而BSRR是原子操作不会被中断打断。3. 下拉输入Pull-down原理引脚内部有一个下拉电阻约40kΩ把引脚拉到低电平如果外部把引脚拉到高电平引脚就读到高电平特点✅ 默认低电平适合按键接VCC的场合✅ 抗干扰能力强应用场景按键输入按键另一端接VCC读取开关状态配置方法寄存器编程c// 配置PA0为下拉输入 GPIOA-CRL ~(0xF 0); // 清除CNF0和MODE0位 GPIOA-CRL | (0x8 0); // CNF010上拉/下拉输入MODE000输入模式 GPIOA-BRR | (1 0); // 清除 ODRODR写 0选择下拉4. 模拟输入Analog原理引脚直接连到ADC模块用于采集模拟电压数字输入缓冲器被禁止引脚的电平变化不会触发中断特点✅ 专门用于ADC采集✅ 功耗低应用场景电位器读数温度传感器电池电压检测配置方法寄存器编程c// 配置PA0为模拟输入 GPIOA-CRL ~(0xF 0); // 清除CNF0和MODE0位 // CNF000MODE000模拟输入模式如何用寄存器配置GPIO模式关键寄存器配置GPIO模式主要用这两个寄存器GPIOx_CRL配置低8位引脚Pin0~Pin7GPIOx_CRH配置高8位引脚Pin8~Pin15每个引脚占用4位CNF[1:0]配置模式输入/输出、推挽/开漏等MODE[1:0]配置速度输入模式下这两位为00实际代码示例示例按键输入上拉输入模式c#include stm32f10x.h int main(void) { // 1. 开启GPIOA时钟 RCC-APB2ENR | (1 2); // 2. 配置PA0为上拉输入假设按键接在PA0另一端接GND GPIOA-CRL ~(0xF 0); // 清除CNF0和MODE0位 GPIOA-CRL | (0x8 0); // CNF010上拉/下拉输入MODE000输入模式 GPIOA-BSRR (1 0); // 置位 ODRODR写 1选择上拉 // 3. 主循环检测按键 while(1) { if ((GPIOA-IDR (1 0)) 0) { // PA0为低电平按键按下 // 做点什么... } } }将上述代码改成使用官方宏定义的形式c#include stm32f10x.h int main(void) { // 1. 开启GPIOA时钟 RCC-APB2ENR | RCC_APB2ENR_IOPAEN; // 2. 配置PA0为上拉输入假设按键接在PA0另一端接GND GPIOA-CRL ~GPIO_CRL_CNF0; // 清除CNF0位 GPIOA-CRL | GPIO_CRL_CNF0_1; // CNF010上拉/下拉输入 GPIOA-CRL ~GPIO_CRL_MODE0; // MODE000输入模式 GPIOA-BSRR GPIO_BSRR_BS0; // 置位 ODRODR写 1选择上拉 // 3. 主循环检测按键 while(1) { if ((GPIOA-IDR GPIO_IDR_IDR0) 0) { // PA0为低电平按键按下 // 做点什么... } } }总结这篇文章我梳理了STM32 GPIO的8种工作模式输出模式推挽输出最常用能输出高/低电平开漏输出用于I2C、电平匹配复用推挽/开漏用于外设功能输入模式浮空输入外部有上拉/下拉时用上拉输入按键接GND时用下拉输入按键接VCC时用模拟输入用于ADC采集作者一个焊板子的人欢迎关注获取更多硬件工程师学习笔记如果觉得有帮助欢迎点赞收藏也欢迎在评论区交流讨论