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=]');