5.10 GPIO 使用说明
本章说明 N32G41x 标准外设库中 GPIO 与 AFIO 驱动的文件组成、22 个公开函数,以及 IORemap、LedBlink 两个示例。端口结构、复用功能映射与引脚锁定序列请配合用户手册的“GPIO 和 AFIO”章节阅读,芯片已知问题以勘误手册为准。
5.10.1 相关文件
| 相对路径 | 作用 |
|---|---|
firmware/n32g41x_std_periph_driver/inc/n32g41x_gpio.h |
定义 GPIO_InitType 结构体与引脚、模式、上下拉、翻转率、驱动能力、复用功能、EXTI 线来源等宏,并按复位与初始化、读取、写入、配置、AFIO 配置、EXTI 线配置六个区段声明 22 个公开函数 |
firmware/n32g41x_std_periph_driver/src/n32g41x_gpio.c |
实现上述 22 个函数:端口与引脚复位,模式与复用字段写入,端口数据读写,引脚锁定序列,AFIO 与 EXTI 线配置 |
projects/n32g41x_EVAL/examples/GPIO/ |
GPIO 示例根目录,含 IORemap、LedBlink 2 个示例 |
projects/n32g41x_EVAL/examples/GPIO/LedBlink/ |
该示例的工程目录组成:MDK-ARM/、EWARM/、inc/、src/、readme.txt |
projects/n32g41x_EVAL/bsp/ |
两个示例共用的板级支持文件:评估板 LED 与按键定义、日志串口初始化、毫秒延时函数 |
5.10.2 API 参考
以下 22 个公开函数按 n32g41x_gpio.h 的声明顺序分为 6 组;每个条目给出功能摘要与 n32g41x_gpio.c 中该函数正上方的注释原文。
复位与初始化
GPIO_DeInit、GPIO_DeInitPin、GPIO_InitPeripheral、GPIO_InitStruct
读取
GPIO_ReadInputDataBit、GPIO_ReadInputData、GPIO_ReadOutputDataBit、GPIO_ReadOutputData
写入
GPIO_SetBits、GPIO_WritePBSC、GPIO_ResetBits、GPIO_WriteBit、GPIO_Write、GPIO_TogglePin
配置
GPIO_ConfigPinLock、GPIO_ConfigPinRemap
AFIO 配置
AFIO_ConfigSPINSSMode、AFIO_ConfigEXTIFlitEN、AFIO_ConfigIOFlitNum、AFIO_DIGEFTEnable
EXTI 线配置
GPIO_ConfigEXTILine、GPIO_ClearEXTILine
void GPIO_DeInit(void)将 GPIOx 外设寄存器复位为默认复位值。
name GPIO_DeInit.
fun Reset the GPIOx peripheral registers to their default reset values.
param none
return none
void GPIO_DeInitPin(GPIO_Module *GPIOx, uint32_t Pin)将选定的 GPIOx 引脚恢复为默认复位值。
name GPIO_DeInitPin.
fun Restores the selected GPIOx pins to their default reset values.
param GPIOx :
- GPIOA
- GPIOB
- GPIOC
- GPIOD
param Pin :
- GPIO_PIN_0
- GPIO_PIN_1
- GPIO_PIN_2
- GPIO_PIN_3
- GPIO_PIN_4
- GPIO_PIN_5
- GPIO_PIN_6
- GPIO_PIN_7
- GPIO_PIN_8
- GPIO_PIN_9
- GPIO_PIN_10
- GPIO_PIN_11
- GPIO_PIN_12
- GPIO_PIN_13
- GPIO_PIN_14
- GPIO_PIN_15
- GPIO_PIN_ALL
return none
void GPIO_InitPeripheral(GPIO_Module *GPIOx, const GPIO_InitType *GPIO_InitParam)按 GPIO_InitType 结构体的值初始化选定的 GPIOx 引脚。
name GPIO_InitPeripheral.
fun Initialize the selected GPIOx pins with the value of the GPIO_InitType structure.
param GPIOx :
- GPIOA
- GPIOB
- GPIOC
- GPIOD
param GPIO_InitParam :
- Pin
- GPIO_PIN_0
- GPIO_PIN_1
- GPIO_PIN_2
- GPIO_PIN_3
- GPIO_PIN_4
- GPIO_PIN_5
- GPIO_PIN_6
- GPIO_PIN_7
- GPIO_PIN_8
- GPIO_PIN_9
- GPIO_PIN_10
- GPIO_PIN_11
- GPIO_PIN_12
- GPIO_PIN_13
- GPIO_PIN_14
- GPIO_PIN_15
- GPIO_PIN_ALL
- GPIO_Mode
- GPIO_MODE_INPUT
- GPIO_MODE_OUTPUT_PP
- GPIO_MODE_OUTPUT_OD
- GPIO_MODE_AF_PP
- GPIO_MODE_AF_OD
- GPIO_MODE_ANALOG
- GPIO_Pull
- GPIO_NO_PULL
- GPIO_PULL_UP
- GPIO_PULL_DOWN
- GPIO_Slew_Rate
note: only effective for pins PA0, PA1, PA2, PB5, PB6, PB7
- GPIO_SLEW_RATE_FAST
- GPIO_SLEW_RATE_SLOW
- GPIO_Current
- GPIO_DS_HIGH
- GPIO_DS_LOW
- GPIO_Alternate
- GPIO_AF0
- GPIO_AF1
- GPIO_AF2
- GPIO_AF3
- GPIO_AF4
- GPIO_AF5
- GPIO_AF6
- GPIO_AF7
- GPIO_AF8
- GPIO_AF9
- GPIO_AF10
- GPIO_AF11
- GPIO_AF12
- GPIO_AF13
- GPIO_AF14
- GPIO_NO_AF NO alternate Function mapping
return none
void GPIO_InitStruct(GPIO_InitType *GPIO_InitStructure)为 GPIO_InitType 的各成员赋予默认值。
name GPIO_InitStruct.
fun Assign default values to each GPIO_InitType member.
param GPIO_InitStructure :
pointer to GPIO_InitType structure.
return none
uint8_t GPIO_ReadInputDataBit(const GPIO_Module *GPIOx, uint16_t Pin)获取指定输入端口的引脚状态。
name GPIO_ReadInputDataBit.
fun Get the pin status on the specified input port.
param GPIOx :
- GPIOA
- GPIOB
- GPIOC
- GPIOD
param Pin :
- GPIO_PIN_0
- GPIO_PIN_1
- GPIO_PIN_2
- GPIO_PIN_3
- GPIO_PIN_4
- GPIO_PIN_5
- GPIO_PIN_6
- GPIO_PIN_7
- GPIO_PIN_8
- GPIO_PIN_9
- GPIO_PIN_10
- GPIO_PIN_11
- GPIO_PIN_12
- GPIO_PIN_13
- GPIO_PIN_14
- GPIO_PIN_15
return the pin state on the input port.
uint16_t GPIO_ReadInputData(const GPIO_Module *GPIOx)获取指定 GPIO 端口的输入数据。
name GPIO_ReadInputData.
fun Get the input data on the designated GPIO port.
param GPIOx :
- GPIOA
- GPIOB
- GPIOC
- GPIOD
return the data value on the GPIO input port.
uint8_t GPIO_ReadOutputDataBit(const GPIO_Module *GPIOx, uint16_t Pin)获取指定输出端口的引脚状态。
name GPIO_ReadOutputDataBit.
fun Get the pin status on the specified output port.
param GPIOx :
- GPIOA
- GPIOB
- GPIOC
- GPIOD
param Pin :
- GPIO_PIN_0
- GPIO_PIN_1
- GPIO_PIN_2
- GPIO_PIN_3
- GPIO_PIN_4
- GPIO_PIN_5
- GPIO_PIN_6
- GPIO_PIN_7
- GPIO_PIN_8
- GPIO_PIN_9
- GPIO_PIN_10
- GPIO_PIN_11
- GPIO_PIN_12
- GPIO_PIN_13
- GPIO_PIN_14
- GPIO_PIN_15
return the pin state on the output port.
uint16_t GPIO_ReadOutputData(const GPIO_Module *GPIOx)获取指定 GPIO 端口的输出数据。
name GPIO_ReadOutputData.
fun Get the output data on the designated GPIO port.
param GPIOx :
- GPIOA
- GPIOB
- GPIOC
- GPIOD
return the data value on the GPIO output port.
void GPIO_SetBits(GPIO_Module *GPIOx, uint16_t Pin)置位选定的数据端口位。
name GPIO_SetBits.
fun Sets the selected data port bits.
param GPIOx :
- GPIOA
- GPIOB
- GPIOC
- GPIOD
param Pin :
- GPIO_PIN_0
- GPIO_PIN_1
- GPIO_PIN_2
- GPIO_PIN_3
- GPIO_PIN_4
- GPIO_PIN_5
- GPIO_PIN_6
- GPIO_PIN_7
- GPIO_PIN_8
- GPIO_PIN_9
- GPIO_PIN_10
- GPIO_PIN_11
- GPIO_PIN_12
- GPIO_PIN_13
- GPIO_PIN_14
- GPIO_PIN_15
return none
使用提示: 实现向 GPIOx->PBSC 写入 Pin,PBSC 中写 1 的位被置位、写 0 的位保持不变,单次 AHB 写即可完成,不需要读改写,也不需要关中断。
void GPIO_WritePBSC(GPIO_Module *GPIOx, uint16_t Pin, uint8_t bitstatus)通过 GPIOx_PBSC 置位或清除选定的数据端口位。
name GPIO_WritePBSC.
fun Sets or clears the selected data port bits via GPIOx_PBSC.
param GPIOx :
- GPIOA
- GPIOB
- GPIOC
- GPIOD
param Pin :
- GPIO_PIN_0
- GPIO_PIN_1
- GPIO_PIN_2
- GPIO_PIN_3
- GPIO_PIN_4
- GPIO_PIN_5
- GPIO_PIN_6
- GPIO_PIN_7
- GPIO_PIN_8
- GPIO_PIN_9
- GPIO_PIN_10
- GPIO_PIN_11
- GPIO_PIN_12
- GPIO_PIN_13
- GPIO_PIN_14
- GPIO_PIN_15
param bitstatus :
- Bit_SET
- Bit_RESET
return none
使用提示:bitstatus 为 Bit_SET 时写 GPIOx->PBSC = Pin 置位,其余取值写 GPIOx->PBSC = Pin << 16 清除,即 PBSC 的高 16 位为清除位。
void GPIO_ResetBits(GPIO_Module *GPIOx, uint16_t Pin)复位选定的数据端口位。
name GPIO_ResetBits.
fun Reset the selected data port bits.
param GPIOx :
- GPIOA
- GPIOB
- GPIOC
- GPIOD
param Pin :
- GPIO_PIN_0
- GPIO_PIN_1
- GPIO_PIN_2
- GPIO_PIN_3
- GPIO_PIN_4
- GPIO_PIN_5
- GPIO_PIN_6
- GPIO_PIN_7
- GPIO_PIN_8
- GPIO_PIN_9
- GPIO_PIN_10
- GPIO_PIN_11
- GPIO_PIN_12
- GPIO_PIN_13
- GPIO_PIN_14
- GPIO_PIN_15
return none
使用提示: 实现向 GPIOx->PBC 写入 Pin,写 1 的位被清除、写 0 的位保持不变。
void GPIO_WriteBit(GPIO_Module *GPIOx, uint16_t Pin, Bit_OperateType BitCmd)置位或复位选定的数据端口位。
name GPIO_WriteBit.
fun Set or reset the selected data port bits.
param GPIOx :
- GPIOA
- GPIOB
- GPIOC
- GPIOD
param Pin :
- GPIO_PIN_0
- GPIO_PIN_1
- GPIO_PIN_2
- GPIO_PIN_3
- GPIO_PIN_4
- GPIO_PIN_5
- GPIO_PIN_6
- GPIO_PIN_7
- GPIO_PIN_8
- GPIO_PIN_9
- GPIO_PIN_10
- GPIO_PIN_11
- GPIO_PIN_12
- GPIO_PIN_13
- GPIO_PIN_14
- GPIO_PIN_15
param BitCmd :
- Bit_RESET
- Bit_SET
return none
使用提示:BitCmd 不等于 Bit_RESET 时向 GPIOx->PBSC 写入 Pin,等于 Bit_RESET 时向 GPIOx->PBC 写入 Pin,两种写法都不影响 Pin 之外的位。
void GPIO_Write(GPIO_Module *GPIOx, uint16_t data_value)向指定的 GPIO 数据端口写入数据。
name GPIO_Write.
fun Write data on the designated GPIO data port.
param GPIOx :
- GPIOA
- GPIOB
- GPIOC
- GPIOD
param data_value :
the value to be written to the port output data register.
- 0~0xFFFF
return none
使用提示: 实现直接把 data_value 整字写入 GPIOx->POD,写入范围为 0~0xFFFF,会覆盖该端口全部 16 个引脚的输出电平,不是逐位操作。
void GPIO_TogglePin(GPIO_Module *GPIOx, uint16_t Pin)翻转指定端口引脚的电平。
name GPIO_TogglePin.
fun Toggle the specified port pin level.
param GPIOx :
- GPIOA
- GPIOB
- GPIOC
- GPIOD
param Pin :
- GPIO_PIN_0
- GPIO_PIN_1
- GPIO_PIN_2
- GPIO_PIN_3
- GPIO_PIN_4
- GPIO_PIN_5
- GPIO_PIN_6
- GPIO_PIN_7
- GPIO_PIN_8
- GPIO_PIN_9
- GPIO_PIN_10
- GPIO_PIN_11
- GPIO_PIN_12
- GPIO_PIN_13
- GPIO_PIN_14
- GPIO_PIN_15
return none
使用提示: 实现是 GPIOx->POD ^= Pin,即读回输出数据寄存器再整字写回,与 GPIO_SetBits、GPIO_ResetBits 的单次写不同。
void GPIO_ConfigPinLock(GPIO_Module *GPIOx, uint16_t Pin)配置 GPIO 端口锁定寄存器。
name GPIO_ConfigPinLock.
fun GPIO port lock register configuration.
param GPIOx :
- GPIOA
- GPIOB
- GPIOC
- GPIOD
param Pin :
- GPIO_PIN_0
- GPIO_PIN_1
- GPIO_PIN_2
- GPIO_PIN_3
- GPIO_PIN_4
- GPIO_PIN_5
- GPIO_PIN_6
- GPIO_PIN_7
- GPIO_PIN_8
- GPIO_PIN_9
- GPIO_PIN_10
- GPIO_PIN_11
- GPIO_PIN_12
- GPIO_PIN_13
- GPIO_PIN_14
- GPIO_PIN_15
return none
使用提示: 实现按 w1 → w0 → w1 的次序把 GPIO_PLOCK_PLOCKK | Pin 与 Pin 交替写入 GPIOx->PLOCK,再连续两次读回该寄存器,即手册要求的 w1→w0→w1→r0 序列;序列中间不能改变 PLOCK[15:0]。
void GPIO_ConfigPinRemap(uint8_t PortSource, uint32_t PinSource, uint32_t AlternateFunction)配置引脚复用映射。
name GPIO_ConfigPinRemap.
fun Pin remapping configuration.
param PortSource :
- GPIOA_PORT_SOURCE
- GPIOB_PORT_SOURCE
- GPIOC_PORT_SOURCE
- GPIOD_PORT_SOURCE
param PinSource :
- GPIO_PIN_SOURCE0
- GPIO_PIN_SOURCE1
- GPIO_PIN_SOURCE2
- GPIO_PIN_SOURCE3
- GPIO_PIN_SOURCE4
- GPIO_PIN_SOURCE5
- GPIO_PIN_SOURCE6
- GPIO_PIN_SOURCE7
- GPIO_PIN_SOURCE8
- GPIO_PIN_SOURCE9
- GPIO_PIN_SOURCE10
- GPIO_PIN_SOURCE11
- GPIO_PIN_SOURCE12
- GPIO_PIN_SOURCE13
- GPIO_PIN_SOURCE14
- GPIO_PIN_SOURCE15
param AlternateFunction :
- GPIO_AF0
- GPIO_AF1
- GPIO_AF2
- GPIO_AF3
- GPIO_AF4
- GPIO_AF5
- GPIO_AF6
- GPIO_AF7
- GPIO_AF8
- GPIO_AF9
- GPIO_AF10
- GPIO_AF11
- GPIO_AF12
- GPIO_AF13
- GPIO_AF14
- GPIO_NO_AF NO alternate Function mapping
return none
void AFIO_ConfigSPINSSMode(uint32_t AFIO_SPIx_NSS, uint32_t SpiNssMode)SPIx NSS 配置成推挽复用模式时配置 NSS 空闲状态。
name AFIO_ConfigSPINSSMode.
fun Selects the alternate function SPIx NSS mode.
param AFIO_SPIx_NSS :
choose which SPI configuration.
- AFIO_SPI1_NSS
- AFIO_SPI2_NSS
param SpiNssMode :
specifies the SPI_NSS mode to be configured.
- AFIO_SPI_NSS_HIGH_IMPEDANCE
- AFIO_SPI_NSS_HIGH_LEVEL
return none
void AFIO_ConfigEXTIFlitEN(FunctionalState Cmd)配置 EXTI 滤波使能。
name AFIO_ConfigEXTIFlitEN.
fun Configure EXTI filter enable.
param Cmd :
- ENABLE
- DISABLE
return none
void AFIO_ConfigIOFlitNum(uint32_t filter_clk)以 HCLK 时钟周期为单位配置 IO 滤波时间。
name AFIO_ConfigIOFlitNum.
fun Configure the IO filter time in HCLK clock cycles.
param filter_clk
- GPIO_FILTER_BYPASS
- GPIO_FILTER_1_CLK
- GPIO_FILTER_2_CLK
- GPIO_FILTER_3_CLK
return none
void AFIO_DIGEFTEnable(const GPIO_Module *GPIOx, uint32_t Pin, FunctionalState Cmd)使能或禁止端口引脚的数字化毛刺滤波器。
name AFIO_DIGEFTEnable.
fun Enables or disables the digital glitch filter of port pins.
param GPIOx :
- GPIOA
- GPIOB
- GPIOC
- GPIOD
param Pin :
- GPIO_PIN_0
- GPIO_PIN_1
- GPIO_PIN_2
- GPIO_PIN_3
- GPIO_PIN_4
- GPIO_PIN_5
- GPIO_PIN_6
- GPIO_PIN_7
- GPIO_PIN_8
- GPIO_PIN_9
- GPIO_PIN_10
- GPIO_PIN_11
- GPIO_PIN_12
- GPIO_PIN_13
- GPIO_PIN_14
- GPIO_PIN_15
- GPIO_PIN_ALL
param Cmd :
- ENABLE
- DISABLE
return none
void GPIO_ConfigEXTILine(uint8_t PortSource, uint32_t PinSource)选择用作 EXTI 线的 GPIO 引脚。一条 EXTI 线只能配置一个引脚。
name GPIO_ConfigEXTILine.
fun Selects the GPIO pin used as EXTI Line. A single EXTI line can only be configured with a single pin.
param PortSource :
- GPIOA_PORT_SOURCE
- GPIOB_PORT_SOURCE
- GPIOC_PORT_SOURCE
- GPIOD_PORT_SOURCE
param PinSource :
- GPIO_PIN_SOURCE0
- GPIO_PIN_SOURCE1
- GPIO_PIN_SOURCE2
- GPIO_PIN_SOURCE3
- GPIO_PIN_SOURCE4
- GPIO_PIN_SOURCE5
- GPIO_PIN_SOURCE6
- GPIO_PIN_SOURCE7
- GPIO_PIN_SOURCE8
- GPIO_PIN_SOURCE9
- GPIO_PIN_SOURCE10
- GPIO_PIN_SOURCE11
- GPIO_PIN_SOURCE12
- GPIO_PIN_SOURCE13
- GPIO_PIN_SOURCE14
- GPIO_PIN_SOURCE15
return none
使用提示: 实现把 PortSource 与 PinSource 一并写入 AFIO 的 EXTI 线配置寄存器,同一引脚源只能绑定一个端口,重复配置会覆盖上一次的选择。
void GPIO_ClearEXTILine(uint8_t LineSource)清除用作 EXTI 线的 GPIO 引脚。
name GPIO_ClearEXTILine.
fun Clear the GPIO pin used as EXTI Line.
param LineSource :
- GPIO_EXTILINE_SOURCE0
- GPIO_EXTILINE_SOURCE1
- GPIO_EXTILINE_SOURCE2
- GPIO_EXTILINE_SOURCE3
- GPIO_EXTILINE_SOURCE4
- GPIO_EXTILINE_SOURCE5
- GPIO_EXTILINE_SOURCE6
- GPIO_EXTILINE_SOURCE7
- GPIO_EXTILINE_SOURCE8
- GPIO_EXTILINE_SOURCE9
- GPIO_EXTILINE_SOURCE10
- GPIO_EXTILINE_SOURCE11
- GPIO_EXTILINE_SOURCE12
- GPIO_EXTILINE_SOURCE13
- GPIO_EXTILINE_SOURCE14
- GPIO_EXTILINE_SOURCE15
return none
使用提示: 实现按 LineSource 清除 AFIO 中对应 EXTI 线的端口选择位,使该线不再由任何 GPIO 引脚驱动。
5.10.3 Demo 示例说明
本节说明 GPIO 的 2 个示例:IORemap 让 SWD 引脚 PA13、PA14 在调试功能与普通输出之间切换,LedBlink 用推挽输出控制评估板上的三路 LED。
5.10.3.1 IORemap SWD 引脚复用为普通 IO
工程目录: projects/n32g41x_EVAL/examples/GPIO/IORemap/
初始化日志串口→配置 PA1、PA7 为推挽输出与 PA4 为上拉输入→轮询 KEY1 的按下状态→按下期间把 PA13、PA14 释放为普通推挽输出并每 50 ms 轮流翻转→松开后恢复两只引脚的 SWD 复用功能并点亮 LED2
| 项目 | 源码解读 |
|---|---|
| 功能 | 按住 KEY1 时把 SWD 引脚 PA13(SWDIO)、PA14(SWCLK)从调试功能释放为推挽输出并轮流翻转; 松开 KEY1 时把两脚恢复为 SWD 复用功能。 LED1 亮表示两脚处于普通输出状态,LED2 亮表示处于 SWD 状态。 |
| 源码组成 | src/main.c:LED 与按键初始化、SWD_Function_Initialize、SWD_As_GPIO_Initialize 与主循环;inc/main.h:SWDIO_PORT/SWDIO_PIN、SWCLK_PORT/SWCLK_PIN 等宏与函数声明;src/n32g41x_it.c、inc/n32g41x_it.h:中断服务函数;readme.txt:功能、环境与使用说明;MDK-ARM/、EWARM/:Keil 与 IAR 工程。 |
| 关键配置 | LED1 为 PA1、LED2 为 PA7,均初始化为 GPIO_MODE_OUTPUT_PP;KEY1 为 PA4,初始化为 GPIO_MODE_INPUT 且上下拉取 BUTTON_KEY1_PULL,按下电平为 BUTTON_KEY1_STATE。SWD 状态下 PA13 配置为 GPIO_MODE_AF_PP、GPIO_PULL_UP、GPIO_AF0,PA14 配置为 GPIO_MODE_AF_PP、GPIO_PULL_DOWN、GPIO_AF0;普通输出状态下 PA13、PA14 一起配置为 GPIO_MODE_OUTPUT_PP、GPIO_NO_AF。系统时钟 HSI+PLL,N32G412 为 80 MHz,N32G415 为 96 MHz。 |
| 程序与数据路径 | main 先调用 log_init 并打印 IO remaping demo!,再初始化 LED 与 KEY1 后进入循环:读到 KEY1 为按下电平时点亮 LED1、熄灭 LED2,调用 SWD_As_GPIO_Initialize,随后以 50 ms 间隔用 GPIO_TogglePin 轮流翻转 PA13、PA14,直到 KEY1 松开;KEY1 未按下时调用 SWD_Function_Initialize,点亮 LED2、熄灭 LED1,并等待 KEY1 再次按下。 |
| 主要 API | GPIO_InitStruct、GPIO_InitPeripheral、GPIO_ConfigPinRemap、GPIO_ReadInputDataBit、GPIO_TogglePin、GPIO_SetBits、GPIO_ResetBits |
| 验证方法 | 复位运行后串口打印 IO remaping demo!;未按 KEY1 时 LED2 常亮; 按住 KEY1 时 LED1 常亮,在 PA13、PA14 上外接 LED 或示波器可看到两脚每 50 ms 轮流翻转。 |
| 使用提示 | N32G41x 没有 JTAG 接口,只支持 SWD 调试(PA13 为 SWDIO,PA14 为 SWCLK); 下载程序后需取下评估板 J5 上 SWDIO 与 SWCLK 的跳线帽。 按住 KEY1 期间 SWD 不可用。 开发环境为 KEIL MDK-ARM V5.34 或 IAR EWARM 8.50.1,芯片支持 N32G412x8L7、N32G412xBL7、N32G415x8L7、N32G415xBL7。 |
核心代码解读与移植
示例让同一组引脚轮流承担两种角色:KEY1 按下时把 SWD 引脚释放为普通输出,松开时恢复 SWD 复用功能。
数据路径: KEY1(PA4)电平 → GPIO_ReadInputDataBit → SWD_As_GPIO_Initialize 或 SWD_Function_Initialize 改写 PA13、PA14 的模式与复用字段 → GPIO_TogglePin 翻转 PA13、PA14 → 外接 LED 或示波器观察
1. 用宏定义两只 SWD 引脚。 inc/main.h 把 SWDIO 定义为 PA13、SWCLK 定义为 PA14,并把两者的端口时钟都取为 RCC_AHB_PERIPH_GPIO,后续配置都通过这组宏访问引脚。
/* SWD pin defines */
#define SWDIO_PORT GPIOA
#define SWDIO_PIN GPIO_PIN_13
#define SWDIO_CLK RCC_AHB_PERIPH_GPIO
#define SWCLK_PORT GPIOA
#define SWCLK_PIN GPIO_PIN_14
#define SWCLK_CLK RCC_AHB_PERIPH_GPIO
移植到其它板卡时,SWD 引脚由芯片固定,通常只需改动 bsp/inc/n32g41x_stb.h 里的 LED 与按键定义。
2. 主循环按 KEY1 状态切换角色。 KEY1 按下时先点亮 LED1、熄灭 LED2,再调用释放 SWD 引脚的初始化函数;KEY1 未按下时走另一分支恢复 SWD。
while(1)
{
if (GPIO_ReadInputDataBit(BUTTON_KEY1_PORT, BUTTON_KEY1_PIN) == BUTTON_KEY1_STATE)
{
/* Turn on Led1 */
LED_On(LED1_PORT, LED1_PIN);
比较电平用 BUTTON_KEY1_STATE,它由 bsp/inc/n32g41x_stb.h 给出;换板或改按键有效电平时同步改这个宏。
3. 内层循环轮流翻转两只引脚。 释放引脚后在嵌套的 while(1) 里交替翻转 PA13 与 PA14,两次翻转之间各延时 50 ms,并在每轮结束后检查 KEY1 是否松开。
/* Toggle SWDIO pin */
GPIO_TogglePin(SWDIO_PORT, SWDIO_PIN);
/* Toggle SWCLK pin */
GPIO_TogglePin(SWCLK_PORT, SWCLK_PIN);
翻转间隔由两次 SysTick_Delay_Ms(50) 决定,调整观察频率时改这两处参数。
4. 释放与恢复 SWD 引脚的两段配置。 SWD_As_GPIO_Initialize 先把 PA13、PA14 的复用字段写为 GPIO_NO_AF,再把两脚一起初始化为推挽输出;SWD_Function_Initialize 反过来把复用字段写为 GPIO_AF0,并按 PA13 上拉、PA14 下拉分别初始化。
/* Remap PA13 (SWDIO) and PA14 (SWCLK) to GPIO_NO_AF (release from SWD) */
GPIO_ConfigPinRemap(GPIOA_PORT_SOURCE, GPIO_PIN_SOURCE15, GPIO_NO_AF);
GPIO_ConfigPinRemap(GPIOA_PORT_SOURCE, GPIO_PIN_SOURCE14, GPIO_NO_AF);
/* Configure PA15 and PA14 as gpio output push-pull */
GPIO_InitStructure.Pin = SWDIO_PIN | SWCLK_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.GPIO_Alternate = GPIO_NO_AF;
GPIO_InitPeripheral(SWDIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.Pin = SWDIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP;
GPIO_InitStructure.GPIO_Alternate = GPIO_AF0;
GPIO_InitPeripheral(SWDIO_PORT, &GPIO_InitStructure);
源码里释放 SWD 的注释写作 Remap PA13 (SWDIO) to AF0、配置输出时又写作 Configure PA15 and PA14,而代码实际传入的引脚源是 GPIO_PIN_SOURCE15 与 GPIO_PIN_SOURCE14,使用的是 GPIO_NO_AF。移植到复用功能映射不同的芯片时,需要同步核对引脚源编号与复用功能编号。
对应源码: inc/main.h、src/main.c
5.10.3.2 LedBlink LED 闪烁
工程目录: projects/n32g41x_EVAL/examples/GPIO/LedBlink/
使能 GPIO 与板级时钟→配置 PA1、PA7、PB1 为推挽输出→LED1 与 LED3 各翻转 4 次→主循环按 LED1、LED2、LED3 顺序轮流点亮
| 项目 | 源码解读 |
|---|---|
| 功能 | 用推挽输出控制评估板上的 LED1、LED2、LED3:先让 LED1 与 LED3 一起闪烁 4 次,再按 LED1 → LED2 → LED3 的顺序轮流点亮并循环。 |
| 源码组成 | src/main.c:LED_Init、LED_On、LED_Off、LED_Blink 四个辅助函数与 main 的闪烁、轮流点亮流程;inc/main.h:四个函数的声明;src/n32g41x_it.c、inc/n32g41x_it.h:中断服务函数;readme.txt:功能、环境与使用说明;MDK-ARM/、EWARM/:Keil 与 IAR 工程。 |
| 关键配置 | LED1 为 PA1、LED2 为 PA7、LED3 为 PB1,LED_Init 中统一配置为 GPIO_MODE_OUTPUT_PP、GPIO_NO_AF、GPIO_NO_PULL、GPIO_SLEW_RATE_FAST、GPIO_DS_HIGH,并调用 RCC_EnableAHBPeriphClk 打开对应端口时钟。循环用 uint32_t i 从 0 到 7 共 8 次翻转,每次间隔 SysTick_Delay_Ms(500)。系统时钟 HSI+PLL,N32G412 为 80 MHz,N32G415 为 96 MHz。 |
| 程序与数据路径 | main 依次调用三次 LED_Init 打开 PA1、PA7、PB1 的时钟并配置为推挽输出,随后在 for 循环里用 LED_Blink 翻转 LED1 与 LED3 并延时 500 ms,共 8 次;接着用 LED_Off 熄灭三路 LED,最后在 while (1) 里按 LED1、LED2、LED3 的顺序点亮,每次点亮都熄灭上一路并延时 500 ms。 |
| 主要 API | GPIO_InitStruct、GPIO_InitPeripheral、GPIO_SetBits、GPIO_ResetBits、GPIO_TogglePin;时钟使能 RCC_EnableAHBPeriphClk,延时 SysTick_Delay_Ms |
| 验证方法 | 复位运行后 LED1 与 LED3 同时闪烁 4 次,随后 LED1、LED2、LED3 依次点亮并循环; 以 500 ms 的节奏观察即可判断翻转与轮流点亮全部生效。 |
| 使用提示 | 开发环境为 KEIL MDK-ARM V5.34 或 IAR EWARM 8.50.1,芯片支持 N32G412x8L7、N32G412xBL7、N32G415x8L7、N32G415xBL7; LED 与引脚对应关系取自评估板定义,换板时需要同步修改。 |
核心代码解读与移植
示例用三个辅助函数把引脚配置、点亮、熄灭与翻转封装起来,主程序只负责编排闪烁与轮流点亮的次序。
数据路径: main → LED_Init → RCC_EnableAHBPeriphClk 打开端口时钟、GPIO_InitPeripheral 写入 PA1/PA7/PB1 的输出模式 → LED_Blink/LED_On/LED_Off → GPIO_TogglePin/GPIO_SetBits/GPIO_ResetBits → 引脚电平 → LED 亮灭
1. 逐个初始化三路 LED。 main 开头对三路 LED 各调用一次 LED_Init,分别传入自己的端口、引脚与时钟宏。
/* LED port init */
LED_Init(LED1_PORT, LED1_PIN, LED1_CLOCK);
LED_Init(LED2_PORT, LED2_PIN, LED2_CLOCK);
LED_Init(LED3_PORT, LED3_PIN, LED3_CLOCK);
三个端口与引脚来自 bsp/inc/n32g41x_stb.h;换板时改这组宏即可,主程序与辅助函数不用动。
2. 先让两路 LED 闪烁 4 次。 for 循环从 0 到 7 共 8 次,每轮翻转 LED1 与 LED3 后延时 500 ms,因此表现为“闪烁 4 次”。
/* LED1 and LED3 blink 4 times */
for(i=0;i<8;i++)
{
LED_Blink(LED1_PORT, LED1_PIN);
LED_Blink(LED3_PORT, LED3_PIN);
SysTick_Delay_Ms(500);
}
闪烁次数由循环上界 8 决定,节奏由 SysTick_Delay_Ms(500) 决定,改观察效果时同步调整这两处。
3. 主循环按顺序轮流点亮。 进入 while (1) 后先熄灭 LED3 再点亮 LED1,然后每轮熄灭上一路、点亮下一路,各延时 500 ms。
/* Turn on LED1 and turn off LED3*/
LED_Off(LED3_PORT, LED3_PIN);
LED_On(LED1_PORT, LED1_PIN);
SysTick_Delay_Ms(500);
/* Turn on LED2 and turn off LED1*/
LED_Off(LED1_PORT, LED1_PIN);
LED_On(LED2_PORT, LED2_PIN);
SysTick_Delay_Ms(500);
/* Turn on LED3 and turn off LED2 */
LED_Off(LED2_PORT, LED2_PIN);
LED_On(LED3_PORT, LED3_PIN);
SysTick_Delay_Ms(500);
轮流点亮的顺序就是这三段的先后次序,增加或调换 LED 时按同样方式追加一段。
4. 初始化函数把参数写进 GPIO_InitType。 LED_Init 先用 GPIO_InitStruct 取默认值,再逐项填入引脚与输出参数,最后交给 GPIO_InitPeripheral 写入寄存器。
/* Init GPIO as output push-pull mode */
InitStruct.Pin = Pin;
InitStruct.GPIO_Slew_Rate = GPIO_SLEW_RATE_FAST;
InitStruct.GPIO_Mode = GPIO_MODE_OUTPUT_PP;
InitStruct.GPIO_Alternate = GPIO_NO_AF;
InitStruct.GPIO_Pull = GPIO_NO_PULL;
InitStruct.GPIO_Current = GPIO_DS_HIGH;
翻转率、驱动能力与上下拉都在这段里给定,换成开漏输出或需要上拉时改 InitStruct.GPIO_Mode 与 InitStruct.GPIO_Pull。
对应源码: src/main.c、inc/main.h、projects/n32g41x_EVAL/bsp/inc/n32g41x_stb.h
5.10.4 注意与排障
| 场景 | 检查与建议 | 来源 |
|---|---|---|
| I/O 端口寄存器的访问宽度 | 每个 I/O 端口位可以任意编程,但必须按 32 位字访问 I/O 端口寄存器,不允许 16 位半字或 8 位字节访问。 | 用户手册 |
| 逐位改变输出而不影响其它位 | 向位设置/清除寄存器 GPIOx_PBSC 和位清除寄存器 GPIOx_PBC 中要改变的位写 1 即可单独置位或清除,未写入 1 的位保持不变,单次 AHB 写操作完成,软件不需要禁止中断。 | 用户手册 |
| 引脚配置被意外改写 | 锁定机制在某个端口位上执行 LOCK 序列后,到下一次复位之前不能再更改该引脚配置; PLOCKK 只有在按 w1→w0→w1→r0 序列操作后才置 1,序列过程中 PLOCK[15:0] 不能改变,序列出错必须重做。 |
用户手册 |
| 用了复用功能却没有输出 | 端口配置为复用功能模式时,使用前必须对端口位配置寄存器 GPIOx_AFL/GPIOx_AFH 和输出类型寄存器 GPIOx_POTYPE(推挽或开漏)编程; 复用输入或输出由外设决定。 |
用户手册 |
| 翻转率配置位并非每个端口都有 | 翻转率配置位不是每个端口齐全:GPIOB 上只有 SR5、SR6、SR7,GPIOA 上只有 SR0、SR1、SR2,GPIOC、GPIOD 上没有这些位。 | 用户手册 |
| SPI NSS 处于 AFIO 推挽模式 | GPIOx_AFH 中的 SPI1_NSS、SPI2_NSS 位在对应 SPI 作为从机时必须配置为 0,即 NSS 空闲时为高阻态。 | 用户手册 |
| IO 滤波时间的时钟来源 | IO 滤波时间以 HCLK 分频后的时钟为周期,分频值由 RCC 的 GPIOFCLKDIV 配置,改滤波档位时要一并核对这个分频。 | 用户手册 |
N32G412、N32G415 系列勘误手册 V1.0.0(2026.6.30)的勘误列表只列出一行 A 版芯片条目且勘误链接列为空,未列出 GPIO 相关条目。