本帖最后由 jf_37047872 于 2023-3-5 17:06 编辑
【作品概述】 本次参赛作品是一款基于瑞萨RA4M2开发板设计的多参数物联网采集终端,主要用于研究温湿度与光照对植物生长的影响。根据比赛规则,本次主要采用瑞萨R7FA4M2AD3CFP作为主控芯片,通过瑞萨HS3003低功耗MEMS高精度传感器采集温湿度数据,通过瑞萨ISL29035传感器采集环境光照强度数据,通过Dialog半导体公司(瑞萨电子全资子公司)的DA16200超低功耗WIFI模块实现相关数据定时上传至OneNet中国移动物联网开放平台,同时可通过0.96寸OLED显示屏实时查看终端当前数据。考虑到物联网采集终端部署环境可能缺少外接电源供应,本次设计采用2节18650锂电池作为移动电源,通过LDO及DCDC提供5V及12V各5组系统电源接口,带有电源电量指示功能,同时还通过USB Type-C接口实现5V输入升压充电功能。考虑到采集终端固件升级的便利性需求,实现了USB程序自升级功能。
【应用背景】 随着现代农业技术的不断进步,越来越多的植物可以通过人工方式进行培育和种植。在各类环境因素中,温湿度和光照强度对于植物的生长具有非常显著的影响,而且不同的植物对于温湿度和光照强度的要求更是具有很大的差异。在大面积、多品种开展同步对比试验的情况下,依靠人工方式每天记录这些环境参数已经几乎不可能,基于“物联网平台+边缘计算+传感器”的解决方案已成为该领域的标配。虽然应用需求旺盛,市场前景广阔,但目前在能耗、采样精度、通信、存储、便携性及边缘计算能力等方面依然存在诸多问题需要技术解决。 【方案设计】
1、整体架构:本项目隶属于智慧农业物联网解决方案的一部分,重点解决终端数据采集问题。详见下图。 2、硬件框图:本项目涉及的硬件包括独立电源、主控、温湿度传感器、光照强度传感器、WIFI通信模块和OLED显示屏等部分,下图展示了具体的系统结构、硬件型号和主要技术参数。 3、软件框架:本项目以“RASC配置器+KEILv5”方式开发,依托瑞萨官方提供的FSP(灵活软件配置包)代码框架,快速实现各类应用层逻辑及功能,整体框架及应用层各模块功能说明如下图所示。
【成果展示】 1、实现功能清单: (1)电源模块:2节18650锂电池独立供电,提供5组LDO降压5V输出接口及5组DCDC升压12V输出接口,提供TYPE-C充电接口,5V升压充电,提供5段电量指示功能,带USB接口OVP。本模块通过自制PCB方式设计制作。 (2)温湿度测量模块:实现温湿度参数测量、分辨率设置、获取当前传感器分辨率、获取传感器ID、切换工作模式(配置模式及工作模式)等功能。通过单一I2C硬件接口,以“挂载多个从设备”方式与主控通信,通过从设备地址切换实现多设备通信功能。 (3)光照强度测量模块:实现光照强度参数测量、单字节读写数据、批量读写数据、工作模式切换、ADC分辨率设置、设备ID获取等功能。由于本模块与温湿度测量模块从设备硬件地址相同,只能以INT引脚的中断信号通过切换模块工作模式实现单一I2C硬件接口多个从设备同时挂载目标。 (4)OLED显示模块:实现命令与数据的发送、屏幕开启和关闭、数据与字符显示、清屏等功能。根据项目目标,通过自定义屏幕显示字库,实现界面显示框架及各项参数动态显示。通过单一I2C硬件接口,以“挂载多个从设备”方式与主控通信,通过从设备地址切换实现多设备通信功能。 (5)WIFI通信模块:实现设备初始化、模式设置(AP、STA及AP+STA模式)、联网、数据发送、数据获取等功能。根据项目目标,通过调用互联网API接口实现北京时间获取;由于接口返回数据采用JSON格式,通过将KEIL官方JANSSON库移植到RA4M2主控,实现了结果数据解析。实现相关传感器测量结果实时传送至中移物联OneNET平台。 2、功能模块代码展示:考虑到本文篇幅有限,且网页编辑器代码展示效果有限(无缩进格式支持),本部分仅展示部分模块代码,完整KEIL工程及代码请下载附件。 (1)HS3003模块:
- /**********************************************************************************************************************
- 模块说明
- **********************************************************************************************************************/
- /*
- 描述:本模块为HS3003温湿度传感器驱动程序,该传感器采用I2C接口通信;HS3003硬件地址:0x44
- MCU接口描述:I2C接口选择:I2C3;I2C引脚:SDA:0409;SCL:0408
- 作者:yagi@2023-2-18
- 转载请注明出处,版权由@yagi所有
- */
- /**********************************************************************************************************************
- 文件引用
- **********************************************************************************************************************/
- #include "bsp_hs3003_i2c.h"
- #include "bsp_sci_i2c.h"
- #include "bsp_api.h"
- #include "common_data.h"
- #include "hal_data.h"
- //#define HS300X_DEBUG
- /**********************************************************************************************************************
- 全局变量定义
- **********************************************************************************************************************/
- double Humidity = 0.0; //湿度测量结果(百分数)
- double Temperature = 0.0; //温度测量结果
- extern volatile bool I2C_send_complete_flag; //I2C发送完成标志
- extern volatile bool I2C_receive_complete_flag; //I2C接收完成标志
- #ifdef HS300X_DEBUG
- uint8_t tmp01,tmp02,tmp03,tmp04;
- #endif
- /**********************************************************************************************************************
- 函数定义
- **********************************************************************************************************************/
- /******************************
- * @brief 测量函数
- * @param
- * @arg 无
- * @retval 无
- ******************************/
- void Measurement(void)
- {
- uint16_t timeout_ms = 100; //等待超时时间(100毫秒)
- //uint8_t Slaver_Addr = 0x88; //采用大端格式,bit0:读写方向(0),bit1~bit7:从设备地址(0x44)
- uint8_t p_dest[4] = {}; //接收从设备数据指针
- bool MeasurementCompleted = false; //测量完成标志位
- //向从设备(hs3003)发送测量请求
- R_SCI_I2C_Write (g_sci3_i2c.p_ctrl,NULL,0,false);
- I2C_send_complete_flag = false;
- //等待I2C发送完毕
- while ((true != I2C_send_complete_flag) && timeout_ms)
- {
- R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);
- timeout_ms--;
- }
- timeout_ms = 100;
- //向从设备(hs3003)获取数据,根据标志位状态,判断测量是否完成
- while(true != MeasurementCompleted)
- {
- R_SCI_I2C_Read (g_sci3_i2c.p_ctrl,&p_dest[0],4,false);
- I2C_receive_complete_flag = false;
- //等待I2C接收完毕
- while ((true != I2C_receive_complete_flag) && timeout_ms)
- {
- R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);
- timeout_ms--;
- }
- timeout_ms = 100;
- //判断测量标志位:00表示测量结果数据有效,01表示测量结构数据已过期
- if(0 == ((p_dest[0] & 0xC0) >> 6))
- {
- MeasurementCompleted = true;
- }
- }
- //计算测量结果
- #ifdef HS300X_DEBUG
- tmp01 = p_dest[0];
- tmp02 = p_dest[1];
- tmp03 = p_dest[2];
- tmp04 = p_dest[3];
- #endif
- Humidity = (double)(((p_dest[0] & 0x3F) << 8) | p_dest[1]) / (double)(16383U) * 100.0 ;
- Temperature = (((p_dest[2] << 8) | (p_dest[3] & 0xFC)) >>2 ) * 165.0 / (double)(16383U) - 40 ;
- }
- /******************************
- * @brief HS3003工作模式切换(上电后10ms内执行)
- * @param
- * @arg tmp_mode:工作模式
- * 设置模式:hs3003_cmd_enter_programming_mode
- * 普通模式:hs3003_cmd_enter_normal_mode
- * @retval 无
- ******************************/
- void Mode_Set(hs3003_cmd_t tmp_mode)
- {
- uint16_t timeout_ms = 100; //等待超时时间(100毫秒)
- uint8_t src[3] = {(uint8_t)tmp_mode,0x00,0x00}; //组装成完整指令
- R_SCI_I2C_Write (g_sci3_i2c.p_ctrl,&src[0],3,false); //发送指令
- I2C_send_complete_flag = false;
- //等待I2C发送完毕
- while ((true != I2C_send_complete_flag) && timeout_ms)
- {
- R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);
- timeout_ms--;
- }
- }
- /******************************
- * @brief 读取HS3003温湿度分辨率
- * @param
- * @arg tmp_type:温度/湿度选择
- * 湿度:0x01
- * 温度:0x02
- * @retval 分辨率:
- * 8位精度 : resolution_8bit
- * 10位精度 : resolution_10bit
- * 12位精度 : resolution_12bit
- * 14位精度 : resolution_14bit
- ******************************/
- hs3003_resolution_t Resolution_Get(uint8_t tmp_type)
- {
- uint8_t tmp_r[3]; //保存HS3003中当前分辨率结果
- uint16_t timeout_ms = 100; //等待超时时间(100毫秒)
- if(0x01 == tmp_type)
- {
- Mode_Set(hs3003_cmd_Humidity_read_reg); //发送读取湿度分辨率指令
- }
- else
- {
- Mode_Set(hs3003_cmd_Temperature_read_reg); //发送读取温度分辨率指令(默认)
- }
- R_SCI_I2C_Read (g_sci3_i2c.p_ctrl,&tmp_r[0],3,false); //接收HS3003返回的分辨率读取结果
- I2C_receive_complete_flag = false;
- while ((true != I2C_receive_complete_flag) && timeout_ms) //等待I2C接收完毕
- {
- R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);
- timeout_ms--;
- }
- if(0x81 == tmp_r[0]) //判断返回结果状态(0x81表示获取成功)
- {
- switch ((uint8_t)((tmp_r[1] & 0x0C) >> 2))
- {
- case 0x00:
- {
- return hs3003_resolution_8bit;
- break;
- }
- case 0x01:
- {
- return hs3003_resolution_10bit;
- break;
- }
- case 0x02:
- {
- return hs3003_resolution_12bit;
- break;
- }
- case 0x03:
- {
- return hs3003_resolution_14bit;
- break;
- }
- }
- }
- return hs3003_resolution_14bit; //默认返回结果为14位精度
- }
- /******************************
- * @brief 设置HS3003温湿度分辨率
- * @param
- * @arg tmp_type:温度/湿度选择
- * 湿度:0x01
- * 温度:0x02
- * @arg tmp_res:分辨率
- * 8位精度 : resolution_8bit
- * 10位精度 : resolution_10bit
- * 12位精度 : resolution_12bit
- * 14位精度 : resolution_14bit
- * @retval 无
- ******************************/
- void Resolution_Set(uint8_t tmp_type,hs3003_resolution_t tmp_res)
- {
- uint8_t tmp_r[3]; //保存HS3003中当前分辨率结果
- uint16_t timeout_ms = 100; //等待超时时间(100毫秒)
- if(0x01 == tmp_type)
- {
- Mode_Set(hs3003_cmd_Humidity_read_reg); //发送读取湿度分辨率指令
- }
- else
- {
- Mode_Set(hs3003_cmd_Temperature_read_reg); //发送读取温度分辨率指令(默认)
- }
- R_SCI_I2C_Read (g_sci3_i2c.p_ctrl,&tmp_r[0],3,false); //接收HS3003返回的分辨率读取结果
- I2C_receive_complete_flag = false;
- while ((true != I2C_receive_complete_flag) && timeout_ms) //等待I2C接收完毕
- {
- R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);
- timeout_ms--;
- }
- if(0x81 == tmp_r[0]) //判断返回结果状态(0x81表示获取成功)
- {
- if(0x01 == tmp_type)
- {
- tmp_r[0] = (uint8_t)hs3003_cmd_Humidity_write_reg; //写入湿度分辨率指令
- }
- else
- {
- tmp_r[0] = (uint8_t)hs3003_cmd_Temperature_write_reg; //写入温度分辨率指令
- }
- tmp_r[1] = (uint8_t)(tmp_res << 2); //分辨率值
- timeout_ms = 100; //设置等待超时时间(100毫秒)
- R_SCI_I2C_Write (g_sci3_i2c.p_ctrl,&tmp_r[0],3,false); //发送指令
- I2C_send_complete_flag = false;
- while ((true != I2C_send_complete_flag) && timeout_ms) //等待I2C发送完毕
- {
- R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);
- timeout_ms--;
- }
- }
- }
- /******************************
- * @brief 读取HS3003设备ID
- * @param
- * @arg 无
- * @retval 设备ID(32bit)
- ******************************/
- uint32_t ID_Get(void)
- {
- uint32_t tmp_id; //保存HS3003设备ID读取结果
- uint8_t tmp_r[3] = {0x00,0x00,0x00}; //保存I2C读取结果
- uint16_t timeout_ms = 100; //等待超时时间(100毫秒)
- Mode_Set(hs3003_cmd_Sensor_ID_UPPER_reg); //发送读取设备ID高16位指令
- R_SCI_I2C_Read (g_sci3_i2c.p_ctrl,&tmp_r[0],3,false); //接收I2C读取结果
- I2C_receive_complete_flag = false;
- while ((true != I2C_receive_complete_flag) && timeout_ms) //等待I2C接收完毕
- {
- R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);
- timeout_ms--;
- }
- timeout_ms = 100;
- if(0x81 == tmp_r[0]) //判断返回结果状态(0x81表示获取成功)
- {
- tmp_id = (uint32_t)((tmp_r[1] << 24) | (tmp_r[2] << 16)); //保存设备ID高16位
- }
- Mode_Set(hs3003_cmd_Sensor_ID_LOWER_reg); //发送读取设备ID低16位指令
- R_SCI_I2C_Read (g_sci3_i2c.p_ctrl,&tmp_r[0],3,false); //接收I2C读取结果
- I2C_receive_complete_flag = false;
- while ((true != I2C_receive_complete_flag) && timeout_ms) //等待I2C接收完毕
- {
- R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);
- timeout_ms--;
- }
- if(0x81 == tmp_r[0]) //判断返回结果状态(0x81表示获取成功)
- {
- tmp_id = (uint32_t)((tmp_r[1] << 8) | (tmp_r[2])); //保存设备ID低16位
- }
- return tmp_id;
- }
复制代码
(2)OLED模块:
- /**********************************************************************************************************************
- 模块说明
- **********************************************************************************************************************/
- /*
- 描述:本模块为OLED屏幕显示驱动程序,该显示屏采用I2C接口通信;ISL29035硬件地址:0x78
- MCU接口描述:I2C接口选择:I2C3;I2C引脚:SDA:0409;SCL:0408
- 作者:yagi@2023-2-20
- 转载请注明出处,版权由@yagi所有
- */
- /**********************************************************************************************************************
- 文件引用
- **********************************************************************************************************************/
- #include "bsp_oled_i2c.h"
- #include "bsp_sci_i2c.h"
- #include "bsp_api.h"
- #include "common_data.h"
- #include "hal_data.h"
- #include "bsp_font.h"
- //#define OLED_DEBUG
- /**********************************************************************************************************************
- 全局变量定义
- **********************************************************************************************************************/
- extern volatile bool I2C_send_complete_flag; //I2C发送完成标志
- extern volatile bool I2C_receive_complete_flag; //I2C接收完成标志
- /**********************************************************************************************************************
- 函数定义
- **********************************************************************************************************************/
- /******************************
- * @brief oled写命令
- * @param
- * @arg tmp_cmd:命令
- * @retval 无
- ******************************/
- void oled_write_cmd(uint8_t tmp_cmd)
- {
- uint16_t timeout_ms = 100; //等待超时时间(100毫秒)
- uint8_t p_dest[2] = {0x00,tmp_cmd}; //指令存放空间
- R_SCI_I2C_Write (g_sci3_i2c.p_ctrl,&p_dest[0],2,false); //发送指令
- I2C_send_complete_flag = false;
- //等待I2C发送完毕
- while ((true != I2C_send_complete_flag) && timeout_ms)
- {
- R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);
- timeout_ms--;
- }
- }
- /******************************
- * @brief oled写数据
- * @param
- * @arg tmp_data:数据
- * @retval 无
- ******************************/
- void oled_write_data(uint8_t tmp_data)
- {
- uint16_t timeout_ms = 100; //等待超时时间(100毫秒)
- uint8_t p_dest[2] = {0x40,tmp_data}; //数据存放空间
- R_SCI_I2C_Write (g_sci3_i2c.p_ctrl,&p_dest[0],2,false); //发送数据
- I2C_send_complete_flag = false;
- //等待I2C发送完毕
- while ((true != I2C_send_complete_flag) && timeout_ms)
- {
- R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);
- timeout_ms--;
- }
- }
- /******************************
- * @brief oled初始化
- * @param
- * @arg 无
- * @retval 无
- ******************************/
- void oled_init(void)
- {
- R_BSP_SoftwareDelay(200U, BSP_DELAY_UNITS_MILLISECONDS); //延时200ms
- oled_write_cmd(0xA8); //设置分辨率
- oled_write_cmd(0x3F); //128*64
- oled_write_cmd(0xDA); //设置COM硬件引脚配置,适应分辨率
- oled_write_cmd(0x12); //128*64
- oled_write_cmd(0xD3); //设置显示偏移
- oled_write_cmd(0x00); //0x00为没有偏移
- oled_write_cmd(0x40); //设置显示存储器开始行(40-7F,对应行0-63)
- oled_write_cmd(0xA1); //设置SEGMENT重映射
- oled_write_cmd(0x81); //设置对比度
- oled_write_cmd(0xFF); //00-FF,数值越大对比度越高
- oled_write_cmd(0xA4); //恢复RAM内容显示(RESET),0xA5:进入显示开启状态(不管RAM内容)
- oled_write_cmd(0xA6); //设置显示方式:正常显示,0xA7:反向显示
- oled_write_cmd(0xD5); //设置显示时钟分频([A0:A3])及振荡器频率([A7:A4])
- oled_write_cmd(0xF0); //(RESET:10000000)
- oled_write_cmd(0x8D); //充电泵设置(使能充电)
- oled_write_cmd(0x14); //0x14:允许在显示开启的时候使用 0x10:不允许在显示开启的时候使用
- oled_write_cmd(0xAE); //显示关
- oled_write_cmd(0x20); //设置内存地址模式
- oled_write_cmd(0x02); //0x00:水平模式;0x01:垂直模式;0x02:页地址模式(RESET)
- oled_write_cmd(0xB0); //设置GDDRAM页起始地址(页地址模式:B0-B7)
- oled_write_cmd(0xC8); //设置COM扫描方式(0xC0:上下反置左到右,0xC8:正常右到左)
- oled_write_cmd(0x00); //设置列的起始地址(页地址模式)
- oled_write_cmd(0x10); //设置列的最低有效位(LSB)地址(页地址模式)
- oled_write_cmd(0x40); //设置显示存储器开始行(40-7F,对应行0-63)
- oled_write_cmd(0xD9); //设置预充电时间
- oled_write_cmd(0x22); //预充电时间
- oled_write_cmd(0xDB); //设置取消选择级别
- oled_write_cmd(0x20); //0.65*VCC:0x00;0.77*VCC:0x20(RESET);0.83*VCC:0x30
- oled_write_cmd(0xAF); //显示开
-
- oled_clear();
- oled_off();
- }
- /******************************
- * @brief oled清屏
- * @param
- * @arg 无
- * @retval 无
- ******************************/
- void oled_clear(void)
- {
- for(uint8_t i = 0;i<8;i++)
- {
- oled_write_cmd(0xB0 | i); //设置GDDRAM页起始地址(页地址模式)
- oled_write_cmd(0x00); //设置低列的起始地址(页地址模式)
- oled_write_cmd(0x10); //设置高列的起始地址(页地址模式)
- for(uint8_t j = 0;j<128;j++)
- {
- oled_write_data(0x00);
- }
- }
- }
- /******************************
- * @brief oled屏幕测试
- * @param
- * @arg 无
- * @retval 无
- ******************************/
- void oled_test(void)
- {
- for(uint8_t i = 0;i<8;i++)
- {
- oled_write_cmd(0xB0 | i); //设置GDDRAM页起始地址(页地址模式)
- oled_write_cmd(0x00); //设置低列的起始地址(页地址模式)
- oled_write_cmd(0x10); //设置高列的起始地址(页地址模式)
- for(uint8_t j = 0;j<128;j++)
- {
- oled_write_data(0x01);
- }
- }
- }
- /******************************
- * @brief oled开启
- * @param
- * @arg 无
- * @retval 无
- ******************************/
- void oled_on(void)
- {
- oled_write_cmd(0x8D); //充电泵设置(使能充电)
- oled_write_cmd(0x24); //0x14:允许在显示开启的时候使用 0x10:不允许在显示开启的时候使用
- oled_write_cmd(0xAF); //显示开
- }
- /******************************
- * @brief oled关闭
- * @param
- * @arg 无
- * @retval 无
- ******************************/
- void oled_off(void)
- {
- oled_write_cmd(0x8D); //充电泵设置(使能充电)
- oled_write_cmd(0x24); //0x14:允许在显示开启的时候使用 0x10:不允许在显示开启的时候使用
- oled_write_cmd(0xAE); //显示关
- }
- /******************************
- * @brief oled显示
- * @param
- * @arg x:起始页编号
- * @arg y:起始列编号
- * @arg g:字符高度(页)
- * @arg k:字符宽度(位)
- * @arg *data:指向存放显示数据空间的指针
- * @retval 无
- ******************************/
- void oled_display(uint8_t x,uint8_t y,uint8_t g,uint8_t k,uint8_t * data)
- {
- for(uint8_t i = 0;i<g;i++)
- {
- oled_write_cmd(0xB0 | (i + x));
- oled_write_cmd(0x10 + (y >> 4 & 0x0F));
- oled_write_cmd(y & 0x0F);
- for(uint8_t j = 0;j<k;j++)
- {
- oled_write_data(*data++);
- }
- }
- }
- /******************************
- * @brief oled显示3位数字(16*8)
- * @param
- * @arg x:起始页编号
- * @arg y:起始列编号
- * @arg n:位数(取值范围:2-5)
- * @arg tmp_num:指向存放显示数据空间的指针
- * @retval 无
- ******************************/
- void oled_display_num(uint8_t x,uint8_t y,uint8_t n,uint8_t tmp_num)
- {
- switch (n)
- {
- case 0x02:
- {
- oled_display(x,y,2,8,font_char[tmp_num/10]);
- oled_display(x,y+8,2,8,font_char[tmp_num%10]);
- break;
- }
- case 0x03:
- {
- oled_display(x,y,2,8,font_char[tmp_num/100]);
- oled_display(x,y+8,2,8,font_char[tmp_num%100/10]);
- oled_display(x,y+16,2,8,font_char[tmp_num%10]);
- break;
- }
- case 0x04:
- {
- oled_display(x,y,2,8,font_char[tmp_num/1000]);
- oled_display(x,y+8,2,8,font_char[tmp_num%1000/100]);
- oled_display(x,y+16,2,8,font_char[tmp_num%100/10]);
- oled_display(x,y+24,2,8,font_char[tmp_num%10]);
- break;
- }
- case 0x05:
- {
- oled_display(x,y,2,8,font_char[tmp_num/10000]);
- oled_display(x,y+8,2,8,font_char[tmp_num%10000/1000]);
- oled_display(x,y+16,2,8,font_char[tmp_num%1000/100]);
- oled_display(x,y+24,2,8,font_char[tmp_num%100/10]);
- oled_display(x,y+32,2,8,font_char[tmp_num%10]);
- break;
- }
- default:
- break;
- }
- }
复制代码
3、主要功能演示效果: (暂略)
【设计心得】 通过本项目的设计制作,基本掌握了瑞萨RA系列产品的开发方式和代码框架体系。与之前使用的意法半导体、兆易创新、国民技术、武汉芯源等同类基于ARM Cortex-M系列MCU产品相比,作为基于ARM内核的MCU产品起步较晚的瑞萨,目前已具有非常完整产品线,包括基于ARM Cortex-M4、M23、M33、M85等内核MCU产品,每种内核又包括入门(E)、增强(M)、低功耗(L)、联网应用(W)、电机(T)等系列产品。与此同时,瑞萨官方提供的开发体系非常成熟,支持e2studio和RASC+等两种开发方式,后者支持主流嵌入式开发平台(包括KEIL及IAR等)。依托于完整的FSP(灵活配置软件包)代码框架,极大减少了用户开发所需时间和代码编写工作量,有效提升了项目开发效率。例如:本项目中使用到的各类板载外设,包括GPIO、UART、I2C、RCU、AGT等,只需引用HAL库相关文件,通过调用其中的设备CTRL、CFG、API等对象(这部分对象的声明和定义已通过RASC可视化配置后自动生成代码),仅需寥寥几行代码即可轻松实现相关功能,相较于其他厂商基于寄存器、库函数及HAL库等开发方式,效率之高不言而喻。此外,瑞萨RA系列MCU产品在低功耗、触摸应用、RTOS及安全协议等方面具有显著的技术优势。 在本项目的制作过程中,也发现了一些有待完善的问题。一是FSP代码体系较为庞杂,要发挥其强大的开发辅助作用,需要开发人员熟悉其代码框架。同时,官方提供的FSP说明文档中描述的文件体系结构,仅适用于采用e2studio系统进行开发的场景,而KEIL或IAR中的文件体系与说明文档存在较大差异,对于刚接触的新手并不是十分友好。为此,我在论坛里专门发表了一篇帖子(【RA4M2设计挑战赛】第一步:熟悉瑞萨的代码框架(非常重要) ),以帮助大家尽快熟悉FSP体系。二是板载的部分功能(例如:触摸按键)必需使用特定的编程器(JLINK V9以上),而这些设备的价格不菲,且本次活动中官方并未提供,在一定程度上影响和制约了学生等群体对这些功能的体验和学习,希望在未来的活动中能提供更多支持。
|