完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
使用高精度晶振作为RTC时钟源,想让闹钟1秒输出与GPS的1PPS同步,现在是用EXTI的上升沿触发中断检测1次GPS的1PPS秒脉冲,在中断函数里用HAL_RTC_SetTime()和HAL_RTC_SetDate()写入RTC时间并关闭EXTI中断,之后的闹钟输出要比1PPS晚几十毫秒,如何能让两个输出尽量接近? |
|
相关推荐
1个回答
|
|
如果你想让闹钟1秒输出与GPS的1PPS同步,建议使用RTC闹钟的周期性唤醒功能,而不是使用外部中断检测1PPS秒脉冲。具体步骤如下:
1. 使用HAL_RTC_Init()初始化RTC模块,将RTC时钟源设置为高精度晶振,RTC的时钟频率为LSE(32.768kHz) 2. 使用HAL_RTCEx_SetWakeUpTimer_IT()函数设置RTC的周期性唤醒功能,使得RTC每秒钟唤醒一次系统。在该函数的回调函数中,设置闹钟并输出闹钟即可。 3. 在HAL_RTCEx_RTCEventCallback()回调函数中将RTC的时间清零。 参考代码如下: ```c /* RTC初始化 */ void RTC_Init(void) { /* 使能备份访问 */ HAL_PWR_EnableBkUpAccess(); /* 使能LSE */ __HAL_RCC_LSE_CONFIG(RCC_LSE_ON); /* 等待LSE稳定 */ while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET); /* 选择LSE为RTC时钟源 */ __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSE); /* 使能RTC时钟 */ __HAL_RCC_RTC_ENABLE(); /* 初始化RTC */ hrtc.Instance = RTC; hrtc.Init.HourFormat = RTC_HOURFORMAT_24; hrtc.Init.AsynchPrediv = 127; hrtc.Init.SynchPrediv = 255; hrtc.Init.OutPut = RTC_OUTPUTSOURCE_NONE; HAL_RTC_Init(&hrtc); } /* RTC唤醒回调函数 */ void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc) { /* 关闭闹钟 */ HAL_RTC_DeactivateAlarm(&hrtc, RTC_ALARM_A); /* 输出闹钟 */ HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET); /* 将时间清零 */ RTC_TimeTypeDef sTime; sTime.Hours = 0; sTime.Minutes = 0; sTime.Seconds = 0; HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN); } /* RTC事件回调函数 */ void HAL_RTCEx_RTCEventCallback(RTC_HandleTypeDef *hrtc) { /* 将时间清零 */ RTC_TimeTypeDef sTime; sTime.Hours = 0; sTime.Minutes = 0; sTime.Seconds = 0; HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN); } /* 设置RTC唤醒时间和周期 */ void RTC_SetWakeUpTime(uint32_t WakeUpCounter) { /* 关闭唤醒定时器 */ HAL_RTCEx_DeactivateWakeUpTimer(&hrtc); /* 设置唤醒周期 */ HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, WakeUpCounter, RTC_WAKEUPCLOCK_RTCCLK_DIV16); /* 设置闹钟,下一个唤醒时间为1秒后 */ RTC_TimeTypeDef sTime; sTime.Hours = 0; sTime.Minutes = 0; sTime.Seconds = 1; HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN); RTC_AlarmTypeDef sAlarm; sAlarm.AlarmTime.Hours = 0; sAlarm.AlarmTime.Minutes = 0; sAlarm.AlarmTime.Seconds = 1; sAlarm.AlarmTime.SubSeconds = 0; sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE; sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET; sAlarm.AlarmMask = RTC_ALARMMASK_NONE; sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL; sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE; sAlarm.AlarmDateWeekDay = 1; sAlarm.Alarm = RTC_ALARM_A; HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN); } ``` 在主函数中,可以使用以下代码调用RTC初始化和设置唤醒时间的函数: ```c /* 初始化RTC */ RTC_Init(); /* 设置唤醒时间 */ RTC_SetWakeUpTime(32768); ``` 这样配置之后,RTC每秒钟唤醒一次系统并输出闹钟,与GPS的1PPS秒脉冲同步。如果你想在接收到外部中断后立即输出闹钟,可以使用HAL_RTC_WaitForSynchro()函数使得时间设置立即生效。具体代码如下: ```c /* 外部中断回调函数 */ void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if(GPIO_Pin == GPIO_PIN_5){ /* 设置RTC时间为当前时间 */ RTC_TimeTypeDef sTime; sTime.Hours = your_hours; sTime.Minutes = your_minutes; sTime.Seconds = your_seconds; HAL_RTC_WaitForSynchro(&hrtc); HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN); /* 关闭中断并输出闹钟 */ HAL_NVIC_DisableIRQ(EXTI9_5_IRQn); HAL_RTC_DeactivateAlarm(&hrtc, RTC_ALARM_A); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET); } } ```
最佳答案
|
|
1 条评论
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
2234 浏览 1 评论
AD7686芯片不传输数据给STM32,但是手按住就会有数据。
2053 浏览 3 评论
4664 浏览 0 评论
如何解决MPU-9250与STM32通讯时,出现HAL_ERROR = 0x01U
2197 浏览 1 评论
hal库中i2c卡死在HAL_I2C_Master_Transmit
2734 浏览 1 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-26 14:01 , Processed in 0.956653 second(s), Total 87, Slave 66 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号