eefocus_4014269 发表于 2026-6-21 17:35:25

[评测分享] 【瑞萨EK-RA4C1】⑤作品提交:WIFI自动校准时钟

测评文章合集:
【瑞萨EK-RA4C1】①热气腾腾的开箱,诚意满满的分享
//m.qjumbo.com/forum/thread-235437-1-1.html

【瑞萨EK-RA4C1】②点灯及串口收发走一波 :)
//m.qjumbo.com/forum/thread-235526-1-1.html

【瑞萨EK-RA4C1】③从零开始玩转液晶
//m.qjumbo.com/forum/thread-235543-1-1.html

【瑞萨EK-RA4C1】④液晶配RTC(实时时钟),完美!
//m.qjumbo.com/forum/thread-235589-1-1.html


https://www.bilibili.com/video/BV17Hj86tESP/



上一篇中,完成了液晶配RTC,实现了一个基础款实时时钟。
时间需要提前在程序里预设好。



这里实际有一个非常不完美的问题点:靠单片机的RTC模块计时,一天会有8~10秒的偏差。
一个月会有4分钟偏差,一年会达到1小时偏差!!!
这哪能忍。


因此当前必须有靠谱的校时设备,这时我想到了万能的ESP8266(ESP-01S模块)
他的接线也很简单,VCC-GND与开发板上的VCC-GND相连(注意EN引脚要与VCC连接)。
串口连接方式如下,需要注意,其同时与PC机虚拟串口相连。
ESP8266 TXD————————EK-RA4C1 P206(SCI4 RXD)————PC机虚拟串口 RXD
ESP8266 RXD————————EK-RA4C1 P207(SCI4 TXD)————PC机虚拟串口 TXD




连接好后的实物图如下:
P206 P207用的是活动针脚连接




其实在连接开发板之前,先应该用USB转串口工具,对ESP-01S模块进行测试。

测试过程及结果分别如下:


1.发送
AT
返回OK

2.发送客户端模式
AT+CWMODE=1   
返回OK
(只发送一次)

3输入WIFI名称及密码连接WIFI
AT+CWJAP="WIFI名称","WIFI密码"
返回WIFI CONNECTED
(如果再发送一次返回WIFI DISCONNECT)

4.设置时间地域

发送AT+CIPSNTPCFG=1,8

返回OK

5.获取时间

发送AT+CIPSNTPTIME?

返回
AT+CIPSNTPTIME?
+CIPSNTPTIME:Sat Jun 20 21:22:42 2026
OK



最后一步返回值,就包含了我们需要的北京时间。
我们对其进行提取、加工、转换,并渎赋值给RTC时间,就实现了精准校时。
整个程序流程如下:





这里最关键的是校时函数,以及串口接收中断。

校时函数如下:
核心就是发送查询时间指令,并对收到的字符串进行提取(本例仅提取时、分、秒),并进行加工转换(由字符串转化为整数),并设置给RTC时间

void calibration_time(void)
{
      int len=0;

    R_SCI_UART_Write(&g_uart4_ctrl, UART_BUF5, strlen(UART_BUF5));//发送查询时间指令
    R_BSP_SoftwareDelay (20, BSP_DELAY_UNITS_MILLISECONDS);


    for(int i=0;i<100;i++)
         {
               UART_BUF7=UART_BUF6;
         }

    R_SCI_UART_Write(&g_uart4_ctrl, UART_BUF7, strlen(UART_BUF7));   //发送获取时间指令
    R_BSP_SoftwareDelay (5, BSP_DELAY_UNITS_MILLISECONDS);

      hour1= UART_BUF7;   //小时的十位
      hour1= UART_BUF7;   //小时的个位

      min1= UART_BUF7;   //分钟的十位
      min1= UART_BUF7;   //分钟的个位

      sec1= UART_BUF7;   //秒的十位
      sec1= UART_BUF7;   //秒的个位

    hour2=atoi(hour1);    //字符串转化为整数
    min2=atoi(min1);
    sec2=atoi(sec1);

    set_time.tm_hour = hour2;
    set_time.tm_min = min2;
    set_time.tm_sec = sec2;

    R_RTC_CalendarTimeSet(&g_rtc0_ctrl, &set_time);    //设置时间

}



串口接收中断如下:
void uart4_callback (uart_callback_args_t * p_args)
      {
               switch (p_args->event)
                   {
                      case UART_EVENT_RX_CHAR:
                      {
                              /* 把串口接收到的数据存入大数组 */
                              //R_SCI_UART_Write(&g_uart4_ctrl, (uint8_t *)&(p_args->data), 1);
                                                UART_BUF6 = p_args->data;

                              break;
                      }
                      case UART_EVENT_TX_COMPLETE:
                      {
                              break;
                      }
                      default:
                              break;
                   }
      }


运行过程中,既可以手动校时,也可以自动校时
手动校时:按下SW1即可
自动校时:每天00:00:10自动校时


最终运行结果如下,跟百度上的北京时间差距在1s以内,达到校时目的。






完整程序如下:
hal_entry.c

/*
* Copyright (c) 2020 - 2026 Renesas Electronics Corporation and/or its affiliates
*
* SPDX-License-Identifier: BSD-3-Clause
*/

#include "hal_data.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


const uint8_t digit_start_addresses=
{
{ 15,16 },   /* LCD_9 big*/
{ 17,25 },   /* LCD_8 big*/
{ 27,28 },   /* LCD_7 big*/
{ 12,6 },      /* LCD_10 medium*/
{ 24,11 },   /* LCD_11 medium*/
{ 19,20 },   /* LCD_12 medium*/
{ 32,29 },   /* LCD_13 medium*/
{ 14,18 },   /* LCD_14 medium*/
};


const uint8_t big_digit_data =
{
      { 0x05, 0x0f }, // 0 digit 0EGF,DCBA
      { 0x00, 0x06 }, // 1 digit
      { 0x06, 0x0b }, // 2 digit
      { 0x02, 0x0f }, // 3 digit
      { 0x03, 0x06 }, // 4 digit
      { 0x03, 0x0d }, // 5 digit
      { 0x07, 0x0d }, // 6 digit
      { 0x00, 0x07 }, // 7 digit
      { 0x07, 0x0f }, // 8 digit
      { 0x03, 0x0f }// 9 digit
};

const uint8_t medium_digit_data =
{
    { 0x0a, 0x0f }, // 0 digit FGE0,ABCD
    { 0x00, 0x06 }, // 1 digit
    { 0x06, 0x0d }, // 2 digit
    { 0x04, 0x0f }, // 3 digit
    { 0x0c, 0x06 }, // 4 digit
    { 0x0c, 0x0b }, // 5 digit
    { 0x0e, 0x0b }, // 6 digit
    { 0x00, 0x0e }, // 7 digit
    { 0x0e, 0x0f }, // 8 digit
    { 0x0c, 0x0f }// 9 digit
};


const uint8_t small_digit_data =
{
    { 0x0A,0x08,0x01,0x0A }, // 0 digit EGF0,DNIH,LMJA,CKB0
    { 0x00,0x00,0x00,0x0A }, // 1 digit
    { 0x0C,0x08,0x01,0x06 }, // 2 digit
    { 0x04,0x08,0x01,0x0E }, // 3 digit
    { 0x06,0x00,0x00,0x0E }, // 4 digit
    { 0x06,0x08,0x01,0x0C }, // 5 digit
    { 0x0E,0x08,0x01,0x0C }, // 6 digit
    { 0x00,0x00,0x01,0x0A }, // 7 digit
    { 0x0E,0x08,0x01,0x0E }, // 8 digit
    { 0x06,0x08,0x01,0x0E }// 9 digit
};



void display_digit(uint8_t LCD_address,uint8_t digit)
{

      switch (LCD_address)
      {
                case 5:
                {
                        R_SLCDC_Modify(&g_slcdc0_ctrl, 37, small_digit_data, 0xF);
                        R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
                        R_SLCDC_Modify(&g_slcdc0_ctrl, 41, small_digit_data, 0xF);
                        R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
                        R_SLCDC_Modify(&g_slcdc0_ctrl, 40, small_digit_data, 0xF);
                        R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
                        R_SLCDC_Modify(&g_slcdc0_ctrl, 35, small_digit_data, 0xF);
                        R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
                        break;
                }
                case 6:
                {
                        R_SLCDC_Modify(&g_slcdc0_ctrl, 21, small_digit_data, 0xF);
                        R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
                        R_SLCDC_Modify(&g_slcdc0_ctrl, 7, small_digit_data, 0xF);
                        R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
                        R_SLCDC_Modify(&g_slcdc0_ctrl, 9, small_digit_data, 0xF);
                        R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
                        R_SLCDC_Modify(&g_slcdc0_ctrl, 22, small_digit_data, 0xF);
                        R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
                        break;
                }

                case 9:
                        {
                              R_SLCDC_Modify(&g_slcdc0_ctrl, digit_start_addresses, big_digit_data, 0xF);
                              R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
                              R_SLCDC_Modify(&g_slcdc0_ctrl, digit_start_addresses, big_digit_data, 0xF);
                              R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
                              break;
                        }
                case 8:
                        {
                              R_SLCDC_Modify(&g_slcdc0_ctrl, digit_start_addresses, big_digit_data, 0xF);
                              R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
                              R_SLCDC_Modify(&g_slcdc0_ctrl, digit_start_addresses, big_digit_data, 0xF);
                              R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
                              break;
                        }
                case 7:
                        {
                              R_SLCDC_Modify(&g_slcdc0_ctrl, digit_start_addresses, big_digit_data, 0xF);
                              R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
                              R_SLCDC_Modify(&g_slcdc0_ctrl, digit_start_addresses, big_digit_data, 0xF);
                              R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
                              break;
                        }
                case 10:
                        {
                              R_SLCDC_Modify(&g_slcdc0_ctrl, digit_start_addresses, medium_digit_data, 0xF);
                              R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
                              R_SLCDC_Modify(&g_slcdc0_ctrl, digit_start_addresses, medium_digit_data, 0xF);
                              R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
                              break;
                        }
                case 11:
                        {
                              R_SLCDC_Modify(&g_slcdc0_ctrl, digit_start_addresses, medium_digit_data, 0xF);
                              R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
                              R_SLCDC_Modify(&g_slcdc0_ctrl, digit_start_addresses, medium_digit_data, 0xF);
                              R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
                              break;
                        }
                case 12:
                        {
                              R_SLCDC_Modify(&g_slcdc0_ctrl, digit_start_addresses, medium_digit_data, 0xF);
                              R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
                              R_SLCDC_Modify(&g_slcdc0_ctrl, digit_start_addresses, medium_digit_data, 0xF);
                              R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
                              break;
                        }
                case 13:
                        {
                              R_SLCDC_Modify(&g_slcdc0_ctrl, digit_start_addresses, medium_digit_data, 0xF);
                              R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
                              R_SLCDC_Modify(&g_slcdc0_ctrl, digit_start_addresses, medium_digit_data, 0xF);
                              R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
                              break;
                        }
                case 14:
                        {
                              R_SLCDC_Modify(&g_slcdc0_ctrl, digit_start_addresses, medium_digit_data, 0xF);
                              R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
                              R_SLCDC_Modify(&g_slcdc0_ctrl, digit_start_addresses, medium_digit_data, 0xF);
                              R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
                              break;
                        }

      }




}


rtc_time_t set_time =
{
    .tm_sec= 00,      /* 秒,范围从 0 到 59 */
    .tm_min= 00,      /* 分,范围从 0 到 59 */
    .tm_hour = 00,      /* 小时,范围从 0 到 23*/
    .tm_mday = 21,      /* 一月中的第几天,范围从 1 到 31*/
    .tm_mon= 6,       /* 月份,范围从 0 到 11*/
    .tm_year = 126,   /* 自 1900 起的年数,2026为126*/
    .tm_wday = 6,       /* 一周中的第几天,范围从 0 到 6*/
};

rtc_time_t get_time;
int rtc_second= 0;      //秒
int rtc_minute =0;      //分
int rtc_hour =0;         //时
int rtc_day =0;          //日
int rtc_month =0;      //月
int rtc_year =0;      //年
int rtc_week =0;      //周

//RTC回调函数
volatile bool rtc_flag = 0;//RTC延时1s标志位
volatile bool rtc_alarm_flag = 0;//RTC闹钟

unsigned char buff[]="Hello World!\n";

unsigned char UART_BUF1[] = "AT\r\n"; //AT指令确认
unsigned char UART_BUF2[] = "AT+CWMODE=1\r\n"; //STA模式
unsigned char UART_BUF3[] = "AT+CWJAP=\"WIFI名称\",\"WIFI密码\"\r\n"; //连接wifi
unsigned char UART_BUF4[] = "AT+CIPSNTPCFG=1,8\r\n";
unsigned char UART_BUF5[] = "AT+CIPSNTPTIME?\r\n";



int len=0;
unsigned char UART_BUF6 ;
unsigned char UART_BUF7 ;

unsigned char hour1,min1,sec1;
int hour2,min2,sec2;
bsp_io_level_t key;




void calibration_time(void)
{
      int len=0;

    R_SCI_UART_Write(&g_uart4_ctrl, UART_BUF5, strlen(UART_BUF5));//发送查询时间指令
    R_BSP_SoftwareDelay (20, BSP_DELAY_UNITS_MILLISECONDS);


    for(int i=0;i<100;i++)
         {
               UART_BUF7=UART_BUF6;
         }

    R_SCI_UART_Write(&g_uart4_ctrl, UART_BUF7, strlen(UART_BUF7));
    R_BSP_SoftwareDelay (5, BSP_DELAY_UNITS_MILLISECONDS);


      hour1= UART_BUF7;
      hour1= UART_BUF7;

      min1= UART_BUF7;
      min1= UART_BUF7;

      sec1= UART_BUF7;
      sec1= UART_BUF7;



/*      R_SCI_UART_Write(&g_uart4_ctrl, hour1, strlen(hour1));
    R_BSP_SoftwareDelay (5, BSP_DELAY_UNITS_MILLISECONDS);
      R_SCI_UART_Write(&g_uart4_ctrl, min1, strlen(min1));
    R_BSP_SoftwareDelay (5, BSP_DELAY_UNITS_MILLISECONDS);
      R_SCI_UART_Write(&g_uart4_ctrl, sec1, strlen(sec1));
    R_BSP_SoftwareDelay (5, BSP_DELAY_UNITS_MILLISECONDS);*/

    hour2=atoi(hour1);
    min2=atoi(min1);
    sec2=atoi(sec1);

    set_time.tm_hour = hour2;
    set_time.tm_min = min2;
    set_time.tm_sec = sec2;

    R_RTC_CalendarTimeSet(&g_rtc0_ctrl, &set_time);

}




/*******************************************************************************************************************//**
* @briefBlinky example application
*
* Blinks all leds at a rate of 1 second using the software delay function provided by the BSP.
*
**********************************************************************************************************************/
void hal_entry (void)
{

      R_SLCDC_Open(&g_slcdc0_ctrl, &g_slcdc0_cfg);
      R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
      R_SLCDC_Start(&g_slcdc0_ctrl);

      R_RTC_Open(&g_rtc0_ctrl, &g_rtc0_cfg);
      R_RTC_ClockSourceSet(&g_rtc0_ctrl);
      R_RTC_CalendarTimeSet(&g_rtc0_ctrl, &set_time);
      R_RTC_PeriodicIrqRateSet(&g_rtc0_ctrl, RTC_PERIODIC_IRQ_SELECT_1_SECOND);


    R_SCI_UART_Open(&g_uart4_ctrl, &g_uart4_cfg);

      while(1)
      {
                R_IOPORT_PinRead(&g_ioport_ctrl, BSP_IO_PORT_05_PIN_13, &key);

                if(rtc_flag)
                {
                R_RTC_CalendarTimeGet(&g_rtc0_ctrl, &get_time);//获取RTC计数时间
                rtc_second=get_time.tm_sec;//秒
                rtc_minute=get_time.tm_min;//分
                rtc_hour=get_time.tm_hour;//时
                rtc_day=get_time.tm_mday;//日
                rtc_month=get_time.tm_mon;//月
                rtc_year=get_time.tm_year; //年
                rtc_week=get_time.tm_wday;//周

                if(rtc_hour == 0 && rtc_minute ==0 && rtc_second == 10) //夜里00:00:10自动校校时
                {
                        calibration_time();
                }

                display_digit(6,rtc_second%10);   //秒的个位
                display_digit(5,rtc_second/10);   //秒的十位

                display_digit(10,rtc_minute%10);   //分的个位
                display_digit(11,rtc_minute/10);   //分的十位

                display_digit(12,rtc_hour%10);   //时的个位
                display_digit(13,rtc_hour/10);   //时的十位

                R_SLCDC_Modify(&g_slcdc0_ctrl, 10, 0x02, 0xF);//时跟分之间的冒号
                R_SLCDC_Modify(&g_slcdc0_ctrl, 17, 0x08, 0xF);//Renesas图标

                }


               if(key==0)
                {
                        calibration_time();
                        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_06_PIN_10, BSP_IO_LEVEL_LOW);
                  R_BSP_SoftwareDelay (50, BSP_DELAY_UNITS_MILLISECONDS);
                }
                else
                        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_06_PIN_10, BSP_IO_LEVEL_HIGH);
                }
}

/* Callback function */
void rtc_callback(rtc_callback_args_t *p_args)
{
    /* TODO: add your own code here */
    if(p_args->event == RTC_EVENT_PERIODIC_IRQ)
      rtc_flag=1;
    else if(p_args->event == RTC_EVENT_ALARM_IRQ)
      rtc_alarm_flag=1;
}


void uart4_callback (uart_callback_args_t * p_args)
      {
               switch (p_args->event)
                   {
                      case UART_EVENT_RX_CHAR:
                      {
                              /* 把串口接收到的数据存入大数组 */
                              //R_SCI_UART_Write(&g_uart4_ctrl, (uint8_t *)&(p_args->data), 1);
                                                UART_BUF6 = p_args->data;

                              break;
                      }
                      case UART_EVENT_TX_COMPLETE:
                      {
                              break;
                      }
                      default:
                              break;
                   }
      }





eefocus_4014269 发表于 2026-6-25 20:41:04

自己顶一个先。:lol
页: [1]
查看完整版本: [评测分享] 【瑞萨EK-RA4C1】⑤作品提交:WIFI自动校准时钟

Baidu
map