大数跨境
0
0

工程师笔记 | 使用RT-Thread的Arduino兼容层开发ES32应用程序

工程师笔记 | 使用RT-Thread的Arduino兼容层开发ES32应用程序 东软载波微电子
2022-09-23
0
导读:对于已经对Arduino开发有一定基础的人来说,RTduino能够减少学习芯片、操作系统的时间,仅需很少的时间就能做出成果。


工程师笔记 | 使用RT-Thread的Arduino兼容层开发ES32应用程序


Arduino在2005年发布,致力于让非电子专业的学生、爱好者、设计师等可以快速实现一些设计和想法。经过多年发展,Arduino的社区生态已经十分丰富,大多数常用的外设都可以找到对应的库使用,避免了重复开发的繁琐。时至今日,在Arduino的官网上已经有了100多种硬件、5000多个库可供选择。


RT-Thread是一款国产的嵌入式实时操作系统,支持多线程任务切换、中断管理,支持丰富的功能和软件包。RTduino(https://github.com/RTduino/RTduino)表示为RT-Thread的Arduino生态兼容层,是RT-Thread的软件包。旨在兼容Arduino丰富的生态(如Arduino库,以及作品等),来丰富RT-Thread生态,降低RT-Thread操作系统以及与RT-Thread适配的芯片的学习门槛。可以让用户通过Arduino的函数和编程方法,轻松地将RT-Thread以及特定的芯片使用起来。不用再拘泥于Arduino的开发板,而是能够使用各种类型的板子,大幅降低开发难度和开发周期。

对于专业的开发人员来说,直接使用Arduino库可以极大的减少开发成本和各类不同芯片、bsp的学习成本,甚至能够直接应用成熟的Arduino项目,避免重复开发。

对于已经对Arduino开发有一定基础的人来说,RTduino能够减少学习芯片、操作系统的时间,仅需很少的时间就能做出成果,在这之后还可以借此逐步深入学习RT-Thread操作系统等其他嵌入式开发的领域。

而对于完全不了解嵌入式开发的爱好者来说,还可以搭配各类可视化编程界面使用,从简单的搭积木开始,逐渐学习编写代码,再到完成更加复杂的项目。

本文将介绍如何在ES-PDS-ES32F3696LX开发板上开启RTduino,并简要介绍keil和rt-thread studio下Arduino库的使用方法和注意事项。

1. 硬件配置

需求:ES-PDS-ES32F3696LX开发板,ES-Bridge,BMI160传感器模块(可选),AHT10温湿度传感器模块(可选)

开发板的背面,有两排与Arduino UNO的管脚分布相同的管脚,提供GPIO、PWM、I2C、SPI等功能,正面有LED灯、按键等功能。

按照实验需要,分别连接ES-Bridge的对应管脚和开发板的管脚,测试功能是否正常。

2. 系统配置

RTduino支持在keil或者RT-Thread Studio环境下编译运行,但由于Arduino的编译环境是gcc,因此如果使用了第三方库,keil环境编译可能会不通过,需要自行修改部分代码和编译参数。目前,如果想要使用RTduino,需要至少rt-thread 4.1.1版本才能支持。

注:使用ES32F3696LX开发板时,请设置控制台使用的串口为uart2

RT-Thread Kernel --->
Kernel Device Object --->
(uart2) the device name for console

2.1 使用Keil+Env

  1. Env 工具下敲入 menuconfig 命令,进入菜单,开启Arduino:
Hardware Drivers Config --->
Onboard Peripheral Drivers --->
[*] Support Arduino


  1. 进入RTduino配置,确认配置:
RT-Thread online packages --->
Arduino libraries --->
RTduino: Arduino Ecological Compatibility Layer

(注意:目前ES32的驱动程序不支持软件I2C,请进入RT-Thread Components -> Device Drivers -> Use GPIO to simulate I2C,取消选择此项)
  1. 开启Adafruit库支持(可选,建议开启)

    返回到Arduino libraries,进入Sensors,选择使用Adafruit Unified Sensor和Adafruit BusIO。

    Adafruit提供了更简洁易用的SPI/I2C接口和丰富的传感器框架,不使用则会影响后续的用例测试和传感器测试,但不影响其他功能。

  2. 使用 pkgs --update下载RTduino包:

  3. 使用scons --target=mdk5生成工程文件:

  4. 打开工程,开始编译即可。

2.2 使用RT-Thread Studio

  1. 选择 文件 -> 导入 -> BSP导入:

  2. 选择es32f369x的bsp路径,并填写工程名称、芯片(es32f3696lx):

  3. 打开RT-Thread Settings,配置好其他设置(console选择uart2)后,选择硬件,板载设备驱动,开启Arduino支持:


    (注意:目前ES32的驱动程序不支持软件I2C,请进入组件->设备驱动程序->使用I2C驱动程序中,关闭"使用GPIO模拟I2C")

  4. 开启Adafruit库支持可选,建议开启打开软件包->Arduino libraries->Sensors,开启Adafruit Unified Sensor和Adafruit BusIO,方便后续使用传感器

  5. 保存后稍等片刻,等待Studio下载库并完成配置,然后点击锤子图标编译即可。


  • 可能遇到的问题与解决方案
  1. Unknown flag "-T"

    项目->属性->C/C++构建->GNU ARM Cross C++ Linker -> General在右侧添加lds连接脚本"${workspace_loc:/${ProjName}/drivers/linker_scripts/link.lds}"(需要先删除原有的再添加)

  2. 无法正常启动,直接进入HardFault

    选择 项目->属性->C/C++构建->GNU ARM Cross C++ Complier-> Miscellaneous ,在Other compiler flags 中添加 -mcpu=cortex-m3 -mthumb

  3. gcc版本的startup入口点存在问题,打开"libraries\CMSIS\Device\EastSoft\ES32F36xx\Startup\gcc\startup_es32f36xx.S",找到bl main,改为bl entry

3. 实验说明

arduino_main.c文件中存放标准的setup-loop循环及简单的led灯闪烁程序。applications/arduino_pinout/examples/arduino_example.cpp文件中存放有使用arduino进行编程的示例,可以用该文件的内容覆盖arduino_main.cpp文件的内容进行实验测试。

为了方便测试,arduino_example.cpp文件中除了arduino工程常见的setup-loop函数外,还提供了一系列宏定义控制的功能,用于测试Arduino兼容层的各项功能是否正常,并提供各个功能的使用实例。

详细使用说明请参见applications/arduino_pinout/README.MD,文档中包含了arduino管脚与rt-thread的管脚对应关系、使用说明、注意事项等。

3.0 Serial 串口通信

串口通信是默认开启的,无需通过宏定义切换,当进入Setup函数时会向rt-thread控制台发送一句话


3.1 GPIO: ARDU_TEST_GPIO

开启此宏定义,会将D4设为高电平,D7设为低电平,D2和D18每隔0.25秒切换一次高低电平(其中D18为LED灯,可观察到闪烁)。可以使用ES-Bridge连接对应的管脚,观察电压波形


3.2 PWM: ARDU_TEST_PWM

开启此宏定义,会在D3、D5、D6三个管脚上设置不同占空比的波形,可连接ES-Bridge查看

3.3 I2C: ARDU_TEST_I2C和ARDU_TEST_ADAFRUIT_I2C

默认I2C接口为I2C0,使用的管脚为D14(PB7)-SDA,D15(PB6)-SCL

这两个宏定义都是I2C功能,区别仅仅只是接口不同,ARDU_TEST_I2C使用Arduino原生接口,ARDU_TEST_ADAFRUIT_I2C使用Adafruit库的接口,比原生接口更方便一些。(如果使用Adafruit_I2C,前面需要使用Adafruit_BusIO软件包)

使用ES-Bridge的I2C管脚连接开发板的对应管脚,可观察到开发板发送过来的消息。


3.4 SPI: ARDU_TEST_SPI和ARDU_TEST_ADAFRUIT_SPI

默认SPI接口为SPI0,使用的管脚为D11(PB5)-MOSI,D12(PB4)-MISO,D13(PD3)-SCK D10(PB0)-NSS片选

同样都是SPI接口,区别仅仅只是使用的库不同。需要注意的是使用原生的SPI库需要自己控制片选引脚的电平,Adafruit库在初始化时指定片选引脚。(如果使用Adafruit_SPI,前面需要使用Adafruit_BusIO软件包

用例功能说明:

SPI程序会先发送一次test,然后读取4个字节,在下一次循环的时候会发送上一次读到的数据并再次读取4个字节。

先打开ES-Bridge的SPI功能,并在发送并输入4个字节的数据,并点击同步数据,然后运行开发板上的程序或重新复位,可以看到ES-Bridge先收到了一个"test",然后不断收到"abcd"。


(备注:目前编译会出现警告"Please define SS pin number in arduino_pinout.h and make sure this board supports SPI!",不影响功能和使用)


3.5 Interrupt 中断: ARDU_TEST_INT

使用方向键的中键,测试中断形式响应外界输入。按下方向键的中键,可以看到串口打印的消息。


3.6 GPIO输入:  ARDU_TEST_DIGITAL_READ

测试读取GPIO输入的功能。在Loop循环的过程中,会读取方向键四向的状态,如果检测到按下,会通过串口打印消息。


3.7 ADC: ARDU_TEST_ADC_READ

依次读取A0-A5,共6个ADC模拟输入管脚的数据,并显示。

注:由于ES32的BSP暂时不支持调节ADC的分辨率,返回的数据均为真实的ADC采样值,需要自行计算出真实的电压。


3.8 Arduino第三方库使用(以BMI160传感器库为例)

注意,虽然RTduino的接口与Arduino的接口一致,但是由于编译环境等的不同,还是有可能无法直接使用,需要根据情况,进行一些修改(尤其是keil环境下)。

从Arduino库下载BMI160的驱动库DFRobot_BMI160 1.0.0,下载完毕后,解压放置到packages\RTduino-latest\libraries\user目录下。

连接好BMI160传感器模块与开发板上的I2C0接口。

需要修改一处:这个库有一处函数重载歧义

int8_t DFRobot_BMI160::I2cGetRegs(struct bmi160Dev *dev, uint8_t reg_addr, uint8_t *data, uint16_t len)
{
    ...
    //将原代码Wire.requestFrom(dev->id,len); 改为下面一行   
    Wire.requestFrom(dev->id,(uint8_t)len); 
    ...
}
  • 用keil编译时还有以下问题:
  1. 缺少INT8_C和UINT8_C宏定义,手动添加

    #ifndef INT8_C
    #define INT8_C(x) ((int8_t)x)
    #endif
    #ifndef UINT8_C
    #define UINT8_C(x) ((uint8_t)x)
    #endif
  2. 选择DFRobot_BMI160.cpp文件,右键点击并选择Options,在C/C++页中,在Misc Control的输入框中输入--gnu --cpp11

解决以上问题后,能成功调用传感器获取加速度和重力等信息

  • 如果用RT-Thread Studio编译,则不存在这些问题,只需修改存在歧义的问题即可直接使用

完成配置后,打开宏定义ARDU_TEST_BMI160_PKG即可在rt-thread的控制台上看到传感器的读数


4. 示例程序

本节的所有示例以keil环境下为例,但同样在RT-Thread Studio环境下也可以编译。相比较于传统的以C语音为主的嵌入式开发,Arduino编程使用C++可以大幅度降低编程的复杂程度,加快开发进度。Arduino的库隐藏了所有与底层寄存器相关的信息,用户即使完全不了解所使用的芯片信息,只要能够调用Arduino的库函数,也能够完成诸如读取外部传感器数据、控制外部设备、与其他设备通信等功能。与RTthread结合后产生的RTduino可以充分运用这一优势,使用Arduino库简化开发。

1. LED灯闪烁

这是最基本的测试工程,也是默认的arduino_main.cpp文件的内容,用于测试配置是否正确,开发板功能是否正常。

打开工程后,直接编译运行即可,如果配置无误,可观察到板子上的LED4持续闪烁

2. 传感器数据读取并打印

本节简要介绍如何利用Arduino库,仅使用几行代码,读取传感器的数据并显示,展示Arduino强大的快速开发能力。无需特别配置,甚至不需要知道芯片的外设信息,只要导入了传感器库并正确连接传感器,就能够直接驱动传感器,极大地减少了调试时间。此用例需要使用Adafruit Unified Sensor和Adafruit BusIO软件包。

  1. 将板卡上的I2C0接口连接到AHT10和BMI160传感器

  2. 下载对应的arduino包,地址如下:

    https://github.com/adafruit/Adafruit_AHTX0

    https://github.com/DFRobot/DFRobot_BMI160

    也可以从Arduino官方库下载

    https://www.arduino.cc/reference/en/libraries/adafruit-ahtx0/

    https://www.arduino.cc/reference/en/libraries/dfrobot_bmi160/

    (注:从Arduino网站下载的bmi160库存在一些问题,建议使用github版本)
    其中的AHTX0也可以通过RT的软件包管理下载,打开RT-Thread online packages -> Arduino libraries -> Sensors,选择 Adafruit AHTX0 (AHT10 & AHT20)即可

  3. 下载后,将解压出来的文件夹复制到 packages\RTduino-latest\libraries\user 路径

  4. 调用scons --target=mdk5重新生成keil工程文件

  5. 给添加的cpp文件添加'--cpp11 --gnu'(具体操作过程参见3.8节中的第2个问题) 包含arduino_main.cpp和传感器库文件DFRobot_BMI160.cpp、Adafruit_AHTX0.cpp

  6. 打开arduino_main.cpp文件,删除原有内容,并粘贴以下代码

    #include <Arduino.h>
    #include <Adafruit_AHTX0.h>
    #include <DFRobot_BMI160.h>

    DFRobot_BMI160 *bmi160;
    Adafruit_AHTX0 *aht10;

    void setup(void)
    {
        //初始化BMI160
        bmi160=new DFRobot_BMI160();
        int result= bmi160->I2cInit();
        if (result)
        {
            Serial.println("BMI160 Init failed.");
        }
        bmi160->setStepPowerMode(bmi160->stepNormalPowerMode);
        
        //初始化AHT10
        aht10=new Adafruit_AHTX0();
        if (!aht10->begin())
            Serial.println("AHT10 begin failed");
        Serial.println("AHT10 Sensor info:");
        aht10->getHumiditySensor()->printSensorDetails();
        aht10->getTemperatureSensor()->printSensorDetails();
        
        //开启I2C总线(非必要,传感器初始化时会自动开启)
        Wire.begin();
    }

    void loop(void)
    {
        
        int16_t data[3]={0,0,0};
        //读取加速度计数据
        bmi160->getAccelData(data);
        Serial.print("Accel=");
        Serial.print(data[0]);
        Serial.print(",");
        Serial.print(data[1]);
        Serial.print(",");
        Serial.println(data[2]);
        //读取陀螺仪数据
        bmi160->getGyroData(data);
        Serial.print("Gyro =");
        Serial.print(data[0]);
        Serial.print(",");
        Serial.print(data[1]);
        Serial.print(",");
        Serial.println(data[2]);
        
        //读取温湿度计数据
        sensors_event_t humi_event,temp_event;
        aht10->getEvent(&humi_event,&temp_event);
        Serial.print("Humi=");
        Serial.print(humi_event.relative_humidity);
        Serial.print(",Temp=");
        Serial.println(temp_event.temperature);
        
        Serial.println();
        //延迟1s
        delay(1000);
    }
  7. 运行结果

5. 可视化编程

Arduino的代码本身比较简单易懂,通过一些工具可以以拖曳方块的形式实现可视化的编程,这些工具生成的代码在RTduino中大部分情况下也是可以通用的。目前大部分的工具界面大同小异,左侧为用户可以通过搭积木的方式,进行程序流程的设计,右侧为工具根据搭建的结果输出的代码,包含setup和loop循环,只需要将右侧的代码复制到arduino_main.cpp文件中,替换原有的setup和loop函数,即可实现在RTduino上进行可视化编程,而无需自己编写代码。

下面以一个控制LED灯周期闪烁的程序为例,展示可视化编程的效果:


左侧为可视化编程界面,右侧为生成的Arduino代码,按照左侧搭建好程序流程,将代码复制到arduino_main.cpp文件并替换setup和loop函数,编译后下载运行,可以看到串口输出的"hello",并通过ES-Bridge观察到D2的电平信号。

演示使用的可视化编程软件为Mixly(地址:http://mixly.org/),其他软件如ArduBlockly(https://tftcanvas.blascarr.com/,可在线开发)等的使用基本,都有提供类似的功能和模块(包括简单的IO或是串口,一些还能够支持SPI等模块),只需要将软件生成的代码复制到arduino_main.cpp文件中即可。


△ArduBlockly的界面(实现同样的功能)

注1:尽管大多数情况下生成的代码都能够正常使用,但是由于底层驱动的不同,存在一些区别,如:RTduino框架的SPI需要先调用begin以获取spi device,才能使用其他功能。

注2:目前可视化编程仅支持以代码的形式使用,暂时只能使用标准Arduino库的功能,需要底层支持的如电机控制、TFT等暂时无法使用。

6. 其他说明

  1. 目前RTduino和ES32的RTduino适配还处于初步阶段,如有问题,可以尝试查看applications/arduino_pinout目录下的README.MD或查找RTduino官方文档。

  2. 如果需要调整I2C/SPI/UART的管脚等信息,可以使用ES-CodeMaker进行对应的调整。注意Arduino相关的GPIO/I2C/SPI等功能需要全部使能,否则调用对应的接口时会出错。

  3. 使用非默认的SPI/I2C时,只需要在初始化函数中传入对应的rt-thread设备名,如I2C : Wire.begin("i2c1") 或 SPI : SPI.begin("spi1")。


关注我们
FOLLOW US


QQ技术交流群
314276054
微信公众号
东软载波微电子
天猫旗舰店
Eastsoft旗舰店
【声明】内容源于网络
0
0
东软载波微电子
上海东软载波微电子有限公司官方服务号
内容 40
粉丝 0
东软载波微电子 上海东软载波微电子有限公司官方服务号
总阅读6
粉丝0
内容40