韦东山《ARM 架构与编程》3-2 GPIO 引脚操作方法概述 · 学习笔记

韦东山《ARM 架构与编程》3-2 GPIO 引脚操作方法概述 · 学习笔记

所属课程 :ARM 架构与编程 · 基于 STM32F103

所在章节 :第三章 第一个程序(点亮 LED)· 第 2 节

原视频 :https://video.100ask.net/p/t_pc/course_pc_detail/video/v_5f858f7de4b0e95a89c3d4c6

整理日期:2026-09-28

目录

  • 摘要
  • 一、本节在课程中的位置
    • [1.1 承上启下](#1.1 承上启下)
    • [1.2 本节的定位:通用方法论,而非芯片手册导读](#1.2 本节的定位:通用方法论,而非芯片手册导读)
  • [二、GPIO 的概念](#二、GPIO 的概念)
  • [三、GPIO 的使用:四要素初始化框架](#三、GPIO 的使用:四要素初始化框架)
    • [3.1 要素一:使能(电源 / 时钟)](#3.1 要素一:使能(电源 / 时钟))
    • [3.2 要素二:模式(Mode / 功能复用)](#3.2 要素二:模式(Mode / 功能复用))
    • [3.3 要素三:方向(Direction)](#3.3 要素三:方向(Direction))
    • [3.4 要素四:数值(Value / 电平)](#3.4 要素四:数值(Value / 电平))
  • [四、GPIO 寄存器的读写方法](#四、GPIO 寄存器的读写方法)
    • [4.1 方法一:读-改-写(read-modify-write)](#4.1 方法一:读-改-写(read-modify-write))
    • [4.2 方法二:set-reg / clr-reg(置位 / 清零寄存器)](#4.2 方法二:set-reg / clr-reg(置位 / 清零寄存器))
    • [4.3 两种方法的对比](#4.3 两种方法的对比)
  • [五、GPIO 的其他功能](#五、GPIO 的其他功能)
  • 六、本节结论与延伸
  • [附录 A:术语速查](#附录 A:术语速查)
  • [附录 B:读完本节后的自查清单](#附录 B:读完本节后的自查清单)

摘要

本节承接 3-1 的点灯命题,抽象出 GPIO 通用操作框架:先使能时钟,再由模式寄存器选定 GPIO 功能,继而设方向为输入或输出,最后读写数据寄存器输出或采集电平。读写遵循"不影响其他位"原则,有读-改-写与 set/clr 寄存器两种实现,为后续芯片级编程建立统一范式。


一、本节在课程中的位置

1.1 承上启下

第三章的"点灯链路"中,本节处于从硬件到软件的抽象层:

text 复制代码
3-1 硬件知识_LED 原理图   ← 已完成:知道引脚是哪根、什么电平点亮
        ↓
3-2 GPIO 引脚操作方法概述  ← 本节:不谈具体芯片,回答"通用地看,
        ↓                    让引脚输出/输入电平要走哪几步"
3-3 STM32F103 的 GPIO 操作方法
        ↓
3-4 STM32F103 的 LED 编程
  • 承上:3-1 的结论是"引脚输出高/低电平即可控制 LED",但"怎么让引脚输出电平"悬而未决------这正是本节的命题。
  • 启下:3-3 将把本节的通用框架落到 STM32F103 的具体寄存器(CRL/CRH、ODR、BSRR 等)上,3-4 再翻译成可编译的程序。

1.2 本节的定位:通用方法论,而非芯片手册导读

课程刻意把这一节做成芯片无关的概述:无论 STM32F103、I.MX6ULL 还是 STM32MP157,也无论是 51、AVR 还是其他 MCU,GPIO 的操作要素都相同。先建立这个"通用模板",再去看任何一款芯片的手册,都只是往模板里填寄存器名字------这是本节最重要的学习收益。


二、GPIO 的概念

GPIO :General-purpose input/output,通用输入输出口。

它是芯片与外部世界交互的最基础通道:

方向 物理行为 典型应用
输出 引脚上出现高电平 / 低电平 驱动 LED、蜂鸣器、继电器
输入 读取引脚当前电平 按键检测、传感器信号采集

"通用"二字的含义:这些引脚不固定用途,由软件配置决定其方向与功能,既可当输出口也可当输入口。

芯片上的 GPIO 通常分组编排 :有多组 GPIO(如 GPIOA、GPIOB、GPIOC...),每组含多个引脚(典型为 16 个,Pin0~Pin15)。3-1 中从原理图读出的 PC13,指的就是"C 组第 13 号引脚"------引脚编号体系与本节的分组概念直接对应。


三、GPIO 的使用:四要素初始化框架

本节的核心内容是把 GPIO 的初始化与使用归纳为四个要素,顺序不可颠倒:

text 复制代码
① 使能(电源/时钟)
        ↓
② 模式(Mode:GPIO 还是其他功能)
        ↓
③ 方向(Direction:输出还是输入)
        ↓
④ 数值(Value:写电平 / 读电平)

3.1 要素一:使能(电源 / 时钟)

  • 大多数芯片为降低功耗,默认关闭外设的电源或时钟;GPIO 模块不使能,其寄存器写不进去、读出来也无意义。
  • 对应地,芯片手册一般有专门的 power/clock 章节:向指定寄存器的指定位写 1,使能某个 GPIO 模块(Module)。
  • 并非所有芯片都有这一步------有些芯片的 GPIO 没有使能开关,永远处于使能状态(典型如不少传统 51 单片机)。是否存在这一步,查手册即知。

工程教训:在 STM32 等芯片上"程序写了对的寄存器但引脚毫无反应",最常见的原因就是忘了先开 GPIO 时钟。3-1 的误区清单埋下的伏笔,在本节得到解释。

3.2 要素二:模式(Mode / 功能复用)

现代 MCU 的引脚大多是复用引脚:同一个物理引脚,既可以当普通 GPIO,也可以接给串口、USB、I²C、定时器等片上外设使用。

  • 因此在把引脚当 GPIO 用之前,必须先通过功能选择寄存器(IOMUX / 复用选择位)明确声明:"这个引脚用于 GPIO 功能"。
  • 跳过这一步,引脚可能仍连接在其他外设上,后续的"方向""数值"设置全部无效。

3.3 要素三:方向(Direction)

引脚被设置为 GPIO 功能之后,还要指定它是输出 还是输入:

  • 输出:由芯片驱动引脚电平;
  • 输入:由外部器件驱动引脚电平,芯片只负责读取。

方向由方向寄存器(或输出使能寄存器)中的对应位决定。这一步"方向先行"的逻辑很重要:方向都没定,谈输出或输入电平就是无本之木。

3.4 要素四:数值(Value / 电平)

方向确定后,操作数据寄存器即可:

引脚方向 操作 效果
输出 向数据寄存器写 1 / 0 引脚输出高电平 / 低电平
输入 读数据寄存器对应位 得到引脚当前电平(1 = 高,0 = 低)

至此,"让 PC13 输出低电平点亮 LED"这句话被完整翻译成四条寄存器级动作:开时钟 → 选 GPIO 功能 → 设为输出 → 数据寄存器写 0。


四、GPIO 寄存器的读写方法

四要素落到代码上就是"读写寄存器"。但 GPIO 寄存器是一组引脚共用一个 32 位寄存器------每一位属于不同的引脚,这就引出一条铁律:

原则:操作某个引脚对应的位时,不能影响到其他位。

课程给出两种满足该原则的读写方法:

4.1 方法一:读-改-写(read-modify-write)

适用于只有数据寄存器(data_reg)的芯片:

c 复制代码
val  = data_reg;          // 1. 读:取出整个寄存器的当前值
val  = val | (1 << n);    // 2. 改:用位或把第 n 位置 1(清 0 则用 val & ~(1 << n))
data_reg = val;           // 3. 写:整体写回

三步缺一不可:直接写 data_reg = (1 << n) 会把其他 31 位全部清零,殃及同组其他引脚。

位操作速记:

操作 表达式 用途
置 1 `reg = (1 << n)`
清 0 reg &= ~(1 << n) 关闭第 n 位
检测 reg & (1 << n) 读出第 n 位

4.2 方法二:set-reg / clr-reg(置位 / 清零寄存器)

部分芯片除数据寄存器外,还提供一对专用寄存器:

  • set_reg(置位寄存器):向第 n 位写 1 → 该位被置 1;
  • clr_reg(清零寄存器):向第 n 位写 1 → 该位被清 0;
  • 写 0 的位不产生任何效果------这正是"不影响其他位"原则的硬件级实现。
c 复制代码
set_reg = (1 << n);   // 只把第 n 位置 1,一步完成
clr_reg = (1 << n);   // 只把第 n 位清 0,一步完成

4.3 两种方法的对比

对比项 读-改-写 set/clr 寄存器
硬件要求 仅需一个数据寄存器 需要额外的置位/清零寄存器
操作步数 三步 一步
并发风险 读、改、写之间若被中断打断并修改了同一寄存器,结果可能互相覆盖 单次写操作,天然原子,无竞争风险
代码形态 位数组组合 直观、简洁

读-改-写的竞争问题在中断与多任务环境下尤为致命------这也解释了为什么后来的芯片(包括 STM32 的 BSRR 寄存器)普遍采用 set/clr 方案。本节作为概述,正是要提前建立这一判断力:拿到一款芯片,先看它有没有 set/clr 寄存器,再决定用哪种写法。


五、GPIO 的其他功能

除"输出/输入电平"这一基本职能外,GPIO 模块通常还提供若干扩展功能,课程点到即止:

  • 防抖动(去抖):输入信号抖动时的硬件滤波能力,多用于按键类应用;
  • 中断:引脚电平变化触发中断,避免软件轮询;
  • 唤醒:低功耗休眠模式下,由指定引脚的电平变化唤醒芯片;
  • 输出速率(驱动速度):可配置引脚的翻转速率。

其中"输出速率"一条暗含重要的工程权衡:

GPIO 配置的输出速率越高,信号边沿越陡,对外产生的电磁干扰(EMI)越大。

因此速率并非越高越好------驱动 LED 这类低速负载,选择较低的输出速率反而更稳妥。这些功能将在后续章节(按键、中断)中逐一展开。


六、本节结论与延伸

本节的知识可以浓缩为一张"通用 GPIO 操作模板":

text 复制代码
┌─ 1. 使能:power / clock 寄存器(部分芯片无此步)
├─ 2. 模式:功能选择寄存器 → 选定 GPIO 功能
├─ 3. 方向:方向寄存器 → 输出 / 输入
├─ 4. 数值:数据寄存器 → 写电平(输出)/ 读电平(输入)
└─ 读写纪律:不影响其他位 → 读-改-写 或 set/clr 寄存器

两点延伸:

  1. 这套四要素框架是跨芯片复用的:下一节 3-3 只需把 STM32F103 手册里的寄存器名字(GPIOx_CRL/CRH、GPIOx_ODR、GPIOx_BSRR、RCC_APB2ENR)填进模板的四个空位。
  2. "不影响其他位"的原则与 set/clr 寄存器的取舍,是裸机编程与后续 RTOS/Linux 驱动中反复出现的主题------凡是共享资源,都存在同样的"局部修改不得殃及整体"问题。

附录 A:术语速查

术语 含义
GPIO General-purpose input/output,通用输入输出口
时钟使能(Clock Enable) 打开外设工作时钟的寄存器操作,多数芯片 GPIO 使用的前置步骤
复用(Alternate Function) 同一物理引脚可连接不同片上外设,需由功能选择寄存器指定
方向寄存器 决定引脚为输出或输入的寄存器
数据寄存器(data_reg) 写入 / 读出引脚电平的寄存器
set_reg / clr_reg 置位 / 清零寄存器,写 1 生效、写 0 无效
读-改-写(read-modify-write) "读出 → 位操作 → 写回"的三步寄存器局部修改法
输出速率 引脚电平翻转速度,速率越高 EMI 越大

附录 B:读完本节后的自查清单

  • 能背出 GPIO 使用的四要素及它们的先后顺序。
  • 能解释"为什么操作一个引脚的位不能影响其他位"。
  • 能写出置 1、清 0、检测某一位的三条位操作表达式。
  • 能说明读-改-写与 set/clr 寄存器两种方法的差异及各自适用场景。
  • 能解释为什么输出速率不是越高越好。
  • 拿到一款没学过的芯片手册,知道按哪四个关键词去检索 GPIO 章节(power/clock、功能选择、方向、数据)。

本文档依据课程公开目录、原视频页信息及公开学习笔记整理,配合原视频 3-2 使用。

相关推荐
其实防守也摸鱼1 小时前
内网安全防护实践:从攻击视角理解防御要点
java·前端·安全·架构·自动化·nps
智购科技自动售货机工厂1 小时前
数字人民币硬钱包支付失败,排查发现是NFC读卡器功率不足~YH
python·面试·架构·eclipse·emacs
海宇AI1 小时前
零信任架构实战:基于海宇车型识别精准构建自动化车队评估微服务
java·人工智能·架构·自动化
zhangrelay1 小时前
ROS2 Lyrical实验5导航Nav2
linux·笔记·学习·ubuntu·机器人
JWASX2 小时前
Java 转 go 学习 - 基本语法
学习·golang
硅基手札2 小时前
【risc-v专栏03】CSR 速查与特权架构 M/S/U
单片机·架构·risc-v
一木 之林2 小时前
多模态大模型一统精讲 NLP 和 CV:从 ViT、CLIP 到 BLIP、LLaVA 的三段式统一架构
人工智能·自然语言处理·架构
让头发掉下来2 小时前
Kettle学习-17作业的创建与定时调度
学习
157092511342 小时前
Android 架构模式详解:从 MVC、MVP 到 MVVM
android·架构·mvc