AS32S601型MCU芯片电源管理(PMU)模块详解
另一方面,它管理所有唤醒源(如特定GPIO 电平变化、看门狗、RTC等),当检测到有效唤醒信号时,触发芯片从低功耗模式快速恢复到正常工作模式,同时保证唤醒时序的准确性。RISC-V 芯片的多时钟源(内部 32KRC、外部晶振、PLL)由 PMU 统一协调,它可根据工作模式切换时钟源(如休眠时切换到低功耗 32K 时钟,正常工作时切换到高频 PLL 时钟),同时关闭未使用的时钟分支,减少时钟树的冗余
一、电源管理模块 PMU(Power Management Unit)
电源管理模块 PMU是芯片的 “能耗与电源管家”,核心目标是平衡功耗与供电稳定性,适配嵌入式设备的低功耗、长续航需求,具体作用包括:
1. 多电源域的独立管控
为了有效地控制 MCU 的功耗,对模块的划分包括 AON(Always On)模块、Main 模块和 ANA 模块。
AON 模块:其供电有 RTC 模拟 IP 提供 1.2V 的电源,并提供工作的 32KHz时钟。该模块会控制 Main 和 ANA 模块的电源开关。在深度睡眠模式下,AON 会关闭 Main 和ANA 的电源。
Main 模块:该模块包含所有的内核逻辑和外设逻辑。其电源由 PMB 提供。
ANA 模块:该模块包含 ADC、DAC、PLL、ROSC16M、EFLASH 等模拟 IP模块。
例如,当芯片进入深度休眠模式时,PMU 可切断内核和外设电源域的供电,仅保留 RTC 和唤醒源对应的电源域,将静态功耗降至 uA 级;而唤醒后又能按优先级依次恢复各电源域供电,避免上电时序紊乱。

2.低功耗模式的调度与切换
PMU 是 RISC-V 芯片低功耗模式(如 Sleep、Deep Sleep等)的核心控制单元:一方面,它负责解析软件下发的低功耗指令,完成核心时钟关闭、外设休眠、寄存器数据备份等流程;另一方面,它管理所有唤醒源(如特定GPIO 电平变化、看门狗、RTC等),当检测到有效唤醒信号时,触发芯片从低功耗模式快速恢复到正常工作模式,同时保证唤醒时序的准确性。
3.动态电压频率调节(DVFS)
针对支持变频调压的 RISC-V 芯片,PMU 可联动时钟模块(PLL/CLKGEN)实现DVFS 机制:根据 CPU 负载(如指令执行密度、外设工作状态)自动调整内核的供电电压和工作频率。例如,当芯片仅执行低速传感器数据采集任务时,PMU 将内核主频从 160MHz 降至 80MHz,同时降低供电电压,大幅降低动态功耗;当需要执行复杂运算时,再快速提升主频和电压,保障性能需求。
4.电源监测与安全保护
PMU 内置电压、电流监测电路,可实时监控芯片各电源域的供电状态:若出现过压、欠压、过流等异常,PMU 会触发硬件保护机制(如自动切断对应电源域、上报中断),防止芯片烧毁。
5.时钟系统的协同管理
RISC-V 芯片的多时钟源(内部 32KRC、外部晶振、PLL)由 PMU 统一协调,它可根据工作模式切换时钟源(如休眠时切换到低功耗 32K 时钟,正常工作时切换到高频 PLL 时钟),同时关闭未使用的时钟分支,减少时钟树的冗余功耗。
二、 特性
-
支持低功耗模式(SLEEP/DEEP_SLEEP/WAKEUP)的切换
-
支持唤醒源的配置(外部 IO/RTC/IWDG)
-
支持 FIRC 的开启与关闭
系统的电源管理状态有 4 种,分别是正常模式、省电模式、睡眠模式和深度睡眠模式。其四种状态之间的转换如下图所示:

进入省电模式下,系统低频时钟运行(关闭 PLL,系统的工作频率由 OSC 或FIRC 提供),而且可以关闭部分外设。用户可以在正常模式或睡眠模式下进入省电模式。
✳1 省电模式需要关闭PLL
✳2 进入省电模式后,由于时钟变化需要对串口、IIC等外设进行重新配置
✳3 睡眠模式进入省电模式的前提是进入睡眠模式之前MCU是工作在省电模式
对应代码如下所示:
if(key3_flag)
{
key3_flag = 0;
key3_cnt++;
if(old_key3_cnt == key3_cnt)
{
Printf("SRUN State\r\n");
Systemclock_SRUN_Init();
User_Print_Init(115200);
Printf("SRUN State\r\n");
}
else
{
key3_cnt=0;
Printf("Normal State\r\n");
Systemclock_Init();
User_Print_Init(115200);
Printf("Normal State\r\n");
}
}
/*
* Function: Systemclock_SRUN_Init
* Description: Configure Systemclock_Init.
* Param: None
* Return: None.
*/
void Systemclock_SRUN_Init()
{
//注意:此处需要开启系统总线级的时钟配置,具体外设时钟配置可在各模块初始化函数中具体开启,具体请参考时钟树或者下图注释
/* AXIBus3 clock operation Guide*/
AXIBUS3_CLK_ENABLE();
AXI4TOAPB0_CLK_ENABLE();
APBBUS0_CLK_ENABLE();
AXILITEBUS1_CLK_ENABLE();
AXILITEBUS2_CLK_ENABLE();
EFLASH_CLK_ENABLE();
PLIC_CLK_ENABLE();
CLINT_CLK_ENABLE();
USART0_CLK_ENABLE();
DMA0_CLK_ENABLE();
SMU_PLLInitTypeDef SMU_PLLInitStruct;
SMU_ClockInitTypeDef SMU_ClockInitStruct;
/* Set System Clock parameters values */
SMU_ClockInitStruct.SYSCLKSelect = SMU_SYSCLK_FIRC;
SMU_ClockInitStruct.AXI4Bus3CLKDiv = AXI4Bus3CLKDiv1;
SMU_ClockInitStruct.APBBus0CLKDiv = APBBus0CLKDiv1;
SMU_ClockInitStruct.APBBus1CLKDiv = APBBus1CLKDiv1;
SMU_ClockInitStruct.CANX2CLKDiv = CANX2CLKDiv1;
SMU_ClockInit(&SMU_ClockInitStruct);
SMU_PLLCmd(DISABLE);
EFLASH_CLK_UPDATE_ENABLE();
EFLASH_CLK_UPDATE_DISABLE();
FLASH_LockCtrl();
/* Get System Clock values */
SMU_GetClocksFreq(&SMU_ClocksStruct);
}
void Systemclock_Init()
{
//注意:此处需要开启系统总线级的时钟配置,具体外设时钟配置可在各模块初始化函数中具体开启,具体请参考时钟树或者下图注释
/* AXIBus3 clock operation Guide*/
AXIBUS3_CLK_ENABLE();
AXI4TOAPB0_CLK_ENABLE();
APBBUS0_CLK_ENABLE();
AXILITEBUS1_CLK_ENABLE();
AXILITEBUS2_CLK_ENABLE();
EFLASH_CLK_ENABLE();
PLIC_CLK_ENABLE();
CLINT_CLK_ENABLE();
USART0_CLK_ENABLE();
DMA0_CLK_ENABLE();
SMU_PLLInitTypeDef SMU_PLLInitStruct;
SMU_ClockInitTypeDef SMU_ClockInitStruct;
/* Set PLL parameters values */
SMU_PLLInitStruct.OscillatorType = SMU_OSCILLATORTYPE_OSC;
SMU_PLLInitStruct.FIRCOscState = DISABLE;
SMU_PLLInitStruct.FIRCCalibrationValue = 0x00;
SMU_PLLInitStruct.PLLConfig.PLLState = ENABLE;
SMU_PLLInitStruct.PLLConfig.PLLSource = SMU_PLLCLK_OSC;
SMU_PLLInitStruct.PLLConfig.PLLDivR = 0x04;
SMU_PLLInitStruct.PLLConfig.PLLDivQ = 0x01;
SMU_PLLInitStruct.PLLConfig.PLLDivN = 0x14;
SMU_PLLInitStruct.PLLConfig.PLLDivF = 0x78;
SMU_PLLInit(&SMU_PLLInitStruct);
/* Ensure that the EFLASH is consistent with the system clock */
FLASH_UnlockCtrl();
FLASH_SetCLKFreq(0x78)
/* Set System Clock parameters values */
SMU_ClockInitStruct.SYSCLKSelect = SMU_SYSCLK_PLL;
SMU_ClockInitStruct.AXI4Bus3CLKDiv = AXI4Bus3CLKDiv1;
SMU_ClockInitStruct.APBBus0CLKDiv = APBBus0CLKDiv1;
SMU_ClockInitStruct.APBBus1CLKDiv = APBBus1CLKDiv1;
SMU_ClockInitStruct.CANX2CLKDiv = CANX2CLKDiv1;
SMU_ClockInit(&SMU_ClockInitStruct);
EFLASH_CLK_UPDATE_ENABLE();
EFLASH_CLK_UPDATE_DISABLE();
FLASH_LockCtrl();
/* Get System Clock values */
SMU_GetClocksFreq(&SMU_ClocksStruct);
}
在睡眠模式下,用户需要复位/禁止 PLL 输出、禁止 FIRC 输出时钟、ADC、DAC 等处于低功耗模式,要进入睡眠/深度睡眠模式,请遵循以下步骤:
-
读取唤醒信息:读取 PMU_WKP 寄存器,若有位为 1 则写 1 清除该位,若皆为 0 则进入下一步操作;
-
配置唤醒通道:将 PMU_WKEN 寄存器的对应唤醒通道配置为 1,其他通道配置为0;
-
保存备份信息:将需要备份的信息存储到 Bkp RAM 内;
-
配置睡眠模式:配置 PMU_MODE 寄存器的值,配置 1 进入深度睡眠模式,配置 2 进入睡眠模式;
-
系统将自动睡眠。 唤醒后,可通过 PMU_WKP 寄存器读取唤醒信息,获取唤醒源。
注意:


*1:进入睡眠/深度睡眠前要确认唤醒寄存器状态是否清空,唤醒后要及时清除唤醒寄存器
*2:DeepSleep 唤醒:等效于系统软重启,程序从复位入口重新执行,片内常规 RAM数据完全丢失;关键数据需预先存入备份 RAM(Backup RAM)以实现掉电 / 深睡保留。

*3:Sleep 唤醒:系统仅恢复 CPU 运行,程序从 Sleep 指令下一条语句继续执行(通常是 while (1) 循环内断点),常规 RAM 数据完整保留,无需重新初始化时钟、外设等硬件配置。
以下为进入唤醒睡眠模式流程图


此图为我司提供的开发板对应电流3.62mA
在深度睡眠模式下,需要 PMU 关闭 PMB 输出,使 Main 和 ANA 进入掉电状态。此时唤醒只能通过 RTC 或外部引脚唤醒进入正常工作模式。以下为进入唤醒深度睡眠模式流程图


此图为我司提供的开发板对应电流291uA
对应代码:
/*
* Brief: Main program
* Description:
* Param: None.
* Return: None.
*/
void main()
{
uint32_t led_count = 0;
Systemclock_Init();
delay_init(SMU_ClocksStruct.AXIBus0_Frequency/1000000);
/* Initialize print usart */
User_Print_Init(115200);
User_KEY_Init();
Wake_KEY_Init();
/* Configure the FCU */
//FCUConfig();
/* USART send data */
Printf("AS32X601 Power mode switching!\r\n");
PMU_WKFlagJudg();
#if IWDG
IWDG_SetPrescaler(200);
IWDG_SetDivider(745);
IWDG_SetTimeout(4);
IWDG_ENCmd(I_CFG_EN,ENABLE);
IWDG_ResetCounter();
num = IWDG_GetCounter();
#endif
#if IWDG
PMU_WakeUpSourceCmd(PMU_WKSource_IWDG, ENABLE);
#endif
#if RTC
RTC_Config();//10S后唤醒
PMU_WakeUpSourceCmd(PMU_WKSource_RTC, ENABLE);
#endif
/* Enable PH2 wakeup source */
PMU_WakeUpSourceCmd(PMU_WKSource_PH2, ENABLE);
PMU_WakeUpSourceCmd(PMU_WKSource_PH3, ENABLE);
PMU_WakeUpSourceCmd(PMU_WKSource_PH4, ENABLE);
PMU_WakeUpSourceCmd(PMU_WKSource_PH5, ENABLE);
PMU_WakeUpSourceCmd(PMU_WKSource_PH6, ENABLE);
PMU_WakeUpSourceCmd(PMU_WKSource_PH7, ENABLE);
PMU_WakeUpSourceCmd(PMU_WKSource_PH8, ENABLE);
PMU_WakeUpSourceCmd(PMU_WKSource_PH9, ENABLE);
pwk = (PMU->WKEN)&0x3FFF;
Printf("WKEN %x\r\n", pwk);
while(1)
{
if(key1_flag)
{
key1_flag = 0;
/* Set sleep mode */
power_status = PMU_GetPowerModeStatus();
if((power_status == PMU_PowerMode_INIT)||(power_status == PMU_PowerMode_Normal))
{
PMU_ClearFlag(0x3FFF);
Printf("POWER_SATUS %d\r\n", power_status);
Printf("DEEP SLEEP!\r\n");
PMU_PowerModeConfig(PMU_PowerMode_DeepSleep);
}
}
if(key2_flag)
{
key2_flag = 0;
power_status = PMU_GetPowerModeStatus();
if((power_status == PMU_PowerMode_INIT)||(power_status == PMU_PowerMode_Normal))
{
PMU_ClearFlag(0x3FFF);
Printf("POWER_SATUS %d\r\n", power_status);
Printf("SLEEP!\r\n");
PMU_PowerModeConfig(PMU_PowerMode_Sleep);
}
}
}
}
/*
* Function: PMU_WKFlagJudg
* Description: Wake up source status judgment.
* Param: None.
* Return: None.
*/
void PMU_WKFlagJudg(void)
{
Printf("WKFR: 0x%x !\r\n", PMU->WKFR);
if(PMU_GetFlagStatus(PMU_FLAG_IWDGWK) == SET)
{
Printf("IWDG wake up!\r\n");
PMU_ClearFlag(PMU_CLEAR_IWDGWKF);
}
if(PMU_GetFlagStatus(PMU_FLAG_RTCWK) == SET)
{
Printf("RTC wake up!\r\n");
PMU_ClearFlag(PMU_CLEAR_RTCWKF);
}
if(PMU_GetFlagStatus(PMU_FLAG_PH0WK) == SET)
{
Printf("PH0 wake up!\r\n");
PMU_ClearFlag(PMU_CLEAR_PH0WKF);
}
if(PMU_GetFlagStatus(PMU_FLAG_PH1WK) == SET)
{
Printf("PH1 wake up!\r\n");
PMU_ClearFlag(PMU_CLEAR_PH1WKF);
}
if(PMU_GetFlagStatus(PMU_FLAG_PH2WK) == SET)
{
Printf("PH2 wake up!\r\n");
PMU_ClearFlag(PMU_CLEAR_PH2WKF);
}
if(PMU_GetFlagStatus(PMU_FLAG_PH3WK) == SET)
{
Printf("PH3 wake up!\r\n");
PMU_ClearFlag(PMU_CLEAR_PH3WKF);
}
if(PMU_GetFlagStatus(PMU_FLAG_PH4WK) == SET)
{
Printf("PH4 wake up!\r\n");
PMU_ClearFlag(PMU_CLEAR_PH4WKF);
}
if(PMU_GetFlagStatus(PMU_FLAG_PH5WK) == SET)
{
Printf("PH5 wake up!\r\n");
PMU_ClearFlag(PMU_CLEAR_PH5WKF);
}
if(PMU_GetFlagStatus(PMU_FLAG_PH6WK) == SET)
{
Printf("PH6 wake up!\r\n");
PMU_ClearFlag(PMU_CLEAR_PH6WKF);
}
if(PMU_GetFlagStatus(PMU_FLAG_PH7WK) == SET)
{
Printf("PH7 wake up!\r\n");
PMU_ClearFlag(PMU_CLEAR_PH7WKF);
}
if(PMU_GetFlagStatus(PMU_FLAG_PH8WK) == SET)
{
Printf("PH8 wake up!\r\n");
PMU_ClearFlag(PMU_CLEAR_PH8WKF);
}
if(PMU_GetFlagStatus(PMU_FLAG_PH9WK) == SET)
{
Printf("PH9 wake up!\r\n");
PMU_ClearFlag(PMU_CLEAR_PH9WKF);
}
PMU_WakeUpSourceCmd(PMU_WKSource_PH2, DISABLE);
PMU_WakeUpSourceCmd(PMU_WKSource_PH3, DISABLE);
PMU_WakeUpSourceCmd(PMU_WKSource_PH4, DISABLE);
PMU_WakeUpSourceCmd(PMU_WKSource_PH5, DISABLE);
PMU_WakeUpSourceCmd(PMU_WKSource_PH6, DISABLE);
PMU_WakeUpSourceCmd(PMU_WKSource_PH7, DISABLE);
PMU_WakeUpSourceCmd(PMU_WKSource_PH8, DISABLE);
PMU_WakeUpSourceCmd(PMU_WKSource_PH9, DISABLE);
Printf("WKFR: 0x%x !\r\n", PMU->WKFR);
}
/*
* Function: Systemclock_Init
* Description: Configure Systemclock_Init.
* Param: None
* Return: None.
*/
void Systemclock_Init()
{
//注意:此处需要开启系统总线级的时钟配置,具体外设时钟配置可在各模块初始化函数中具体开启,具体请参考时钟树或者下图注释
// 1. 使用串口时,由于串口挂在APB0总线下,需要在此处开启AXIBUS3时钟、AXI4TOAPB0时钟以及APBBUS0时钟。
// 2. 使用延时函数时,需要开启CLINT时钟
// 3. 使用eflash、qspi时,需要开启AXIBUS3时钟、AXILITEBUS2时钟
//注意:osc经过PLLDIVN分频之后频率应在0.95-2.1MHz之间
// core_clock (无需使能) = pll_Q = osc % PLLDIVN x PLLDIVF % PLLDIVQ (注:此部分时钟计算范围应在16-180MHz之间)
// AXI4Bus0 (无需使能) = pll_Q = osc % PLLDIVN x PLLDIVF % PLLDIVQ (注:此部分时钟计算范围应在16-180MHz之间)
// AXI4Bus1 (无需使能) = pll_Q % 2 (注:此部分时钟计算范围应在8-90MHz之间)
// AXI4Bus2 (无需使能) = pll_Q (注:此部分时钟计算范围应在16-180MHz之间)
// |__AXILite4Bus0 (无需使能) = AXI4Bus2
// AXI4Bus3 (按需使能) = pll_Q % 2 % AXI4Bus3CLKDiv (注:此部分时钟计算范围应在8-90MHz之间)
// |__AXI4TOAPB0_CLK (按需使能)
// | |__APBBus0 (按需使能) = AXI4Bus3 % APBBus0CLKDiv (注:此部分时钟计算范围应在4-45MHz之间)
// |__AXI4TOAPB1_CLK (按需使能)
// | |__APBBus1 (按需使能) = AXI4Bus3 % APBBus1CLKDiv (注:此部分时钟计算范围应在4-45MHz之间)
// |__AXILite4Bus1 (按需使能) = AXI4Bus3
// |__AXILite4Bus2 (按需使能) = AXI4Bus3
// CANCLK (接口使能) = pll_R = osc % PLLDIVN x PLLDIVF % PLLDIVR (注:此部分时钟计算范围应在8-80MHz之间)
// APBBusS (无需使能) = 32.768kHz
/* AXIBus3 clock operation Guide*/
AXIBUS3_CLK_ENABLE();
AXI4TOAPB0_CLK_ENABLE();
APBBUS0_CLK_ENABLE();
AXILITEBUS1_CLK_ENABLE();
AXILITEBUS2_CLK_ENABLE();
EFLASH_CLK_ENABLE();
PLIC_CLK_ENABLE();
CLINT_CLK_ENABLE();
USART0_CLK_ENABLE();
DMA0_CLK_ENABLE();
SMU_PLLInitTypeDef SMU_PLLInitStruct;
SMU_ClockInitTypeDef SMU_ClockInitStruct;
/* Set PLL parameters values */
SMU_PLLInitStruct.OscillatorType = SMU_OSCILLATORTYPE_OSC;
SMU_PLLInitStruct.FIRCOscState = DISABLE;
SMU_PLLInitStruct.FIRCCalibrationValue = 0x00;
SMU_PLLInitStruct.PLLConfig.PLLState = ENABLE;
SMU_PLLInitStruct.PLLConfig.PLLSource = SMU_PLLCLK_OSC;
SMU_PLLInitStruct.PLLConfig.PLLDivR = 0x04;
SMU_PLLInitStruct.PLLConfig.PLLDivQ = 0x01;
SMU_PLLInitStruct.PLLConfig.PLLDivN = 0x14;
SMU_PLLInitStruct.PLLConfig.PLLDivF = 0x78;
SMU_PLLInit(&SMU_PLLInitStruct);
/* Ensure that the EFLASH is consistent with the system clock */
FLASH_UnlockCtrl();
FLASH_SetCLKFreq(0x78);
/* Set System Clock parameters values */
SMU_ClockInitStruct.SYSCLKSelect = SMU_SYSCLK_PLL;
SMU_ClockInitStruct.AXI4Bus3CLKDiv = AXI4Bus3CLKDiv1;
SMU_ClockInitStruct.APBBus0CLKDiv = APBBus0CLKDiv1;
SMU_ClockInitStruct.APBBus1CLKDiv = APBBus1CLKDiv1;
SMU_ClockInitStruct.CANX2CLKDiv = CANX2CLKDiv1;
SMU_ClockInit(&SMU_ClockInitStruct);
EFLASH_CLK_UPDATE_ENABLE();
EFLASH_CLK_UPDATE_DISABLE();
FLASH_LockCtrl();
/* Get System Clock values */
SMU_GetClocksFreq(&SMU_ClocksStruct);
}
/*
* Function : FCUConfig
* Description: Configure the FPU behavior
* Param : None
* Return : None
*/
void FCUConfig(void)
{
FCU_CLK_ENABLE();
FCU_InitTypeDef FCU_InitStructure;
FCU_StructInit(&FCU_InitStructure);
FCU_InitStructure.FCU_Channel = FCU_CHANNEL_IWDG; /* Specifies the channel to be configured */
FCU_InitStructure.FCU_FaultToResetCnt = 0; /* Specifies the count to reset under the fault level */
FCU_InitStructure.FCU_AlarmToFaultCnt = 1; /* Specifies the count to change the level from alarm to fault */
FCU_InitStructure.FCU_FaultAction = GLOBAL_SOFTWARE_RESET; /* Specifies the actin when the fault occured every time */
FCU_InitStructure.FCU_AlarmAction = NONE; /* Specifies the actin when the alarm occured every time */
FCU_InitStructure.FCU_FaultLevel = FAULT; /* Specifies the fault level */
FCU_InitStructure.FCU_MaskEnable = DISABLE; /* Specifies the mask enable */
FCU_Init(&FCU_InitStructure);
FCU_ClearSoftwareFault(FCU_CHANNEL_IWDG);
FCU_Cmd(FCU_CHANNEL_IWDG,ENABLE);
}
/*
* Function: User_KEY_Init
* Description: Configure KEY GPIO.
* Param: None.
* Return: None.
*/
void Wake_KEY_Init()
{
GPIO_InitTypeDef GPIO_InitStructure;
/* GPIOB Configure */
GPIO_InitStructure.GPIO_Pin = 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_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_IType = GPIO_IPU;
GPIO_InitStructure.GPIO_OType = GPIO_Out_PP;
GPIO_InitStructure.GPIO_OStrength = GPIO_OStrength_9mA;
GPIO_Init(GPIOH, &GPIO_InitStructure);
}
/*
* Function: User_KEY_Init
* Description: Configure KEY GPIO.
* Param: None.
* Return: None.
*/
void User_KEY_Init()
{
GPIO_InitTypeDef GPIO_InitStructure;
PLIC_InitTypeDef PLIC_InitStructure;
GPIOB_CLK_ENABLE();
GPIOE_CLK_ENABLE();
PLIC_CLK_ENABLE();
/* GPIOE Configure */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_IType = GPIO_IPU;
GPIO_InitStructure.GPIO_OType = GPIO_Out_PP;
GPIO_InitStructure.GPIO_OStrength = GPIO_OStrength_9mA;
GPIO_Init(GPIOE, &GPIO_InitStructure);
/* GPIOB Configure */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_3;
GPIO_Init(GPIOB, &GPIO_InitStructure);
PLIC_InitStructure.PLIC_IRQChannel = GPIOE_IRQn;
PLIC_InitStructure.PLIC_IRQPriority = 1;
PLIC_InitStructure.PLIC_IRQChannelCmd = ENABLE;
PLIC_Init(&PLIC_InitStructure);
PLIC_InitStructure.PLIC_IRQChannel = GPIOB_IRQn;
PLIC_InitStructure.PLIC_IRQPriority = 2;
PLIC_InitStructure.PLIC_IRQChannelCmd = ENABLE;
PLIC_Init(&PLIC_InitStructure);
/*Clear Interrupt start state*/
GPIO_ClearITPendingBit(GPIOE, GPIO_Pin_10);
GPIO_ClearITPendingBit(GPIOB, GPIO_Pin_4|GPIO_Pin_3);
/*Config Interrupt trigger type*/
GPIO_ITConfig(GPIOE, GPIO_Pin_10, GPIO_ITType_EDGEDOWN, ENABLE);
GPIO_ITConfig(GPIOB, GPIO_Pin_4|GPIO_Pin_3, GPIO_ITType_EDGEDOWN, ENABLE);
}
void GPIOE_IRQ_Handler()
{
if(GPIO_GetITStatus(GPIOE, GPIO_Pin_10) == SET)
{
key1_flag = 1;
/*Clear Interrupt start state*/
GPIO_ClearITPendingBit(GPIOE, GPIO_Pin_10);
}
}
void GPIOB_IRQ_Handler()
{
if(GPIO_GetITStatus(GPIOB, GPIO_Pin_4) == SET)
{
key2_flag = 1;
/*Clear Interrupt start state*/
GPIO_ClearITPendingBit(GPIOB, GPIO_Pin_4);
}
if(GPIO_GetITStatus(GPIOB, GPIO_Pin_3) == SET)
{
key3_flag = 1;
/*Clear Interrupt start state*/
GPIO_ClearITPendingBit(GPIOB, GPIO_Pin_3);
}
}
更多推荐


所有评论(0)