GPIO输入输出

注释 1 MODECNF 必须组合起来理解:

  • MODE 先决定它是输入还是输出,并在输出时选择速度;
  • CNF 再决定输入/输出的具体电气类型。

不能脱离 MODE 单独解释 CNF

1. 为什么 LED 使用 CNF13=00

板载 LED 的电路是:

text 复制代码
3.3V → LED → 510Ω → PC13

程序必须主动控制 PC13 输出:

text 复制代码
低电平 → LED亮
高电平 → LED灭

因此 PC13 必须满足:

  1. 是普通 GPIO,不是 USART、TIM 等外设控制;
  2. 能主动输出稳定的高、低电平;
  3. 不需要多设备共用一根信号线;
  4. 不需要外部上拉电阻才能输出高电平。

最符合的模式就是:

text 复制代码
通用推挽输出
CNF13 = 00

"通用"表示引脚由软件通过 ODR/BSRR/BRR 控制;"推挽"表示引脚内部既能主动拉高,也能主动拉低。

2. 为什么 MODE13=10

PC13 是特殊引脚,数据手册规定其作为输出使用时,速度最高为 2 MHz。

STM32F1 的 MODE 编码为:

MODE 含义
00 输入模式
01 输出,最高10 MHz
10 输出,最高2 MHz
11 输出,最高50 MHz

所以 PC13 应选择:

text 复制代码
MODE13 = 10

CNF13=00 合起来:

text 复制代码
CNF13 MODE13
  00      10

即:

text 复制代码
0010₂ = 0x2

PC13 位于 CRH[23:20],所以最终写入:

c 复制代码
0x2U << 20

也就是:

text 复制代码
0x00200000

3. CNF 到底控制什么

CNF 是 Configuration,即"配置类型"。

但它的解释取决于 MODE。

3.1 当 MODE=00:输入模式

此时 CNF 的含义是:

MODE CNF 模式 典型用途
00 00 模拟输入 ADC、电位器、模拟传感器
00 01 浮空输入 外部电路已经提供确定电平
00 10 上拉/下拉输入 按键、开关、可能悬空的数字信号
00 11 保留 不使用

模拟输入:MODE=00,CNF=00

text 复制代码
MODE = 00
CNF  = 00

适合:

  • ADC 采集;
  • 电位器电压;
  • 光敏电阻模拟量;
  • 热敏电阻模拟量。

模拟输入模式会关闭数字输入部分,减少数字电路对模拟信号的影响和功耗。

例如:

c 复制代码
/* PA0配置为模拟输入 */
GPIOA->CRL &= ~(0xFU << 0);

清零后就是:

text 复制代码
CNF0=00
MODE0=00

浮空输入:MODE=00,CNF=01

浮空输入内部既不上拉,也不下拉。

适合外部电路保证信号始终有确定电平的场景,例如:

  • 推挽数字芯片的输出;
  • 某些串口 RX;
  • 外部模块的数字输出;
  • 已经有外部上拉/下拉电阻的信号。

如果引脚没有外部驱动,浮空输入可能随机读取到 0 或 1,所以普通按键一般不应直接使用浮空输入。

上拉/下拉输入:MODE=00,CNF=10

适合:

  • 按键;
  • 开关;
  • 开漏输出信号;
  • 可能暂时断开的数字输入。

STM32F1 有一个特殊设计:

text 复制代码
MODE=00,CNF=10

只表示"上拉/下拉输入",具体是上拉还是下拉,由 ODR 对应位决定:

ODR 对应位 模式
0 下拉输入
1 上拉输入

例如 PC13 配置为上拉输入:

c 复制代码
GPIOC->CRH &= ~(0xFU << 20);
GPIOC->CRH |=  (0x8U << 20);  /* CNF=10,MODE=00 */

GPIOC->ODR |= (1U << 13);     /* ODR13=1,选择上拉 */

配置为下拉输入:

c 复制代码
GPIOC->ODR &= ~(1U << 13);    /* ODR13=0,选择下拉 */

这是 STM32F1 很重要的一个特点:

输入上拉/下拉模式下,ODR 不再控制输出电平,而是选择上拉还是下拉。


3.2 当 MODE≠00:输出模式

只要 MODE 是 011011,引脚就是输出模式。此时 CNF 的含义变为:

CNF 输出模式 典型用途
00 通用推挽输出 LED、蜂鸣器、普通控制信号
01 通用开漏输出 软件 I²C、线与、双向电平转换
10 复用推挽输出 USART TX、SPI、PWM、定时器输出
11 复用开漏输出 硬件 I²C 等开漏外设

4. 推挽输出是什么

推挽输出内部可以简化成两个开关:

text 复制代码
        3.3V
          │
      上方晶体管
          │
GPIO引脚 ─┤
          │
      下方晶体管
          │
         GND

输出高电平时:

text 复制代码
上方晶体管导通
下方晶体管关闭
GPIO被主动连接到3.3V

输出低电平时:

text 复制代码
上方晶体管关闭
下方晶体管导通
GPIO被主动连接到GND

特点:

  • 可以主动输出高电平;
  • 可以主动输出低电平;
  • 上升沿和下降沿都比较快;
  • 不需要外部上拉;
  • 不能与另一个推挽输出直接并联。

典型用途:

  • LED;
  • 有源蜂鸣器;
  • 继电器驱动输入;
  • 电机驱动器方向信号;
  • 芯片使能信号;
  • 普通高低电平控制。

所以板载 LED 使用通用推挽输出最直接:

text 复制代码
CNF13=00

5. 开漏输出是什么

开漏输出内部只有负责拉低的晶体管:

text 复制代码
外部上拉电阻
3.3V ── 电阻 ──┬── GPIO信号线
                │
            下拉晶体管
                │
               GND

GPIO 写 0:

text 复制代码
晶体管导通
引脚被主动拉低

GPIO 写 1:

text 复制代码
晶体管关闭
引脚处于高阻状态
依靠外部上拉电阻变成高电平

因此开漏输出本身只能:

  • 主动输出低电平;
  • 释放总线;
  • 不能主动输出高电平。

5.1 开漏有什么用

多个设备共用一根线

多个开漏设备可以接在一起:

text 复制代码
只要任意一个设备拉低 → 总线就是低电平
所有设备都释放 → 上拉电阻将总线拉高

这就是"线与"特性,I²C 使用的就是这种方式。

电平转换

例如 MCU 使用 3.3 V,外部总线使用 5 V:

text 复制代码
GPIO只负责拉低
总线高电平由外部5V上拉产生

但能否这样做还要检查引脚是否 5 V tolerant。

防止输出冲突

两个推挽输出如果一个输出高、另一个输出低,相当于把电源和地短接,可能产生很大电流。

开漏设备之间不会主动"一个拉高、一个拉低",因此更适合共享总线。

5.2 LED 能不能使用开漏输出

理论上可以。

这块板的 LED 已经连接到 3.3 V:

text 复制代码
3.3V → LED → 电阻 → PC13

如果 PC13 配置成通用开漏:

  • 写 0:PC13 拉低,LED 亮;
  • 写 1:PC13 高阻,LED 熄灭。

但这里没有共享总线、电平转换等需求,所以使用开漏没有必要。通用推挽输出的状态更确定,也是普通 LED 控制的常规选择。


6. "通用"和"复用"是什么意思

这是 CNF 中另一组关键概念。

通用输出

通用输出由 CPU 软件控制:

c 复制代码
GPIOC->BSRR = GPIO_BSRR_BS13;
GPIOC->BRR  = GPIO_BRR_BR13;

适合:

  • 软件控制 LED;
  • 软件控制蜂鸣器;
  • 普通片选信号;
  • 电机方向信号。

对应:

text 复制代码
CNF=00:通用推挽
CNF=01:通用开漏

复用输出

复用输出不是由普通 GPIO 输出寄存器持续控制,而是把引脚交给某个片上外设。

例如:

text 复制代码
PA9 交给 USART1_TX
PA5 交给 SPI1_SCK
PA6 交给 TIM3_CH1 输出PWM
PB6 交给 I2C1_SCL

对应:

text 复制代码
CNF=10:复用推挽
CNF=11:复用开漏

复用推挽什么时候用

典型应用:

  • USART TX;
  • SPI SCK;
  • SPI MOSI;
  • 定时器 PWM;
  • 定时器输出比较;
  • MCO 时钟输出。

例如 PA9 作为 USART1 TX:

text 复制代码
MODE = 非00
CNF  = 10

即复用推挽输出。

此时引脚电平由 USART 外设产生,而不是程序不断调用 GPIO_SetBits()

复用开漏什么时候用

最典型的是硬件 I²C:

text 复制代码
SCL:复用开漏输出
SDA:复用开漏输出

对应:

text 复制代码
MODE = 非00
CNF  = 11

因为 I²C 要求多个设备共享信号线,并允许任何设备拉低总线。


7. 一张表记住全部配置

MODE CNF 完整模式 常见用途
00 00 模拟输入 ADC
00 01 浮空输入 外部推挽数字信号
00 10 上拉/下拉输入 按键、开关
00 11 保留 不使用
01/10/11 00 通用推挽输出 LED、蜂鸣器、控制信号
01/10/11 01 通用开漏输出 软件 I²C、共享信号线
01/10/11 10 复用推挽输出 USART TX、SPI、PWM
01/10/11 11 复用开漏输出 硬件 I²C

这里的 01/10/11 分别表示 10 MHz、2 MHz、50 MHz 输出速度,选择时还要看具体引脚的数据手册限制。


8. 以后如何选择 CNF

先问第一个问题:

text 复制代码
这是输入还是输出?

如果是输入:

text 复制代码
是模拟电压?
    → 模拟输入

外部电路始终提供确定的高低电平?
    → 浮空输入

信号可能悬空,需要默认电平?
    → 上拉或下拉输入

如果是输出,再问:

text 复制代码
由CPU软件直接控制,还是交给片上外设?

软件控制:

text 复制代码
普通独立信号?
    → 通用推挽

需要共享线路、线与或外部上拉?
    → 通用开漏

外设控制:

text 复制代码
USART、SPI、PWM等普通输出?
    → 复用推挽

I²C等开漏总线?
    → 复用开漏

#mermaid-svg-Q0VL0XgkzSC1ubQR{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Q0VL0XgkzSC1ubQR .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Q0VL0XgkzSC1ubQR .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Q0VL0XgkzSC1ubQR .error-icon{fill:#552222;}#mermaid-svg-Q0VL0XgkzSC1ubQR .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Q0VL0XgkzSC1ubQR .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Q0VL0XgkzSC1ubQR .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Q0VL0XgkzSC1ubQR .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Q0VL0XgkzSC1ubQR .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Q0VL0XgkzSC1ubQR .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Q0VL0XgkzSC1ubQR .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Q0VL0XgkzSC1ubQR .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Q0VL0XgkzSC1ubQR .marker.cross{stroke:#333333;}#mermaid-svg-Q0VL0XgkzSC1ubQR svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Q0VL0XgkzSC1ubQR p{margin:0;}#mermaid-svg-Q0VL0XgkzSC1ubQR .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Q0VL0XgkzSC1ubQR .cluster-label text{fill:#333;}#mermaid-svg-Q0VL0XgkzSC1ubQR .cluster-label span{color:#333;}#mermaid-svg-Q0VL0XgkzSC1ubQR .cluster-label span p{background-color:transparent;}#mermaid-svg-Q0VL0XgkzSC1ubQR .label text,#mermaid-svg-Q0VL0XgkzSC1ubQR span{fill:#333;color:#333;}#mermaid-svg-Q0VL0XgkzSC1ubQR .node rect,#mermaid-svg-Q0VL0XgkzSC1ubQR .node circle,#mermaid-svg-Q0VL0XgkzSC1ubQR .node ellipse,#mermaid-svg-Q0VL0XgkzSC1ubQR .node polygon,#mermaid-svg-Q0VL0XgkzSC1ubQR .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Q0VL0XgkzSC1ubQR .rough-node .label text,#mermaid-svg-Q0VL0XgkzSC1ubQR .node .label text,#mermaid-svg-Q0VL0XgkzSC1ubQR .image-shape .label,#mermaid-svg-Q0VL0XgkzSC1ubQR .icon-shape .label{text-anchor:middle;}#mermaid-svg-Q0VL0XgkzSC1ubQR .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Q0VL0XgkzSC1ubQR .rough-node .label,#mermaid-svg-Q0VL0XgkzSC1ubQR .node .label,#mermaid-svg-Q0VL0XgkzSC1ubQR .image-shape .label,#mermaid-svg-Q0VL0XgkzSC1ubQR .icon-shape .label{text-align:center;}#mermaid-svg-Q0VL0XgkzSC1ubQR .node.clickable{cursor:pointer;}#mermaid-svg-Q0VL0XgkzSC1ubQR .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Q0VL0XgkzSC1ubQR .arrowheadPath{fill:#333333;}#mermaid-svg-Q0VL0XgkzSC1ubQR .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Q0VL0XgkzSC1ubQR .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Q0VL0XgkzSC1ubQR .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Q0VL0XgkzSC1ubQR .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Q0VL0XgkzSC1ubQR .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Q0VL0XgkzSC1ubQR .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Q0VL0XgkzSC1ubQR .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Q0VL0XgkzSC1ubQR .cluster text{fill:#333;}#mermaid-svg-Q0VL0XgkzSC1ubQR .cluster span{color:#333;}#mermaid-svg-Q0VL0XgkzSC1ubQR div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Q0VL0XgkzSC1ubQR .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Q0VL0XgkzSC1ubQR rect.text{fill:none;stroke-width:0;}#mermaid-svg-Q0VL0XgkzSC1ubQR .icon-shape,#mermaid-svg-Q0VL0XgkzSC1ubQR .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Q0VL0XgkzSC1ubQR .icon-shape p,#mermaid-svg-Q0VL0XgkzSC1ubQR .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Q0VL0XgkzSC1ubQR .icon-shape .label rect,#mermaid-svg-Q0VL0XgkzSC1ubQR .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Q0VL0XgkzSC1ubQR .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Q0VL0XgkzSC1ubQR .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Q0VL0XgkzSC1ubQR :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 输入
模拟电压
外部保证确定电平
需要默认电平
输出
CPU软件


片上外设


配置GPIO
输入还是输出?
信号类型
模拟输入 CNF=00
浮空输入 CNF=01
上拉/下拉输入 CNF=10
由谁控制?
是否需要开漏?
通用推挽 CNF=00
通用开漏 CNF=01
外设需要开漏?
复用推挽 CNF=10
复用开漏 CNF=11

这些配置位的原始定义位于《STM32F10xxx参考手册(中文)》第 8.2.1、8.2.2 节,即 GPIOx_CRLGPIOx_CRH 寄存器说明中。:codex-file-citation{path="F:\WorkBuddyOutput\STM32\STM32\参考文档\STM32F10xxx参考手册(中文).pdf" purpose="source"}

相关推荐
单片机仿真设计27 分钟前
【proteus仿真】基于 STM32 单片机货架巡检机器人设计(仿真图+程序)
stm32·单片机·嵌入式硬件·机器人·proteus·毕设
虎王物联9 小时前
STM32 HAL库串口DMA空闲中断:高效接收不定长Modbus数据帧
stm32·单片机·嵌入式硬件·dma·modbus
自小吃多10 小时前
DXF文件导入与PCB板框定义笔记
笔记·嵌入式硬件
SUNNYSPY00110 小时前
AO4402-ASEMI便携设备电源开关AO4402
单片机
单片机仿真设计12 小时前
【proteus仿真】基于 STC89C52 单片机家用智能台灯设计(仿真图+程序)
stm32·单片机·嵌入式硬件·proteus·毕设
2601_9507906812 小时前
深圳国产单片机厂商怎么选?技术能力与服务能力检查表
单片机·嵌入式硬件·国产mcu·芯片厂商·深圳单片机·单片机选型
hongmai66688814 小时前
MP2348GTL-Z:这颗24V/4A同步降压芯片,把性能和体积平衡得恰到好处
c语言·开发语言·arm开发·单片机·5g
笨笨饿14 小时前
#135_代码中的类型重定义艺术:从基础封装到函数类型设计
开发语言·stm32·单片机·嵌入式硬件·mcu·物联网·嵌入式实时数据库
西城微科方案开发15 小时前
高精度低功耗胎压计方案——气压表解决方案
单片机·嵌入式硬件