用得是
STM32L051 按参考手册描述,RCC的CSR寄存器不受系统复位(待机唤醒)影响。现在遇到的问题是,如果每次复位初始化过程中不设置LSEON位(RCC->CSR中),RTC的周期唤醒功能会失效,不知道什么原因?反复看程序也看不出什么毛病,请行家给点指点! 如果每次复位(退出待机)初始化过程中都设置一下LSEON位(通过库函数配置LSE振荡器使能),周期唤醒功能确实有效,每次唤醒后输出RTC时间和采样数据,前后对比会发现每个唤醒周期会延迟1秒,直观的感觉就是:每次唤醒导致RTC暂停了1秒,因此想到是不是每次初始化都设置LSEON位导致的。如果仅在上电初始化过程中设置一次LSEON位,周期唤醒失效,但实际上LSEON位和RTCSEL(RTC时钟选择位)都是正确的(通过串口输出RCC->CSR寄存器)。
主要代码如下:
//--主函数--
int main(void)
{
//外设初始化
HAL_Init();
Power_Config();
Clock_Config();
RTC_Init();
GPIO_Init();
LPUART1_UART_Init();
USART1_UART_Init();
LP
tiM_Init();
CRC_Init();
//检查是否从待机状态唤醒
if(__HAL_PWR_GET_FLAG(PWR_FLAG_SB))
{
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hRTC,RTC_FLAG_WUTF);
}
//等待调压器就绪
while(__HAL_PWR_GET_FLAG(PWR_FLAG_REGLP));
while(1)
{
//任务处理
SystemSleep();
}
}
//RTC初始化
static void RTC_Init(void)
{
uint32_t u32Tmp;
RTC_TimeTypeDef sTime;
RTC_DateTypeDef sDate;
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInit;
hRTC.Instance=RTC;
u32Tmp=HAL_RTCEx_BKUPRead(&hRTC,RTC_BKP_DR0);
if(!(u32Tmp & sta_PowerInitial))//检查是否上电初始状态
{
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;
PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
if(HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE; //如果把LSE开启代码移到if判断外
RCC_OscInitStruct.LSEState = RCC_LSE_ON; //即每次都进行 LSE开启操作
if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) //唤醒生效,否则只能生效一次
{
_Error_Handler(__FILE__, __LINE__);
}
hRTC.Init.HourFormat = RTC_HOURFORMAT_24;
hRTC.Init.AsynchPrediv = 127;
hRTC.Init.SynchPrediv = 255;
hRTC.Init.OutPut = RTC_OUTPUT_DISABLE;
hRTC.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
hRTC.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
hRTC.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
if (HAL_RTC_Init(&hRTC) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
//设置RTC起始时间=17-12-01 00:00:00 星期五
sTime.Hours = 0x0;
sTime.Minutes = 0x0;
sTime.Seconds = 0x0;
sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE; //须保留
sTime.StoreOperation = RTC_STOREOPERATION_RESET; //须保留
if (HAL_RTC_SetTime(&hRTC, &sTime, RTC_FORMAT_BIN) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sDate.Year = 17;
sDate.Month = 12;
sDate.Date = 1;
sDate.WeekDay = 5;
if (HAL_RTC_SetDate(&hRTC, &sDate, RTC_FORMAT_BIN) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
//设置上电初始完成标志和等待配置标志
u32Tmp|=(sta_PowerInitial | sta_WaitConfig);
HAL_RTCEx_BKUPWrite(&hRTC,RTC_BKP_DR0,u32Tmp);
}
}
//待机函数
void SystemSleep(void)
{
uint32_t u32WorkMode;
if(RTC->CR & (RTC_CR_WUTE|RTC_CR_WUTIE))//唤醒定时器已启动
{
//__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hRTC,RTC_FLAG_WUTF);
__HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_IT();
__HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_RISING_EDGE();
}
else
{
if(u32WorkMode & 0x02000000)
HAL_RTCEx_SetWakeUpTimer_IT(&hRTC,u32WorkMode&0xFFFF,RTC_WAKEUPCLOCK_CK_SPRE_17BITS);
else
HAL_RTCEx_SetWakeUpTimer_IT(&hRTC, u32WorkMode&0xFFFF, RTC_WAKEUPCLOCK_CK_SPRE_16BITS);
}
HAL_PWR_EnterSTANDBYMode();
}
本帖最后由 江湖书生 于 2017-12-5 16:40 编辑
这里的设置是指开启LSE。源代码如下
//**Initializes the CPU, AHB and APB busses clocks
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;//|RCC_OSCILLATORTYPE_LSE;
//RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSICalibrationValue = 0;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}如果把上代码中的注释部分恢复(生效),即每次复位初始化都开启一下LSE,周期唤醒就会生效。按理说不需要这样操作。
一周热门 更多>