stm32l4 RTC HAL 不工作
stm32l4 RTC HAL not working
我在带有 FreeRTOS 的 stm32L476 上的 RTC 有一个奇怪的行为。
它只在运行模式下第一次读取,RTC是工作的,因为从运行运行它保存了内部寄存器的值,并且在上升。
此外,如果我在第 583 行的 stm32l4xx_hal_rtc.c 处设置断点时进行调试:
tmpreg = (uint32_t)(hrtc->Instance->TR & RTC_TR_RESERVED_MASK);
*breakpoint* sTime->Hours = (uint8_t)((tmpreg & (RTC_TR_HT | RTC_TR_HU)) >> 16);
我可以看到 tmpreg 和 TR 寄存器如何更新,然后当我单击跳转到下一个断点时 是一样的,我看到显示更新了。
那么为什么它在正常情况下不工作运行?
初始化代码(生成MX方块):
void MX_RTC_Init(void)
{
RTC_TimeTypeDef sTime;
RTC_DateTypeDef sDate;
/**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.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__);
}
/**Initialize RTC and set the Time and Date
*/
if(HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR0) != 0x32F2){
sTime.Hours = 0;
sTime.Minutes = 0;
sTime.Seconds = 0;
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 = RTC_WEEKDAY_MONDAY;
sDate.Month = RTC_MONTH_JANUARY;
sDate.Date = 1;
sDate.Year = 0;
if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR0,0x32F2);
}
}
void HAL_RTC_MspInit(RTC_HandleTypeDef* rtcHandle)
{
if(rtcHandle->Instance==RTC)
{
/* USER CODE BEGIN RTC_MspInit 0 */
/* USER CODE END RTC_MspInit 0 */
/* RTC clock enable */
__HAL_RCC_RTC_ENABLE();
/* USER CODE BEGIN RTC_MspInit 1 */
/* USER CODE END RTC_MspInit 1 */
}
}
读取和打印时钟的任务所有这些任务和功能都是相同的menu.c:
void MenuTask(void const *argument){
for(;;){
/*
* Menus
*/
DrawMenu();
osDelay(100);
}
}
void DrawMenu(){
switch(menuTaskStatus){
/* Not important code */
case MENU_INFO:
menuInfoBar();
break;
}
}
我在 LCD 上打印了一个中间有时钟的条形图
void menuInfoBar(){
//Clock
CheckClock();
if(updateNeeded.Clock){
DrawClock();
updateNeeded.Clock = 0;
}
}
这是有问题的部分,如您所见,我已经尝试等待同步但也没有用。我对同步和 RTC 读取的工作原理有些怀疑。
void CheckClock(){
RTC_TimeTypeDef timeVar;
// HAL_GPIO_TogglePin(LEDR_GPIO_Port, LEDR_Pin);
// if(HAL_RTC_WaitForSynchro(&hrtc) == HAL_OK){
while(HAL_RTC_GetTime(&hrtc,&timeVar,RTC_FORMAT_BIN)!= HAL_OK);
if(timeVar.Seconds != timeVarAnt.Seconds){
timeVarAnt.Minutes = timeVar.Minutes;
timeVarAnt.Hours = timeVar.Hours;
timeVarAnt.Seconds = timeVar.Seconds;
updateNeeded.Clock = 1;
}
// }
}
这里我只在显示器上画了时钟
void DrawClock(){
DISP_locate(49,0);
sprintf((char *)stringBuffer,"%02d:%02d:%02d",(int)timeVarAnt.Hours,(int)timeVarAnt.Minutes,(int)timeVarAnt.Seconds);
DISP_puts((char *)stringBuffer);
}
我可能无法以 100ms 的速度快速读取 RTC?
有人可以向我解释为什么需要同步?数据表解释说如果时钟快 7 倍就可以了,我使用的是 80Mhz APB1 时钟
我发现一些教程和示例与我所做的完全相同,但它们在主循环中读取了具有许多值的 osDelay()。使用 freeRTOS 和从任务读取有问题吗?
时间无关 我试过延迟 5 秒,但也不行
谢谢
此答案没有回答为什么 ST "hal" 不起作用,但它解决了我需要的问题,即使用 RTC。
这是我的新 CheckClock 函数:
void CheckClock(){
uint32_t tmpreg = (uint32_t) hrtc.Instance->TR;
/* Fill the structure fields with the read parameters */
timeVar.Hours = (uint8_t)((tmpreg & (RTC_TR_HT | RTC_TR_HU)) >> 16);
timeVar.Minutes = (uint8_t)((tmpreg & (RTC_TR_MNT | RTC_TR_MNU)) >>8);
timeVar.Seconds = (uint8_t)(tmpreg & (RTC_TR_ST | RTC_TR_SU));
if(timeVar.Seconds != timeVarAnt.Seconds){
HAL_GPIO_TogglePin(LEDR_GPIO_Port, LEDR_Pin);
timeVarAnt.Minutes = timeVar.Minutes;
timeVarAnt.Hours = timeVar.Hours;
timeVarAnt.Seconds = timeVar.Seconds;
updateNeeded.Clock = 1;
}
}
谢谢
编辑 05/2018:
void CheckClock(){
uint32_t tmpreg = (uint32_t) hrtc.Instance->TR;
timeVar.Hours = Bcd2ToByte((uint8_t)((tmpreg & (RTC_TR_HT | RTC_TR_HU)) >> 16));
timeVar.Minutes =Bcd2ToByte( (uint8_t)((tmpreg & (RTC_TR_MNT | RTC_TR_MNU)) >>8));
timeVar.Seconds =Bcd2ToByte( (uint8_t)(tmpreg & (RTC_TR_ST | RTC_TR_SU)));
if(timeVar.Seconds != timeVarAnt.Seconds){
timeVarAnt.Minutes = timeVar.Minutes;
timeVarAnt.Hours = timeVar.Hours;
timeVarAnt.Seconds = timeVar.Seconds;
IBS.updates.Clock = 1;
}
// }
}
可能有点晚了,但我 运行 遇到了同样的问题,结果发现 HAL_GetTime(..)
函数有一个怪癖。 HAL_RTC_GetDate()
必须在它之后调用才能解锁值。
You must call HAL_RTC_GetDate()
after HAL_RTC_GetTime()
to unlock the values
* in the higher-order calendar shadow registers to ensure consistency between the time and date values.
* Reading RTC current time locks the values in calendar shadow registers until current date is read.
这在他们的文档以及 RTC HAL 驱动程序的源代码中作为注释编写。
就我个人而言,我认为 ST 的人应该HAL_RTC_GetTimeAndDate()
避免我们落入这个陷阱。
struct
{
unsigned TR;
}*rcc = (void *)0x56456546;
typedef struct
{
unsigned su :4;
unsigned st :2;
unsigned :1;
unsigned mu :4;
unsigned mt :2;
unsigned :1;
unsigned hu :4;
unsigned ht :2;
unsigned pm :1;
unsigned :9
}RCC_TR_T;
typedef struct
{
uint8_t seconds, minutes, hours, pm;
}TIME_T;
TIME_T *GetTime(TIME_T *time)
{
RCC_TR_T *tr = (RCC_TR_T *)&rcc -> TR;
time -> hours = tr -> hu + tr -> ht * 10;
time -> minutes = tr -> mu + tr -> mt * 10;
time -> seconds = tr -> su + tr -> st * 10;
time -> pm = tr -> pm;
return time;
}
//HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
char xsa[6];
char your_time[9];
sprintf(xsa,"%06x",(uint32_t)hrtc.Instance->TR);
sprintf((char*)your_time,"%c%c:%c%c:%c%c%c",xsa[0],xsa[1],xsa[2],xsa[3],xsa[4],xsa[5],'[=10=]');
我在带有 FreeRTOS 的 stm32L476 上的 RTC 有一个奇怪的行为。
它只在运行模式下第一次读取,RTC是工作的,因为从运行运行它保存了内部寄存器的值,并且在上升。
此外,如果我在第 583 行的 stm32l4xx_hal_rtc.c 处设置断点时进行调试:
tmpreg = (uint32_t)(hrtc->Instance->TR & RTC_TR_RESERVED_MASK);
*breakpoint* sTime->Hours = (uint8_t)((tmpreg & (RTC_TR_HT | RTC_TR_HU)) >> 16);
我可以看到 tmpreg 和 TR 寄存器如何更新,然后当我单击跳转到下一个断点时 是一样的,我看到显示更新了。
那么为什么它在正常情况下不工作运行?
初始化代码(生成MX方块):
void MX_RTC_Init(void)
{
RTC_TimeTypeDef sTime;
RTC_DateTypeDef sDate;
/**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.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__);
}
/**Initialize RTC and set the Time and Date
*/
if(HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR0) != 0x32F2){
sTime.Hours = 0;
sTime.Minutes = 0;
sTime.Seconds = 0;
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 = RTC_WEEKDAY_MONDAY;
sDate.Month = RTC_MONTH_JANUARY;
sDate.Date = 1;
sDate.Year = 0;
if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR0,0x32F2);
}
}
void HAL_RTC_MspInit(RTC_HandleTypeDef* rtcHandle)
{
if(rtcHandle->Instance==RTC)
{
/* USER CODE BEGIN RTC_MspInit 0 */
/* USER CODE END RTC_MspInit 0 */
/* RTC clock enable */
__HAL_RCC_RTC_ENABLE();
/* USER CODE BEGIN RTC_MspInit 1 */
/* USER CODE END RTC_MspInit 1 */
}
}
读取和打印时钟的任务所有这些任务和功能都是相同的menu.c:
void MenuTask(void const *argument){
for(;;){
/*
* Menus
*/
DrawMenu();
osDelay(100);
}
}
void DrawMenu(){
switch(menuTaskStatus){
/* Not important code */
case MENU_INFO:
menuInfoBar();
break;
}
}
我在 LCD 上打印了一个中间有时钟的条形图
void menuInfoBar(){
//Clock
CheckClock();
if(updateNeeded.Clock){
DrawClock();
updateNeeded.Clock = 0;
}
}
这是有问题的部分,如您所见,我已经尝试等待同步但也没有用。我对同步和 RTC 读取的工作原理有些怀疑。
void CheckClock(){
RTC_TimeTypeDef timeVar;
// HAL_GPIO_TogglePin(LEDR_GPIO_Port, LEDR_Pin);
// if(HAL_RTC_WaitForSynchro(&hrtc) == HAL_OK){
while(HAL_RTC_GetTime(&hrtc,&timeVar,RTC_FORMAT_BIN)!= HAL_OK);
if(timeVar.Seconds != timeVarAnt.Seconds){
timeVarAnt.Minutes = timeVar.Minutes;
timeVarAnt.Hours = timeVar.Hours;
timeVarAnt.Seconds = timeVar.Seconds;
updateNeeded.Clock = 1;
}
// }
}
这里我只在显示器上画了时钟
void DrawClock(){
DISP_locate(49,0);
sprintf((char *)stringBuffer,"%02d:%02d:%02d",(int)timeVarAnt.Hours,(int)timeVarAnt.Minutes,(int)timeVarAnt.Seconds);
DISP_puts((char *)stringBuffer);
}
我可能无法以 100ms 的速度快速读取 RTC? 有人可以向我解释为什么需要同步?数据表解释说如果时钟快 7 倍就可以了,我使用的是 80Mhz APB1 时钟
我发现一些教程和示例与我所做的完全相同,但它们在主循环中读取了具有许多值的 osDelay()。使用 freeRTOS 和从任务读取有问题吗?
时间无关 我试过延迟 5 秒,但也不行
谢谢
此答案没有回答为什么 ST "hal" 不起作用,但它解决了我需要的问题,即使用 RTC。
这是我的新 CheckClock 函数:
void CheckClock(){
uint32_t tmpreg = (uint32_t) hrtc.Instance->TR;
/* Fill the structure fields with the read parameters */
timeVar.Hours = (uint8_t)((tmpreg & (RTC_TR_HT | RTC_TR_HU)) >> 16);
timeVar.Minutes = (uint8_t)((tmpreg & (RTC_TR_MNT | RTC_TR_MNU)) >>8);
timeVar.Seconds = (uint8_t)(tmpreg & (RTC_TR_ST | RTC_TR_SU));
if(timeVar.Seconds != timeVarAnt.Seconds){
HAL_GPIO_TogglePin(LEDR_GPIO_Port, LEDR_Pin);
timeVarAnt.Minutes = timeVar.Minutes;
timeVarAnt.Hours = timeVar.Hours;
timeVarAnt.Seconds = timeVar.Seconds;
updateNeeded.Clock = 1;
}
}
谢谢
编辑 05/2018:
void CheckClock(){
uint32_t tmpreg = (uint32_t) hrtc.Instance->TR;
timeVar.Hours = Bcd2ToByte((uint8_t)((tmpreg & (RTC_TR_HT | RTC_TR_HU)) >> 16));
timeVar.Minutes =Bcd2ToByte( (uint8_t)((tmpreg & (RTC_TR_MNT | RTC_TR_MNU)) >>8));
timeVar.Seconds =Bcd2ToByte( (uint8_t)(tmpreg & (RTC_TR_ST | RTC_TR_SU)));
if(timeVar.Seconds != timeVarAnt.Seconds){
timeVarAnt.Minutes = timeVar.Minutes;
timeVarAnt.Hours = timeVar.Hours;
timeVarAnt.Seconds = timeVar.Seconds;
IBS.updates.Clock = 1;
}
// }
}
可能有点晚了,但我 运行 遇到了同样的问题,结果发现 HAL_GetTime(..)
函数有一个怪癖。 HAL_RTC_GetDate()
必须在它之后调用才能解锁值。
You must call
HAL_RTC_GetDate()
afterHAL_RTC_GetTime()
to unlock the values * in the higher-order calendar shadow registers to ensure consistency between the time and date values. * Reading RTC current time locks the values in calendar shadow registers until current date is read.
这在他们的文档以及 RTC HAL 驱动程序的源代码中作为注释编写。
就我个人而言,我认为 ST 的人应该HAL_RTC_GetTimeAndDate()
避免我们落入这个陷阱。
struct
{
unsigned TR;
}*rcc = (void *)0x56456546;
typedef struct
{
unsigned su :4;
unsigned st :2;
unsigned :1;
unsigned mu :4;
unsigned mt :2;
unsigned :1;
unsigned hu :4;
unsigned ht :2;
unsigned pm :1;
unsigned :9
}RCC_TR_T;
typedef struct
{
uint8_t seconds, minutes, hours, pm;
}TIME_T;
TIME_T *GetTime(TIME_T *time)
{
RCC_TR_T *tr = (RCC_TR_T *)&rcc -> TR;
time -> hours = tr -> hu + tr -> ht * 10;
time -> minutes = tr -> mu + tr -> mt * 10;
time -> seconds = tr -> su + tr -> st * 10;
time -> pm = tr -> pm;
return time;
}
//HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
char xsa[6];
char your_time[9];
sprintf(xsa,"%06x",(uint32_t)hrtc.Instance->TR);
sprintf((char*)your_time,"%c%c:%c%c:%c%c%c",xsa[0],xsa[1],xsa[2],xsa[3],xsa[4],xsa[5],'[=10=]');