首页 / 资讯中心 / 文章详情

瑞萨RA4M2与DA14531蓝牙透传方案:UART通信与低功耗无线数据采集实战

瑞萨RA4M2与DA14531蓝牙透传方案:UART通信与低功耗无线数据采集实战 ★ FEATURED ARTICLE
1. 项目缘起与整体方案拆解1.1 为什么选 RA4M2 搭配 DA14531 这套组合手头这个项目最初的诉求很朴素做一块低功耗的无线数据采集节点前端传感器数据通过串口往外送后端要能跟手机 App 做双向数据交互。选型阶段我对比过几种常见路线最后落在瑞萨 RA4M2 加 Dialog DA14531 这个组合上理由其实挺实在的。RA4M2 属于 RA4 系列里的主流型号Cortex-M33 内核主频能跑到 100MHz片上带 512KB Flash、128KB SRAM外设资源里 UART、SPI、I2C、ADC 都齐全最关键的是它的低功耗表现和瑞萨那套 FSP 配置工具配合起来初始化外设基本是点几下鼠标的事。而 DA14531 这颗蓝牙 SoC 在圈子里口碑一直不错BLE 5.1 协议栈发射电流和接收电流都压得很低封装小成本也友好特别适合做那种电池供电、数据量不大的透传场景。把这两颗芯片放一起分工就很清晰了RA4M2 当主控负责采集、运算、协议封装DA14531 当无线通道负责把串口过来的数据通过 BLE 发给手机同时把手机下发的指令回传给主控。两者之间用 UART 连接这是最省事也最稳的物理层方案。提示DA14531 出厂固件默认并不是透传模式需要自己烧录支持 UART 透传的固件或者用 Dialog 的 SDK 二次开发。这一点在选型阶段就要确认清楚否则板子焊好了发现蓝牙端不干活返工很麻烦。1.2 整体数据链路的架构思路整个系统的数据流是这样的传感器或上位机数据进入 RA4M2 的某个 UART 口主控做必要的解析和打包再从另一个 UART 口发给 DA14531DA14531 通过 BLE 的 GATT 服务把数据推给手机反向则是手机写入特征值DA14531 从 UART 吐出来RA4M2 接收后执行相应动作。这里有个容易踩的坑RA4M2 的 UART 引脚是固定的几组选哪一组直接决定了 PCB 布线难度。我这次用的是 SCI 通道具体引脚在 FSP 里配置时会自动分配但硬件设计阶段一定要先查数据手册的引脚复用表别等到画完板子才发现选的那组 UART 跟其他外设冲突。架构上我没有用 SPI 或 I2C 去连蓝牙模块原因很简单透传场景下数据是流式的UART 的异步特性天然适合而且调试的时候拿个 USB 转串口工具就能直接抓数据排查问题成本最低。SPI 虽然速率高但协议复杂DA14531 那边的 SPI 从机模式配置也麻烦对透传这种低速率场景属于杀鸡用牛刀。1.3 方案的优势与适用边界这套组合最大的优势是分工明确、调试解耦。蓝牙不通的时候我可以先用串口助手直接跟 DA14531 对话确认蓝牙端没问题主控逻辑不对的时候我可以绕过蓝牙直接用串口线连 RA4M2 看输出。两个环节独立验证出问题能快速定位是哪一端的锅。适用边界也要说清楚这套方案适合数据量不大、对实时性要求不极端的场景比如传感器周期上报、远程指令下发、参数配置同步。如果你要做音频流或者高频采样数据的实时传输BLE 的带宽和连接间隔会成为瓶颈那就得考虑经典蓝牙或者别的方案了。2. 核心细节解析与实操要点2.1 RA4M2 的 UART 驱动配置要点RA4M2 用 FSP 配置 UART 的时候有几个参数必须搞清楚不然通信会莫名其妙出问题。首先是波特率。我这次跟 DA14531 之间跑的是 115200这是双方都支持的常用速率。有人喜欢拉到 921600 追求速度但实际测试下来长距离杜邦线连接时高波特率误码率明显上升115200 在透传场景下完全够用。波特率的计算跟 RA4M2 的时钟源有关FSP 会自动算分频系数但你要确保 PCLK 时钟配置正确否则实际波特率会有偏差。其次是数据格式。8 位数据位、1 位停止位、无校验这是最通用的配置DA14531 那边也按这个来。校验位在短距离板级通信里意义不大反而增加开销。再就是中断与缓冲。透传场景下数据是连续来的必须用中断或者 DMA 接收不能轮询。我一开始图省事用了轮询结果手机连续发几十字节的时候丢包严重。后来改成接收中断加环形缓冲区问题立刻消失。FSP 里配置 UART 的时候勾选接收中断然后在回调里把数据塞进自己维护的 buffer主循环再慢慢处理。// RA4M2 UART 接收回调的简化示意 void uart_callback(uart_callback_args_t *p_args) { if (p_args-event UART_EVENT_RX_CHAR) { uint8_t byte (uint8_t)p_args-data; ring_buffer_push(rx_buf, byte); } }这段代码看着简单但环形缓冲区的实现要注意读写指针的原子性。如果主循环和中断都在操作指针得用临界区保护或者用无锁的单生产者单消费者队列。我踩过一次坑主循环读指针的时候被中断打断结果读到一个半更新的状态数据错乱。后来加了关中断保护才稳。2.2 DA14531 端的固件与透传服务DA14531 这边是整个项目里最花时间的部分。Dialog 的 SDK 结构跟 STM32 那套不太一样它的 BLE 协议栈是事件驱动的所有操作都围绕ke_msg消息机制转。透传服务的核心是定义一个 GATT 服务里面包含两个特征值一个用于手机写数据Write一个用于模块通知手机Notify。UUID 可以自定义也可以直接用 Dialog 例程里的。我建议自定义避免跟手机里其他设备的服务混淆。数据从 UART 进来后需要触发一个 Notify 把数据推给手机。这里有个细节BLE 的 Notify 单包最大长度受 MTU 限制默认 MTU 是 23 字节实际有效载荷 20 字节。如果 UART 一次来 100 字节你得自己分包发送。我在固件里做了个简单的分包逻辑每 20 字节发一次 Notify手机端按顺序拼接。注意分包发送时如果发送太快协议栈的缓冲区会满导致部分 Notify 失败。稳妥的做法是每发一包等一个发送完成事件再发下一包。Dialog SDK 里有对应的回调可以挂。反向链路是手机写特征值DA14531 收到后从 UART 吐给 RA4M2。这部分相对简单在写回调里把数据往 UART 发送函数里一塞就行。但要注意 UART 发送是阻塞的如果数据量大会卡住 BLE 协议栈的任务。我的做法是维护一个发送队列写回调里只入队实际发送交给主循环处理。2.3 电平匹配与硬件连接细节RA4M2 的 IO 电压是 3.3VDA14531 也是 3.3V理论上可以直接连。但实际布线时我还是串了 22 欧姆的电阻主要是为了抑制信号反射和过冲。板子走线不长的话不串也能工作但加了更保险。接线方式是交叉连接RA4M2 的 TX 接 DA14531 的 RXRA4M2 的 RX 接 DA14531 的 TX地线必须共地。这一点新手容易忘不共地的话两边电平参考不一样通信会时好时坏。另外 DA14531 有个复位引脚和唤醒引脚如果要做低功耗管理这两个脚要接到 RA4M2 的 GPIO 上。我这次没做深度休眠所以只接了电源、地和 UART 三根线简单直接。信号RA4M2 侧DA14531 侧备注TXP4_01RX交叉连接RXP4_02TX交叉连接GNDGNDGND必须共地VCC3.3V3.3V独立供电更稳表格里这个引脚分配是我实际用的但不同封装和板子可能不一样以自己手上的原理图为准。3. 实操过程与核心环节实现3.1 开发环境搭建与工程创建RA4M2 这边我用的是 e2 studio 配合 FSP。安装过程没什么好说的官网下载按提示走就行。新建工程的时候选 RA4M2 对应的型号FSP 版本建议用较新的老版本有些 UART 的 bug。工程建好后在 FSP 的 Stacks 标签页里添加 UART 模块。配置界面里重点填这几个波特率 115200、数据位 8、停止位 1、无校验、接收中断使能。引脚分配在 Pins 标签页里做选好 SCI 通道后 FSP 会自动把 TX/RX 分配到对应引脚你只需要确认跟硬件一致。DA14531 这边用的是 Dialog 的 SmartBond 开发套件Keil 工程。SDK 里有个ble_app_peripheral的例程我是在这个基础上改的。主要改动是加了一个自定义服务以及 UART 的收发逻辑。Dialog 的 UART 驱动封装得比较深初始化的时候要指定波特率和引脚跟 RA4M2 对齐。3.2 UART 双向透传的代码实现先看 RA4M2 这边的主循环逻辑。核心就是一个状态机从环形缓冲区取数据判断是本地处理还是转发给蓝牙。while (1) { // 从传感器 UART 收数据转发给蓝牙 if (ring_buffer_available(sensor_buf) 0) { uint8_t data ring_buffer_pop(sensor_buf); uart_send_to_ble(data, 1); } // 从蓝牙 UART 收数据转发给传感器或执行指令 if (ring_buffer_available(ble_buf) 0) { uint8_t data ring_buffer_pop(ble_buf); process_command(data); } }这段逻辑看着简单但实际跑起来要注意两个 UART 的优先级。如果传感器数据量大蓝牙那边的数据可能被饿死。我的做法是给蓝牙接收更高的优先级或者在主循环里交替处理保证两边都有机会。DA14531 这边的透传逻辑核心是在 UART 接收回调里触发 BLE Notifyvoid uart_rx_callback(uint8_t *data, uint16_t len) { // 分包发送每包不超过 MTU 有效载荷 for (uint16_t i 0; i len; i 20) { uint16_t chunk (len - i 20) ? 20 : (len - i); ble_notify_send(data[i], chunk); // 等待发送完成再发下一包 while (!notify_done_flag); notify_done_flag 0; } }这里的notify_done_flag是在 BLE 发送完成回调里置位的。不加这个等待连续发多包的时候协议栈会返回忙数据就丢了。3.3 手机端 BLE 调试与数据验证手机端我用的是一款通用的 BLE 调试 App能扫描、连接、查看服务、读写特征值。调试阶段这个工具比写专门的 App 效率高得多。连接上 DA14531 后先确认服务列表里能看到自定义的透传服务。然后打开 Notify 开关往 Write 特征值里写一串数据观察 RA4M2 那边的串口输出。反过来让 RA4M2 往串口发数据看手机端 Notify 能不能收到。实测下来双向透传的延迟在几十毫秒级别对于传感器数据上报完全够用。如果发现丢包优先检查两边的波特率是否严格一致以及 UART 中断是否被其他高优先级中断打断太久。提示手机端调试时Android 和 iOS 的 BLE 行为有差异。Android 的 MTU 协商更灵活iOS 默认 MTU 较大但连接参数更保守。如果要做跨平台产品两边都要测。4. 常见问题与排查技巧实录4.1 蓝牙连不上或频繁断连这是最常见的问题。排查顺序我总结成一张表现象可能原因排查方法搜不到设备固件没跑起来检查 DA14531 供电和复位能搜到连不上广播参数问题确认广播间隔和名称连上就断连接参数不匹配调整连接间隔和延迟传数据时断缓冲区溢出降低发送速率或加大缓冲我遇到过一次连上就断的情况查了半天发现是 DA14531 的广播名称里带了特殊字符手机端解析异常。改成纯英文数字后正常。这种问题很隐蔽因为协议栈本身不报错。4.2 UART 数据错乱或丢包UART 问题基本逃不出这几个波特率不匹配、地线没共、中断优先级冲突、缓冲区溢出。波特率不匹配的表现是收到乱码这个用示波器量一下 TX 波形就能确认。地线没共的表现是时好时坏特别是手碰板子的时候变化明显。中断优先级冲突比较隐蔽表现为高负载时丢数据解决方法是把 UART 中断优先级调高或者用 DMA 减轻 CPU 负担。缓冲区溢出的话要么加大缓冲区要么加快处理速度。我一般会把缓冲区设成 256 字节以上并且加一个溢出计数器调试的时候打印出来看。4.3 透传延迟大或数据不同步延迟大通常是连接间隔设置得太长。BLE 的连接间隔最小可以到 7.5ms但手机端为了省电往往会协商成更大的值。如果应用对延迟敏感可以在连接后主动请求更新连接参数。数据不同步的问题多半是分包和拼包逻辑没对齐。发送端按 20 字节分包接收端必须按同样的边界拼或者用带长度头的协议。我后来在数据前面加了一个字节的长度信息接收端先读长度再读内容同步问题就解决了。4.4 实操避坑心得第一个心得先调通串口再碰蓝牙。很多人一上来就整蓝牙结果串口都没通问题混在一起根本没法查。正确顺序是先用串口助手确认 RA4M2 和 DA14531 各自的 UART 都能收发再把两者连起来最后才开蓝牙。第二个心得保留调试串口。RA4M2 上至少留一个 UART 专门打日志不要把所有串口都占满。调试的时候能实时看到程序跑到哪一步比单步断点高效得多。第三个心得DA14531 的固件烧录要留后路。Dialog 的芯片烧录方式跟通用 MCU 不太一样第一次烧录最好用官方开发板验证流程确认工具链没问题再上自己的板子。我有一次把芯片锁了折腾好久才恢复。第四个心得电源要干净。蓝牙对电源噪声敏感DA14531 的供电最好加 LC 滤波跟主控的电源适当隔离。我早期版本两块芯片共用一路 LDO蓝牙发射的时候主控的 ADC 读数会跳后来分开供电就稳了。这套方案我前后调了大概两周大部分时间花在蓝牙固件和分包逻辑上。硬件本身不复杂难点在于协议栈的理解和边界情况的处理。把 UART 透传跑通之后后面加什么传感器、做什么应用都是在这个稳定通道上叠功能的事了。
阅读完成 · 觉得有帮助?
咨询建站