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

RTC周期唤醒问题:LSEON位

[复制链接]
江湖书生 提问时间: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没有时钟,不会工作。
江湖书生 回答时间:2017-12-5 14:31:22
安 发表于 2017-12-5 14:24
PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
RTC使用的LSE为时钟源,如果不开启,等于RTC没 ...

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

忘记说了,芯片是STM32L051。时钟源已经在RTC初始化过程配置过,而且实际试验也证实不是RTC时钟源选择导致的。
江湖书生 回答时间: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。
江湖书生 回答时间: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

查看全部评分

江湖书生 回答时间: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时钟源选择位)都正确,但就是不能唤醒。令人费解!!!
12下一页

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版