RT-Thread ES32F369x BSP 的 Arduino 生态兼容指南:RTduino 适配、引脚排布与功能测试
【免费下载链接】rt-threadRT-Thread is an open source IoT Real-Time Operating System (RTOS). https://rt-thread.github.io/rt-thread/项目地址: https://gitcode.com/gh_mirrors/rt/rt-thread
本文基于 RT-Thread 仓库中bsp/essemi/es32f369x的东软载波 ES-PDS-ES32F369x 开发板(Cortex-M3,96MHz)BSP,系统讲解其 Arduino 生态兼容层 RTduino 的启用方法、Arduino 引脚排布、I2C/SPI 总线使用以及完整的功能测试流程。读完本文,你将掌握如何在 Keil+Env 或 RT-Thread Studio 中为 ES32F3696 开启 RTduino 支持、正确使用 Arduino 标准 API(pinMode/digitalWrite/analogWrite/Wire/SPI)驱动板载外设,并能独立运行 GPIO、PWM、I2C、SPI、中断、ADC 等全套验证用例。
1 RTduino:RT-Thread 的 Arduino 生态兼容层
RTduino 是 RT-Thread 生态中的 Arduino 兼容层软件包,它让开发者可以在 RT-Thread 上直接使用 Arduino 的编程模型(setup()/loop()结构、digitalWrite、analogRead、Wire、SPI等 API),从而复用庞大的 Arduino 第三方库生态。
ES32F3696 芯片所在的 ES-PDS-ES32F369x BSP 已完整适配 RTduino,支持 GPIO、PWM、I2C、SPI 等全部常用功能。除标准 Arduino UNO 接口外,该开发板还额外扩展了4 个 LED(D16~D19)和 1 组五向方向键(D20~D24)对应的 GPIO,方便直接编写板载外设测试程序。
从源码结构看,BSP 的 Arduino 引脚适配代码集中在bsp/essemi/es32f369x/applications/arduino_pinout/目录:
- pins_arduino.h:定义 Arduino 引脚编号宏(D0~D24、A0~A5)、
F_CPU、默认 I2C/SPI 总线名称与LED_BUILTIN; - pins_arduino.c:定义
pin_map_table[]引脚映射表,将 Arduino 引脚关联到 RT-Thread PIN 编号及对应外设; - SConscript:以
PKG_USING_RTDUINO为编译依赖条件,启用 RTduino 后自动纳入构建。
引脚映射表的核心结构如下(摘自 pins_arduino.c):
/* {Arduino Pin, RT-Thread Pin [, Device Name, Channel]} [] means optional Digital pins must NOT give the device name and channel. Analog pins MUST give the device name and channel(ADC, PWM or DAC). Arduino Pin must keep in sequence. */ const pin_map_t pin_map_table[]= { {D0, GET_PIN(E,3), "uart2"}, /* UART2-RX */ {D3, GET_PIN(A,2),"pwm2",3}, /* PWM2 GP32C4T0 CH3 */ {D11, GET_PIN(B,5), "spi0"}, /* SPI0-MOSI */ {D14, GET_PIN(B,7), "i2c0"}, /* I2C0-SDA */ {A0, GET_PIN(C,0),"adc0",0}, /* ADC0 */ /* ... */ };该表的约束规则非常清晰:数字引脚只给 RT-Thread PIN 编号;模拟/PWM/ADC 引脚必须额外给出设备名与通道号,这也是理解后续"对非数字 IO 管脚不要调用 pinMode"注意事项的基础。
2 启用 RTduino 的两种方式
2.1 方式一:Keil + Env
- 在 BSP 目录(
bsp/essemi/es32f369x)打开 Env 工具,输入menuconfig命令(若使用 RT-Thread Studio,则选择RT-Thread Settings),进入以下配置项并勾选:
Hardware Drivers Config ---> Onboard Peripheral Drivers ---> [*] Compatible with Arduino Ecosystem (RTduino)- 进入 RTduino 配置菜单,按需开启 SPI、I2C、Adafruit 等子功能:
RT-Thread online packages ---> system packages ---> RTduino: Arduino Ecological Compatibility Layer- 执行
pkgs --update下载 RTduino 软件包。 - 执行
scons --target=mdk5重新生成 MDK5 工程,编译下载即可。
从 drivers/Kconfig 可以看到,勾选BSP_USING_ARDUINO时会自动连带开启一系列依赖项:
config BSP_USING_ARDUINO bool "Compatible with Arduino Ecosystem (RTduino)" select PKG_USING_RTDUINO select BSP_USING_GPIO select BSP_USING_UART2 select BSP_USING_SPI0 select BSP_USING_I2C0 select BSP_USING_ADC0 select BSP_USING_GP32C4T0_PWM select RTDUINO_USING_WIRE select RTDUINO_USING_SPI imply RTDUINO_USING_SERVO default n即:GPIO、UART2(默认控制台串口)、SPI0、I2C0、ADC0、PWM(GP32C4T0)以及 RTduino 的 Wire/SPI 兼容接口会被一次性选中,这也印证了 README 中"默认只开启了 spi0、i2c0 及 uart2"的说明。
2.2 方式二:RT-Thread Studio
选择文件 → 导入 → BSP 导入:
选择
es32f369x的 BSP 路径,填写工程名称,芯片型号填es32f3696lx:打开RT-Thread Settings,在硬件配置中开启 RTduino 支持:
保存后稍等片刻,Studio 会自动下载软件包并完成配置。
2.3 Studio 编译常见问题与解决方案
问题 1:Unknown flag "-T"
原因:工程链接脚本未正确配置。解决:进入项目 → 属性 → C/C++ 构建 → GNU ARM Cross C++ Linker → General,在右侧添加链接脚本(需先删除原有的再添加):
"${workspace_loc:/${ProjName}/drivers/linker_scripts/link.lds}"问题 2:启动时直接进入 Fault
原因:C++ 编译选项缺少架构指定。解决:进入项目 → 属性 → C/C++ 构建 → GNU ARM Cross C++ Complier → Miscellaneous,在 Other compiler flags 中添加:
-mcpu=cortex-m3 -mthumb3 Arduino 引脚排布
该 BSP 遵循 Arduino UNO 板的引脚排列方式,并额外扩展了 LED 与按键。完整的引脚映射定义在 pins_arduino.c 与 pins_arduino.h 中。
| Arduino 引脚编号 | ES32 引脚编号 | 备注 |
|---|---|---|
| D0 | PE3 | UART2 RX |
| D1 | PE2 | UART2 TX |
| D2 | PE4 | 普通 IO |
| D3 | PA2 | PWM2 通道 3 |
| D4 | PE5 | 普通 IO |
| D5 | PA1 | PWM2 通道 2 |
| D6 | PA0 | PWM2 通道 1 |
| D7 | PE6 | 普通 IO |
| D8 | PB8 | 普通 IO |
| D9 | PB9 | 普通 IO |
| D10 | PB0 | SPI 片选/普通 IO |
| D11 | PB5 | SPI1_MOSI/普通 IO |
| D12 | PB4 | SPI1_MISO/普通 IO |
| D13 | PD3 | SPI1_SCK/普通 IO |
| D14 | PB7 | I2C0_SDA |
| D15 | PB6 | I2C0_SCL |
| D16 | PC8 | LED4 |
| D17 | PC12 | LED5 |
| D18 | PC7 | LED6 |
| D19 | PC6 | LED7 |
| D20 | PF1 | KEY_UP |
| D21 | PF4 | KEY_DOWN |
| D22 | PF6 | KEY_LEFT |
| D23 | PF0 | KEY_RIGHT |
| D24 | PF7 | KEY_CENTER |
| A0 | PC0 | ADC |
| A1 | PC1 | ADC |
| A2 | PC2 | ADC |
| A3 | PC3 | ADC |
| A4 | PA4 | ADC |
| A5 | PA5 | ADC |
对应地,pins_arduino.h 中定义了与表格顺序一致的引脚编号宏:
#define D0 (0) ... #define D24 (24) #define A0 (25) ... #define A5 (30) #define RTDUINO_PIN_MAX_LIMIT A5 /* pin number max limit check */ #define F_CPU 96000000L /* CPU: 96MHz */ #define RTDUINO_DEFAULT_IIC_BUS_NAME "i2c0" #define SS D10 #define RTDUINO_DEFAULT_SPI_BUS_NAME "spi0" #define LED_BUILTIN D16几个值得注意的点:
- 引脚编号 D0~D24、A0~A5 必须按顺序递增,
RTDUINO_PIN_MAX_LIMIT用于引脚编号合法性检查; LED_BUILTIN被定义为 D16(PC8,LED4),因此arduino_main.cpp中默认的 LED 闪烁程序可以直接使用LED_BUILTIN;SS(片选)默认挂在 D10(PB0)上,与 UNO 布局一致。
4 I2C 总线
ES32-Arduino 支持的 I2C 总线为i2c0(引脚 SDA=PB7、SCL=PB6,即 D14/D15)。
I2C 的引脚已被 RT-Thread I2C 设备框架接管,无需直接操控这两个引脚:
- 直接引用 Arduino 官方头文件
#include <Wire.h>即可使用; - 也可以使用
#include <Adafruit_I2CDevice.h>通过 Adafruit 库进行控制。
默认 I2C 总线名称在 pins_arduino.h 中定义为RTDUINO_DEFAULT_IIC_BUS_NAME "i2c0"。
5 SPI 总线
ES32-Arduino 的 SPI 总线为spi0,SCK(PD3)、MISO(PB4)、MOSI(PB5)引脚由 RT-Thread SPI 设备框架接管,同样无需直接操控:
- 直接引用
#include <SPI.h>即可使用; - 或使用
#include <Adafruit_SPIDevice.h>进行控制。
按照 Arduino 编程标准,片选信号(SS,D10)需要用户自行控制。默认 SPI 总线名称在 pins_arduino.h 中定义为RTDUINO_DEFAULT_SPI_BUS_NAME "spi0"。
6 功能测试说明
在 examples/arduino_examples.cpp 中,已经根据功能预设了一系列测试函数,可通过取消/启用对应宏定义来开关各项测试。测试方法:将该文件内容覆盖到 arduino_main.cpp 中(即替换默认的setup()/loop())。
6.1 RTduino 各功能测试宏
| 宏定义 | 名称 | 描述 |
|---|---|---|
| ARDU_TEST_GPIO | 数字 GPIO 测试 | 测试数字管脚的输出功能,包括两个管脚输出高/低电平,一个管脚输出 0.5s 周期的方波 |
| ARDU_TEST_PWM | 模拟 PWM 输出测试 | PWM 功能输出测试,分别在三个 PWM 管脚输出不同的三种占空比的方波 |
| ARDU_TEST_ADAFRUIT_I2C | AdafruitI2C 测试 | 使用 AdafruitI2C 库发送数据,测试正常可以收到不断发送的 "ABtestabtest" |
| ARDU_TEST_ADAFRUIT_SPI | AdafruitSPI 测试 | 使用 AdafruitSPI 库发送数据,测试正常可收到不断的 "test" |
| ARDU_TEST_I2C | I2C 测试 | 通过 I2C 接口发送数据,测试正常可收到不断的 "test" |
| ARDU_TEST_SPI | SPI 测试 | 通过 SPI 接口发送和接收数据,测试正常可收到不断的 "test" |
| ARDU_TEST_INT | 中断测试 | 测试外部中断,按下方向键的中键会打印相关信息 |
| ARDU_TEST_DIGITAL_READ | 数字读测试 | 不断读取各个方向键的状态,并在按下时输出信息 |
| ARDU_TEST_ADC_READ | ADC 测试 | 循环读取各个 ADC 的数据,并通过串口打印 |
| ARDU_TEST_BMI160_PKG | 第三方 BMI160 包测试 | 测试导入的 BMI160 库是否正常,程序会不断读取传感器数据并通过串口打印 |
6.2 测试实现的关键细节
结合 examples/arduino_examples.cpp 源码,各测试的核心逻辑如下:
- GPIO 输出(
ARDU_TEST_GPIO):pinMode(D2/D4/D7/D18, OUTPUT)后通过digitalWrite翻转电平,并在loop()中配合delay(250)产生约 0.5s 周期的方波; - PWM 输出(
ARDU_TEST_PWM):先调用analogWriteFrequency(10)设置 PWM 频率,再对 D3、D5、D6 分别调用analogWrite(80/127/200)输出三种不同占空比; - 中断测试(
ARDU_TEST_INT):attachInterrupt(digitalPinToInterrupt(D24), test_int, FALLING)注册方向键中键(KEY_CENTER)的下降沿中断,触发后串口打印Interrupt Triggered; - 数字读测试(
ARDU_TEST_DIGITAL_READ):将 D20~D23 配置为INPUT,loop()中持续digitalRead并在检测到LOW时打印UP/DOWN/LEFT/RIGHT; - ADC 测试(
ARDU_TEST_ADC_READ):analogRead(A0 + count % 6)循环采样 6 路 ADC 并通过rt_kprintf打印原始值; - SPI 收发(
ARDU_TEST_SPI):SPI.begin()后通过SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE1))配置 100kHz、高位先行、模式 1,手动拉低 D10 片选执行SPI.transfer后再拉高; - I2C 收发(
ARDU_TEST_I2C):Wire.begin()后对地址0x2D执行beginTransmission/write/endTransmission; - Adafruit 封装(
ARDU_TEST_ADAFRUIT_I2C/SPI):实例化Adafruit_I2CDevice i2c_dev(0x2D)、Adafruit_BusIO_Register i2c_reg(&i2c_dev, 0x6261, 2, 0, 2)、Adafruit_SPIDevice spi_dev(D10, 100000)等对象进行读写。
6.3 第三方 Arduino 库导入测试(DFRobot_BMI160)
以 DFRobot_BMI160 库为例(BMI160 六轴传感器):
- 下载库后解压,放到
packages\RTduino-latest\libraries\user目录下; - 该库存在一处函数重载歧义,需要将第 856 行修改为
Wire.requestFrom(dev->id,(uint8_t)len);; - 使用 Keil 编译时还需处理两个问题:
缺少
INT8_C和UINT8_C宏定义:手动在 pins_arduino.h 或其他 Arduino 头文件中添加:#ifndef INT8_C #define INT8_C(x) ((int8_t)x) #endif #ifndef UINT8_C #define UINT8_C(x) ((uint8_t)x) #endif编译报错
Data initializer is not allowed:若使用 AC5 编译器,给arduino_main.cpp和DFRobot_BMI160.cpp添加--cpp11 --gnu;若使用 AC6 编译器,则需修改工程文件,删掉所有的--cpp11 --c11 --gnu;
- 如果用 RT-Thread Studio 编译,则不存在上述编译器问题,只需修改重载歧义即可直接使用。
测试代码中(ARDU_TEST_BMI160_PKG)通过bmi160->I2cInit()初始化,并循环读取加速度计与陀螺仪数据:
int result = bmi160->getAccelData(data); /* 读取加速度数据 */ int result = bmi160->getAccelGyroData(data); /* 读取加速度+陀螺仪数据 */7 使用注意事项
7.1 ADC 返回原始值
目前 ES32 的analogRead返回的是ADC 原始采样值,需要自行计算转换为实际电压值;暂时不支持分辨率调节,启用时会输出警告信息,可忽略。
7.2 对非数字 IO 的管脚不要调用 pinMode
非数字 IO 管脚(如 PWM、ADC、I2C、SPI 引脚)在其他地方已经完成初始化,再次调用pinMode会使其变为普通管脚,且该过程不可逆——原有的预设功能(PWM/ADC/总线)将会失效。即:任何管脚都可以用pinMode变为数字 IO 管脚,但不能再恢复为原来的外设功能。
7.3 SPI/I2C/UART 使用规则
默认只开启了spi0、i2c0 及 uart2(默认控制台串口)。如需使用其他 SPI/I2C/UART,可以在配置中启用,并在初始化时指定对应设备名称。若需要调整管脚信息,可以使用东软载波的 ESCodeMaker 辅助工具生成,但要注意打开对应的外设。
另外,SPI 必须先调用begin()才能使用其他函数。
7.4 RTduino 编译报错 "posix/xxx.h cannot find"
如果编译报错为posix/xxx.h cannot find,说明当前 RT-Thread 版本较旧,缺少 POSIX 头文件,请将 RT-Thread 更新到最新版本(从官方仓库拉取最新源码)后再编译。
8 默认示例程序
在未启用任何测试宏的情况下,arduino_main.cpp 提供了一个最简的 Arduino 风格闪烁程序,可直接作为开发模板:
#include <Arduino.h> void setup(void) { pinMode(LED_BUILTIN, OUTPUT); /* LED_BUILTIN = D16 = PC8(LED4) */ } void loop(void) { digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); delay(250); }9 总结
ES32F369x BSP 通过 RTduino 兼容层为开发者提供了完整的 Arduino 开发体验:统一的 UNO 引脚排布、被设备框架接管的 I2C/SPI 总线、可直接运行的 GPIO/PWM/中断/ADC 测试用例,以及板载 LED 与方向键的便捷扩展。无论是通过 Keil+Env 的命令行工作流,还是 RT-Thread Studio 的图形化配置,都能在数分钟内完成从配置到运行的整个过程。相关代码均可在仓库的bsp/essemi/es32f369x/applications/arduino_pinout/目录下查阅与复用。
【免费下载链接】rt-threadRT-Thread is an open source IoT Real-Time Operating System (RTOS). https://rt-thread.github.io/rt-thread/项目地址: https://gitcode.com/gh_mirrors/rt/rt-thread
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考