打印
[STM32F0]

STM32F0 USART唤醒STOP模式

[复制链接]
2648|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
最近考虑使用STM32F030/042系列做些低功耗的产品,比如车载导航配对的433/315拷贝型遥控器,需要串口通信和STOP模式。

但是遇到比较蛋疼坑爹的事情是,STM32F0系列自带的串口唤醒功能不支持030/042系列,如下:

#define EXTI_Line25      ((uint32_t)0x02000000)  /*!< Internal interrupt line 25
                                                      Connected to the USART1 wakeup
                                                      event, not applicable for STM32F030 devices */
#define EXTI_Line26      ((uint32_t)0x04000000)  /*!< Internal interrupt line 26
                                                      Connected to the USART2 wakeup
                                                      event, applicable only for
                                                      STM32F072 devices */

然后这就TMD蛋疼了,又得按照以前的方式,在休眠之前把RX设置为中断输入脚;被中断唤醒之后,恢复为RX功能。这样操作起来就是不方面,而且容易丢失好几个字节的数据。

//================================================================================================================

/****************************************************************************************
** 函数名称: STM32F030_STOP(void)
** 功能描述: 设置RTC、RX中断唤醒STOP模式
** 参    数:     void
** 返 回 值:   void
** 日   期: 2017年02月27日
**---------------------------------------------------------------------------------------

**--------------------------------------------------------------------------------------
****************************************************************************************/

void STM32F030_STOP(void)

{

RCC_Close();//关闭全部时钟,GPIO设为AN输入
RTC_Config(WAKUP_10S0);//设置RTC唤醒周期,10S
EXIT_Control(INT_RTC_WKP,ENABLE);//RTC中断
EXIT_Control(INT_RX_FALL,ENABLE);//USART-RX中断
while(1)  
{
IWDG_ReloadCounter();//清狗------ IWDG周期12S
WakeupByRx=0;//在USART-RX中断里面置为1
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);//进入低功耗模式,并通过RTC定期唤醒
if(WakeupByRx==1)
break;
}
EXIT_Control(INT_RTC_WKP,DISABLE);//关闭RTC中断
EXIT_Control(INT_RX_FALL,DISABLE);//关闭USART-RX中断

//接下来恢复系统时钟及USART设置等。。。。。。。。。。。。。。。。

}

//================================================================================================================

为什么要两种唤醒方式?因为实际需要,软件一般都要开启看门狗IWDG,而进入STOP模式后IWDG其实还是一直在计数的,如果不定期清除容易被IWDG重启。所以STOP模式的唤醒方式其实有两个:RTC事件+RX中断。


这种方式有个缺点就是容易丢失串口数据,但如果对于数据很多不怕丢几串数据的我来说,这根本不是事儿~~


沙发
幸福小强|  楼主 | 2018-5-13 20:07 | 只看该作者
相信这种应用,很多人会用到吧

使用特权

评论回复
板凳
幸福小强|  楼主 | 2018-5-13 20:09 | 只看该作者
再发个F103的

STOP状态下通过串口唤醒MCU
/*
STOP状态下通过串口唤醒MCU
唤醒机制:在MCU进入STOP状态后,不能直接通过UART等外设唤醒,
在MCU进入STOP前将RX脚设为EXTI模式,并使能对应的中断。
*/
/***************************************************************************************
** 函数名称: main
** 功能描述: 起始入口
** 参    数: None
** 返 回 值: None      
**--------------------------------------------------------------------------------------
** 修 改 人:
** 日   期:
**--------------------------------------------------------------------------------------
****************************************************************************************/
int main(void)
{
System_Init();
PWR_DeInit();
UART_Init();
Global_Variables_Init();
while(1)
{
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
}
}
/***************************************************************************************
** 函数名称: EXTIX_Init
** 功能描述: 把RX改为EXTI,允许中断
** 参    数: None
** 返 回 值: None  
**--------------------------------------------------------------------------------------
** 修 改 人:
** 日   期:
**--------------------------------------------------------------------------------------
****************************************************************************************/
void EXTIX_Init(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource11);
EXTI_InitStructure.EXTI_Line=EXTI_Line11;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}


/*******************************************************************************
* Function Name : EXTI15_10_IRQHandler
* Description : 位于stm32f10x_it.c
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void EXTI15_10_IRQHandler(void)
{
EXTI_ClearITPendingBit(EXTI_Line11);
NVIC_GenerateSystemReset();
}
/***************************************************************************************
** 函数名称: PWR_EnterSTOPMode
** 功能描述: 调整寄存器,进入STOP模式
** 参    数:
** 返 回 值: None      
**--------------------------------------------------------------------------------------
** 修 改 人:
** 日   期:
**--------------------------------------------------------------------------------------
****************************************************************************************/
void PWR_EnterSTOPMode(u32 PWR_Regulator, u8 PWR_STOPEntry)
{
u32 tmpreg = 0;
EXTIX_Init();


/* Select the regulator state in STOP mode ---------------------------------*/
tmpreg = PWR->CR;
/* Clear PDDS and LPDS bits */
tmpreg &= CR_DS_Mask;
/* Set LPDS bit according to PWR_Regulator value */
tmpreg |= PWR_Regulator;
/* Store the new value */
PWR->CR = tmpreg;
/* Set SLEEPDEEP bit of Cortex System Control Register */
*(vu32 *) SCB_SysCtrl |= SysCtrl_SLEEPDEEP_Set;
/* Select STOP mode entry --------------------------------------------------*/
if(PWR_STOPEntry == PWR_STOPEntry_WFI)
{
/* Request Wait For Interrupt */
__WFI();
}
else
{
/* Request Wait For Event */
__WFE();
}
}
/***************************************************************************************
** 函数名称: UART_Init
** 功能描述: 串口初始化
** 参    数: None
** 返 回 值: None      
**--------------------------------------------------------------------------------------
** 修 改 人:
** 日   期:
**--------------------------------------------------------------------------------------
****************************************************************************************/
void UART_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable USART3 clock */
RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART3, ENABLE);
// GPIO Settings for USART3
// PB10: TXD_ROOM
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// PB11: RXD_ROOM
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
//GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);


USART_DeInit(USART3);
USART_InitStructure.USART_BaudRate =9600;
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
USART_InitStructure.USART_StopBits = USART_StopBits_2;
USART_InitStructure.USART_Parity = USART_Parity_Even;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART3, &USART_InitStructure);
UartRxON();
// In initial state, waiting for indoor data...
USART_ITConfig(USART3, USART_IT_TXE, DISABLE);
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
UART_State=UART_RX; //0; // 0: received state 1: transmit state
/* Enable the USART3 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Enable USART3 */
USART_Cmd(USART3, ENABLE);
}

使用特权

评论回复
地板
dongnanxibei| | 2018-5-13 22:28 | 只看该作者
电池应用类的,这个方法确实好。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

107

主题

1415

帖子

2

粉丝