使用注意點:
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號