AS32S601型MCU芯片电源管理(PMU)模块详解

一、电源管理模块 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 时钟),同时关闭未使用的时钟分支,减少时钟树的冗余功耗。

二、 特性

  1. 支持低功耗模式(SLEEP/DEEP_SLEEP/WAKEUP)的切换

  2. 支持唤醒源的配置(外部 IO/RTC/IWDG)

  3. 支持 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 等处于低功耗模式,要进入睡眠/深度睡眠模式,请遵循以下步骤:

  1. 读取唤醒信息:读取 PMU_WKP 寄存器,若有位为 1 则写 1 清除该位,若皆为 0 则进入下一步操作;

  2. 配置唤醒通道:将 PMU_WKEN 寄存器的对应唤醒通道配置为 1,其他通道配置为0;

  3. 保存备份信息:将需要备份的信息存储到 Bkp RAM 内;

  4. 配置睡眠模式:配置 PMU_MODE 寄存器的值,配置 1 进入深度睡眠模式,配置 2 进入睡眠模式;

  5. 系统将自动睡眠。 唤醒后,可通过 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);

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值