请选择 进入手机版 | 继续访问电脑版

你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

RTC周期唤醒问题:LSEON位

[复制链接]
abc5504@139.com 提问时间:2017-12-5 14:00 /
本帖最后由 江湖书生 于 2017-12-5 14:29 编辑

用得是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 发布时间:2017-12-5 14:00

举报

12个回答
废鱼 回答时间:2017-12-5 14:24:19
PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
RTC使用的LSE为时钟源,如果不开启,等于RTC没有时钟,不会工作。
abc5504@139.com 回答时间:2017-12-5 14:31:22
安 发表于 2017-12-5 14:24
PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
RTC使用的LSE为时钟源,如果不开启,等于RTC没 ...

忘记说了,芯片是STM32L051。时钟源已经在RTC初始化过程配置过,而且实际试验也证实不是RTC时钟源选择导致的。
abc5504@139.com 回答时间:2017-12-5 14:32:15
安 发表于 2017-12-5 14:24
PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
RTC使用的LSE为时钟源,如果不开启,等于RTC没 ...

忘记说了,芯片是STM32L051。时钟源已经在RTC初始化过程配置过,而且实际试验也证实不是RTC时钟源选择导致的。
abc5504@139.com 回答时间:2017-12-5 14:35:09
安 发表于 2017-12-5 14:24
PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
RTC使用的LSE为时钟源,如果不开启,等于RTC没 ...

不是这个原因,RTC时钟源选择已经在RTC初始化函数中配置过。
废鱼 回答时间:2017-12-5 16:00:30
如果每次复位初始化过程中不设置LSEON位(RCC->CSR中),RTC的周期唤醒功能会失效。
这里,RCC配置的是开启或者关闭LSE。
abc5504@139.com 回答时间:2017-12-5 16:38:47
本帖最后由 江湖书生 于 2017-12-5 16:40 编辑
安 发表于 2017-12-5 16:00
如果每次复位初始化过程中不设置LSEON位(RCC->CSR中),RTC的周期唤醒功能会失效。
这里,RCC配置的是开启 ...

这里的设置是指开启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,周期唤醒就会生效。按理说不需要这样操作。

废鱼 回答时间:2017-12-5 16:48:41
这里是配置时钟的,如果不配置,LSE就不能开启,这样就不能给RTC提供时钟源。
kylongmu 回答时间:2017-12-5 17:04:18
  1.                 RCC_OscInitStruct.LSEState = RCC_LSE_ON;                                        //即每次都进行        LSE开启操作
  2.                 if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)                        //唤醒生效,否则只能生效一次        
  3.                 {
  4.                         _Error_Handler(__FILE__, __LINE__);
  5.                 }
  6.                
复制代码
进到HAL_RCC_OscConfig里面看:
  1.   /*------------------------------ LSE Configuration -------------------------*/
  2.   if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE)
  3.   {
  4.     /* Check the parameters */
  5.     assert_param(IS_RCC_LSE(RCC_OscInitStruct->LSEState));
复制代码
看到了吗,assert_param第一个就等着你,不设置直接退出。

评分

参与人数 1ST金币 +5 收起 理由
zero99 + 5

查看全部评分

abc5504@139.com 回答时间:2017-12-5 19:56:11
安 发表于 2017-12-5 16:48
这里是配置时钟的,如果不配置,LSE就不能开启,这样就不能给RTC提供时钟源。 ...

在上电复位时会执行一次LSE开启操作,也就是置位LSEON位(该位在RCC->CSR寄存器中),后面的待机唤醒(系统复位)不再执行LSE开启操作。这么考虑的原因是:RCC->CSR寄存器归属备份域,待机唤醒后的复位不影响RCC->CSR寄存器,程序试验也确实是如此。但奇怪得是:虽然RCC->CSR寄存器中的LSEON(LSE使能控制位)和RTCSEL(RTC时钟源选择位)都正确,但就是不能唤醒。令人费解!!!
abc5504@139.com 回答时间:2017-12-5 20:16:34
本帖最后由 江湖书生 于 2017-12-6 19:44 编辑
kylongmu 发表于 2017-12-5 17:04
进到HAL_RCC_OscConfig里面看:
看到了吗,assert_param第一个就等着你,不设置直接退出。
...

1.没有启用参数检查,实际没什么作用。
2.每次复位(上电复位或待机唤醒后复位)都会执行系统时钟配置,在其配置程序中给RCC_OscInitStruct传递参数时不会设置RCC_OSCILLATORTYPE_LSE参数,也就是不管怎样,HAL_RCC_OscConfig函数中关于LSE配置的代码是不会执行的。
废鱼 回答时间:2017-12-6 08:54:05
如果不确定,打印出相关寄存器的值。如果不唤醒,看一下唤醒中断标志位是否清除。
abc5504@139.com 回答时间:2017-12-6 19:55:25
问题绕过去了----周期唤醒每次延后一秒,实际是设置唤醒周期错误导致的。至于每次复位后必须使能LSE,好像是必须的(实际上待机唤醒后RCC->CSR寄存器中的LSEON位一直是1),似乎是个芯片bug。
谢谢各位!

评分

参与人数 1ST金币 +2 收起 理由
zero99 + 2 结贴奖励

查看全部评分

所属标签

相似问题

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版