以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) 时,重点观察以下寄存器:- GPIOA->IDR:读取输入引脚的电平状态。
- GPIOA->PUPDR:检查内部上拉/下拉电阻配置。
- RCC->AHB2ENR:确保 GPIO 时钟使能。
- GPIOA->LCKR:检查引脚配置是否被锁定。
- 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 |
位段 | 描述 |
Bit 0 | EXTI0 中断屏蔽 |
Bit 1 | EXTI1 中断屏蔽 |
Bit 2 | EXTI2 中断屏蔽 |
... | ... |
Bit 8 | EXTI8 中断屏蔽 |
... | ... |
Bit 19 | EXTI19 中断屏蔽 |
Bit 20:31 | 保留 |
2.输出模式(MODE = 0x01)
当 PA8 被配置为输出模式 (MODER = 0x01) 时,重点观察以下寄存器:- GPIOA->ODR:控制引脚的输出电平。
- GPIOA->BSRR:原子性设置/清除引脚输出。STM32原子性设置-CSDN博客
- GPIOA->OTYPER:确认输出类型(推挽/开漏)。
- 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) 时,重点观察以下寄存器:- GPIOA->AFRL/AFRH:选择复用功能编号。
- 外设寄存器(以后介绍)。
1. GPIOx_AFRL 和 GPIOx_AFRH(复用功能选择寄存器)
- 作用:指定复用功能的具体类型,例如连接到 USART、TIM、I2C 等外设。
- 寄存器分为两个部分:
- AFRL(低 32 位引脚 AF0-AF7):用于配置引脚 0-7。
- AFRH(高 32 位引脚 AF8-AF15):用于配置引脚 8-15。
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 输入通道),需要观察和配置以下寄存器:- ADCx_CR(控制寄存器):控制 ADC 的启动、停止、校准等操作。
- ADCx_SQRx(规则组序列寄存器):配置 ADC 通道序列,指定转换顺序。
- ADCx_DR(数据寄存器):放 ADC 转换后的数据。
// 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 输出,需要配置以下寄存器:- DACx_CR(控制寄存器):启用 DAC 通道,设置触发方式等。
- DACx_DHRx(数据保持寄存器):写入要输出的数值。
- DACx_DORx(数据输出寄存器):存放 DAC 当前输出值。
RCC->APB1ENR1 |= (1U << 29); // 使能 DAC 时钟
DAC->CR |= (1U << 0); // 使能 DAC 通道 1
DAC->DHR12R1 = 2048; // 输出中间值(12 位,范围 0-4095)
3. 总结:观察和配置的寄存器
GPIO 寄存器
- MODER:设置为模拟模式(11)。
- PUPDR:设置为无上下拉(00)。
- 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 数据