完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
用得是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(); LPtiM_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(); } |
|
相关推荐
12个回答
|
|
PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
RTC使用的LSE为时钟源,如果不开启,等于RTC没有时钟,不会工作。 |
|
|
|
TOPCB 发表于 2018-12-17 14:29 忘记说了,芯片是STM32L051。时钟源已经在RTC初始化过程配置过,而且实际试验也证实不是RTC时钟源选择导致的。 |
|
|
|
TOPCB 发表于 2018-12-17 14:29 忘记说了,芯片是STM32L051。时钟源已经在RTC初始化过程配置过,而且实际试验也证实不是RTC时钟源选择导致的。 |
|
|
|
TOPCB 发表于 2018-12-17 14:29 不是这个原因,RTC时钟源选择已经在RTC初始化函数中配置过。 |
|
|
|
|
|
|
|
本帖最后由 江湖书生 于 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,周期唤醒就会生效。按理说不需要这样操作。 |
|
|
|
这里是配置时钟的,如果不配置,LSE就不能开启,这样就不能给RTC提供时钟源。
|
|
|
|
看到了吗,assert_param第一个就等着你,不设置直接退出。
|
|
|
|
在上电复位时会执行一次LSE开启操作,也就是置位LSEON位(该位在RCC->CSR寄存器中),后面的待机唤醒(系统复位)不再执行LSE开启操作。这么考虑的原因是:RCC->CSR寄存器归属备份域,待机唤醒后的复位不影响RCC->CSR寄存器,程序试验也确实是如此。但奇怪得是:虽然RCC->CSR寄存器中的LSEON(LSE使能控制位)和RTCSEL(RTC时钟源选择位)都正确,但就是不能唤醒。令人费解!!! |
|
|
|
1.没有启用参数检查,实际没什么作用。 2.每次复位(上电复位或待机唤醒后复位)都会执行系统时钟配置,在其配置程序中给RCC_OscInitStruct传递参数时不会设置RCC_OSCILLATORTYPE_LSE参数,也就是不管怎样,HAL_RCC_OscConfig函数中关于LSE配置的代码是不会执行的。 |
|
|
|
如果不确定,打印出相关寄存器的值。如果不唤醒,看一下唤醒中断标志位是否清除。
|
|
|
|
问题绕过去了----周期唤醒每次延后一秒,实际是设置唤醒周期错误导致的。至于每次复位后必须使能LSE,好像是必须的(实际上待机唤醒后RCC->CSR寄存器中的LSEON位一直是1),似乎是个芯片bug。
谢谢各位! |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
1307 浏览 1 评论
AD7686芯片不传输数据给STM32,但是手按住就会有数据。
1234 浏览 3 评论
2313 浏览 0 评论
如何解决MPU-9250与STM32通讯时,出现HAL_ERROR = 0x01U
1404 浏览 1 评论
hal库中i2c卡死在HAL_I2C_Master_Transmit
1834 浏览 1 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-30 03:22 , Processed in 0.917529 second(s), Total 93, Slave 78 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号