本帖最后由 jinglixixi 于 2025-7-25 18:15 编辑
#申请原创#
@21小跑堂
RA-Eco-RA6M4开发板是一款基于 Arm® Cortex®-M33 内核的开发工具,它有1MB 闪存、192kB支SRAM 及64kb ECC SRAM,其工作主频可达200MHz。
开发板上的外设不多,需自行加以扩展。
RA-Eco-RA6M4以e2studio开发为主,这对于惯用MDK开发的用户带来了少许的不便,但影响不是很大。通过RASC生成Keil工程后,就可回到Keil环节下进行编程、编译及下载。
要在 RA-Eco-RA6M4上实现RTC电子时钟,需要一下3个步骤:
1. 串口打印
鉴于外设资源的稀少,要进行程序的调试,首先就要解决串口打印问题。
由于在RA-Eco-RA6M4开发板上载有USB转TTL电路,故使用它更便于进行串口通信及调试,其电路见图1所示。
图1 USB转TTL电路
此外,在直接与外部串口设备通讯时,还可以通过接口J4来进行连接,该接口如图2所示。
图2 接口J4
有了硬件的支持,就可以用RASC来进行引脚配置的。由于该串口是SCI UART 9,所对应的引脚为 P109和P110。
此时,若观察这2个引脚,会发现它已被配置其他用途,见图3所示。
图3 引脚配置
为此,需要在其引脚所在的功能界面,将其设为“Disabled”,以便重新配置其他功能,见图4所示。
图4 取消原配置
图5 取消后
按图6所示启用串口功能,然后按图7所示来加入串口。
图6 启用串口功能
图7 加入串口
此时,会弹出图8所示的窗口,点击弹出窗口并按图9来设置参数。
图8 弹出窗口
图9 设置参数
随后,按图10所示来修改“Heap size”,以设置堆区大小。
图10 设置堆区
最后,点击右上角的 “Generate Project Content”按钮,以生成工程代码。
在生成代码后,若直接进行编译会出现图11所示的报错信息。
图11 编译报错
当在主程序所在的文件内,添加相应的内容后,会通过编译。
需添加的内容为:
fsp_err_t err = FSP_SUCCESS;
unsigned char send_buff[100];
volatile bool uart_send_complete_flag = false;
void user_uart9_callback (uart_callback_args_t * p_args)
{
if(p_args->event == UART_EVENT_TX_COMPLETE)
{
uart_send_complete_flag = true;
}
}
int fputc(int ch)
{
err = R_SCI_UART_Write(&g_uart9_ctrl, (uint8_t *)&ch, 1);
if(FSP_SUCCESS != err) __BKPT();
while(uart_send_complete_flag == false)
{
}
uart_send_complete_flag = false;
return ch;
}
uart_send_complete_flag = false;
return ch;
}
此时,将主程序修改为:
void hal_entry(void)
{
err = R_SCI_UART_Open(&g_uart9_ctrl, &g_uart9_cfg);
assert(FSP_SUCCESS == err);
while(1)
{
printf("Hellow world ! \r\n");
R_BSP_SoftwareDelay(1000, BSP_DELAY_UNITS_MILLISECONDS);
}
}
、
经程序的编译和下载,其测试结果如图12所示,说明打印功能已实现,
图12 输出测试
2. RTC计时器
在RA6M4内部,配以RTC计时器,使用它可方便地实现电子时钟功能。
要使用RTC功能,需使用RASC在原基础上使能RTC,见图13所示。然后,再按图14所示加入RTC。
图13 参数设置
图14 加入RTC
点击“Generate Project Content”,以再次生成工程代码。
再次使用KEIL打开生成的工程,在原程序中添加如下的函数:
void rtc_callback(rtc_callback_args_t *p_args)
{
if(p_args->event == RTC_EVENT_PERIODIC_IRQ)
rtc_flag=1;
else if(p_args->event == RTC_EVENT_ALARM_IRQ)
rtc_alarm_flag=1;
}
rtc_time_t set_time =
{
.tm_sec = 0, /* 秒,范围从 0 到 59 */
.tm_min = 30, /* 分,范围从 0 到 59 */
.tm_hour = 12, /* 小时,范围从 0 到 23*/
.tm_mday = 20, /* 一月中的第几天,范围从 1 到 31*/
.tm_mon = 11, /* 月份,范围从 0 到 11*/
.tm_year = 121, /* 自 1900 起的年数,2021为121*/
.tm_wday = 5, /* 一周中的第几天,范围从 0 到 6*/
};
rtc_alarm_time_t set_alarm_time=
{
.time.tm_sec = 5,
.time.tm_sec = 5, /* 秒,范围从 0 到 59 */
.time.tm_min = 30, /* 分,范围从 0 到 59 */
.time.tm_hour = 12, /* 小时,范围从 0 到 23*/
.time.tm_mday = 25, /* 一月中的第几天,范围从 1 到 31*/
.time.tm_mon = 7, /* 月份,范围从 0 到 11*/
.time.tm_year = 125, /* 自 1900 起的年数,2021为121*/
.time.tm_wday = 5, /* 一周中的第几天,范围从 0 到 6*/
.sec_match = 1,
.min_match = 0,
.hour_match = 0,
.mday_match = 0,
.mon_match = 0,
.year_match = 0,
.dayofweek_match = 0,
};
将主程序修改为:
void hal_entry(void)
{
err = R_SCI_UART_Open(&g_uart9_ctrl, &g_uart9_cfg);
assert(FSP_SUCCESS == err);
err = R_RTC_Open(&rtc_ctrl, &rtc_cfg);
assert(FSP_SUCCESS == err);
R_RTC_CalendarTimeSet(&rtc_ctrl, &set_time);
R_RTC_PeriodicIrqRateSet(&rtc_ctrl, RTC_PERIODIC_IRQ_SELECT_1_SECOND);
R_RTC_CalendarAlarmSet(&rtc_ctrl, &set_alarm_time);
uint8_t rtc_second= 0; //秒
uint8_t rtc_minute =0; //分
uint8_t rtc_hour =0; //时
uint8_t rtc_day =0; //日
uint8_t rtc_month =0; //月
uint16_t rtc_year =0; //年
uint8_t rtc_week =0; //周
rtc_time_t get_time;
while(1)
{
if(rtc_flag)
{
R_RTC_CalendarTimeGet(&rtc_ctrl, &get_time);//获取RTC计数时间
rtc_flag=0;
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;//周
printf(" %d-%d-%d %d:%d %d\n",rtc_year+1900,rtc_month,rtc_day,rtc_hour,rtc_minute,rtc_second,rtc_week);
}
if(rtc_alarm_flag)
{
rtc_alarm_flag=0;
printf("/************Alarm Clock***********/\n");
}
}
}
经程序的编译和下载,则其测试结果如图15所示,说明RTC计时功能已实现。
图15 计时效果
3. OLED屏显示
为了能够直接地观察计时效果,可为其添加一个OLED显示屏。
为省去连线的麻烦,可利用开发板上的J4接口来连接OLED屏。
在用RASC对所用引脚添加配置后,以KEIL打开新生成的工程。
为实现高低电平的输出其语句定义为:
#define OLED_SCLK_Set() R_IOPORT_PinWrite(&IOPORT_CFG_CTRL, BSP_IO_PORT_01_PIN_13, BSP_IO_LEVEL_HIGH)
#define OLED_SDIN_Set()R_IOPORT_PinWrite(&IOPORT_CFG_CTRL, BSP_IO_PORT_01_PIN_12, BSP_IO_LEVEL_HIGH)
#define OLED_SCLK_Clr()R_IOPORT_PinWrite(&IOPORT_CFG_CTRL, BSP_IO_PORT_01_PIN_13, BSP_IO_LEVEL_LOW)
#define OLED_SDIN_Clr()R_IOPORT_PinWrite(&IOPORT_CFG_CTRL, BSP_IO_PORT_01_PIN_12, BSP_IO_LEVEL_LOW)
以模拟I2C方式方式字节数据的函数为:
void Write_IIC_Byte(unsigned char IIC_Byte)
{
unsigned char i;
unsigned char m,da;
da=IIC_Byte;
OLED_SCLK_Clr();
for(i=0;i<8;i++)
{
m=da;
m=m&0x80;
if(m==0x80)
{OLED_SDIN_Set();}
else
OLED_SDIN_Clr();
da=da<<1;
delay_us(3);
OLED_SCLK_Set();
delay_us(3);
OLED_SCLK_Clr();
delay_us(3);
}
}
对应的初始化函数为:
void OLED_Init(void)
{
Write_IIC_Command(0xAE); //display off
Write_IIC_Command(0x40);//--set start line address
Write_IIC_Command(0xb0);//Set Page Start Address for Page Addressing Mode,0-72
Write_IIC_Command(0xc8);//Set COM Output Scan Direction
Write_IIC_Command(0x81);//--set contrast control register
Write_IIC_Command(0xff);
Write_IIC_Command(0xa1);//--set segment re-map 0 to 127
Write_IIC_Command(0xa6);//--set normal display
Write_IIC_Command(0xa8);//--set multiplex ratio(1 to 64)
Write_IIC_Command(0x1F);
Write_IIC_Command(0xd3);//-set display offset
Write_IIC_Command(0x00);//-not offset
Write_IIC_Command(0xd5);//--set display clock divide ratio/oscillator frequency
Write_IIC_Command(0xf0);//--set divide ratio
Write_IIC_Command(0xd9);//--set pre-charge period
Write_IIC_Command(0x22);
Write_IIC_Command(0xda);//--set com pins hardware configuration
Write_IIC_Command(0x02);
Write_IIC_Command(0x8d);//--set DC-DC enable
Write_IIC_Command(0x14);
Write_IIC_Command(0xdb);//--set vcomh
Write_IIC_Command(0x49);//0x20,0.77xVcc
Write_IIC_Command(0xaf);//--turn on oled panel
}
实现电子时钟显示显示效果的主程序为:
void hal_entry(void)
{
err = R_RTC_Open(&rtc_ctrl, &rtc_cfg);
assert(FSP_SUCCESS == err);
R_RTC_CalendarTimeSet(&rtc_ctrl, &set_time);
R_RTC_PeriodicIrqRateSet(&rtc_ctrl, RTC_PERIODIC_IRQ_SELECT_1_SECOND);
R_RTC_CalendarAlarmSet(&rtc_ctrl, &set_alarm_time);
uint8_t rtc_second= 0; //秒
uint8_t rtc_minute =0; //分
uint8_t rtc_hour =0; //时
uint8_t rtc_day =0; //日
uint8_t rtc_month =0; //月
uint16_t rtc_year =0; //年
uint8_t rtc_week =0; //周
rtc_time_t get_time;
OLED_Init();
OLED_Clear();
OLED_ShowString(0,0,"RA-Eco-RA6M4",16);
OLED_ShowString(0,2," : :",16);
while(1)
{
if(rtc_flag)
{
R_RTC_CalendarTimeGet(&rtc_ctrl, &get_time);//获取RTC计数时间
rtc_flag=0;
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;//周
OLED_ShowNum(0,2,rtc_hour,2,16);
OLED_ShowNum(24,2,rtc_minute,2,16);
OLED_ShowNum(48,2,rtc_second,2,16);
}
if(rtc_alarm_flag)
{
rtc_alarm_flag=0;
}
}
}
经重新编译和下载,则其测试结果如图16所示,设计功能已实现。
图16 显示效果
|
|