|
本帖最后由 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(); } |
微信公众号
手机版
评分
查看全部评分
感谢你的回复。 我看了你说的帖子,我的问题与帖子中的有差别。我这边 stop 模式用的是 rtc 闹钟唤醒。
通过HAL_RTC_SetAlarm_IT 函数设定醒来的时刻,并没有使用wakeup 。目前就是有时候醒不来
评分
查看全部评分
感谢回复。
1.我配置了RCC_MCO引脚,针对无法唤醒的板子,查看时钟,发现时钟正常
2.和你说的一样,用外部中断触发一下,发现程序可以触发醒来,且逻辑正确。
uint8_t minuteMaxBit = (60/minuteInterval) - 1;
解释一下:
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,时钟位需要进位了
评分
查看全部评分