利用rt-thread studio开发瑞萨RA2L1

一、RA2L1瑞萨新近推出M23核芯片

瑞萨芯片给我的第一印象是车规级的,日本车上使用得多

Cortex-M23 =

Cortex-M0/M0 + 硬件除法器 + 性能提升 +

专门的栈溢出硬件检测+

指令集不可忽略的小动作 +

安全扩展(TrustZone for Armv8-M) +

MPU开发者模型的友好化改进

二、rt-thread studio已经对RA2L1进行SDK适配,安装瑞萨的配置包及BSP包即可进行开发

2-1 灵活配置软件包 (FSP) 安装

可快速配置开发板的外设功能,请使用 v3.5.0 版本,目前可在github上下载3.5.0版本(下载地址:https://github.com/renesas/fsp/releases/tag/v3.5.0
(注意文件名称为:setup_fsp_v3_5_0_rasc_v2021-10.exe)
<注意官网为3.6.0版本,不向前兼容,使用3.6.0版本会会导致本工程不可用>
1、找到下载的文件打开(注意文件名称包含为rasc):setup_fsp_v3_5_0_rasc_v2021-10.exe
利用rt-thread studio开发瑞萨RA2L1_第1张图片
2、配置安装路径,安装完成后找到此路径,之后添加 CPK-RA2L1 板级支持包时会用到
利用rt-thread studio开发瑞萨RA2L1_第2张图片
3、勾选 Licenese
利用rt-thread studio开发瑞萨RA2L1_第3张图片
4、点击 install 等待安装完成。
利用rt-thread studio开发瑞萨RA2L1_第4张图片
5、运行 rasc.exe,验证是否安装成功。路径:\eclipse\rasc.exe
利用rt-thread studio开发瑞萨RA2L1_第5张图片
6、成功启动后关闭即可,继续接下来的操作
利用rt-thread studio开发瑞萨RA2L1_第6张图片

2-2 CPK-RA2L1 板级支持包安装

此部分,你可以参考Renesas官网文档《向FSP中添加CPK评估板的BSP 》https://www2.renesas.cn/cn/zh/document/gde/1596896?language=zh&r=1527191
1、下载 3.5.0 版本支持包。
配合 FSP 一起使用,是开发板的图形化配置支持包,请使用 v3.5.0 版本
可在Renesas官网下载:
https://www2.renesas.cn/cn/zh/products/microcontrollers-microprocessors/ra-cortex-m-mcus/cpk-ra2l1-evaluation-board#design_development
利用rt-thread studio开发瑞萨RA2L1_第7张图片
2、在下载的支持包中可以找到以下三个文件
利用rt-thread studio开发瑞萨RA2L1_第8张图片
3、此时找到 FSP 的安装路径,进入 \internal\projectgen\ra\ ,将文件复制到对应的文件夹中。
利用rt-thread studio开发瑞萨RA2L1_第9张图片

4、再次打开 rasc.exe,查看是否添加成功。点击 next 进入工程创建
利用rt-thread studio开发瑞萨RA2L1_第10张图片

5、确认是否存在已添加的 CPK-RA2L1 开发板的支持包,此步骤仅为验证是否添加成功,不必继续创建工程,关闭即可。
利用rt-thread studio开发瑞萨RA2L1_第11张图片
到此基本将瑞萨开发板相关的环境搭建完成。

2-3 在rt-studio安装RA2L1的SDK包

利用rt-thread studio开发瑞萨RA2L1_第12张图片
完成以上操作,即可使用rt_thread studio进行开发工作

三、一个简单实例通过串口读取PM2.5模组空气质量的数据显示于数码管上

3-1、通过串口读取传感器数值解释完后,显示到数码管,数码管驱动为595串行动态扫描方式
程序分为2个线程,一个数据解释线程,一个数码管扫描显示线程

3-2、硬件连接
利用rt-thread studio开发瑞萨RA2L1_第13张图片
利用rt-thread studio开发瑞萨RA2L1_第14张图片
数码管模组原理图
利用rt-thread studio开发瑞萨RA2L1_第15张图片

3-3、rt-thread studio驱动配置
RT_Thread settings中打开UART0

利用rt-thread studio开发瑞萨RA2L1_第16张图片

3-4、RA Smart Configurator配置
添加g_uart0 UART驱动
利用rt-thread studio开发瑞萨RA2L1_第17张图片
配置SC0为异步串口,选择101 100引脚
利用rt-thread studio开发瑞萨RA2L1_第18张图片

3-5、代码编写
PM2.5 接收及解释


#include 
#include 

#include 
#include "display.h"

#define DBG_TAG "app.pm25"
#define DBG_LVL DBG_LOG
#include 

static rt_device_t serial;
static pm25_state_t pm25_state;

uint16_t pm25_data_convert(uint8_t h, uint8_t l)
{
    return h<<8|l;
}

void pm25_thread_entry(void *parameter)
{
    uint8_t ch;

    serial = rt_device_find("uart0");
    if (!serial)
    {
        LOG_E("find %s failed!\n", "uart1");
        return;
    }
    else{
        struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;  /* 初始化配置参数 */
        /* step2:修改串口配置参数 */
        config.baud_rate = BAUD_RATE_9600;        //修改波特率为 9600
        config.data_bits = DATA_BITS_8;           //数据位 8
        config.stop_bits = STOP_BITS_1;           //停止位 1
        config.tx_bufsz  = 0;                   //修改缓冲区 buff size 为 128
        config.rx_bufsz  = 128;                   //修改缓冲区 buff size 为 128
        config.parity    = PARITY_NONE;           //无奇偶校验位

        /* step3:控制串口设备。通过控制接口传入命令控制字,与控制参数 */
        rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, &config);

        rt_device_open(serial, RT_DEVICE_FLAG_RX_NON_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING);
    }

    while(1){

//        rt_thread_delay(10);

        if( rt_device_read(serial, -1, &ch, 1) > 0 ){
            pm25_state.recv_time = 10;

            switch( pm25_state.recv_state )
            {
                case RECV_START1:
                    if( ch==0x42 ){
                        pm25_state.recv_state++;
                        pm25_state.recv_buf[pm25_state.recv_index++] = ch;
                    }
                    break;
                case RECV_START2:
                    if( ch==0x4d ){
                        pm25_state.recv_state++;
                        pm25_state.recv_buf[pm25_state.recv_index++] = ch;
                    }
                    break;
                case RECV_LEN1:
                    pm25_state.recv_state++;
                    pm25_state.recv_buf[pm25_state.recv_index++] = ch;
                    pm25_state.recv_len = ch<<8;
                    break;
                case RECV_LEN2:
                    pm25_state.recv_state++;
                    pm25_state.recv_buf[pm25_state.recv_index++] = ch;
                    pm25_state.recv_len |= ch;
                    break;
                case RECV_DATA:
                    if( pm25_state.recv_index < pm25_state.recv_len ){
                        pm25_state.recv_buf[pm25_state.recv_index++] = ch;
                        if( pm25_state.recv_index == pm25_state.recv_len ){
                            pm25_state.recv_state++;
                        }
                    }
                    break;
                case RECV_END:
//                    LOG_HEX("REPLY", 16, pm25_state.recv_buf, 32);
                    pm25_state.recv_state = 0;
                    pm25_state.recv_index = 0;
                    pm25_decode_t   *pm25_decode_ptr = (pm25_decode_t  *)pm25_state.recv_buf;
                    pm25_state.pm25_data.pm1_0 = pm25_data_convert(pm25_decode_ptr->pm1_0_h,pm25_decode_ptr->pm1_0_l);
                    pm25_state.pm25_data.pm2_5 = pm25_data_convert(pm25_decode_ptr->pm2_5_h,pm25_decode_ptr->pm2_5_l);
                    pm25_state.pm25_data.pm10 = pm25_data_convert(pm25_decode_ptr->pm10_h,pm25_decode_ptr->pm10_l);
                    pm25_state.pm25_data.pm1_0_air = pm25_data_convert(pm25_decode_ptr->pm1_0_air_h,pm25_decode_ptr->pm1_0_air_l);
                    pm25_state.pm25_data.pm2_5_air = pm25_data_convert(pm25_decode_ptr->pm2_5_air_h,pm25_decode_ptr->pm2_5_air_l);
                    pm25_state.pm25_data.pm10_air = pm25_data_convert(pm25_decode_ptr->pm10_air_h,pm25_decode_ptr->pm10_air_l);
                    pm25_state.pm25_data.quantity_0_3 = pm25_data_convert(pm25_decode_ptr->quantity_0_3_h,pm25_decode_ptr->quantity_0_3_l);
                    pm25_state.pm25_data.quantity_0_5 = pm25_data_convert(pm25_decode_ptr->quantity_0_5_h,pm25_decode_ptr->quantity_0_5_l);
                    pm25_state.pm25_data.quantity_1_0 = pm25_data_convert(pm25_decode_ptr->quantity_1_0_h,pm25_decode_ptr->quantity_1_0_l);
                    pm25_state.pm25_data.quantity_2_5 = pm25_data_convert(pm25_decode_ptr->quantity_2_5_h,pm25_decode_ptr->quantity_2_5_l);
                    pm25_state.pm25_data.quantity_5_0 = pm25_data_convert(pm25_decode_ptr->quantity_5_0_h,pm25_decode_ptr->quantity_5_0_l);
                    pm25_state.pm25_data.quantity_10 = pm25_data_convert(pm25_decode_ptr->quantity_10_h,pm25_decode_ptr->quantity_10_l);
                    pm25_state.pm25_data.version = pm25_decode_ptr->version;
                    pm25_state.pm25_data.err_code = pm25_decode_ptr->err_code;

                    display_dig(pm25_state.pm25_data.pm2_5_air);
//
//                    LOG_D("pm1_0 = %d",pm25_state.pm25_data.pm1_0);
//                    LOG_D("pm2_5 = %d",pm25_state.pm25_data.pm2_5);
//                    LOG_D("pm10 = %d",pm25_state.pm25_data.pm10);
//
//                    LOG_D("pm1_0_air = %d",pm25_state.pm25_data.pm1_0_air);
//                    LOG_D("pm2_5_air = %d",pm25_state.pm25_data.pm2_5_air);
//                    LOG_D("pm10_air = %d",pm25_state.pm25_data.pm10_air);
//
//                    LOG_D("quantity_0_3 = %d",pm25_state.pm25_data.quantity_0_3);
//                    LOG_D("quantity_0_5 = %d",pm25_state.pm25_data.quantity_0_5);
//                    LOG_D("quantity_1_3 = %d",pm25_state.pm25_data.quantity_1_0);
//                    LOG_D("quantity_2_5 = %d",pm25_state.pm25_data.quantity_2_5);
//                    LOG_D("quantity_5_0 = %d",pm25_state.pm25_data.quantity_5_0);
//                    LOG_D("quantity_10 = %d",pm25_state.pm25_data.quantity_10);
//                    LOG_D("\n");
                    break;
                default:
                    break;
            }
            if( pm25_state.recv_time > 0 ){
                pm25_state.recv_time --;
                if( pm25_state.recv_time==0 ){
                    pm25_state.recv_state = RECV_START1;
                    pm25_state.recv_index = 0;
                    LOG_E("recv timeout");
                }
            }
        }

//        rt_device_write(serial, 0,"hello world",11);

        rt_thread_delay(10);
    }
}

void pm25_init(void)
{
    rt_thread_t tid1 = RT_NULL;

    tid1 = rt_thread_create("pm25",
                pm25_thread_entry, RT_NULL,
                512,
                10, 10);

    if (tid1 != RT_NULL)
        rt_thread_startup(tid1);
}
INIT_APP_EXPORT(pm25_init);

595动态扫描显示线程

/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2023-02-18     dmjku       the first version
 */

#include 
#include 

#include "display.h"

disp_buf_t disp_buf;

#define SERIAL_RCLK_PIN     "P302"
#define SERIAL_SCLK_PIN     "P303"
#define SERIAL_DIO_PIN      "P301"

rt_uint32_t rclk_pin;
rt_uint32_t sclk_pin;
rt_uint32_t dio_pin;

#define serial_rclk_pin(sta)       rt_pin_write(rclk_pin, sta)
#define serial_sclk_pin(sta)       rt_pin_write(sclk_pin, sta)
#define serial_dio_pin(sta)        rt_pin_write(dio_pin, sta)

const uint8_t dig_code[]={
        /********生成 0-f 的编码********/
        0xC0,0
        0xF9,1
        0xA4,2
        0xB0,3
        0x99,4
        0x92,5
        0x82,6
        0xF8,7
        0x80,8
        0x90,9
        0x88,A
        0x80,B
        0xC6,C
        0xC0,D
        0x86,E
        0x8E,F
};

void display_dig(uint16_t dig)
{
    uint8_t zero=0;
    if( dig/1000 ){
        disp_buf.dig[0] = dig_code[dig/1000];
        dig %= 1000;
        zero = 1;
    }
    else{
        disp_buf.dig[0] = 0xff;
    }

    if( dig/100 ){
        disp_buf.dig[1] = dig_code[dig/100];
        dig %= 100;
        zero = 1;
    }
    else if(zero){
        disp_buf.dig[1] = dig_code[0];
    }
    else{
        disp_buf.dig[1] = 0xff;
    }

    if( dig/10 ){
        disp_buf.dig[2] = dig_code[dig/10];
        dig %= 10;
        zero = 1;
    }
    else if(zero){
        disp_buf.dig[2] = dig_code[0];
    }
    else{
        disp_buf.dig[2] = 0xff;
    }

    if( dig ){
        disp_buf.dig[3] = dig_code[dig];
    }
    else if(zero){
        disp_buf.dig[3] = dig_code[0];
    }
    else{
        disp_buf.dig[3] = 0xff;
    }
}

void display_led(void)
{
    const uint8_t pos_v[] = {0x08,0x04,0x02,0x01};
    static uint8_t pos = 0;
    disp_buf.output[0] = pos_v[pos];
    disp_buf.output[1] = disp_buf.dig[pos];
    pos++;
    if( pos>=4 )
        pos = 0;
}

static void display_wr_byte(uint8_t data)
{
    for( uint8_t i=0; i<8; i++ ){
        serial_dio_pin(data&0x80?1:0);
//        rt_hw_us_delay(1);
        serial_sclk_pin(1);
//        rt_hw_us_delay(1);
        serial_sclk_pin(0);

        data <<= 1;
    }
}

static void display_refresh(void)
{
    for( uint8_t i=DISP_BUF_LEN; i>0; i-- ){
        display_wr_byte(disp_buf.output[i-1]);
    }
    serial_rclk_pin(1);
//    rt_hw_us_delay(1);
    serial_rclk_pin(0);
}

void display_thread_entry(void *paramter)
{
    display_dig(1);
    while( 1 ){

        display_led();

        display_refresh();

        rt_thread_delay(5);
    }
}

void display_init(void)
{
    rclk_pin    = rt_pin_get(SERIAL_RCLK_PIN);
    sclk_pin    = rt_pin_get(SERIAL_SCLK_PIN);
    dio_pin     = rt_pin_get(SERIAL_DIO_PIN);

//    serial_rclk_pin(1);
//    serial_rclk_pin(0);
//    serial_sclk_pin(1);
//    serial_sclk_pin(0);
//    serial_dio_pin(1);
//    serial_dio_pin(0);

    rt_thread_t tid1 = RT_NULL;

    tid1 = rt_thread_create("disp",
            display_thread_entry, RT_NULL,
                512,
                10, 10);

    if (tid1 != RT_NULL)
        rt_thread_startup(tid1);
}
INIT_APP_EXPORT(display_init);

3-6、在RT-thread studio的加持下结合RA Smart Configurator,简单应用无需过多关注硬件,可以快速上手开发,真心好用,比keil+evn+stm32cubeMX还要顺手

你可能感兴趣的:(瑞萨,rt-thread,m23,嵌入式)