这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 瑞萨板卡RA6M4试用报告

共12条 1/2 1 2 跳转至

瑞萨板卡RA6M4试用报告

菜鸟
2025-02-15 19:53:26     打赏

1. 前言

前言

很荣幸参加了这次瑞萨 CPK-RA6M4 的试用活动,感谢EEPW提供的这次宝贵机会。作为一名嵌入式开发爱好者,我一直对瑞萨的 MCU 产品线充满兴趣,这次能够亲身体验 CPK-RA6M4 的强大功能,我感到非常兴奋。



开箱

厚厚的泡沫板中间夹着CPK-RA6M4本体和两本书,可以说很细心了。

Pasted image 20250215183031.png

Pasted image 20250215183048.png

《基础知识》里面包含了《评估板快速入门》的内容。



再此分享一点试用心得:

欢迎讨论。






关键词: 瑞萨     RAM64          串口     FSP     OLED     I    

菜鸟
2025-02-15 19:56:41     打赏
2楼

2. 资料

2.1 RA产品家族

Pasted image 20250116230829.png

采用 Arm Cortex-M 内核的 RA 系列 32 位 MCU


2.2 RA6M4 mcu

RA6M4 使用 200MHz Arm Cortex-M33 TrustZone 内核,并集成了以太网和 OctaSPI(用于扩展扩展闪存与RAM)。

Pasted image 20250116232610.png

2.3 CPK-RA6M4

CPK-RA6M4 是用于中国本地的评估板。


板载资源

image-20250119202803653image-20250119202803653.png

命名方法:

图ra_mcu_naming.png


RA6M4 存储器映射

Pasted image 20250118000226.png


2.4 FSP 简介

FSP 是瑞萨提供的用于MCU开发的固件库。全称为 “Flexible Software Package”,中文译为“灵活配置软件包”。

FSP 旨在以较低的内存占用量提供快速高效的驱动程序和协议栈。 FSP 集成了中间件协议栈、独立于 RTOS 的硬件抽象层(HAL)驱动程序, 以及最基础的板级支持包(BSP)驱动程序。FSP 还支持 FreeRTOS™ 实时操作系统(RTOS)。


2.5 资料汇总

文档

教程



菜鸟
2025-02-15 19:57:15     打赏
3楼

3. 开发环境搭建

可以使用官方的IDE:e2studio  或者 keil。

e2studio自带了FSP,keil需要安装RASC才能配置芯片和生成FSP库代码。


我直接用官方IDE,找了一个老版本v2022-07 setup_fsp_v4_0_0_e2s_v2022-07.exe 直接安装即可。

界面如下:

image-20250215185719210image-20250215185719210.png




菜鸟
2025-02-15 19:58:24     打赏
4楼

4. hello world

点灯。

4.1 新建项目

新建一个RA C/C++ 项目 :

Pasted image 20250119200634.png


器件选择:R7FA6M4AF3CFB 144pins

Pasted image 20250205230946.png

next next 一通之后,(记得选 NO RTOS) …… 确定。


4.2 运行和调试

RA推荐的是J-Link,板子自带J-Link 很香。

image-20250119225930116image-20250119225930116.png


点锤子开始编译,点调试就能进入调试模式:

image-20250119231419111image-20250119231419111.png

如果需要配置,则点:

image-20250119225816911image-20250119225816911.png

image-20250119230535615image-20250119230535615.png

确保这里为J-Link ARM,点击【Debug】就可以进入调试模式。


运行时时钟问题 在运行时一直不会执行hal_entry() 函数,会停到这里 等待PLL稳定。

Pasted image 20250120002549.png

看看时钟配置

Pasted image 20250121234701.png


PLL时钟源来自外部晶振,然而,板子上的X1是没有焊接的

image-20250215190305960image-20250215190305960.png

所以改一下,用片上晶振(HOCO)就可以了

Pasted image 20250121235015.png

点灯代码如下:

void hal_entry(void)
{
   // 取消写保护
   R_PMISC->PWPR = 0;                               ///< Clear BOWI bit - writing to PFSWE bit enabled
R_PMISC->PWPR = 1U << BSP_IO_PWPR_PFSWE_OFFSET;

// 配置LED引脚对应的PFS寄存器
   R_PFS->PORT[BSP_IO_PORT_01_PIN_06>>8].PIN[BSP_IO_PORT_01_PIN_06 & 0xFF].PmnPFS =
      IOPORT_CFG_PORT_DIRECTION_OUTPUT | IOPORT_CFG_PORT_OUTPUT_LOW;

   while(1)
{
 /* 翻转LED灯:LED1 */
 R_PORT1->PODR ^= 1<<(BSP_IO_PORT_01_PIN_06 & 0xFF);
 R_BSP_SoftwareDelay(1000BSP_DELAY_UNITS_MILLISECONDS);
}

}




菜鸟
2025-02-15 19:59:53     打赏
5楼

5. RTOS下检测按键和点灯

5.1 新建FreeRTOS项目

略,看文档中的配置。到选择系统那一步选择FreeRTOS即可。


5.2 使用FSP配置GPIO

led 连接的 P106 引脚,配置如下

Pasted image 20250205235123.png

在线程中增加代码:

void led_thread_entry(void *pvParameters)
{
   FSP_PARAMETER_NOT_USED (pvParameters);

   /* TODO: add your own code here */
   while (1)
   {
       //vTaskDelay (1);
       R_IOPORT_PinWrite(&g_ioport_ctrlBSP_IO_PORT_01_PIN_06BSP_IO_LEVEL_LOW);
       R_BSP_SoftwareDelay(1BSP_DELAY_UNITS_SECONDS); //延时1秒
       R_IOPORT_PinWrite(&g_ioport_ctrlBSP_IO_PORT_01_PIN_06BSP_IO_LEVEL_HIGH);

       R_BSP_SoftwareDelay(1BSP_DELAY_UNITS_SECONDS); //延时1秒
   }
}

5.3 使用按键控制led

#include "led_thread.h"
/* LED Thread entry function */
/* pvParameters contains TaskHandle_t */
void led_thread_entry(void *pvParameters)
{
   FSP_PARAMETER_NOT_USED (pvParameters);

   uint8_t led_level = BSP_IO_LEVEL_HIGH;

   // 打开并启用 IRQ0
   g_external_irq0.p_api->open(g_external_irq0.p_ctrlg_external_irq0.p_cfg);
   g_external_irq0.p_api->enable(g_external_irq0.p_ctrl);
   /* 也可以用下面的方法
   // Open ICU module
      err = R_ICU_ExternalIrqOpen(&g_external_irq9_ctrl, &g_external_irq9_cfg);
   // 允许中断
      err = R_ICU_ExternalIrqEnable(&g_external_irq9_ctrl);
   */

   while (1)
   {

       R_IOPORT_PinWrite(&g_ioport_ctrlBSP_IO_PORT_01_PIN_06led_level);
       if(led_level == BSP_IO_LEVEL_HIGH){
           led_level = BSP_IO_LEVEL_LOW;
       }else{
           led_level = BSP_IO_LEVEL_HIGH;
       }
       xSemaphoreTake(g_s1_semaphoreportMAX_DELAY);
   }
}
/* Callback function */
void external_irq0_callback(external_irq_callback_args_t *p_args)
{
   FSP_PARAMETER_NOT_USED (p_args);
   xSemaphoreGiveFromISR(g_s1_semaphoreNULL);
}




菜鸟
2025-02-15 20:00:50     打赏
6楼

6. 串口打印

可以通过配置USB中间件来进行串口打印。(但是我没有配置成功) 也可以直接配置串口并且重定向print可参考: 瑞萨RA开发(1)----使用串口进行打印电子时钟制作(瑞萨RA)(1)----使用串口进行打印

6.1 配置USB外设

选择New Stack -> Connectivity -> USB PCDC

Pasted image 20250210224944.png


将添加4个模块到项目中:

image-20250210225338237image-20250210225338237.png

  • 用于全速USB的PCDC驱动 (r_usb_pcdc)

  • 基本USB驱动 (r_usb_basic)

  • 两个粉色的模块是,用于传输和接收数据的DMAC(直接内存访问控制器)


现在r_usb_basic 红色警告是因为UCLK(USB模块的时钟必须为48MHz),配置时钟为48MHz即可。

使用内部时钟配置锁相环。PLL2配置为240M,PLL最大为200M速率。

Pasted image 20250210231941.png

疑惑:

Pasted image 20250210235108.png

PLL也配好了,但是这里显示不支持。还有好几个设置不能更改。放弃!

6.2 配置串口

选择这两个引脚来做串口 P101(TX0) P410(RX0)

Pasted image 20250211001504.png

(为什么不把P101 和 P100 放一块呢,本来直接用这两个引脚最好)

Pasted image 20250211001612.png

增加串口模块

Pasted image 20250211001150.png

配置:

image-20250211002025196image-20250211002025196.png

PIN配置:

image-20250211002105699image-20250211002105699.png


重定向printf配置:

在 project -> c/c++ project settings 中 删掉配置(--specs=rdimon.specs

image-20250211002552934image-20250211002552934.png

原因是:如果在链接器脚本文件中使用了--specs=rdimon.specs参数,则编译器会使用rdimon.specs文件中的系统调用函数来实现printf函数。 在这种情况下,printf函数的输出会被重定向到一个固定的地址


串口代码:

#include "hal_data.h"
#include <stdio.h>
FSP_CPP_HEADER
void R_BSP_WarmStart(bsp_warm_start_event_t event);
FSP_CPP_FOOTER

// 发送回调函数
fsp_err_t err = FSP_SUCCESS;
volatile bool uart_send_complete_flag = false;
void uart0_callback (uart_callback_args_t * p_args)
{
   if(p_args->event == UART_EVENT_TX_COMPLETE)
   {
       uart_send_complete_flag = true;
   }
}

// printf 重定向
#ifdef __GNUC__                                 //串口重定向
   #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
   #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif

PUTCHAR_PROTOTYPE
{
       err = R_SCI_UART_Write(&g_uart0_ctrl, (uint8_t *)&ch1);
       if(FSP_SUCCESS != err__BKPT();
       while(uart_send_complete_flag == false){}
       uart_send_complete_flag = false;
       return ch;
}
int _write(int fd,char *pBuffer,int size)
{
   for(int i=0;i<size;i++)
   {
       __io_putchar(*pBuffer++);
   }
   return size;
}

/*******************************************************************************************************************//**
* main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used.  This function
* is called by main() when no RTOS is used.
**********************************************************************************************************************/
void hal_entry(void)
{
   // 开启并初始化UART
   err = R_SCI_UART_Open(&g_uart0_ctrl&g_uart0_cfg);
   assert(FSP_SUCCESS == err);

   while(1){
       printf("test");

       //R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_MILLISECONDS);
   }

}




菜鸟
2025-02-15 20:01:55     打赏
7楼

7. I2C 驱动 OLED


7.1 IIC 配置

添加 IIC 模块

Pasted image 20250211234316.png

配置IIC:

Pasted image 20250211235819.png


Pasted image 20250211235904.png


7.2 I2C 回调函数

回调函数


i2c_master_event_t i2c_event ;


void IIC_master_callback(i2c_master_callback_args_t *p_args)
{
   i2c_event = p_args->event;
   if(I2C_MASTER_EVENT_RX_COMPLETE == p_args->event)
   {
       // 接收完成
       // gI2CRxCplt = true;

   }
   else if(I2C_MASTER_EVENT_TX_COMPLETE == p_args->event)
   {
       // 发送完成
       // gI2CTxCplt = true;
   }

}


通过 I2C_MASTER_EVENT_TX_COMPLETE == p_args->event 来判断发送完成。

7.3 写数据和写命令

// IIC Write Command
void Write_IIC_Command(unsigned char IIC_Command)
{
   uint8_t ii[2]={0x00,0x00};
   ii[1= IIC_Command;


   err = R_IIC_MASTER_Write(&g_i2c_master0_ctrlii0x02false);
assert(FSP_SUCCESS == err);

while ((I2C_MASTER_EVENT_TX_COMPLETE != i2c_event&& timeout_ms1>0)
{
 R_BSP_SoftwareDelay(1UBSP_DELAY_UNITS_MICROSECONDS);
 timeout_ms1--;
}
if (I2C_MASTER_EVENT_ABORTED == i2c_event)
{
 __BKPT(0);
}
   
i2c_event = I2C_MASTER_EVENT_ABORTED;
timeout_ms1           = 1000;

}
/**********************************************
// IIC Write Data
**********************************************/
void Write_IIC_Data(unsigned char IIC_Data)
{
   uint8_t ii[2]={0x40,0x00};
   ii[0= 0x40;
   ii[1= IIC_Data;
   err = R_IIC_MASTER_Write(&g_i2c_master0_ctrlii0x02false);
   assert(FSP_SUCCESS == err);
         
   while ((I2C_MASTER_EVENT_TX_COMPLETE != i2c_event&& timeout_ms1>0){
 R_BSP_SoftwareDelay(1UBSP_DELAY_UNITS_MICROSECONDS);
              timeout_ms1--;
       }
 if (I2C_MASTER_EVENT_ABORTED == i2c_event)
 {
  __BKPT(0);
 }
         
 i2c_event = I2C_MASTER_EVENT_ABORTED;
 timeout_ms1           = 1000;
}

void OLED_WR_Byte(unsigned dat,unsigned cmd)
{
   if(cmd){
 Write_IIC_Data(dat);
   }
   else {
    Write_IIC_Command(dat);
}
}


其他OLED方法封装一下即可。




菜鸟
2025-02-15 20:02:43     打赏
8楼

8. 光强度采集

板子上有一个 ISL29035 感光模块,可以读取可见光强度。

参考:

8.1 I2C配置

原理图

Pasted image 20250213165303.png

设备地址为:0x44(0b1000100)

Pasted image 20250213165345.png


写数据

设备地址+操作地址+数据

Pasted image 20250213171716.png

// 写数据
void ISL29035_writeRegister( int reg_address, uint8_t val) {

   uint8_t ii[2]={reg_address, val};


   err_isl29035 = R_IIC_MASTER_Write(&g_i2c_isl29035_ctrl, ii, 0x02, false);
   assert(FSP_SUCCESS == err_isl29035);
   /* Since there is nothing else to do, block until Callback triggers*/
   //while ((I2C_MASTER_EVENT_TX_COMPLETE != i2c_event) && timeout_ms)
   while ((I2C_MASTER_EVENT_TX_COMPLETE != i2c_isl29035_event) && timeout_ms2>0)
   {
      R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MICROSECONDS);
      timeout_ms2--;
   }
   if (I2C_MASTER_EVENT_ABORTED == i2c_isl29035_event)
   {
      __BKPT(0);
   }
   /* Read data back from the I2C slave */
   i2c_isl29035_event = I2C_MASTER_EVENT_ABORTED;
   timeout_ms2           = 500;
}

读数据 设备地址+操作地址+设备地址+数据读取

Pasted image 20250213173617.png

Pasted image 20250213171820.png



// 读数据
uint8_t DigitalLightISL29035_readRegister(uint8_t reg_address) {

   uint8_t value;
   err_isl29035 = R_IIC_MASTER_Write(&g_i2c_isl29035_ctrl, &reg_address, 0x01, false);
   assert(FSP_SUCCESS == err_isl29035);
   /* Since there is nothing else to do, block until Callback triggers*/
   while ((I2C_MASTER_EVENT_TX_COMPLETE != i2c_isl29035_event) && timeout_ms2>0)
   {
       R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MICROSECONDS);
       timeout_ms2--;
       }
   if (I2C_MASTER_EVENT_ABORTED == i2c_isl29035_event)
   {
       __BKPT(0);
       }
   /* Read data back from the I2C slave */
   i2c_isl29035_event = I2C_MASTER_EVENT_ABORTED;
   timeout_ms2 = 500;

   /* Read data from I2C slave */
   err_isl29035 = R_IIC_MASTER_Read(&g_i2c_isl29035_ctrl, &value, 0x01, false);
   assert(FSP_SUCCESS == err_isl29035);
   while ((I2C_MASTER_EVENT_RX_COMPLETE != i2c_isl29035_event) && timeout_ms2)
   {
       R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);
       timeout_ms2--;
   }
   if (I2C_MASTER_EVENT_ABORTED == i2c_isl29035_event)
   {
       __BKPT(0);
   }

   i2c_isl29035_event = I2C_MASTER_EVENT_ABORTED;
   timeout_ms2           = 500;
   return value;
}


8.2 初始化和读取数据


int DigitalLightISL29035_init(void) {
   uint8_t reg = 0;

   // 读取设备ID
   reg = ISL29035_readRegister(CHIP_ID);//CHIP_ID->0x0f

   uint8_t chip_id = (reg >> 3& 0x7;
   if (chip_id != 0x5) {
       return -1;
   }

   //清除BOUT位
   ISL29035_writeRegister(CHIP_IDreg & 0x7f);//CHIP_ID->0x0f

   //确保芯片处于停止模式
   ISL29035_writeRegisterCOMMAND_I0);//COMMAND_I->0x00
   //设置分辨率

   ISL29035_writeRegister(COMMAND_II0x06 );//COMMAND_2->0x01=0x06 = 0b00000110 adc分辨率01为12位 范围10=16000,
   // 范围和分辨率的时间
   full_scale_lux_range = 2// 1000 4000 16000 64000
   integration_time = 1// 16 12 8 4
   //设置为单次模式
   ISL29035_writeRegisterCOMMAND_IOPMODE_ALS_ONCE);//COMMAND_I->0x00 = 0b00100000 010  周期内仅测量一次

   return 0;
}

uint32_t DigitalLightISL29035_readIRLux(void) {
   uint16_t data = 0;
   uint8_t lh;
   //设置为单次模式
   ISL29035_writeRegisterCOMMAND_IOPMODE_ALS_ONCE);
   //等待时间
   if(integration_time==0)
   {
       R_BSP_SoftwareDelay(105BSP_DELAY_UNITS_MILLISECONDS);
   }
   else if(integration_time==1 || integration_time==2)
   {
       R_BSP_SoftwareDelay(7BSP_DELAY_UNITS_MILLISECONDS);
   }
   else if(integration_time==3)
   {
       R_BSP_SoftwareDelay(1BSP_DELAY_UNITS_MILLISECONDS);
   }

   l=ISL29035_readRegister(DATA_L);//DATA_L->0x02
   h=ISL29035_readRegister(DATA_H);//DATA_H->0x03

   data=(h << 8| l;

   uint32_t ranges=0;
   if(full_scale_lux_range==0)
       ranges=1000;
   else if(full_scale_lux_range==1)
       ranges=4000;
   else if(full_scale_lux_range==2)
       ranges=16000;
   else if(full_scale_lux_range==3)
       ranges=64000;

   uint32_t adc_count_max=0;
   if(integration_time==0)
       adc_count_max=65536;
   else if(integration_time==1)
       adc_count_max=4096;
   else if(integration_time==2)
       adc_count_max=256;
   else if(integration_time==3)
       adc_count_max=16;
   return ranges * (uint32_t)data /adc_count_max;


}


8.3 显示数据到OLED

void hal_entry(void)
{

   char msg[100= {0,};

   // oled i2c 初始化
   fsp_err_t err = R_IIC_MASTER_Open(&g_i2c_master0_ctrl&g_i2c_master0_cfg);
   assert(FSP_SUCCESS==err);

   // ISL29035 i2c 初始化
   err = R_IIC_MASTER_Open(&g_i2c_isl29035_ctrl&g_i2c_isl29035_cfg);
   assert(FSP_SUCCESS==err);


   // oled
   OLED_Init();
   OLED_Clear();

   OLED_ShowString(2,0,"hello,"16);
   OLED_ShowZh(2+6*800); // 瑞 6*8为上面字符宽度
   OLED_ShowZh(2+6*8+16+201); // 萨 +16(上个汉字宽度)+2(间隙)
   // 恭喜发财
   OLED_ShowZh(2132);
   OLED_ShowZh(2+(2+16)*1133);
   OLED_ShowZh(2+(2+16)*2134);
   OLED_ShowZh(2+(2+16)*3135);



   // 光电传感器
   DigitalLightISL29035_init();

   while(1){
       lux = DigitalLightISL29035_readIRLux();
       sprintf(msg"lux=%04d  "lux);
       OLED_ShowString(20,10msg16);
       R_BSP_SoftwareDelay(1000BSP_DELAY_UNITS_MILLISECONDS);
   }

光强度:

8346021ced712d2d3d53cafd92c79bf.jpg


1baf0b590a2e438c68ac83546b449b0.jpg







菜鸟
2025-02-15 20:03:32     打赏
9楼

9. 动态显示福

大过年的,显示个福,旋转的福。福到了。

参考:Oled实现动图显示——篮球少年


素材

fudao.gif


拆分: 在这个在线网站处理 https://ezgif.com/split

Pasted image 20250213231957.png

图很多,只要最左侧一列。后面发现边框好看但是转换后基本没有了,所以只取中间。这个软件也可以裁剪

Pasted image 20250213234123.png

取其中8张。

使用Image2Lcd转换

Pasted image 20250213234349.png

将图片保存为 x.bmp

使用 PCtoLCD 软件转换

Pasted image 20250214134113.png

注:如果生成的数据有大括号记得去掉。

绘制图片:

const unsigned char gImage_a1[128= {
  0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xF0,0xF8,0x38,0x3C,0x7C,0xFC,0xFC,0x7E,0x7E
 ,0x7E,0x7C,0x7C,0x7C,0x7C,0x7C,0x78,0x78,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00
 ,0x00,0xE0,0xFC,0xFF,0xFF,0xFF,0xF1,0xF3,0x31,0x11,0x00,0x41,0x71,0xFF,0xFE,0x84
 ,0x06,0x86,0xB6,0x96,0x92,0x82,0x82,0x82,0xF7,0xFF,0xFF,0xFF,0xFE,0xFC,0x00,0x00
 ,0x00,0x03,0x3F,0xFF,0xFF,0xF7,0xF3,0xF8,0x08,0x00,0x00,0xFC,0xF8,0xF8,0x00,0x01
 ,0x01,0xCD,0x01,0x01,0x40,0x24,0x00,0x00,0x80,0xFF,0xFF,0xFF,0x7F,0x1F,0x00,0x00
 ,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x0F,0x1E,0x1C,0x3C,0x3F,0x3F,0x3F,0x3E,0x3C
 ,0x3E,0x3E,0x3E,0x3E,0x3E,0x1E,0x1C,0x0C,0x07,0x07,0x03,0x00,0x00,0x20,0x00,0x00
};

void OLED_BMP(unsigned char x0unsigned char y0unsigned char x1unsigned char y1unsigned char BMP[])
{
   unsigned int j=0;
   unsigned char x,y;

 if(y1%8==0)
   {
       y=y1/8;
   }
 else
       y=y1/8+1;
   for(y=y0;y<y1;y++)
   {
       OLED_Set_Pos(x0,y);
   for(x=x0;x<x1;x++)
       {
           OLED_WR_Byte(BMP[j++],OLED_DATA);
       }
   }
}

// 绘制,图片尺寸 32*32
OLED_BMP(0,0,32,4gImage_a1);


再简单修改一下,用循环把这几张图跑起来就成动态的“福”了,效果:

Pasted image 20250214142746.png




工程师
2025-02-16 11:07:47     打赏
10楼

其实可以按主题拆成好几个帖子,这种塞在一个帖子里做法,内容太多,看起来贼费劲


共12条 1/2 1 2 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]