首先非常感谢电子工程世界论坛和得捷举办的Follow me活动,感谢第二季第三期任务讲解的老师。通过一个月的学习让我学到很多有关瑞萨芯片开发的相关知识。
入门任务
环境搭建
万事开头难,单片机的开发第一步就是搭建开发环境。瑞萨的开发软件是e2Studio,离线安装包有多重下载方式,GitHub的下载链接为: 。当然官网也有下载链接,在此不再贴上去了。软件版本有很多,建议下载5.5最新版本,我也是用这个版本完成任务的。打开GitHub的下载链接点击如下图的红框就可以进行下载
下载好的安装包安装方式也是比较简单的,点击后就可平常的安装方式一样。以下是安装过程,画红框是需要自己勾选的,其他的就按照默认选择就可以。
瑞萨也推出支持MDK和IAR的工程创建软件,可以下载如下图的方框安装使用,使用方式和e2Studio的方式差不多,只是在新建工程时需要选择MDK或IAR做编译软件,MDK也需要进行一些配置,配置方式可以在网上查找。本次使用的板卡是EK-RA6M5,板上带有JLink仿真器,所以e2Studio软件完全够用。
下载调试示例程序
安装好后需要在开始菜单中找到e2Studio的快捷链接,我是找到后拖到桌面,这样方便后续的使用。也可以在安装软件的文件夹中找到,如果没有自定义安装路径的话会安装在C盘的Renesas文件夹下。
瑞萨针对官方多个开发板都提供了丰富的例程,例程的链接是 。可以通过下载压缩包方式下载,也可以直接下载下来。打开安装好的e2Studio软件后导入工程的方法有两种。一种是点击左上角的文件-->从文件系统中打开项目;另外一种是点击项目资源管理器的导入或者点击左上角的文件-->导入,选择常规下的来自文件夹或归档的文件项目。如下图
然后选择导入工程的文件夹路径,建议是e2studio文件夹下的路径,因为创建工程的一些配置文件是放在e2studio文件夹下的,如果选择其他的文件夹路径会出现软件识别多个配置文件,不过也没有影响。本次以_quickstart文件夹下的例程为例。
文件导入后可能是因为版本的问题,直接编译会出现错误,解决方法是打开configuration.xml文件,虽然会有一些警告,但是直接点击确定就可以,然后编译就会没有问题。对其他的例程也是适用的,只不过有些例程还是编译会有问题,这一点就没有办法了。编译的方式是可以点击下图的编译按钮
编译过程和结果会在下方的控制台中显示,编译成功会显示如下内容
接下来是下载程序到板卡上,需要一根microUSB线,需要插入一端只有一个microUSB接口上。然后通过软件下载程序,方式如下图
下载后会提示是否切换仿真界面,如果选择切换会进入仿真界面;选择否还是会在工程文件界面。切换这两个界面的方式如下图
红框是工程文件界面,右侧是仿真界面。程序下载成功后需要点击运行才会运行程序或者USB拔掉重新接上也可以启动程序(该方式适合不用仿真或用J-Link RTT Viewer软件通信用)。启动和仿真按钮如下图所示
本例程的程序下载成功后可以将microUSB线接入J11(USB Full Speed)丝印的接口上。然后可以用串口软件或e2studio的串口插件进行交互,这里我选择串口软件进行交互,波特率是115200,8Bit数据位,1个停止位,无奇偶校验进行连接。连接后出现如下界面
然后可以输入4进行Flash读写测试,测试结果如下
新建工程
在开始Blink和按键任务前,其实刚才介绍的示例程序就可以实现,但是为了更清楚的了解程序是如何实现的,所以从空的工程一步一步进行配置和编写程序实现任务要求的效果。新建工程的方法是点击左上角的文件-->新建-->瑞萨C/C++项目-->Renesas RA。如下图
然后可以双击Renesas RA C/C++ Project,如下图
接下来是命名工程名和选择工程文件保存路径,可以用默认的文件夹路径,也可以取消勾选使用缺省值前的√自定义保存工程文件路径。设置好后点击下一步进入设备型号配置,可以只需修改Device选项即可。在Device选项框的后面点三个点图标找到EK-RA6M5的选项便可。如下图
然后就是多次点击下一步,其中有选择是否添加操作系统的选项。这里没有用到,所以可以多次点击下一步。最后是选择是否创建基础工程还是空的。我这里选择的是空的工程来进行任务效果的实现。
Blink和按键
原理图
Blink和按键的实现需要先看一下原理图,知道LED灯控制引脚和按键引脚接到那个I/O口上。原理图可以在瑞萨官网下载。按键和LED灯控制引脚对应的原理图如下
流程图
因为Blink的实现主要是靠两个定时器实现的,不方便画如流程图中,所以只画了按键处理的流程图
配置
在创建工程是e2studio已经将对应的I/O口进行配置了,所以不需要配置对应引脚。
应用程序代码编写
首先是添加控制LED灯闪烁频率和亮灭程度的两个定时器,创建方法是打开configuration.xml文件,在stacks中点击New stack,在Timers先后创建两个Timer General PWM(r_gpt),如下图
然后分别点击对应的Timer Stack后点击下方的属性,按照如下图的修改进行修改
然后按快捷键Ctrl+S保存修改的配置,点击右上角的Generate Project Content生成对应的程序到工程文件中。
之后是应用程序的编写,首先是创建控制LED灯亮灭的.h文件,这里定义成bsp_led.h,主要是对三个LED灯的亮灭控制,打开后可以发现都是宏定义。宏定义BLUE、GREEN和RED是三个LED灯对应的控制引脚端口号;TURN_GREEN_ON、TURN_GREEN_OFF和TURN_GREEN_TOGGLE分别是控制绿灯亮、灭和状态翻转的。
接下来是新建自己编写的.c和.h文件,可以在src文件夹中直接创建.c和.h文件。软件会自动识别并放入到工程当中一并进行编译。src文件夹一般是用户程序文件夹,hal_entry.c文件也在该文件夹下。
按键对应的文件有bsp_key.c和.h文件。其中.h文件宏定义KEY2_SW1_PIN和KEY1_SW2_PIN是对应两个按键引脚的端口号;KEY_ON和KEY_OFF分别表示按键按下和没有按下。.c文件定义按键扫描函数,入口参数是两个按键的宏定义KEY2_SW1_PIN和KEY1_SW2_PIN,返回的是按键是否被按下(KEY_ON和KEY_OFF)。
两个定时器的回调函数定义在gpt_blinker.c和.h文件中,函数led_duty_frequency_update和led_duty_cycle_update分别是更新控制LED闪烁频率和亮灭程度的定时器设置值;gpt_blinker_Init是两个定时器的初始化;gpt_blinker_callback和gpt_green_callback分别是两个定时器的回调函数。
hal_entry.c是用户函数的入口函数定义的.c文件。和其他的厂家不一样的就是用户函数的入口不是main而是hal_entry。在hal_entry函数中自己编写的函数如下。
gpt_blinker_Init();
while (1)
{
/* Enable access to the PFS registers. If using r_ioport module then register protection is automatically
* handled. This code uses BSP IO functions to show how it is used.
*/
if( Key_Scan(KEY1_SW2_PIN) == KEY_ON )
{
g_board_status.led_intensity = (uint16_t) ((g_board_status.led_intensity + 1) % BLINK_INTENSITY_SUM);
key_press_down_flag = 1;
}
if( Key_Scan(KEY2_SW1_PIN) == KEY_ON )
{
g_board_status.led_frequency = (uint16_t)((g_board_status.led_frequency + 1) % BLINK_FREQ_SUM);
key_press_down_flag = 1;
}
if (key_press_down_flag)
{
key_press_down_flag = 0;
led_duty_frequency_update();
led_duty_cycle_update();
}
}
首先是初始化两个定时器,然后是不断判断两个按键是否被按下。如果被按下就分别控制闪烁频率和亮度的定时器设置值,最后是根据按键被按下标志key_press_down_flag是否被置1来更新两个定时器的设置值。
两个按键分别修改的是g_board_status.led_intensity和g_board_status.led_frequency的值,这两个变量是取值于gpt_blinker.c文件中的g_pwm_dcs和g_pwm_rates数组的值。如果想修改闪烁频率和亮度的可选项,则可以在gpt_blinker.h文件中进行定义,并修改宏定义BLINK_INTENSITY_SUM和BLINK_FREQ_SUM的值就可以在两个数组中进行添加。
验证
编译和下载成功后的效果如下
VID_20241210_111900
对应程序源码
基础任务
quad-spi flash和octo-spi flash配置及读写速度测试
原理图
SPI和OSPIFlash对应的原理图如下所示
流程图
测试QSPI和OSPIFlash读写速度的方法是用定时器计算Flash读写一定数据量的时间,对应的简易流程图如下
配置
在新建工程中打开Stacks,按照如下顺序创建stack和属性配置,以及时钟的配置。首先是取消引脚的复用,如下图所示
配置好后依然是按Ctrl+S进行保存并点击Generate Project Content。
应用程序代码编写
这里参考ospi的例程,用J-Link RTT Viewer进行交互,所以可以把ospi例程下的SEGGER_RTT文件夹和common_utils.h。ospi_commands.c和.h文件、ospi_ep.c和.h文件、ospi_test.c和.h文件和qspi_test.c和.h文件是从_quickstart例程中复制下来并做了适当的修改的。
在hal_entry函数中编写如下代码
/* TODO: add your own code here */
fsp_err_t fsp_err;
uint32_t ospi_read_result = 0;
uint32_t ospi_write_result = 0;
uint32_t qspi_read_result = 0;
uint32_t qspi_write_result = 0;
timer_info_t timer_info;
uint32_t block_size_actual = 0;
APP_PRINT("\r\nenter the text block size specifying a 2K boundary (eg 24):");
while (1)
{
block_size_actual = process_input_data();
if ((block_size_actual >= 2) && (block_size_actual <= 64))
{
APP_PRINT("%d\r\n",block_size_actual);
fsp_err = R_GPT_Open(g_memory_performance.p_ctrl, g_memory_performance.p_cfg);
uint32_t ospi_performance_write_result = 0;
uint32_t ospi_performance_read_result = 0;
uint32_t timer_frequency;
R_GPT_InfoGet(g_memory_performance.p_ctrl, &timer_info);
timer_frequency = timer_info.clock_frequency;
ospi_performance_test (block_size_actual, &ospi_performance_write_result, &ospi_performance_read_result);
/* Multiply uSec calcs by 100, to avoid losses due to small results in integer maths
* * Scaled to fit within uint32_t */
ospi_write_result = ((100000000 / timer_frequency) * ospi_performance_write_result) / 100;
qspi_write_result = ((100000000 / timer_frequency) * qspi_write_test(block_size_actual)) / 100;
APP_PRINT("Writing to flash completed\r\n");
APP_PRINT("Reading the text block from external Quad-SPI and Octo-SPI flash memories...\r\n");
ospi_read_result = ((100000000 / timer_frequency) * ospi_performance_read_result) / 100;
qspi_read_result = ((100000000 / timer_frequency) * qspi_read_test(block_size_actual)) / 100;
APP_PRINT("Reading from flash completed\r\n");
R_GPT_Close(g_memory_performance.p_ctrl);
/* Handle error */
if (FSP_SUCCESS != fsp_err)
{
/* Fatal error */
APP_PRINT("ospi qspi read test failed\r\n");
}
APP_PRINT("block_size_actual Value is:%d",block_size_actual);
APP_PRINT("\r\n-------------------------------------------------");
APP_PRINT("\r\nOperation/Flash Quad-SPI Octa-SPI");
APP_PRINT("\r\n-------------------------------------------------");
APP_PRINT("\r\nWrite %6ld %6ld", qspi_write_result , ospi_write_result);
APP_PRINT("\r\nRead %6ld %6ld", qspi_read_result , ospi_read_result);
APP_PRINT("\r\n-------------------------------------------------");
APP_PRINT("\r\nNote: Times are in microseconds");
}
else
{
APP_PRINT("\r\nInvalid size, nenter the text block size specifying a 2K boundary (eg 24):");
}
}
逻辑和例程中的一样,只是用J-Link RTT打印输出信息和获取测试需要的数据。
验证
烧写到板卡后可以用J-Link RTT Viewer软件进行测试,目前输入两位数测试数据时需要通过复制才可以,输入一个数值后就会立马进行测试,这也是第一次使用J-Link RTT Viewer软件造成的。测试完成后可以继续输入数值进行测试。
对应程序源码
DAC配置生成波形及性能测试
配置
在新建工程的基础上进行如下图的配置
应用程序代码编写
在hal_entry函数编写如下代码
fsp_err_t err = FSP_SUCCESS;
/* Open the DAC channel */
err = R_DAC_Open (&g_dac_ctrl, &g_dac_cfg);
double w = 0,dac_value = 0;
/* handle error */
if (FSP_SUCCESS != err)
{
/* DAC module open failed */
while(1)
{
}
}
while (1)
{
w += (PI / 30);
if (w >= (2 * PI))
{
w = 0;
}
dac_value = (sin(w) + 1) / 2 * 4095;
R_DAC_Write(&g_dac_ctrl, (uint16_t)dac_value);
R_DAC_Start(&g_dac_ctrl);
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_MILLISECONDS);
}
代码也是参考直播时记录的代码。
验证
对应输出的引脚是P014,所以用示波器查看输出波形如下
对应程序源码
进阶任务
示例程序中新增命令打印信息
添加步骤
在s_menu_items数组中添加如下内容
{"followme" , Followme_display_menu},
最终的数组定义如下
/* Table of menu functions */
static st_menu_fn_tbl_t s_menu_items[] =
{
{"followme" , Followme_display_menu},
{"Kit Information" , kis_display_menu},
{"Web Server" , eth_emb_display_menu},
{"Network Name Lookup" , eth_www_display_menu},
{"Quad-SPI and Octo-SPI Speed Comparison" , ext_display_menu},
{"Cryptography and USB High speed (MSC)" , enc_display_menu},
{"Next Steps", ns_display_menu },
{"", NULL }
};
在menu_kis.c文件中添加如下函数的定义
/**********************************************************************************************************************
* Function Name: Followme_display_menu
* Description : .
* Return Value :
*********************************************************************************************************************/
test_fn Followme_display_menu(void)
{
int8_t c = -1;
//uint32_t value = 0;
sprintf (s_print_buffer, "%s%s", gp_clear_screen, gp_cursor_home);
/* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
print_to_console((void*)s_print_buffer);
print_to_console((uint8_t *)"Please enter a number(0~9):");
/* provide small delay so board_status should be up to date */
vTaskDelay (s_ticks_to_wait);
//xEventGroupSetBits (g_update_console_event, STATUS_DISPLAY_MENU_KIS);
while (CONNECTION_ABORT_CRTL != c)
{
c = input_from_console ();
if ((MENU_EXIT_CRTL == c) || (CONNECTION_ABORT_CRTL == c))
{
break;
}
else
{
sprintf (s_print_buffer, "%s%s", gp_clear_screen, gp_cursor_home);
/* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
print_to_console((void*)s_print_buffer);
sprintf (s_print_buffer, "You entered:%d", c - '0');
print_to_console((void*)s_print_buffer);
print_to_console((uint8_t *)"\r\n\r\n> Press space bar to return to MENU Or Continue entering numbers\r\n");
}
}
//xEventGroupClearBits (g_update_console_event, STATUS_DISPLAY_MENU_KIS);
return (0);
}
/**********************************************************************************************************************
End of function Followme_display_menu
*********************************************************************************************************************/
在menu_kis.h文件中添加如下函数的声明
extern test_fn Followme_display_menu(void);
验证
实现的效果是用串口软件打开后,先输入1进入自己编写的程序中,然后通过数值键输入任意的数字,输入后就立马打印输入的数值。目前没有做到输入更多的字符进行打印。效果如下图
对应程序源码
扩展任务
设计一个类似信号发生器功能的例程。可在示例程序上修改。通过命令或按键,设置DAC输出波形,可通过flash存储历史波形等信息
配置
配置和基础任务的配置一样,只不过基础任务是分成两个任务,需要合成一个作为扩展任务的使用,在此省略配置过程。
流程图
实现扩展任务的方式比较简单,首先是上电检查Flash中的数据是否是有效的,如果有效就按读取的值进行输出,否则可以按默认值或不输出。当有按键或串口有输入时就做对应的修改。流程图如下
应用程序代码编写
首先是用了基础任务的src文件夹下的程序。也添加了按键的.c和.h文件(和入门任务的程序一样)。hal_entry函数写的自定义函数如下
fsp_err_t err = FSP_SUCCESS;
double w = 0,dac_value = 0;
double freq = 10;
uint8_t dac_freq = 10;
/* Open the DAC channel */
err = R_DAC_Open (&g_dac_ctrl, &g_dac_cfg);
if (FSP_SUCCESS != err)
{
/* DAC module open failed */
APP_PRINT("DAC open falied\r\n");
R_DAC_Close(&g_dac_ctrl);
}
getDACsetferq(flash_value);
if (flash_value[0] != 0)
{
freq = flash_value[0];
}
APP_PRINT("read DAC value is:%d\r\n",dac_freq);
/* handle error */
while (1)
{
//qspi_DAC_input_value = process_input_data();
if( Key_Scan(KEY1_SW2_PIN) == KEY_ON )
{
dac_freq += 10;
freq = dac_freq;
flash_value[0] = freq;
saveDACfreq(flash_value);
APP_PRINT("read DAC value is:%d\r\n",dac_freq);
}
if( Key_Scan(KEY2_SW1_PIN) == KEY_ON )
{
dac_freq -= 10;
if (dac_freq <= 0)
{
dac_freq = 10;
}
flash_value[0] = freq;
saveDACfreq(flash_value);
APP_PRINT("read DAC value is:%d\r\n",dac_freq);
}
w += (PI / freq);
if (w >= (2 * PI))
{
w = 0;
}
dac_value = (sin(w) + 1) / 2 * 4095;
R_DAC_Write(&g_dac_ctrl, (uint16_t)dac_value);
R_DAC_Start(&g_dac_ctrl);
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_MICROSECONDS);
}
验证
实现的效果是一个按键按下会增加正玄波的频率;另一个按键被按下会减少频率值,且最小值为10。效果如下图
对应程序源码
|