【感谢】感谢面包板论坛,感谢瑞萨,能为我提供这个RA4E1开发板的试用机会。
【前言】我前后试用的瑞萨的多款开发板,都给我留下很好的印象。这次是我第一次在面包板社区参与评测活动。拿到开发板后,我认真的阅读了官方的资料,结合我以前的经验,移植了一个OLED显示时间的示例。示例中用到了硬件I2C驱动、RTC驱动,结合在一起我制作了一个综合示例。现在将示例的制作过程分享如下:
一、新建工程:
1、打开RASC,新建工程如下图所示:
选择FSP,我这里选4.2版本的,再选择芯片,按昭下图指引,再选择生成目标工程,我这里选择mdk5,然后选择下一步:
选择非安全分离的选项,如下:
选择非操作系统:
选择默认,点击finish生成工程:
要显示时间,我们这里驱动OLED屏,为i2c接口的ssd1306,我们这里配置iic_master stack
配置i2c0的地址、IO、中断回调函数、如下图:
为是获取时间,我们还需要开启RTC,用周期中断来获取时间。如下图所示添加RTC
配置RTC的中断回调函数、开启同期中断。配置如下图所示:
生成工程:
到此rasc配置生成工程结束,rasc为我们做了很多前期的工作,使得后面的工作只需要实现指定的中断回调,以及实现指定的功能。
工程代码实现:
打开工程,找到colock文件夹下面,打开mdk工程:
打开工程后,我们编译,会报错,就是我们的RTC、I2C中断回调函数没有实现:
RASC,在生成功工程时,已经帮我把把i2c的低层代码实现,我们只需要执行R_IIC_MASTER_Open就可以了代码为:
err =R_IIC_MASTER_Open(&g_i2c_master0_ctrl, &g_i2c_master0_cfg);
assert(FSP_SUCCESS == err);
同时我们定义一个i2c中断枚举的变量:i2c_master_event_t g_i2c_callback_event = I2C_MASTER_EVENT_ABORTED;
在中断回调中,我们更新这个标志位,以便程序中判断数据发送与接收的情况,中断回调函数如下:
void i2c_callback(i2c_master_callback_args_t * p_args)
{
g_i2c_callback_event = I2C_MASTER_EVENT_ABORTED;
if (NULL != p_args)
{
/* capture callback event for validating the i2c transfer event*/
g_i2c_callback_event = p_args->event;
}
}
OLED驱动,oled驱动,我们移植从其他工程上的代码过来,我们只需要更新一个oledinit、i2cwritebite两个函数就行了。在OLED_I2C_Init中,我们打开i2c然后判断打开情况:
fsp_err_t err;
void OLED_I2C_Init(void)
{
err =R_IIC_MASTER_Open(&g_i2c_master0_ctrl, &g_i2c_master0_cfg);
assert(FSP_SUCCESS == err);
}
在I2C_WriteByte函数中,我们首先组装发送字符数据,主要是区分向ssd1306发送的是写命令,还是写数据,然后用系统的函数来发送数据,并且对发送情况进行判断,如果发送结束了就返回。同时添加了一个超时标志,如果发送超时也会退出。代码如下:
//向OLED寄存器地址写一个byte的数据
int I2C_WriteByte(uint8_t mode,uint8_t data)
{
uint8_t g_txBuff[2] = {0};
uint16_t timeout_ms = 0;
if(mode)
g_txBuff[0] = 0x40;
else
g_txBuff[0] = 0x000;
g_txBuff[1] = data;
err = R_IIC_MASTER_Write(&g_i2c_master0_ctrl, g_txBuff,2,true);
//
assert(FSP_SUCCESS == err);
timeout_ms = 10;
while((I2C_MASTER_EVENT_TX_COMPLETE != g_i2c_callback_event) && timeout_ms)
{
R_BSP_SoftwareDelay(100U, BSP_DELAY_UNITS_MICROSECONDS);
timeout_ms--;
}
g_i2c_callback_event = I2C_MASTER_EVENT_ABORTED;
return 0;
}
其余,还有就是修改一下延时函数,使用R_BSP_SoftwareDelay(500,BSP_DELAY_UNITS_MILLISECONDS);
OlED驱动好后,我们继续添加RTC的代码。
RTC时钟模块是一个时间外设,主要用于日期时间的存储和控制,有别于一般MCU中的Timer,RTC时钟有两种计时模式,日期模式和计时模式,RTC常见的操作包括设置时间、设置定时闹铃、配置周期性中断以及启动或停止操作。
我们这个示例主要使用RTC的日期与周期中断,利用每一秒中断,来更新OLED的显示标志。
用R_RTC_Open()函数进行初始化和开启RTC。
/* Initialize the RTC module*/
err = R_RTC_Open(&g_rtc0_ctrl, &g_rtc0_cfg);
/* Handle any errors. This function should be defined by the user. */
assert(FSP_SUCCESS == err);
用R_RTC_CalendarTimeGet ()函数进行获取RTC计数时间。
R_RTC_CalendarTimeGet(&g_rtc0_ctrl, &get_time);//获取RTC计数时间
用R_RTC_PeriodicIrqRateSet()函数进行设置周期中断
/* Set the periodic interrupt rate to 1 second */
R_RTC_PeriodicIrqRateSet(&g_rtc0_ctrl, RTC_PERIODIC_IRQ_SELECT_1_SECOND);
我们赋与初值:
rtc_time_t set_time =
{
.tm_sec = 0, /* 秒,范围从 0 到 59 */
.tm_min = 30, /* 分,范围从 0 到 59 */
.tm_hour = 12, /* 小时,范围从 0 到 23*/
.tm_mday =
06
, /* 一月中的第几天,范围从 1 到 31*/
.tm_mon =
08
, /* 月份,范围从 0 到 11*/
.tm_year = 12
3
, /* 自 1900 起的年数,2021为121*/
.tm_wday = 5, /* 一周中的第几天,范围从 0 到 6*/
// .tm_yday=0, /* 一年中的第几天,范围从 0 到 365*/
// .tm_isdst=0; /* 夏令时*/
};
在初始化时,更新RTC时间。
我们添回RTC中断函数,如果1秒产生了中断,则更新标与,以便主程序查询到标志。
/* 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;
}
在主程序中,我们查询RTC周期中断标志,如果标与更新了,则获取当时RTC时间,更新OLED显示:
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(&g_rtc0_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;//周
H1 = rtc_hour/10;
H2 = rtc_hour%10;
M1 = rtc_minute/10;
M2 = rtc_minute%10;
S1 = rtc_second/10;
S2 = rtc_second%10;
}
Draw_Rolling_Clock();
以上是编程的思路,程序源码,我附在附件中。
【注意事项】
生成的工程中有几点需要注意
1、工程中不要有中文路径,要不mdk编译时会提示找不到文件。
2、打开例程时,需要用RASC重新生成一下工程,要不会提示找不到源文件。
3、生成的示例,在Flash Download时里面没有正确配置内存起始、长度,需要我们手工添加:
4、在使用SEGGER——RTT打印时,不同的固件,连接地址也不时,大家可以打开.map文件,找到_SEGGER_RTT地址,来指定,要不会看不到打印内容:
6、FSP现在版本更新很快,有些低版本与新版本的工程不一定兼容。
【总结】
RA4E1这款芯片性价比非常高,在低功耗领域可以应该在许多的工程之中。
【附工程源码】