FuShenxiao 发表于 2024-10-24 16:58

STM32H7S78-DK测评(四)——RTC测试

<div class='showpostmsg'> 本帖最后由 FuShenxiao 于 2024-10-24 16:58 编辑

<p>STM32的RTC指的是实时时钟(Real-Time Clock),它是一种用于计时和日期记录的硬件模块。在STM32微控制器中,RTC模块是由一个32位的计数器和一组用于保存日期和时间的寄存器组成的。由于RTC具有较高的精度和稳定性,从而能保持准确的日期和时间信息,因此它常用于需要精确定时和实时数据处理的应用场景。</p>

<p>本来以为RTC实现挺简单的,没想到这里还有那么多坑,主要是CubeMX代码生成存在一些问题。</p>

<p><span style="font-size:18px;"><strong>在CubeMX中配置</strong></span></p>

<p>选择STM32H7S78-DK模板</p>

<p>配置RTC</p>

<p style="text-align: center;"></p>

<p style="text-align: center;">&nbsp;</p>

<p style="text-align: center;"> &nbsp;&nbsp;</p>

<p>为了能输出时间和日期,还需要配置UART4</p>

<p style="text-align: center;"> &nbsp;</p>

<p><strong><span style="font-size:18px;">代码编写</span></strong></p>

<p>生成RTC初始化代码如下</p>

<pre>
<code>void MX_RTC_Init(void)
{

/* USER CODE BEGIN RTC_Init 0 */

/* USER CODE END RTC_Init 0 */

RTC_PrivilegeStateTypeDef privilegeState = {0};
RTC_TimeTypeDef sTime = {0};
RTC_DateTypeDef sDate = {0};

/* USER CODE BEGIN RTC_Init 1 */

/* USER CODE END RTC_Init 1 */

/** 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;
hrtc.Init.OutPutPullUp = RTC_OUTPUT_PULLUP_NONE;
hrtc.Init.BinMode = RTC_BINARY_NONE;
if (HAL_RTC_Init(&amp;hrtc) != HAL_OK)
{
    Error_Handler();
}
privilegeState.rtcPrivilegeFull = RTC_PRIVILEGE_FULL_NO;
privilegeState.backupRegisterPrivZone = RTC_PRIVILEGE_BKUP_ZONE_NONE;
privilegeState.backupRegisterStartZone2 = RTC_BKP_DR0;
privilegeState.backupRegisterStartZone3 = RTC_BKP_DR0;
if (HAL_RTCEx_PrivilegeModeSet(&amp;hrtc, &amp;privilegeState) != HAL_OK)
{
    Error_Handler();
}

/* USER CODE BEGIN Check_RTC_BKUP */

/* USER CODE END Check_RTC_BKUP */

/** Initialize RTC and set the Time and Date
*/
sTime.Hours = 0x15;
sTime.Minutes = 0x0;
sTime.Seconds = 0x0;
sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sTime.StoreOperation = RTC_STOREOPERATION_RESET;
if (HAL_RTC_SetTime(&amp;hrtc, &amp;sTime, RTC_FORMAT_BCD) != HAL_OK)
{
    Error_Handler();
}
sDate.WeekDay = RTC_WEEKDAY_THURSDAY;
sDate.Month = RTC_MONTH_OCTOBER;
sDate.Date = 0x24;
sDate.Year = 0x24;

if (HAL_RTC_SetDate(&amp;hrtc, &amp;sDate, RTC_FORMAT_BCD) != HAL_OK)
{
    Error_Handler();
}
/* USER CODE BEGIN RTC_Init 2 */

/* USER CODE END RTC_Init 2 */

}</code></pre>

<p>编写printf重定向</p>

<pre>
<code>int fputc(int ch,FILE *p)
{
    char c=ch;
    HAL_UART_Transmit(&amp;huart4,(unsigned char *)&amp;c,1,50);
    return ch;
}

void UART4_SendByte(char c)
{
    HAL_UART_Transmit(&amp;huart4,(unsigned char *)&amp;c,1,50);
}

void UART4_SendData(char *p,int len)
{
    HAL_UART_Transmit(&amp;huart4,(unsigned char *)p,len,50);
}</code></pre>

<p>编写输出RTC日历的代码</p>

<pre>
<code>static void RTC_CalendarShow(uint8_t *showtime, uint8_t *showdate)
{
RTC_DateTypeDef sdatestructureget;
RTC_TimeTypeDef stimestructureget;

/* Get the RTC current Time */
HAL_RTC_GetTime(&amp;hrtc, &amp;stimestructureget, RTC_FORMAT_BIN);
/* Get the RTC current Date */
HAL_RTC_GetDate(&amp;hrtc, &amp;sdatestructureget, RTC_FORMAT_BIN);
/* Display time Format : hh:mm:ss */
sprintf((char *)showtime, "%2d:%2d:%2d", stimestructureget.Hours, stimestructureget.Minutes, stimestructureget.Seconds);
/* Display date Format : mm-dd-yyyy */
sprintf((char *)showdate, "%2d-%2d-%2d", sdatestructureget.Month, sdatestructureget.Date, 2000 + sdatestructureget.Year);
printf("%s\r\n", showtime);
printf("%s\r\n", showdate);
}</code></pre>

<p>初始化时间/日期字符串</p>

<pre>
<code>uint8_t aShowTime = "hh:ms:ss";
uint8_t aShowDate = "mm-dd-yyyy";</code></pre>

<p>在主函数循环中加入如下代码</p>

<pre>
<code>RTC_CalendarShow(aShowTime, aShowDate);
HAL_Delay(1000);</code></pre>

<p>但是,这样还是有问题的。</p>

<p>问题出在 <strong>HAL_StatusTypeDef RTC_EnterInitMode(RTC_HandleTypeDef *hrtc)</strong></p>

<p>其代码如下</p>

<pre>
<code>HAL_StatusTypeDef RTC_EnterInitMode(RTC_HandleTypeDef *hrtc)
{
uint32_t tickstart;
HAL_StatusTypeDef status = HAL_OK;

/* Check if the Initialization mode is set */
if (READ_BIT(RTC-&gt;ICSR, RTC_ICSR_INITF) == 0U)
{
    /* Set the Initialization mode */
    SET_BIT(RTC-&gt;ICSR, RTC_ICSR_INIT);

    tickstart = HAL_GetTick();
    /* Wait till RTC is in INIT state and if Time out is reached exit */
    while ((READ_BIT(RTC-&gt;ICSR, RTC_ICSR_INITF) == 0U) &amp;&amp; (status != HAL_TIMEOUT))
    {
      if ((HAL_GetTick()- tickstart) &gt; RTC_TIMEOUT_VALUE)
      {
      /* New check to avoid false timeout detection in case of preemption */
      if (READ_BIT(RTC-&gt;ICSR, RTC_ICSR_INITF) == 0U)
      {
          status = HAL_TIMEOUT;

          /* Change RTC state */
          hrtc-&gt;State = HAL_RTC_STATE_TIMEOUT;
      }
      else
      {
          break;
      }
      }
    }
}

return status;
}</code></pre>

<p>问题出现在执行&nbsp;<strong>SET_BIT(RTC-&gt;ICSR, RTC_ICSR_INIT);</strong> 之后,寄存器的初始化位并没有置1。</p>

<p>阅读手册可知需要对DBP置1才能使能写RTC寄存器。</p>

<p style="text-align: center;"> &nbsp;</p>

<div></div>

<p>在进入RTC之前会调用 <strong>HAL_RTC_MspInit(hrtc);</strong></p>

<p style="text-align: center;"> &nbsp;</p>

<p>于是我们就可以进入 <strong>HAL_RTC_MspInit</strong> 中使能写RTC寄存器,添加一句&nbsp;<strong>HAL_PWR_EnableBkUpAccess();</strong> 用于允许访问备份区。</p>

<pre>
<code>void HAL_RTC_MspInit(RTC_HandleTypeDef* rtcHandle)
{

RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
if(rtcHandle-&gt;Instance==RTC)
{
/* USER CODE BEGIN RTC_MspInit 0 */
    HAL_PWR_EnableBkUpAccess();
/* USER CODE END RTC_MspInit 0 */

/** Initializes the peripherals clock
*/
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;
    PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
    if (HAL_RCCEx_PeriphCLKConfig(&amp;PeriphClkInit) != HAL_OK)
    {
      Error_Handler();
    }

    /* RTC clock enable */
    __HAL_RCC_RTC_ENABLE();
    __HAL_RCC_RTCAPB_CLK_ENABLE();
/* USER CODE BEGIN RTC_MspInit 1 */

/* USER CODE END RTC_MspInit 1 */
}
}</code></pre>

<p>于是RTC就可以正常使用了。</p>

<p><strong><span style="font-size:18px;">结果展示</span></strong></p>

<p style="text-align: center;"> &nbsp;</p>

<p>&nbsp;</p>

<div>完整工程代码<br />
</div>
</div><script>                                        var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;"   style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
                                       
                                        if(parseInt(discuz_uid)==0){
                                                                                                (function($){
                                                        var postHeight = getTextHeight(400);
                                                        $(".showpostmsg").html($(".showpostmsg").html());
                                                        $(".showpostmsg").after(loginstr);
                                                        $(".showpostmsg").css({height:postHeight,overflow:"hidden"});
                                                })(jQuery);
                                        }                </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script>

freebsder 发表于 2024-10-24 19:19

<p>S又是个主打哪个方向的型号?</p>

FuShenxiao 发表于 2024-10-24 20:06

freebsder 发表于 2024-10-24 19:19
S又是个主打哪个方向的型号?

<p>我觉得主要是它的高性能图像显示能力吧,主要吸引人的是它DMA2D,也就是GPU功能,这块开发板的屏幕有480*800,已经挺大的了。</p>

freebsder 发表于 2024-10-25 10:38

FuShenxiao 发表于 2024-10-24 20:06
我觉得主要是它的高性能图像显示能力吧,主要吸引人的是它DMA2D,也就是GPU功能,这块开发板的屏幕有480* ...

<p>感觉MCU硬件也要过剩了,和PC当年一样,软件跟不上。</p>
页: [1]
查看完整版本: STM32H7S78-DK测评(四)——RTC测试