stm32l4 RTC HAL无法正常工作

时间:2017-10-31 16:20:50

标签: c stm32 freertos hal real-time-clock

我在带有FreeRTOS的stm32L476上使用RTC有一个奇怪的行为。

它只在RUN模式下第一次读取,RTC正在工作,因为从运行到运行它会保存内部寄存器的值并且正在上升。

如果我在第583行的stm32l4xx_hal_rtc.c中设置断点时进行DEBUG:

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;

    }
}

我在液晶显示屏上打印一个时钟位于中间的条形

void menuInfoBar(){

    //Clock
    CheckClock();
    if(updateNeeded.Clock){
        DrawClock();
        updateNeeded.Clock = 0;
    }

}

这是有问题的部分,因为你可以看到我试过等待同步但也没有用。我对这个syncro和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);
}

我有可能无法快速读取RTC为100ms? 有人可以向我解释为什么需要同步化?数据表解释说如果时钟快了7倍就可以了,我使用的是80Mhz APB1时钟<​​/ p>

我发现一些教程和示例与我做的完全一样,但是他们在主循环上读取了许多值的osDelay()。使用freeRTOS和从任务中读取是一个问题吗?

时间无关我尝试了5s延迟并且也无效

由于

4 个答案:

答案 0 :(得分:6)

有点晚了但是我遇到了同样的问题,事实证明HAL_GetTime(..)函数有一个怪癖。必须在它之后调用HAL_RTC_GetDate()来解锁值。

  

您必须在HAL_RTC_GetTime()之后调用HAL_RTC_GetDate()来解锁值     *在高阶日历影子寄存器中,以确保时间和日期值之间的一致性。     *读取RTC当前时间会锁定日历影子寄存器中的值,直到读取当前日期为止。

这是在他们的文档中以及RTC HAL驱动程序的源代码中写的。

就我个人而言,我相信ST的家伙应该制作一个HAL_RTC_GetTimeAndDate()并让我们陷入这个陷阱。

答案 1 :(得分:0)

         //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],'\0');

答案 2 :(得分:-1)

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;
}

答案 3 :(得分:-2)

这个答案没有解释为什么ST&#34; hal&#34;不起作用,但它解决了我需要的东西,即使用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;
    }
    //  }
}