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

电子说

1.4w人已加入

描述

一、电源管理模块 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 级;而唤醒后又能按优先级依次恢复各电源域供电,避免上电时序紊乱。

mcu

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 种,分别是正常模式、省电模式、睡眠模式和深度睡眠模式。其四种状态之间的转换如下图所示:

mcu

进入省电模式下,系统低频时钟运行(关闭 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 Statern" );

Systemclock_SRUN**_Init();**

User_Print_Init(115200);

Printf( "SRUN Statern" );

}

else

{

key3_cnt=0;

Printf( "Normal Statern");

Systemclock_Init();

User_Print_Init(115200);

Printf( "Normal Statern");

}

}

/ *

*** 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 寄存器读取唤醒信息,获取唤醒源。

注意:

mcu

mcu

*1:进入睡眠/深度睡眠前要确认唤醒寄存器状态是否清空,唤醒后要及时清除唤醒寄存器

*2:DeepSleep 唤醒:等效于系统软重启,程序从复位入口重新执行,片内常规 RAM数据完全丢失;关键数据需预先存入备份 RAM(Backup RAM)以实现掉电 / 深睡保留。

mcu

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

以下为进入唤醒睡眠模式流程图

mcu

mcu此图为我司提供的开发板对应电流3.62mA

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

mcu

mcu此图为我司提供的开发板对应电流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!rn");

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 %xrn", 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 %drn", power_status);

Printf( "DEEP SLEEP!rn");

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 %drn", power_status);

Printf( "SLEEP!rn");

PMU_PowerModeConfig(PMU_PowerMode_Sleep);

}

}

}

}

/ *

*** Function: PMU_WKFlagJudg**

*** Description: Wake up source status judgment.**

*** Param: None.**

*** Return: None.**

*/

voidPMU_WKFlagJudg(void)

{

Printf( "WKFR: 0x%x ! rn" , PMU->WKFR);

if(PMU_GetFlagStatus(PMU_FLAG_IWDGWK) == SET)

{

Printf( "IWDG wake up!rn");

PMU_ClearFlag(PMU_CLEAR_IWDGWKF);

}

if(PMU_GetFlagStatus(PMU_FLAG_RTCWK) == SET)

{

Printf( "RTC wake up!rn");

PMU_ClearFlag(PMU_CLEAR_RTCWKF);

}

if(PMU_GetFlagStatus(PMU_FLAG_PH0WK) == SET)

{

Printf( "PH0 wake up!rn");

PMU_ClearFlag(PMU_CLEAR_PH0WKF);

}

if(PMU_GetFlagStatus(PMU_FLAG_PH1WK) == SET)

{

Printf( "PH1 wake up!rn");

PMU_ClearFlag(PMU_CLEAR_PH1WKF);

}

if(PMU_GetFlagStatus(PMU_FLAG_PH2WK) == SET)

{

Printf( "PH2 wake up!rn");

PMU_ClearFlag(PMU_CLEAR_PH2WKF);

}

if(PMU_GetFlagStatus(PMU_FLAG_PH3WK) == SET)

{

Printf( "PH3 wake up!rn");

PMU_ClearFlag(PMU_CLEAR_PH3WKF);

}

if(PMU_GetFlagStatus(PMU_FLAG_PH4WK) == SET)

{

Printf( "PH4 wake up!rn");

PMU_ClearFlag(PMU_CLEAR_PH4WKF);

}

if(PMU_GetFlagStatus(PMU_FLAG_PH5WK) == SET)

{

Printf( "PH5 wake up!rn");

PMU_ClearFlag(PMU_CLEAR_PH5WKF);

}

if(PMU_GetFlagStatus(PMU_FLAG_PH6WK) == SET)

{

Printf( "PH6 wake up!rn");

PMU_ClearFlag(PMU_CLEAR_PH6WKF);

}

if(PMU_GetFlagStatus(PMU_FLAG_PH7WK) == SET)

{

Printf( "PH7 wake up!rn");

PMU_ClearFlag(PMU_CLEAR_PH7WKF);

}

if(PMU_GetFlagStatus(PMU_FLAG_PH8WK) == SET)

{

Printf( "PH8 wake up!rn");

PMU_ClearFlag(PMU_CLEAR_PH8WKF);

}

if(PMU_GetFlagStatus(PMU_FLAG_PH9WK) == SET)

{

Printf( "PH9 wake up!rn");

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 ! rn" , 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**

*/

voidFCUConfig(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);

}

}

审核编辑 黄宇

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分