STM32调试Debug,读,写 GPIO 寄存器(含实例代码)

以STM32G070CBT6 PA8为例
注:下面调试界面的打开方式为
下面图中调试界面中的寄存器仅用于指明具体位置,并不代表实际的实验现象
本文涉及寄存器的读写操作,不熟悉的可以移步 STM32寄存器读写操作-CSDN博客

MODER寄存器

GPIOA->MODER
  • 作用:配置 PA8 的工作模式(输入、输出、复用或模拟)。
  • 位置:MODER[17:16] 对应 PA8。
    • 00:输入模式。
    • 01:输出模式。
    • 10:复用功能。
    • 11:模拟模式。
if ((GPIOA->MODER & GPIO_MODER_MODE8_Msk) != 0x0) {
    // 如果 MODER8 不为 00,说明未配置为输入模式
    // 应清除 MODER8 对应的位:
    GPIOA->MODER &= ~GPIO_MODER_MODE8_Msk; // 设置为输入模式
}
如图PA8被配置为输入模式

1.输入模式(MODE = 0x00)

PA8 被配置为输入模式 (MODER = 0) 时,重点观察以下寄存器:
  1. GPIOA->IDR:读取输入引脚的电平状态。
  2. GPIOA->PUPDR:检查内部上拉/下拉电阻配置。
  3. RCC->AHB2ENR:确保 GPIO 时钟使能。
  4. GPIOA->LCKR:检查引脚配置是否被锁定。
  5. SYSCFG->EXTICR:检查是否被配置为外部中断。

1. GPIOx_IDR(输入数据寄存器)

  • 作用:用于读取引脚的当前输入电平状态。
  • 位置:GPIOA->IDR 的第 n 位对应引脚 PAx。
  • 观测值:
    • 0:引脚电平为低电平。
    • 1:引脚电平为高电平。
if (GPIOA->IDR & GPIO_IDR_ID8) {
    // PA8 当前为高电平
} else {
    // PA8 当前为低电平
}

2. GPIOx_PUPDR(上下拉电阻配置寄存器)

  • 作用:确定输入模式下引脚是否启用了内部上拉或下拉电阻。
  • 位置:PUPDR[2n:2n+1],其中 n 是引脚编号。
  • 配置值:
    • 00:无上下拉(浮空)。
    • 01:上拉。
    • 10:下拉。
    • 11:保留。
uint32_t pupd = (GPIOA->PUPDR & GPIO_PUPDR_PUPD8_Msk) >> GPIO_PUPDR_PUPD8_Pos;


if (pupd == 0x1) {
    // PA8 配置为上拉
} else if (pupd == 0x2) {
    // PA8 配置为下拉
} else {
    // PA8 无上下拉(浮空)
}

3. RCC_IOPENR(GPIO 时钟使能寄存器)

  • 作用:确保 GPIO 端口的时钟已经使能。
  • 位置:RCC->IOPENR 的对应位。
  • 如果 GPIO 时钟未使能,GPIO 引脚的配置和状态读取将无效。
if ((RCC->IOPENR & RCC_IOPENR_GPIOAEN_Msk)>>RCC_IOPENR_GPIOAEN_Pos) {
    // GPIOA 时钟已使能
} else {
    // GPIOA 时钟未使能
}

4. GPIOx_LCKR(引脚锁定寄存器)

  • 作用:用于检查引脚配置是否被锁定。
  • 位置:GPIOA->LCKR 的第 n 位对应引脚 PAx。
  • 如果引脚配置被锁定,任何对引脚配置的更改将被禁止。
if (GPIOA->LCKR & GPIO_LCKR_LCK8) {
    // PA8 配置已被锁定
}

5. SYSCFG_EXTICR(外部中断配置寄存器)

  • 位置:EXTICR3[3:0]
  • 作用:检查引脚是否被配置为外部中断源。
  • 如果 EXTI 被配置为与输入引脚关联,那么外部信号可能影响引脚的行为。
if ((SYSCFG->EXTICR[2] & SYSCFG_EXTICR3_EXTI8_Msk) == SYSCFG_EXTICR3_EXTI8_PA) {
    // PA8 被配置为 EXTI8 信号源
}
为什么是在这个位置呢?
SYSCFG_EXTICR3 之所以对应 EXTI8,是因为在 STM32 系列芯片中, EXTI 控制寄存器16 个 EXTI 线路(EXTI0 ~ EXTI15) 分配到 4 个配置寄存器(EXTICR1 ~ EXTICR4) 中,每个寄存器管理 4 条 EXTI 线路

EXTICR 寄存器的分配规则
寄存器
管理的 EXTI 线
EXTICR1
EXTI0 ~ EXTI3
EXTICR2
EXTI4 ~ EXTI7
EXTICR3
EXTI8 ~ EXTI11
EXTICR4
EXTI12 ~ EXTI15

为什么 PA8 属于 EXTICR3?
  • PA8 对应的 外部中断线(EXTI8)。
  • 根据上述分配表,EXTI8 位于 SYSCFG_EXTICR3 中。
  • 在 EXTICR3 的 低 4 位(位 0-3) 用于配置 EXTI8 的引脚来源。

EXTICR3 的位定义
SYSCFG_EXTICR3 寄存器中:
位段
描述
[3:0]
EXTI8
的引脚映射
[7:4]
EXTI9
的引脚映射
[11:8]
EXTI10
的引脚映射
[15:12]
EXTI11
的引脚映射
[31:16]
保留

EXTI8 的引脚映射值
值 (位 3:0)
GPIO 引脚
0000
PA8
0001
PB8
0010
PC8
0011
PD8
0100
PF8
但是,当 PA8 的复位值和配置为外部中断对应的寄存器值都为 0 时(即 SYSCFG_EXTICR3 的 EXTI8 对应位段为 0000),的确容易让人产生混淆。此时,你需要结合 其他调试手段和寄存器的状态 来确认 PA8 是否真正被配置为外部中断引脚。
检查 EXTI 寄存器
  EXTI_IMR1(Interrupt Mask Register 1)
EXTI_IMR1 寄存器位定义
EXTI_IMR1 是 32 位寄存器,具体位定义如下:
位段
描述
Bit 0
EXTI0 中断屏蔽
Bit 1
EXTI1 中断屏蔽
Bit 2
EXTI2 中断屏蔽
...
...
Bit 8
EXTI8 中断屏蔽
...
...
Bit 19
EXTI19 中断屏蔽
Bit 20:31
保留
例如,当 EXTI_IMR1 的第 8 位(Bit 8)= 1 时,表示 EXTI8(对应 PA8 等)被使能,可以触发中断。

2.输出模式(MODE = 0x01)

PA8 被配置为输出模式 (MODER = 0x01) 时,重点观察以下寄存器:
  1. GPIOA->ODR:控制引脚的输出电平。
  2. GPIOA->BSRR:原子性设置/清除引脚输出。STM32原子性设置-CSDN博客
  3. GPIOA->OTYPER:确认输出类型(推挽/开漏)。
  4. GPIOA->OSPEEDR:配置输出速度(低速、中速、高速、超高速)。

1. GPIOx_ODR(输出数据寄存器)

  • 作用:控制引脚的输出电平状态。
  • 描述:写 0 输出低电平,写 1 输出高电平。
  • 观察内容:
    • 通过设置 ODR 的某一位,改变引脚输出电平(非原子性操作,谨慎使用)。
    • 读取 ODR 确认当前设置的输出值。
// 设置 PA8 输出高电平
GPIOA->ODR |= GPIO_ODR_OD8;

// 设置 PA8 输出低电平
GPIOA->ODR &= \~GPIO_ODR_OD8;

// 读取 PA8 当前输出状态
if (GPIOA->ODR & GPIO_ODR_OD8) {
    // PA8 输出高电平
} else {
    // PA8 输出低电平
}

2. GPIOx_BSRR(位设置/清除寄存器)

  • 作用:用于原子性地设置或清除引脚输出状态,避免读-改-写引发竞态条件。
  • 描述:
    • GPIOx_BSRR[15:0]:设置引脚为高电平。
    • GPIOx_BSRR[31:16]:清除引脚(设置为低电平)。
    • 两个位段同时被置1时,以清除位优先
// 设置 PA8 为高电平(使用 BSRR)
GPIOA->BSRR = GPIO_BSRR_BS8;

// 设置 PA8 为低电平(使用 BSRR)
GPIOA->BSRR = GPIO_BSRR_BR8;

3. GPIOx_OTYPER(输出类型寄存器)

  • 作用:配置引脚输出类型。
  • 描述:
    • 0:推挽输出(Push-Pull)。
    • 1:开漏输出(Open-Drain)。
  • 用途:确认引脚的输出类型是否符合设计要求。
// 设置 PA8 为开漏输出
GPIOA->OTYPER |= GPIO_OTYPER_OT8;

// 设置 PA8 为推挽输出
GPIOA->OTYPER &= \~GPIO_OTYPER_OT8;

4. GPIOx_OSPEEDR(输出速度寄存器)

  • 作用:配置引脚的输出速度,影响引脚的转换速率。
  • 描述:
    • 00:低速。
    • 01:中速。
    • 10:高速。
    • 11:非常高速。
  • 用途:观察输出速度是否满足电路需求。
// 设置 PA8 为高速输出
GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEED8_1;
GPIOA->OSPEEDR &= \~GPIO_OSPEEDR_OSPEED8_0;

3.复用模式(MODE = 0x10)

PA8 被配置为复用模式 (MODER = 0x10) 时,重点观察以下寄存器:
  1. GPIOA->AFRL/AFRH:选择复用功能编号。
  2. 外设寄存器(以后介绍)。

1. GPIOx_AFRL 和 GPIOx_AFRH(复用功能选择寄存器)

  • 作用:指定复用功能的具体类型,例如连接到 USART、TIM、I2C 等外设。
  • 寄存器分为两个部分:
    • AFRL(低 32 位引脚 AF0-AF7):用于配置引脚 0-7。
    • AFRH(高 32 位引脚 AF8-AF15):用于配置引脚 8-15。
我们通过手册查看PA8的复用编号

PA8 的复用功能及 AFR 寄存器值

PA8 的复用功能存储在 AFRH 的第 0-3 位中(低 4 位)。以下是每种复用模式的值和功能:
复用模式 (AF)
功能描述
AFR 值
AF0
MCO (Microcontroller Clock Output)
0x0
AF1
SPI2_NSS
0x1
AF2
TIM1_CH1
0x2
AF3
-
0x3
AF4
-
0x4
AF5
-
0x5
AF6
-
0x6
AF7
EVENTOUT
0x7

AFR 寄存器中的具体配置

GPIOx_AFRH 是 32 位寄存器,其中每 4 位对应一个引脚复用配置。PA8 是 GPIO 高复用寄存器(AFRH)的第 0-3 位。
  • 寄存器位置:
    • GPIOA->AFR[1] 是复用高寄存器 (AFRH)。
    • PA8 使用 AFR[1] 的 第 0-3 位。
  • 值对应表:
    • 0000(AF0):配置为 MCO。
    • 0001(AF1):配置为 SPI2_NSS。
    • 0010(AF2):配置为 TIM1_CH1。
    • 0011(AF3):未定义。
    • 0100(AF4):未定义。
    • 0101(AF5):未定义。
    • 0110(AF6):未定义。
    • 0111(AF7):配置为EVENTOUT。
// 配置 PA8 为 SPI2_SCK (AF1)
GPIOA->AFR[1] &= \~GPIO_AFRH_AFSEL8_Msk;  // 清除 AFRH 第 0-3 位
GPIOA->AFR[1] |= (0x1 << GPIO_AFRH_AFSEL8_Pos); // 设置为 AF1

4.模拟模式(MODE = 0x11)

PA8 被配置为模拟模式 (MODER = 0x11) 时,重点观察以下寄存器:
在模拟模式下,引脚不受数字输入/输出电路控制,通常用于 ADC(模数转换)、DAC(数模转换) 和其他模拟信号功能。

1. GPIO 寄存器观察

1.1 GPIOx_MODER(模式寄存器)

  • 作用:配置 GPIO 引脚的工作模式。
  • 值含义:
    • 00:输入模式。
    • 01:通用输出模式。
    • 10:复用功能模式。
    • 11:模拟模式。
观察内容
  • 确保对应引脚的模式设置为 11。
  • 每个引脚占据 2 位。例如,配置 PA8 为模拟模式:
GPIOA->MODER &= \~(0x3U << (2 * 8)); // 清零
GPIOA->MODER |= (0x3U << (2 * 8));  // 设置为模拟模式

1.2 GPIOx_PUPDR(上下拉寄存器)

  • 作用:配置引脚的上拉/下拉电阻。
  • 在 模拟模式 下,通常不需要上拉/下拉电阻,因此应设置为 无上下拉(00)。
观察内容
  • 确保对应引脚的上下拉配置为 00。
    GPIOA->PUPDR &= \~(0x3U << (2 * 8)); // 设置为无上下拉

1.3 GPIOx_OTYPER 和 GPIOx_OSPEEDR

  • 在模拟模式下:
    • OTYPER(输出类型):无效。
    • OSPEEDR(输出速度):无效。
  • 这些寄存器与模拟模式无关,GPIO 输出电路已关闭。

2. 相关外设寄存器观察

在模拟模式下,通常对应 ADC(模数转换器) 或 DAC(数模转换器) 等外设,需要配置对应的寄存器。

2.1 ADC(模数转换器)相关寄存器

当引脚配置为模拟输入(如 PA8 作为 ADC 输入通道),需要观察和配置以下寄存器:
  1. ADCx_CR(控制寄存器):控制 ADC 的启动、停止、校准等操作。
  2. ADCx_SQRx(规则组序列寄存器):配置 ADC 通道序列,指定转换顺序。
  3. ADCx_DR(数据寄存器):放 ADC 转换后的数据。
示例:配置 PA8 为 ADC 输入通道 8
// 1. GPIO 配置为模拟模式
GPIOA->MODER |= (0x3U << (2 * 8)); // PA8 设置为模拟模式
GPIOA->PUPDR &= \~(0x3U << (2 * 8)); // 无上下拉

// 2. ADC 配置
RCC->AHB2ENR |= (1U << 13);          // 使能 ADC 时钟

ADC1->CR &= \~(1U << 29);             // 清除深度省电模式(ADVREGEN)
ADC1->SQR1 |= (8U << 6);             // 规则组第一个通道配置为通道 8
ADC1->SMPR1 |= (0x7U << (3 * 8));    // 采样时间选择最大值

ADC1->CR |= (1U << 0);               // 启动 ADC
while (!(ADC1->ISR & (1U << 0)));    // 等待 ADC 就绪

ADC1->CR |= (1U << 2);               // 开始转换
while (!(ADC1->ISR & (1U << 2)));    // 等待转换完成

uint32_t value = ADC1->DR;           // 读取 ADC 数据寄存器

2.2 DAC(数模转换器)相关寄存器

如果引脚用于 DAC 输出,需要配置以下寄存器:
  1. DACx_CR(控制寄存器):启用 DAC 通道,设置触发方式等。
  2. DACx_DHRx(数据保持寄存器):写入要输出的数值。
  3. DACx_DORx(数据输出寄存器):存放 DAC 当前输出值。
示例:配置 DAC 输出到 PA4(DAC 通道 1)
RCC->APB1ENR1 |= (1U << 29);         // 使能 DAC 时钟

DAC->CR |= (1U << 0);                // 使能 DAC 通道 1
DAC->DHR12R1 = 2048;                 // 输出中间值(12 位,范围 0-4095)

3. 总结:观察和配置的寄存器

GPIO 寄存器

  1. MODER:设置为模拟模式(11)。
  2. PUPDR:设置为无上下拉(00)。
  3. OTYPER 和 OSPEEDR:在模拟模式下无效,不需要配置。

外设寄存器

根据具体功能配置:
  • ADC 寄存器:
    • CR:控制 ADC 
    • SQRx:配置输入通道。
    • SMPRx:设置采样时间
    • DR:读取 ADC 转换结果。
  • DAC 寄存器:
    • CR:启用 DAC 通道 
    • DHRx:设置输出值。
    • DORx:输出寄存器,表示当前输出值。

完整示例:PA8 配置为 ADC 输入

// 1. 配置 PA8 为模拟模式
GPIOA->MODER &= \~(0x3U << (2 * 8));
GPIOA->MODER |= (0x3U << (2 * 8));
GPIOA->PUPDR &= \~(0x3U << (2 * 8)); // 无上下拉

// 2. 配置 ADC
RCC->AHB2ENR |= (1U << 13);        // 使能 ADC1 时钟

ADC1->CR &= \~(1U << 29);           // 清除深度省电模式
ADC1->SQR1 |= (8U << 6);           // 配置规则通道 8
ADC1->SMPR1 |= (0x7U << (3 * 8));  // 采样时间最大值

ADC1->CR |= (1U << 0);             // 使能 ADC
while (!(ADC1->ISR & (1U << 0)));  // 等待 ADC 就绪

ADC1->CR |= (1U << 2);             // 开始转换
while (!(ADC1->ISR & (1U << 2)));  // 等待转换完成

uint32_t adc_value = ADC1->DR;     // 读取 ADC 数据

如有侵权,联系删除

### STM32 Debug仿真教程:使用ST-Link调试配置方法 #### 配置环境 为了在STM32中进行Debug仿真,需确保已安装并正确配置STM32CubeIDE以及连接好ST-LINK硬件设备。ST-LINK作为一款集成在线仿真与下载功能的工具,能够通过SWD接口实现对STM32微控制器的有效调试[^1]。 #### 设置项目属性 在STM32CubeIDE中创建或打开一个项目后,右键点击该项目,在弹出菜单中选择`Properties`选项。随后导航至`C/C++ Build -> Settings`路径下,确认编译器设置无误,并确保生成的目标文件适用于当前使用的MCU型号[^3]。 #### 配置调试驱动 进入项目的运行配置界面(`Run Configurations`),切换到`Debugger`标签页。在此处应勾选`Use Debug Driver`选项以启用ST-LINK调试支持;同时建议激活`Update Target before Debugging`参数来保证每次启动调试前更新目标设备固件版本一致性。 #### FLASH算法设定 继续深入至更详细的Flash加载策略定义阶段——即按下上述提到过的Settings按钮之后所展示出来的窗口里头。这里可以指定特定于不同存储介质类型的flash烧录方式及其关联参数调整可能性等细节处理部分。 #### 启动调试会话 完成以上准备工作之后就可以正式开启一次完整的调试流程啦!只需回到主界面上找到对应图标或者通过快捷键组合Ctrl+F11即可轻松触发整个过程执行起来咯~ 当然如果中途遇到任何异常状况也不要慌张哦,记得及时查阅相关日志记录以便快速定位问题所在之处哈! ```python # 示例代码片段用于演示如何初始化串口通信(假设需要用到SVD文件) import pyocd def initialize_debug_session(device_name='stm32f4xx'): session = pyocd.session.Session.get_for_board(board_id=device_name) target = session.target # 进入 halt 状态 target.halt() # 执行其他必要的初始化操作... return target target_device = initialize_debug_session() print(f"Target Device Initialized: {target_device.part_families}") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Flocx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值