RISC-V MCU 应用教程之低功耗之睡眠模式
以RISC-V MCU CH32V307为例
睡眠模式下,所有的IO引脚都保持它们在运行模式时的状态。
所有的外设时钟都正常工作。进入睡眠前,尽量关闭无用的外设时钟,以降低功耗。
该模式唤醒所需的时间最短,几乎不耗时间,约 2~3 us。
此模式下,以144MHz运行时,使能所有外设时的睡眠电流约15.1mA,关闭所有外设的睡眠电流约4.1mA(除了唤醒中断引脚时钟和电源模块时钟)。
2. 进入睡眠模式
2.1 Sleep_Now模式
-
配置内核寄存器
PFIC_SCTLR控制位SLEEPDEEP=0 -
执行
WFI或WFE指令
2.2 Sleep_On_Exit模式
-
配置内核寄存器
PFIC_SCTLR控制位SLEEPDEEP=0 -
执行
WFI睡眠指令时,配置PFIC_SCTLR控制位SLEEPONEXIT=1,系统唤醒后控制器离开中断服务函数时,继续进入低功耗模式 -
执行
WFI指令
3. 退出睡眠模式
3.1 Sleep_Now模式
-
任意中断,具体可参考中断向量表
-
唤醒事件:
-
配置一个外部或内部EXTI线为事件模式,当CPU从WFE唤醒后,因为对应事件线的挂起位没有被置位,不必清除相应外设的中断挂起位或PFIC中断通道挂起位。
-
在外设的控制寄存器使能一个中断,但不在PFIC中使能,同时需要使能寄存器
PFIC_SCTLR控制位SEVONPEND。当CPU从WFE唤醒后,需要清除相应外设的中断挂起位或PFIC中断通道挂起位。
-
3.2 Sleep_On_Exit模式
-
任意中断,具体可参考中断向量表
4. 参考代码
1 #include "debug.h" 2 3 void wakeup_init(void) 4 { 5 GPIO_InitTypeDef GPIO_InitStructure = {0}; 6 EXTI_InitTypeDef EXTI_InitStructure = {0}; 7 8 RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA |RCC_APB2Periph_AFIO , ENABLE); 9 10 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; 11 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 12 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 13 GPIO_Init(GPIOA, &GPIO_InitStructure); 14 15 /* GPIOA.3 ----> EXTI_Line3 */ 16 GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource3); 17 EXTI_InitStructure.EXTI_Line = EXTI_Line3; 18 19 /* WFI - EXTI_Mode_Interrupt, WFE - EXTI_Mode_Event*/ 20 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; 21 22 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; 23 EXTI_InitStructure.EXTI_LineCmd = ENABLE; 24 EXTI_Init(&EXTI_InitStructure); 25 26 /* when configured as event, no need to enable NVIC */ 27 NVIC_SetPriority(EXTI3_IRQn,0x00); 28 NVIC_EnableIRQ(EXTI3_IRQn); 29 30 } 31 32 int main(void) 33 { 34 Delay_Init(); 35 USART_Printf_Init(256000); 36 37 wakeup_init(); 38 39 printf("ch32v307 sleep test\r\n"); 40 Delay_Ms(2000); 41 42 // NVIC->SCTLR |= (1<<1); /* set SLEEPONEXIT */ 43 // NVIC->SCTLR |= (1<<4); /* set SEVONPEND */ 44 45 /* wait for interrupt, wakeup pin configured as EXTI_Mode_Interrupt */ 46 __WFI(); 47 48 /* wait for event, wakeup pin configured as EXTI_Mode_Event */ 49 // __WFE(); 50 51 printf("wakeup\r\n"); 52 53 // printf("NVIC pending %ld\r\n",NVIC_GetPendingIRQ(EXTI3_IRQn)); 54 // printf("EXTI pend %d\r\n",EXTI_GetFlagStatus(EXTI3_IRQn)); 55 56 // NVIC_ClearPendingIRQ(EXTI3_IRQn); 57 // EXTI_ClearFlag(EXTI3_IRQn); 58 59 while(1) 60 { 61 printf("run in main loop\r\n"); 62 Delay_Ms(1000); 63 } 64 } 65 66 67 __attribute__((interrupt("WCH-Interrupt-fast"))) 68 void EXTI3_IRQHandler(void) 69 { 70 if(EXTI_GetITStatus(EXTI_Line3)!=RESET) 71 { 72 printf("exti3 interrupt\r\n"); 73 EXTI_ClearITPendingBit(EXTI_Line3); /* Clear Flag */ 74 } 75 }

浙公网安备 33010602011771号