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

STM32L151 stop模式 rtc 闹钟唤醒不稳定

[复制链接]
firstwangjin 提问时间:2018-5-22 20:47 /
本帖最后由 firstwangjin 于 2018-5-24 11:26 编辑

1.芯片 stm32l151CBT6

2.使用 cubemx 生成的框架代码。

芯片工作一会儿进入 stop模式,到某个时刻点闹钟唤醒。发现经常有设备到闹钟点没有醒来。


//时钟B 延时minutes后唤醒
void setMinuteDelayAlarmB(RTC_TimeTypeDef sTime,uint8_t minutes)
{   
  ...
  if(HAL_RTC_SetAlarm_IT(&hrtc,&sAlarm,RTC_FORMAT_BIN) != HAL_OK)
  {
    /* Initialization Error */
    Error_Handler();
  }   
  HAL_NVIC_SetPriority(RTC_Alarm_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);
}


//rtc 中断许可

  HAL_NVIC_SetPriority(RTC_Alarm_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);



上面是我写的alarm 设置唤醒,关于alarm 事件的配置省略了。

HAL_RTC_SetAlarm_IT 是库函数,

就可以完成 ALARM 对STOP模式的唤醒。

目前的问题是,有时候alarm 唤醒会失效


详细如下
1.Rtc 使用外部时钟

void SystemClock_Config(void)
{

RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInit;


   __HAL_RCC_PWR_CLK_ENABLE();
    /**Configure the main internal regulator output voltage
    */
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);


    /**Initializes the CPU, AHB and APB busses clocks
    */
//RCC_OSCILLATORTYPE_HSI 是為了ADC 使用
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE|RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSICalibrationValue = 0;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_5;

RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
    _Error_Handler(__FILE__, __LINE__);
}


    /**Initializes the CPU, AHB and APB busses clocks
    */
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;


if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
    _Error_Handler(__FILE__, __LINE__);
}


PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;
PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
    _Error_Handler(__FILE__, __LINE__);
}


    /**Configure the Systick interrupt time
    */
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);


    /**Configure the Systick
    */
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);


/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}



* RTC init function */
static void MX_RTC_Init(void)
{
__HAL_RCC_PWR_CLK_ENABLE();

RTC_TimeTypeDef sTime;
RTC_DateTypeDef sDate;
RTC_AlarmTypeDef sAlarm;


    /**Initialize RTC Only
    */
hrtc.Instance = RTC;
hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
hrtc.Init.AsynchPrediv = 127;
hrtc.Init.SynchPrediv = 255;
hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
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__);
}

    /**Initialize RTC and set the Time and Date
    */
if(HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR0) != 0x32F2)
{
sTime.Hours = 19;
sTime.Minutes = 34;
sTime.Seconds = 30;
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.WeekDay = 1;
sDate.Month = 4;
sDate.Date = 25;
sDate.Year = 18;


if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) != HAL_OK)
{
    _Error_Handler(__FILE__, __LINE__);
}


    HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR0,0x32F2);
}

/**Enable the WakeUp
    */
if (HAL_RTCEx_SetWakeUpTimer(&hrtc, 0, RTC_WAKEUPCLOCK_RTCCLK_DIV16) != HAL_OK)
{
    _Error_Handler(__FILE__, __LINE__);
}

}


2.每隔3分钟调用下面函数,设定新的timer Wakeup 用来切换工作

void setMinuteAlarmA(RTC_TimeTypeDef sTime,uint8_t minuteInterval)
{
    /**Enable the Alarm A
*/

RTC_AlarmTypeDef sAlarm;
sAlarm.AlarmTime = sTime;
sAlarm.AlarmTime.Seconds = 10;


uint8_t minuteMaxBit = (60/minuteInterval) - 1;
//设置分钟
uint8_t minuteBit = sAlarm.AlarmTime.Minutes/minuteInterval;
if(minuteBit == minuteMaxBit)
{
    sAlarm.AlarmTime.Minutes = 0;
   
    //考虑小时位升级
    if(sAlarm.AlarmTime.Hours ==23) //23点后是0点
    {
      sAlarm.AlarmTime.Hours = 0;
    }
    else//否则小时位进1
    {
       sAlarm.AlarmTime.Hours++;
    }
}
else
{
    minuteBit++;
    sAlarm.AlarmTime.Minutes = minuteBit*minuteInterval;
}


sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
sAlarm.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY;
sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_WEEKDAY;
sAlarm.AlarmDateWeekDay = 1;
sAlarm.Alarm = RTC_ALARM_A;
if(HAL_RTC_SetAlarm_IT(&hrtc,&sAlarm,RTC_FORMAT_BIN) != HAL_OK)
{
    /* Initialization Error */
    Error_Handler();
}

HAL_NVIC_SetPriority(RTC_Alarm_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);
}


void enterSotpMode()
{
  GPIO_InitTypeDef GPIO_InitStruct;
  
  __HAL_RCC_PWR_CLK_ENABLE();    /* Enable Power Control clock */
  HAL_PWREx_EnableUltraLowPower();  /* Enable Ultra low power mode */
  HAL_PWREx_EnableFastWakeUp(); /* Enable the fast wake up from Ultra low power mode */   
  
  SX1278LoRaSetOpMode( RFLR_OPMODE_SLEEP );
  
  GPIO_InitStruct.Pin = 0xF9ff;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);  

  GPIO_InitStruct.Pin = GPIO_PIN_3;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);  
  
  //d
  GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_8;
  GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  
  //  
  //GPIO_InitStruct.Pin = 0xFfFf;
  GPIO_InitStruct.Pin = 0xFf3f;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  //PBOOT0 低电平
  GPIO_InitStruct.Pin = GPIO_PIN_4;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  

  GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14;
  GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);


  GPIO_InitStruct.Pin = GPIO_PIN_All;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
  
  GPIO_InitStruct.Pin = GPIO_PIN_13;
  GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  
  
  
  //20180515
    /*Configure GPIO pin : PA8 */
  GPIO_InitStruct.Pin = GPIO_PIN_8;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.Alternate = GPIO_AF0_MCO;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  
  
  //__HAL_RCC_GPIOA_CLK_DISABLE();
  __HAL_RCC_GPIOB_CLK_DISABLE();  
  //__HAL_RCC_GPIOC_CLK_DISABLE();  
  __HAL_RCC_GPIOH_CLK_DISABLE();
  

  HAL_PWREx_EnableUltraLowPower();
  HAL_PWREx_EnableFastWakeUp();
  HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
  
  SystemClock_Config();
  MX_GPIO_Init();
  HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);
  SX1278LoraInit();  
  
}



收藏 评论22 发布时间:2018-5-22 20:47

举报

22个回答
feixiang20 回答时间:2018-5-23 00:56:57
可能是PWR之WakeUp的问题,可参考代码资料【使用RTC闹钟,从待机模式唤醒的问题】

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

firstwangjin 回答时间:2018-5-23 10:06:54
feixiang20 发表于 2018-5-23 00:56
可能是PWR之WakeUp的问题,可参考代码资料【使用RTC闹钟,从待机模式唤醒的问题】 ...

感谢你的回复。 我看了你说的帖子,我的问题与帖子中的有差别。我这边 stop 模式用的是 rtc 闹钟唤醒。
通过HAL_RTC_SetAlarm_IT 函数设定醒来的时刻,并没有使用wakeup 。目前就是有时候醒不来
回答时间:2018-5-23 10:35:27
楼主,建议加个可以通过外部唤醒的,如果唤醒不的情况下,外部唤醒后,看一下时钟是否已经停止,看一下真实的时钟。

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

firstwangjin 回答时间:2018-5-23 11:10:22
安 发表于 2018-5-23 10:35
楼主,建议加个可以通过外部唤醒的,如果唤醒不的情况下,外部唤醒后,看一下时钟是否已经停止,看一下真实 ...

感谢回复。
1.我配置了RCC_MCO引脚,针对无法唤醒的板子,查看时钟,发现时钟正常
2.和你说的一样,用外部中断触发一下,发现程序可以触发醒来,且逻辑正确。
回答时间:2018-5-23 11:42:22
如果时钟正常,那就看一下时钟alarm寄存器是否是正确的。是否因为设置错误导致未唤醒。
firstwangjin 回答时间:2018-5-23 12:33:50
配置好 rtc后,alarm通过库函数 HAL_RTC_SetAlarm_IT 设定,寄存器操作由库函数替代了
回答时间:2018-5-23 14:21:44
可能是因为你算法的问题,楼主计算完时间后,最好打印一下,是否是得到的时间。下面这句话我不是很理解:
uint8_t minuteMaxBit = (60/minuteInterval) - 1;
firstwangjin 回答时间:2018-5-23 15:32:26
安 发表于 2018-5-23 14:21
可能是因为你算法的问题,楼主计算完时间后,最好打印一下,是否是得到的时间。下面这句话我不是很理解:
u ...

解释一下:
1.设置时间的格式 我选择的是RTC_FORMAT_BIN ,所以分钟和秒数 值范围 0-59 ,小时数是 0-23
2.现在假设我需要每隔 minuteInterval(假设是10) 时刻进行唤醒,  比如现在时刻是 15:13分,按此间隔,我需要在 15:20 15:30 ....16:00 ....这些时刻唤醒。
按10分钟间隔算,一小时有 6次,比如15:00 ,15:10 , 15:20,15:30,15:40,15:50   (次数可以看成是 0-5,最大数是5),这里的minuteMaxBit 就是最大次数,到了最大次数,下一次唤醒 分钟位就设为0,时钟位需要进位了
回答时间:2018-5-23 17:14:09
嗯。怀疑还是算法算错时间的问题,楼主可以加个打印,打印一下每次得到的唤醒时间,看一下每次不能唤醒的时候,alarm设置的时刻。

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

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