使用注意点:
1.使用低功耗时GPIO的配置:未使用到的GPIO配置为上拉输入此时外部不要有下拉否则会产生漏电流,使用了模拟功能的GPIO(如ADC,TOUCH,LCD等)需关闭其数字功能。
2.PA12引脚上电时会有15ms左右的高电平,应避免使用此IO输出。
3.PB23为复位引脚,若做输入输出使用时在使用ISP下载时需关闭RST的使能,否则可能导致下次无法正常下载或代码一直复位。
4.PB22为默认BOOT引脚,最好不要一直接地否则会导致上电后过10秒或60秒才能运行用户代码。
一、GPIO 基本功能概述
CH592微控制器的 GPIO(通用输入输出)引脚具备高度灵活性,可通过配置实现以下核心功能:基础输入输出:支持推挽输出、多种输入模式,满足数字信号的发送与接收需求。
中断响应:可配置为中断触发引脚,快速响应外部事件(如电平变化、边沿跳变)。
功能重映射:部分引脚支持外设功能映射,提升硬件资源的复用性。
GPIO 作为硬件交互的核心接口,是连接外部设备(如传感器、LED、按键等)的关键通道,掌握其配置方法是开发 CH592 应用的基础。
二、GPIO 模式配置
CH592 的 GPIO 引脚模式需通过专用配置函数设定,不同模式对应不同的硬件行为,需根据实际场景选择。
2.1 输出模式
仅支持推挽输出,并提供两种驱动能力选择,适应不同负载需求:5mA 驱动:适用于低功耗场景或小电流负载(如小型 LED)。20mA 驱动:适用于需要较大驱动电流的设备(如继电器、蜂鸣器)。
配置示例:将 PA4 引脚设置为 5mA 推挽输出模式:
GPIOA_ModeCfg(GPIO_Pin_4, GPIO_ModeOut_PP_5mA); // PA4 配置为 5mA 推挽输出
2.2 输入模式
支持三种输入模式,需根据外部信号特性选择:
上拉输入(GPIO_ModeIN_PU):引脚内部接 pull-up 电阻,未接外部信号时默认高电平,适用于按键等外部无固定电平的场景。
下拉输入(GPIO_ModeIN_PD):引脚内部接 pull-down 电阻,未接外部信号时默认低电平,适用于需要稳定基准的输入场景。
浮空输入(GPIO_ModeIN_Floating):无内部上下拉,电平完全由外部信号决定,适用于接收稳定的外部数字信号(如 UART 通信)。
配置示例:将 PA5 配置为上拉输入模式:
GPIOA_ModeCfg(GPIO_Pin_5, GPIO_ModeIN_PU); // PA5 配置为上拉输入
2.3 模拟开漏输出
CH592 无硬件开漏输出模式,但可通过软件切换引脚状态模拟实现,适用于需要线与(Wire-AND)功能的场景(如 I2C 通信):
输出高电平:将引脚配置为上拉输入模式(依赖内部上拉电阻拉高电平)。
输出低电平:将引脚配置为推挽输出模式,并默认输出低电平。
实现逻辑示例:
// 模拟开漏输出高电平 GPIOA_ModeCfg(GPIO_Pin_6, GPIO_ModeIN_PU); // 模拟开漏输出低电平 GPIOA_ModeCfg(GPIO_Pin_6, GPIO_ModeOut_PP_5mA); GPIOA_ResetBits(GPIO_Pin_6); // 输出低电平
三、GPIO 电平操作
电平操作函数用于直接控制输出引脚状态或读取输入引脚状态,需注意操作前需确保引脚已配置为对应模式(输出模式用于写操作,输入模式用于读操作)。
3.1输出电平设置
提供三种常用输出操作,通过函数直接控制引脚电平:
设置高电平:GPIOA_SetBits(pin)
示例:将 PA4 输出高电平
GPIOA_SetBits(GPIO_Pin_4);
设置低电平:GPIOA_ResetBits(pin)
示例:将 PA4 输出低电平
GPIOA_ResetBits(GPIO_Pin_4);
翻转电平:GPIOA_InverseBits(pin)(高电平变低,低电平变高)
示例:翻转 PA4 电平
GPIOA_InverseBits(GPIO_Pin_4);
3.2 输入电平读取
通过函数读取输入引脚的实时电平状态,返回值为0(低电平)或非0(高电平):
函数:GPIOA_ReadPortPin(pin)
示例:读取 PA5 引脚电平
uint32_t pin_state = GPIOA_ReadPortPin(GPIO_Pin_5); if(pin_state != 0) { // PA5 为高电平 } else { // PA5 为低电平 }
四、GPIO 中断配置
GPIO 中断可用于响应外部事件(如按键按下、传感器触发),减少 CPU 轮询开销,提升系统效率。配置需遵循 “引脚模式→触发方式→标志处理→中断使能” 的流程。
4.1 支持中断的引脚
基础中断引脚:PA0-PA15、PB0-PB15。
扩展中断引脚:部分封装支持 PB22、PB23,需通过GPIO 重映射配置(见第五章)。
4.2 中断触发方式
支持四种触发条件,需根据外部信号特性选择:
低电平触发:引脚电平持续为低时触发中断。
高电平触发:引脚电平持续为高时触发中断。
上升沿触发:引脚电平从低跳变为高时触发(瞬间变化)。
下降沿触发:引脚电平从高跳变为低时触发(瞬间变化)。
配置示例:
将 PA6 配置为下降沿触发中断:
GPIOA_ITModeCfg(GPIO_Pin_6, GPIO_ITMode_FallEdge); // 下降沿触发
4.3 中断标志处理
中断触发后,需通过标志函数判断中断源并清除标志(否则会持续触发中断):
读取 PA 口所有中断标志:GPIOA_ReadITFlagPort()(返回值为标志寄存器值)。
读取指定引脚中断标志:GPIOA_ReadITFlagBit(pin)(返回0表示未触发,非0表示已触发)。
清除指定引脚中断标志:GPIOA_ClearITFlagBit(pin)。
示例:清除 PA6 中断标志:
GPIOA_ClearITFlagBit(GPIO_Pin_6); // 清除 PA6 中断标志
4.4 完整中断配置流程示例
// 步骤1:配置引脚为输入模式(中断引脚需先设为输入) GPIOA_ModeCfg(GPIO_Pin_6, GPIO_ModeIN_PU); // 步骤2:设置中断触发方式(下降沿) GPIOA_ITModeCfg(GPIO_Pin_6, GPIO_ITMode_FallEdge); // 步骤3:清除可能存在的旧标志 GPIOA_ClearITFlagBit(GPIO_Pin_6); // 步骤4:使能 GPIOA 中断 PFIC_EnableIRQ(GPIO_A_IRQn);
五、GPIO 重映射
部分外设功能可映射到不同引脚,提升硬件布局灵活性。
例如,将 PB8/PB9 的中断功能映射到 PB22/PB23(适用于需要扩展中断引脚的场景)。
配置示例:启用 PB22/PB23 作为中断引脚(替代 PB8/PB9):
GPIOPinRemap(ENABLE, RB_PIN_INTX); // 使能中断引脚重映射
六、完整程序演示
下述程序演示了GPIO输出,GPIO输入和GPIO中断:
#include "CH59x_common.h" // 引脚宏定义(保持不变) #define LED_PIN GPIO_Pin_4 // 连接 LED 的引脚 #define TEST_PIN GPIO_Pin_5 // 用于输入测试的引脚 #define WAKE_PIN_1 GPIO_Pin_6 // 用于中断唤醒的引脚 1 #define WAKE_PIN_2 GPIO_Pin_7 // 用于中断唤醒的引脚 2 #define ALL_WAKE_PINS (WAKE_PIN_1 | WAKE_PIN_2) // 所有唤醒引脚的组合 // 中断来源枚举(保持不变) typedef enum { WAKE_NONE = 0, // 无中断 WAKE_FROM_PIN1, // 来自引脚 1 的中断 WAKE_FROM_PIN2 // 来自引脚 2 的中断 } WakeSource; volatile WakeSource gpio_wake_source = WAKE_NONE; // 记录中断来源 /** * @brief 初始化调试串口 UART1 */ void UART1_DebugInit(void) // 明确指定串口编号,更具辨识度 { GPIOA_SetBits(GPIO_Pin_9); GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP_5mA); UART1_DefInit(); // 默认初始化 UART1 } /** * @brief 初始化LED控制引脚 */ void LED_GPIO_Init(void) // 明确功能:LED的GPIO初始化 { // 配置 LED 引脚为推挽输出 GPIOA_SetBits(LED_PIN); // 初始输出高电平,关闭 LED(假设低电平有效) GPIOA_ModeCfg(LED_PIN, GPIO_ModeOut_PP_5mA); } /** * @brief 初始化测试输入引脚并检测状态 */ void TestPin_GPIO_InitAndCheck(void) // 强调包含初始化和状态检测 { // 配置测试引脚为上拉输入并读取状态 GPIOA_ModeCfg(TEST_PIN, GPIO_ModeIN_PU); uint32_t pin_state = GPIOA_ReadPortPin(TEST_PIN); PRINT("TEST_PIN (pull-up input) status: 0x%x\n", pin_state); // 配置测试引脚为下拉输入并读取状态 GPIOA_ModeCfg(TEST_PIN, GPIO_ModeIN_PD); pin_state = GPIOA_ReadPortPin(TEST_PIN); PRINT("TEST_PIN (pull-down input) status: 0x%x\n", pin_state); } /** * @brief 初始化中断唤醒引脚及中断配置 */ void WakeupPins_IRQ_Init(void) // 明确包含唤醒引脚和中断初始化 { // 配置唤醒引脚为上拉输入 GPIOA_ModeCfg(ALL_WAKE_PINS, GPIO_ModeIN_PU); // 分别配置中断触发方式,便于灵活调整 GPIOA_ITModeCfg(WAKE_PIN_1, GPIO_ITMode_FallEdge); // 下降沿触发 GPIOA_ITModeCfg(WAKE_PIN_2, GPIO_ITMode_FallEdge); // 下降沿触发 // 清除可能存在的中断标志 GPIOA_ClearITFlagBit(ALL_WAKE_PINS); // 使能 GPIOA 中断 PFIC_EnableIRQ(GPIO_A_IRQn); } /** * @brief 处理唤醒中断事件 * @param source: 中断来源 */ void WakeupEvent_Process(WakeSource source) // 强调"处理"动作 { // 根据不同中断来源执行不同操作 switch(source) { case WAKE_FROM_PIN1: PRINT("WAKE_PIN_1 interrupt detected\n"); // 可添加引脚 1 中断的特定处理逻辑 break; case WAKE_FROM_PIN2: PRINT("WAKE_PIN_2 interrupt detected\n"); // 可添加引脚 2 中断的特定处理逻辑 break; default: break; } } /** * @brief 测试引脚状态周期性检测 */ void TestPin_PeriodicCheck(void) // 明确是周期性检测 { uint32_t pin_state = GPIOA_ReadPortPin(TEST_PIN); static uint16_t counter = 0; // 变量名更具意义 counter++; if(counter % 20 == 0) { PRINT("TEST_PIN: 0x%x\n", pin_state); } } /** * @brief GPIOA 中断处理函数 */ __INTERRUPT __HIGH_CODE void GPIOA_IRQHandler(void) // 中断函数名遵循芯片规范,保持不变 { uint32_t int_flags = GPIOA_ReadITFlagPort() & R16_PA_INT_EN; // 检查并处理 WAKE_PIN_1 中断 if(int_flags & WAKE_PIN_1) { gpio_wake_source = WAKE_FROM_PIN1; GPIOA_ClearITFlagBit(WAKE_PIN_1); } // 检查并处理 WAKE_PIN_2 中断 if(int_flags & WAKE_PIN_2) { gpio_wake_source = WAKE_FROM_PIN2; GPIOA_ClearITFlagBit(WAKE_PIN_2); } } int main(void) { SetSysClock(CLK_SOURCE_PLL_60MHz); // 设置系统时钟为 60MHz UART1_DebugInit(); // 初始化调试串口 LED_GPIO_Init(); // 初始化 LED 引脚 TestPin_GPIO_InitAndCheck();// 初始化测试输入引脚并检测 WakeupPins_IRQ_Init(); // 初始化中断唤醒引脚及中断 PRINT("Program started @ChipID=0x%02x\n", R8_CHIP_ID); // 点亮 LED,指示程序启动成功 GPIOA_ResetBits(LED_PIN); DelayMs(500); while(1) { // 每 100 毫秒翻转一次 LED 状态,指示程序正常运行 GPIOA_InverseBits(LED_PIN); // 检查是否有中断发生并处理 if(gpio_wake_source != WAKE_NONE) { WakeupEvent_Process(gpio_wake_source); // 处理中断事件 gpio_wake_source = WAKE_NONE; // 清除中断标志 } TestPin_PeriodicCheck(); // 周期性检测测试引脚 DelayMs(100); } }
浙公网安备 33010602011771号