[评测分享] 【瑞萨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;
}
}
自己顶一个先。:lol
页:
[1]