当前位置: 首页 > news >正文

嵌入式学习笔记3.基于寄存器方式控制GPIO


1. 模式寄存器 (GPIOx->MODER)

模式寄存器一共有32位,每2位一组,对应着1个不同的1/0引脚。这些位通过软件写人,用于配置1/0引脚的模式:

  • 00:输入模式(复位值)
  • 01:通用输出模式
  • 10:复用功能模式
  • 11:模拟模式

eg:向GPIOA_MODER寄存器的bit1和bitO写人01,表示将引脚PA0设置为输出模式;向GPI0C_MODER寄存器的bit31和bit30写人11,表示将引脚PC15设置为模拟模式。

1. 模式寄存器 (GPIOx->MODER)
MODER 寄存器用于配置引脚是输入、输出还是复用功能。每个引脚由两位控制。
配置为输入模式:00
配置为通用输出模式:01
配置为复用功能模式:10
配置为模拟模式:11
操作方法:先清零,再置位。// 示例:将 PA5 配置为通用输出模式 (01)
// 1. 清零 PA5 对应的位 (第10位和第11位)
GPIOA->MODER &= ~(0x03 << (5 * 2)); 
// 2. 设置 PA5 为通用输出模式 (01)
GPIOA->MODER |=  (0x01 << (5 * 2));// 示例:将 PA6 配置为输入模式 (00)
// 只需清零即可
GPIOA->MODER &= ~(0x03 << (6 * 2));

2. 输出类型寄存器 (GPIOx->OTYPER)

输出类型寄存器(GPIOx_OTYPER)
该寄存器用于控制GPIO端口各引脚的输出类型,该寄存器在引脚配置为输出模式后才有效,其他工作模式下无效。
输出类型寄存器一共有32位,如表6-3所示。高16位保留,低16位的每1位对应一个不同的1/0引脚。这些位通过软件写人,用于配置1/0引脚的输出类型:

  • 0:推挽输出(复位值)
  • 1:开漏输出

例如:向GPIOB_OSPEEDR寄存器的bit1写人1,表示将引脚PB1设置为开漏输出模式。

2. 输出类型寄存器 (GPIOx->OTYPER)
OTYPER 寄存器用于配置输出引脚是推挽(Push-Pull)还是开漏(Open-Drain)。每个引脚由一位控制。
推挽输出:0 (输出高低电平)
开漏输出:1 (只能拉低电平,需要外部上拉电阻才能输出高电平)
操作方法:通常与 MODER 配合使用。// 示例:将 PA5 配置为推挽输出
GPIOA->OTYPER &= ~(0x01 << 5); // 清零第5位// 示例:将 PA7 配置为开漏输出
GPIOA->OTYPER |= (0x01 << 7); // 置位第7位

3. 输出速度寄存器 (GPIOx->OSPEEDR)

  • 00:低速(复位值)
  • 01:中速
  • 10:高速
  • 11:超高速

例如:向GPI0D_MODER寄存器的bi15和bit14写人11,表示将引脚PD7的输出速度设置为超高速。

3. 输出速度寄存器 (GPIOx->OSPEEDR)
OSPEEDR 寄存器用于配置输出引脚的切换速度。每个引脚由两位控制。
低速:00
中速:01
高速:10
超高速:11 (部分引脚支持)
操作方法:先清零,再置位。
c
运行
// 示例:将 PA5 配置为高速输出 (10)
GPIOA->OSPEEDR &= ~(0x03 << (5 * 2)); // 清零
GPIOA->OSPEEDR |=  (0x02 << (5 * 2)); // 设置为 10

4. 上下拉寄存器 (GPIOx->PUPDR)

  • 00:既无上拉也无下拉(复位值)
  • 01:上拉
  • 10:下拉
  • 11:保留

例如:向GPIOE_PUPDR寄存器的bit17和bit16写入01,表示使能引脚PE8的上拉电阻。

4. 上下拉寄存器 (GPIOx->PUPDR)
PUPDR 寄存器用于配置引脚的上拉或下拉电阻。每个引脚由两位控制。无上拉 / 下拉:00
上拉:01
下拉:10
操作方法:先清零,再置位。
// 示例:将 PA6 (输入引脚) 配置为上拉
GPIOA->PUPDR &= ~(0x03 << (6 * 2)); // 清零
GPIOA->PUPDR |=  (0x01 << (6 * 2)); // 设置为 01// 示例:将 PA5 (输出引脚) 配置为无上拉/下拉
GPIOA->PUPDR &= ~(0x03 << (5 * 2)); // 只需清零

5. 输入数据寄存器 (GPIOx->IDR)

  • 0:对应引脚输入低电平
  • 1:对应引脚输入高电平

例如:如果读到GPIOA_IDR寄存器的bit7为1,表示引脚PA7输人高电平。

注意:输入数据寄存器是只读模式,不能通过软件写人。当引脚设置为输出模式或复用模式时,也可以通过输入数据寄存器读取引脚的电平状态。

5. 输入数据寄存器 (GPIOx->IDR)
IDR 寄存器用于读取引脚的当前电平状态。它是只读寄存器。
操作方法:使用按位与(&)操作来读取特定引脚。// 示例:读取 PA6 的电平状态
uint32_t pin_state = GPIOA->IDR & (0x01 << 6);if (pin_state) {// PA6 为高电平
} else {// PA6 为低电平
}


6. 输出数据寄存器 (GPIOx->ODR) 

  • 0:对应引脚输出低电平
  • 1:对应引脚输出高电平

例如:向GPIOA_ODR寄存器的bi5写人1,表示引脚PA5输出高电平。

6. 输出数据寄存器 (GPIOx->ODR) 用于控制输出引脚的电平。
ODR:直接读写整个端口的输出状态。读改写(Read-Modify-Write)操作可能引发竞态条件。操作方法:// 使用 ODR 控制 PA5
GPIOA->ODR |= (0x01 << 5);  // PA5 输出高电平 (Set)
GPIOA->ODR &= ~(0x01 << 5); // PA5 输出低电平 (Reset)// HAL库也提供了直接操作BSRR的宏
__HAL_GPIO_SET_PIN(GPIOA, GPIO_PIN_5);
__HAL_GPIO_RESET_PIN(GPIOA, GPIO_PIN_5);

  • 高16位用于控制对应的I0引脚输出低电平:写入1对应引脚输出低电平,写人 0没有任何作用。
  • 低16位用于控制对应的1/0引脚输出高电平:写入1对应引脚输出高电平,写人 0没有任何作用。

和GPIOx_ODR寄存器相比,使用GPIOx_BSRR寄存器控制引I脚有两个优势:

①GPIOx_BSRR寄存器的操作是原子操作,不会被中断所打断。

②在控制多个引脚同时输出高/低电平时更加方便。

7.置位 / 复位寄存器 (GPIOx->BSRR)
BSRR:推荐使用。高 16 位用于复位(置 0),低 16 位用于置位(置 1)。操作是原子的,不会有竞态条件。
操作方法:// 使用 BSRR 控制 PA5 (更安全、更高效)
#define SET_PIN5  (0x01 << 5)
#define RESET_PIN5 (0x01 << (5 + 16))GPIOA->BSRR = SET_PIN5;    // PA5 输出高电平
GPIOA->BSRR = RESET_PIN5;  // PA5 输出低电平

7. 复用功能寄存器 (GPIOx->AFRL, GPIOx->AFRH)

AFRL (用于引脚 0-7) 和 AFRH (用于引脚 8-15) 寄存器用于选择复用功能的具体外设。每个引脚由四位控制。

操作方法:需要查阅芯片数据手册(Datasheet)来确定外设对应的 AF 编号。

// 示例:将 PA9 配置为 USART1_TX (假设 AF 编号为 7)
// PA9 在 AFRH 寄存器中,对应位 [15:12]
// 1. 清零 PA9 对应的 4 个位
GPIOA->AFRH &= ~(0x0F << ((9 - 8) * 4)); 
// 2. 设置 AF 编号为 7 (0111)
GPIOA->AFRH |=  (0x07 << ((9 - 8) * 4));

8. 配置锁存寄存器 (GPIOx->LCKR)

LCKR 寄存器用于锁定引脚的配置,防止意外修改。一旦锁定,只有在下次复位后才能重新配置。

操作方法:遵循特定的 “锁定序列”。

// 示例:锁定 PA5 的配置
// 1. 写 LCKR 寄存器,设置 LCKK 位和要锁定的引脚位
GPIOA->LCKR = (GPIO_PIN_5 | GPIO_LCKK_Msk);
// 2. 再次写 LCKR 寄存器,同样设置 LCKK 位和引脚位
GPIOA->LCKR = (GPIO_PIN_5 | GPIO_LCKK_Msk);
// 3. 第三次读 LCKR 寄存器
volatile uint32_t temp = GPIOA->LCKR;
// 4. 第四次读 LCKR 寄存器。如果 LCKK 位为 1,则锁定成功。
if ((GPIOA->LCKR & GPIO_LCKK_Msk) == GPIO_LCKK_Msk) {// PA5 配置已成功锁定!
}

总结:HAL 库函数 vs. 直接寄存器操作

功能 (Function)HAL 库函数 (HAL Library Function)直接寄存器操作 (Direct Register Access)
初始化配置HAL_GPIO_Init()GPIOx->MODEROTYPEROSPEEDRPUPDRAFRL/H
读取输入HAL_GPIO_ReadPin()GPIOx->IDR & GPIO_PIN_x
写输出HAL_GPIO_WritePin()GPIOx->ODR = ... 或 GPIOx->BSRR = ...
翻转输出HAL_GPIO_TogglePin()GPIOx->ODR ^= GPIO_PIN_x 或 GPIOx->BSRR = ...
锁定配置HAL_GPIO_LockPin()GPIOx->LCKR (遵循锁定序列)
http://www.dtcms.com/a/414377.html

相关文章:

  • 自动驾驶中的传感器技术53——Radar(14)
  • 杭州网站推广技巧十大跨境电商公司
  • Boost电路项目实战:从原理到实战全解析(含电流环电压环)
  • a-input输入框,苹果电脑(MAC)输入法的输入Bug
  • C# TCP - 串口转发1.0
  • Unity数据持久化操作——二进制篇
  • Linux基础开发工具 --- vim
  • ip route-static 概念及题目
  • 教做3d的网站自媒体平台大全
  • 高性能分布式对象存储RustFS
  • 操作系统应用开发(九)RustDesk远程桌面介绍——东方仙盟筑基期
  • 【Rust GUI开发入门】编写一个本地音乐播放器(2. Rodio播放库的使用)
  • 企业网站建设的方法有哪些wordpress 工具安装教程
  • LabVIEW 模拟单摆运动(DAE 法)
  • 【计算机基础】网络系列(一)HTTP
  • Linux与STM32实时性与系统资源解析
  • 深圳网站建设icxun邯郸二手房出售信息
  • 展示内容框
  • 衡石HQL深度解析:如何用类SQL语法实现跨源数据的高效联邦查询?
  • 明明是新电脑,却越用越卡?如何优化?
  • StringBuffer和StringBuilder
  • 华为本地pbr及mqc及traffic-filter使用案例
  • Spring 依赖注入
  • 南宁做网站优化的公司类似58同城分类信息网站开发
  • ArkTS基础语法
  • ROS-Jazzy_rclpy
  • Socket 编程 TCP(准备阶段)
  • 【Ultralytics】评估报错:解决 KeyError: ‘info‘ 错误
  • 哪些是实名制网站母了猜猜看游戏做网站
  • 【Linux】TCP原理