STM32L0 进入STOP模式后串口中断方式唤醒

实现功能:单片机以一定的采样频率(如2Khz)进行采样,例如每分钟(60s)只采前30s,后30s休眠(定时休眠唤醒),等到下一分钟再自动wakeup,如此循环30分钟。30分钟之后,单片机进入休眠stop模式。用串口中断的方式将休眠的单片机唤醒。

实现方法:

1、定时休眠唤醒code

HAL_Delay(2000);//进行采样的时间
HAL_RTCEx_DeactivateWakeUpTimer(&RTCHandle);
HAL_RTCEx_SetWakeUpTimer_IT(&RTCHandle, 2, RTC_WAKEUPCLOCK_RTCCLK_DIV16);
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);//调用库函数进入STOP模式
SystemClockConfig_STOP();//停机模式后唤醒,恢复时钟源
count1++;
while(count1==1)//循环的次数
{
Rx_Init();
count1=0;
flag3=0;
__HAL_RTC_ALARM_DISABLE_IT(&RTCHandle, RTC_IT_ALRA);
__HAL_RTC_ALARM_CLEAR_FLAG(&RTCHandle, RTC_IT_ALRA);
HAL_TIM_Base_Stop(&TimHandle);   //定时器停止
HAL_RTCEx_DeactivateWakeUpTimer(&RTCHandle);
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);//调用库函数进入STOP模式
}
计算方法:例如休眠4s
/*  RTC Wakeup Interrupt Generation:
Wakeup Time Base = (RTC_WAKEUPCLOCK_RTCCLK_DIV /(LSE or LSI))
Wakeup Time = Wakeup Time Base * WakeUpCounter
= (RTC_WAKEUPCLOCK_RTCCLK_DIV /(LSE or LSI)) * WakeUpCounter
==> WakeUpCounter = Wakeup Time / Wakeup Time BaseTo configure the wake up timer to 4s the WakeUpCounter is set to 0x1FFF:
RTC_WAKEUPCLOCK_RTCCLK_DIV = RTCCLK_Div16 = 16
Wakeup Time Base = 16 /(~39.000KHz) = ~0,410 ms
Wakeup Time = ~4s = 0,410ms  * WakeUpCounter
==> WakeUpCounter = ~4s/0,410ms = 9750 = 0x2616 */
HAL_RTCEx_SetWakeUpTimer_IT(&RTCHandle, 0x2616, RTC_WAKEUPCLOCK_RTCCLK_DIV16);

局限性:用内部时钟LSI,大小固定导致Wakeup Time Base 被限制。 Wakeup Time(最大)=0.41ms*65535(0xffff)=26.869s,可能达不到休眠时间要求。

另一种方法:改HAL_RTCEx_SetWakeUpTimer_IT(&RTCHandle, 2, RTC_WAKEUPCLOCK_CK_SPRE_16BITS);

这里RTC_WAKEUPCLOCK_CK_SPRE_16BITS是设置CR寄存器中的低三位,唤醒时钟选择,这里选择1hz,2表示工作2S后进入唤醒中断,这个数随便改,改成多少就是休眠多少时间。

2、串口中断唤醒

唤醒机制:在MCU进入STOP状态后,不能直接通过UART等外设唤醒,在MCU进入STOP前将RX脚设为EXTI模式,并使能对应的中断。唤醒后重新初始化串口、配置时钟。(这里贴两份代码,一份是我参考的百战天虫的code,另一份我自己的)

by:百战天虫

void Rx_Init()
{
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_GPIOA_CLK_ENABLE();
  // 配置UART1的Rx引脚为EXIT模式
  GPIO_InitStruct.Pin = USARTx_RX_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; // 特别注意这里要使用中断模式
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(USARTx_TX_GPIO_PORT, &GPIO_InitStruct);
  HAL_NVIC_SetPriority(EXTI4_15_IRQn, 2, 0);
  HAL_NVIC_EnableIRQ(EXTI4_15_IRQn);
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin==USARTx_RX_PIN)
{
//  HAL_NVIC_EnableIRQ(SysTick_IRQn);
SystemClockConfig_STOP();//停机模式后唤醒,恢复时钟源
HAL_Init();
SystemClock_Config();
SystemPower_Config();
HAL_SPI_DeInit(&hspi1);
HAL_GPIO_DeInit(GPIOA,GPIO_PIN_10);//串口重新初始化时HAL_UART_Init()函数会判断if(huart->State == HAL_UART_STATE_RESET),此时才会执行HAL_UART_MspInit(huart),配置串口IO口,这句话必须有!
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
SPI_GPIO_Init();
UartHandle.Instance        = USARTx;
UartHandle.Init.BaudRate   = uart_baud;
UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
UartHandle.Init.StopBits   = UART_STOPBITS_1;
UartHandle.Init.Parity     = UART_PARITY_NONE;
UartHandle.Init.HwFlowCtl  = UART_HWCONTROL_NONE;
UartHandle.Init.Mode       = UART_MODE_TX_RX;
GPIO_InitTypeDef  GPIO_InitStruct;
/*##-1- Enable peripherals and GPIO Clocks #################################*/
/* Enable GPIO TX/RX clock */
USARTx_TX_GPIO_CLK_ENABLE();
USARTx_RX_GPIO_CLK_ENABLE();
/* Enable USART2 clock */
USARTx_CLK_ENABLE();
/*##-2- Configure peripheral GPIO ##########################################*/
/* UART TX GPIO pin configuration  */
GPIO_InitStruct.Pin       = USARTx_TX_PIN;
GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull      = GPIO_NOPULL;
GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_HIGH  ;
GPIO_InitStruct.Alternate = USARTx_TX_AF;
HAL_GPIO_Init(USARTx_TX_GPIO_PORT, &GPIO_InitStruct);
/* UART RX GPIO pin configuration  */
GPIO_InitStruct.Pin = USARTx_RX_PIN;
GPIO_InitStruct.Alternate = USARTx_RX_AF;
HAL_GPIO_Init(USARTx_RX_GPIO_PORT, &GPIO_InitStruct);
HAL_NVIC_DisableIRQ(EXTI4_15_IRQn);
__HAL_GPIO_EXTI_CLEAR_IT(USARTx_RX_PIN);
HAL_NVIC_SetPriority(USARTx_IRQn, 4, 0);
HAL_NVIC_EnableIRQ(USARTx_IRQn);
}
}

结束!

最后贴上硬石的按键唤醒,很有参考价值!

http://www.ing10bbs.com/forum.php?mod=viewthread&tid=244&extra=page%3D2%26filter%3Dlastpost%26orderby%3Dlastpost%26typeid%3D11

STM32L051C8T6是一款低功耗的32位微控制器,具有丰富的外设接口和强大的计算能力。其中的Stop模式是一种低功耗模式,可以通过按键和串口唤醒。 在Stop模式下,微控制器的主频停止工作,但由于内部的RTC(实时时钟)仍然工作,因此可以通过定时器或外部中断来保持唤醒功能。本文主要介绍通过按键和串口唤醒的实现方法。 首先,通过按键来唤醒。在Stop模式下,可以配置一个外部中断引脚作为唤醒源,使按键按下时产生中断信号。通过配置外部中断的触发方式为上升或下降沿触发,设置中断优先级,并使能中断,当按键按下时,中断引脚会产生中断信号,使芯片从Stop模式唤醒并执行相应的中断服务程序。 其次,通过串口唤醒。在Stop模式下,可以配置串口的特殊唤醒功能,使能串口唤醒功能,并设置相应的触发条件。例如,可以设置当串口接收到特定的数据或位变化时触发唤醒。当满足特定的条件时,串口会产生唤醒信号,使芯片从Stop模式唤醒并执行相应的处理程序。 以上就是使用STM32L051C8T6的Stop模式实现按键和串口唤醒的简要介绍。具体的实现方法需要根据具体的应用场景和需求进行详细的配置和编程。通过合理配置外部中断串口唤醒功能,可以实现低功耗的同时保持按键和串口唤醒功能,提高系统的灵活性和响应速度。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值