本帖最后由 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(); } |
STM32L151RDT6 SDIO读写SD卡 FIFO下溢错误,不知是什么原因
STM32L152 RTC唤醒STOP mode问题
STM32L152系列自带LCD驱动段码液晶屏,怎么驱动想要亮的段亮
STM32L151为何FLASH擦除后全是是0x00?
求助!!STM32L151中的RTC唤醒(wake up)中断问题
STM32L152普通I/O模拟SPI驱动W25Q16问题
STM32L152开发板原理图及说明文档
STM32L1系列,如何释放PA15为普通GPIO端口
STM32L151读取W25Q16的ID错误,请帮忙看看是什么原因
STM32L151 STOP模式唤醒程序跑哪儿了
你好! 唤醒失败的板子,后续一直睡眠,除非用外部中断触发。 这种现象的板子,具有随机和普遍性。
我采用喂狗后,唤不醒就重启了。这是个问题啊
下面是昨天运行的一段日志:
time now :19时43分04秒 HAL_IWDG_Refresh ! //喂狗时刻
Rset B :Send data DelayTimeout Time:19时43分24秒 // 设置alarmB 用来唤醒喂狗,设置完成后立即进入stop模式
Client Mode VERSION 1.30.. //设备又一次重启,重启后立即喂狗 ,查看下面的时刻是 19时43分31秒,alarmB并没有醒来喂狗,导致超时
time now :19时43分31秒 HAL_IWDG_Refresh !
time now :19时43分31秒 ThreadClientOnlineRequest delaytime .... randDelay = 939 sum =21
Rset B :Send data DelayTimeout Time:19时43分52秒
HAL_RTCEx_SetWakeUpTimer_IT 函数直接设定:
该函数下有 IS_RTC_WAKEUP_COUNTER(COUNTER) ((COUNTER) <= 0xFFFF) ,虽然counter 值是uint32_t,但是不能超过65535,刚开始我 使用RTC_WAKEUPCLOCK_RTCCLK_DIV16 . CLOCK 为 32.768k 16分频,这样的话 2048 个计数值才代表1s,计数器范围不够使用。后来只能用1hz 时钟。
不知道1hz 时钟的精度如何? RTC_WAKEUPCLOCK_CK_SPRE_17BITS 这个值的真正含义又是什么,和RTC_WAKEUPCLOCK_CK_SPRE_16BITS (1hz)相比,使用起来又有和区别?
解释一下:
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,时钟位需要进位了
评分
查看全部评分
感谢你的回复。 我看了你说的帖子,我的问题与帖子中的有差别。我这边 stop 模式用的是 rtc 闹钟唤醒。
通过HAL_RTC_SetAlarm_IT 函数设定醒来的时刻,并没有使用wakeup 。目前就是有时候醒不来
评分
查看全部评分
感谢回复。
1.我配置了RCC_MCO引脚,针对无法唤醒的板子,查看时钟,发现时钟正常
2.和你说的一样,用外部中断触发一下,发现程序可以触发醒来,且逻辑正确。
uint8_t minuteMaxBit = (60/minuteInterval) - 1;
评分
查看全部评分
你好,下面log是昨天追了一天后未唤醒的信息。
time now :20时50分36秒 ThreadSendSensorData Client has send sensor data Success!!!
Rset B :Next turn time 2018年05月23日20时55分05秒
time now :20时50分36秒 ThreadSendSensorData Reset AlarmB to make sure can Wake UP...
时刻是 20:50:36 alarmB 设定的唤醒时间是 20:55:05 ,但是最终程序并没有唤醒
可以加微信请教啊 15601756551
if (HAL_RTC_SetAlarm(&hrtc, &sAlarm, RTC_FORMAT_BIN) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
if(HAL_RTC_SetAlarm_IT(&hrtc,&sAlarm,RTC_FORMAT_BIN) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
评分
查看全部评分
是的目前的程序里只保留了HAL_RTC_SetAlarm_IT 这一个函数