RISC-V MCU 应用教程之RTC自动唤醒
以RISC-V MCU CH32V307为例。 RTC,Real Time Clock,实时时钟,可以在不需要外部中断的情况下唤醒低功耗模式下的MCU。
RTC提供的定时闹钟事件,可以周期性的唤醒MCU。
1. RTC唤醒配置
RTC唤醒配置步骤如下:
-
配置RTC时钟
-
配置外部中断线17为上升沿触发
-
开启RTC闹钟事件中断
:::tip
详细的 RTC 配置可参考
:::
2. 参考代码
参考代码 - RTC唤醒停止模式
#include "debug.h" void rtc_exit17_init(void) { EXTI_InitTypeDef EXTI_InitStructure = {0}; EXTI_ClearITPendingBit(EXTI_Line17); EXTI_InitStructure.EXTI_Line = EXTI_Line17; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); NVIC_SetPriority(RTCAlarm_IRQn,0x00); NVIC_EnableIRQ(RTCAlarm_IRQn); } void rtc_init(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); PWR_BackupAccessCmd(ENABLE); /* enable LSI */ RCC_LSICmd(ENABLE); /* wait for LSI to stabilize */ while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET); /* select LSI as rtc clock */ RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); RCC_RTCCLKCmd(ENABLE); RTC_WaitForLastTask(); RTC_WaitForSynchro(); /* enable Alarm interrupt */ RTC_ITConfig(RTC_IT_ALR, ENABLE); RTC_WaitForLastTask(); /* set rtc prescaler value */ RTC_SetPrescaler(32767); RTC_WaitForLastTask(); } int main(void) { /* Configure unused GPIO as IPD to reduce power consumption */ GPIO_InitTypeDef GPIO_InitStructure = {0}; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB| RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOE, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_Init(GPIOD, &GPIO_InitStructure); GPIO_Init(GPIOE, &GPIO_InitStructure); /***************************************/ Delay_Init(); USART_Printf_Init(256000); rtc_init(); rtc_exit17_init(); printf("ch32v307 stop mode wakeup by rtc test\r\n"); Delay_Ms(2000); /* set alarm event after 5s */ RTC_SetAlarm(RTC_GetCounter()+5); RTC_WaitForLastTask(); /* set SLEEPONEXIT */ NVIC->SCTLR |= (1<<1); /* set regulator in low power mode,need enable rcc of pwr */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI); SystemInit(); printf("wakeup\r\n"); while(1) { printf("run in main loop\r\n"); Delay_Ms(1000); } } __attribute__((interrupt("WCH-Interrupt-fast"))) void RTCAlarm_IRQHandler(void) { EXTI_ClearITPendingBit(EXTI_Line17); RTC_ClearITPendingBit(RTC_IT_ALR); if(PWR_GetFlagStatus(PWR_FLAG_WU) != RESET) { /* clear wakeup flag */ PWR_ClearFlag(PWR_FLAG_WU); } SystemInit(); printf("RTCAlarm_IRQHandler\r\n"); /* set alarm event after 5s */ RTC_SetAlarm(RTC_GetCounter()+5); RTC_WaitForLastTask(); }
参考代码 - RTC唤醒待机模式
#include "debug.h" void rtc_exit17_init(void) { EXTI_InitTypeDef EXTI_InitStructure = {0}; EXTI_ClearITPendingBit(EXTI_Line17); EXTI_InitStructure.EXTI_Line = EXTI_Line17; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); } void rtc_init(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); PWR_BackupAccessCmd(ENABLE); /* enable LSI */ RCC_LSICmd(ENABLE); /* wait for LSI to stabilize */ while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET); /* select LSI as rtc clock */ RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); RCC_RTCCLKCmd(ENABLE); RTC_WaitForLastTask(); RTC_WaitForSynchro(); /* enable Alarm interrupt */ RTC_ITConfig(RTC_IT_ALR, ENABLE); RTC_WaitForLastTask(); /* set rtc prescaler value */ RTC_SetPrescaler(32767); RTC_WaitForLastTask(); } int main(void) { /* Configure unused GPIO as IPD to reduce power consumption */ GPIO_InitTypeDef GPIO_InitStructure = {0}; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB| RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOE, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_Init(GPIOD, &GPIO_InitStructure); GPIO_Init(GPIOE, &GPIO_InitStructure); /***************************************/ Delay_Init(); USART_Printf_Init(256000); rtc_init(); rtc_exit17_init(); printf("ch32v307 standby mode wakeup by rtc test\r\n"); Delay_Ms(2000); /* set alarm event after 5s */ RTC_SetAlarm(RTC_GetCounter()+5); RTC_WaitForLastTask(); /* set PWR register, need enable rcc of pwr */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); /* standby mode, mcu will reset after wakeup event */ PWR_EnterSTANDBYMode(); printf("wakeup\r\n"); while(1) { printf("run in main loop\r\n"); Delay_Ms(1000); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律