资讯详情

资讯详情

RA4M2与DA14531 BLE双向透传实战:从硬件连接到稳定通信

1. 为什么选 RA4M2 搭配 DA14531 做 BLE 透传如果你手头有一块 RA4M2 开发板又刚好拿到几片 DA14531 模块想把它们凑成一套能跑双向透传的蓝牙节点那这套组合其实挺有意思。RA4M2 是瑞萨 RA 系列里偏主流的一颗 Cortex-M33主频 100MHz带 TrustZone外设资源对串口、定时器、DMA 这些常规需求完全够用DA14531 则是 Dialog 那颗主打低功耗的 BLE SoC官方叫 SmartBond TINY封装小、功耗低在蓝牙标签、传感器节点这类场景里出镜率很高。把这两颗芯片放一起本质上是做一个主控 蓝牙从机的架构RA4M2 负责业务逻辑、数据采集、协议处理DA14531 负责把数据通过 BLE 发出去同时接收手机端下发的指令再回传给 RA4M2。两者之间最省事的连接方式就是 UART两根线 TX/RX 加一根地线波特率谈好就能跑。这个方案适合谁一类是手上已经有 RA4M2 板子、想快速验证 BLE 功能的开发者另一类是做低功耗数据采集节点需要一个能算 能连的组合又不想上太贵的方案。DA14531 的 BLE 协议栈是现成的RA4M2 的 UART 驱动瑞萨也给了 FSP 配置工具真正要动手写的胶水代码并不多难点在于把两边的数据流打通、把透传的边界情况处理干净。我先把整体数据链路说清楚后面所有细节都围绕这条链路展开手机 App 通过 BLE 连接 DA14531写入特征值DA14531 收到数据后从 UART TX 发给 RA4M2 的 RXRA4M2 解析数据做业务处理再把响应从 UART TX 发回 DA14531DA14531 通过 BLE Notify 把数据推回手机。这条链路看着简单但每一段都有坑。下面我按硬件连接 → RA4M2 侧 UART 驱动 → DA14531 侧 BLE 配置 → 双向透传联调 → 稳定性优化的顺序把踩过的坑和验证过的做法都摊开讲。2. 硬件连线与电平匹配别小看这两根线2.1 引脚分配与交叉连接RA4M2 和 DA14531 之间走 UART接线就三根RA4M2 的 TX 接 DA14531 的 RXRA4M2 的 RX 接 DA14531 的 TXGND 对 GND。听起来是废话但我见过不止一个人把 TX 接 TX、RX 接 RX然后对着收不到数据查了一下午代码。RA4M2 这边我选的是 SCI 通道比如 SCI0对应引脚 P410TX/ P411RX具体用哪组要看你的板子引出情况。DA14531 的 UART 默认引脚在官方参考设计里是 P05TX/ P06RX但这个可以在配置里改后面会讲。注意DA14531 的 UART 引脚是复用功能上电默认状态不一定是 UART必须在初始化代码里显式配置。这一点和很多 MCU 不一样容易漏。2.2 电平与供电的坑RA4M2 的 IO 电平是 3.3VDA14531 也是 3.3V 供电所以电平是匹配的不需要电平转换。但有两个细节要注意第一DA14531 的供电范围是 1.8V 到 3.3V如果你用 3.3V 供电IO 也是 3.3V没问题。但如果你为了省电把 DA14531 供到 1.8V那它的 IO 高电平就只有 1.8VRA4M2 可能识别不到高电平这时候就必须加电平转换。我建议初期调试直接用 3.3V跑通了再考虑降功耗。第二DA14531 在深睡眠模式下 UART 引脚的状态会变如果 RA4M2 这时候还在往 TX 上灌数据可能造成漏电或者误唤醒。稳妥的做法是在 DA14531 进入睡眠前通过一根 GPIO 通知 RA4M2我要睡了先别发或者干脆让 RA4M2 也进入低功耗等待。2.3 波特率的取舍波特率选多少DA14531 的 UART 在 active 模式下最高能跑到 921600但实际用下来115200 是最稳的。原因有两个一是 DA14531 在 BLE 连接间隔内处理 UART 数据的时间窗口有限波特率太高容易丢数据二是 RA4M2 这边如果用中断接收115200 下中断频率完全可控再高就要上 DMA 了。我实测过 230400短包没问题但连续发 200 字节以上的包时DA14531 侧偶发丢字节。后来降到 115200连续跑 24 小时没丢过。所以除非你有明确的吞吐量需求否则 115200 是性价比最高的选择。3. RA4M2 侧 UART 驱动用 FSP 配置还是手写寄存器3.1 FSP 配置的快速路径瑞萨给 RA 系列配了 FSPFlexible Software Package里面有个 Stacks 配置界面选 UART 然后填参数就行。我一般这样配在 FSP 的 Stacks 标签页添加一个 UART 栈选 SCI 通道波特率填 115200数据位 8停止位 1无校验回调函数选接收完成和发送完成两个或者用接收中断逐字节处理引脚在 Pins 标签页里确认别和别的外设冲突。FSP 生成代码后你调用R_SCI_UART_Open()打开然后R_SCI_UART_Write()发送接收靠回调。这套流程官方文档写得很清楚我就不重复了。但有几个 FSP 配置里的细节文档没强调第一接收缓冲区的管理。FSP 的 UART 接收回调是每收到一个字节触发一次如果你配的是逐字节模式或者收满指定长度触发一次。透传场景下数据长度不固定我建议用逐字节回调自己维护一个环形缓冲区这样不会因为长度不匹配丢数据。第二发送的阻塞问题。R_SCI_UART_Write()是异步的调用后立刻返回实际发送在后台进行。如果你连续调用两次 Write 而第一次还没发完第二次会返回错误。透传场景下 RA4M2 可能随时要回数据所以要么在发送前检查状态要么用一个发送队列。3.2 环形缓冲区的实现要点透传的核心是来多少收多少不丢不粘。我在 RA4M2 侧用一个 512 字节的环形缓冲区收数据中断里只做一件事把收到的字节塞进缓冲区更新写指针。主循环里检查读指针和写指针的差值有数据就取出来处理。#define UART_RX_BUF_SIZE 512 static volatile uint8_t rx_buf[UART_RX_BUF_SIZE]; static volatile uint16_t rx_wr 0; static volatile uint16_t rx_rd 0; void uart_rx_callback(uart_callback_args_t *p_args) { if (p_args-event UART_EVENT_RX_CHAR) { uint16_t next (rx_wr 1) % UART_RX_BUF_SIZE; if (next ! rx_rd) { // 缓冲区未满 rx_buf[rx_wr] (uint8_t)p_args-data; rx_wr next; } // 满了就丢弃或者置错误标志 } }这段代码的关键在于next ! rx_rd这个判断它保证缓冲区满的时候不会覆盖未读数据。丢数据总比数据错乱好因为透传场景下上层协议通常有校验丢一包可以重传数据错乱反而更难查。3.3 为什么不用 DMA有人会问透传不是应该上 DMA 吗理论上 DMA 能减轻 CPU 负担但在这个场景下我不推荐原因有三一是 DA14531 侧的数据是 BLE 事件驱动的包与包之间间隔不固定DMA 的传输长度不好预设二是数据量本身不大115200 波特率下每秒最多 11.5KBRA4M2 跑 100MHz中断处理这点数据绰绰有余三是 DMA 配置复杂调试成本高透传初期用中断更容易定位问题。等你的透传逻辑稳定了数据量确实上来了再考虑把接收改成 DMA 加空闲中断的方式那是另一个话题。4. DA14531 侧 BLE 配置从 SDK 例程到透传服务4.1 选对 SDK 例程作为起点DA14531 的 SDK 里例程不少做透传最合适的起点是ble_app_peripheral或者ble_app_barebone。前者带了一个自定义服务后者更精简。我建议从ble_app_peripheral改因为它已经有一个可读写的特征值你只要把读写回调里加上 UART 收发就行。SDK 的工程结构里你要关注这几个文件user_custs1_def.c定义自定义服务的 UUID、特征值属性user_custs1_impl.c特征值的读写回调实现user_peripheral.c连接、断开、广告这些主流程user_uart.c如果你要加 UART可以新建一个或者复用 SDK 里的 UART 驱动。4.2 自定义服务的 UUID 设计透传服务需要两个特征值一个用于手机写数据Write一个用于 DA14531 推数据Notify。UUID 可以自己定但要注意别和标准服务冲突。我一般用 128 位自定义 UUID比如服务 UUID0000ffe0-0000-1000-8000-00805f9b34fb这个其实是常见的透传服务 UUID很多模块在用写特征值0000ffe1-...Notify 特征值0000ffe2-...用这个 UUID 的好处是手机端有很多现成的 BLE 调试 App 能直接识别省得自己写 App。如果你要做产品建议换成自己申请的 UUID避免和别人的设备混淆。4.3 UART 与 BLE 的数据搬运DA14531 侧的核心逻辑是BLE 写回调触发时把数据从 BLE 缓冲区搬到 UART TXUART 收到数据时通过 BLE Notify 推出去。这里有两个关键点第一BLE 写回调里的数据长度。BLE 单包最大 20 字节默认 MTU 23减去 3 字节头如果你手机一次发 100 字节协议栈会拆成 5 包写回调触发 5 次。所以你在写回调里不能假设一次回调就是一整条消息要么在应用层做分包重组要么和手机端约定每次不超过 20 字节。第二UART 发送的时机。DA14531 在 BLE 连接事件之间有空闲窗口UART 发送要在这个窗口内完成。如果数据太长发送跨越了连接事件可能影响 BLE 的稳定性。所以我在 UART 发送前会检查数据长度超过 64 字节就分片发。void user_uart_rx_handler(uint8_t *data, uint16_t len) { // UART 收到数据通过 Notify 推给手机 if (len 0 ble_connected) { struct custs1_val_ntf_ind_req *req KE_MSG_ALLOC_DYN( CUSTS1_VALUE_NTF_IND, prf_get_task_from_id(TASK_ID_CUSTS1), TASK_APP, custs1_val_ntf_ind_req, len); req-conidx 0; req-handle CUSTS1_IDX_FFE2_VAL; req-length len; req-notification true; memcpy(req-value, data, len); ke_msg_send(req); } }这段代码是 DA14531 SDK 的标准 Notify 流程KE_MSG_ALLOC_DYN动态分配消息memcpy填数据ke_msg_send发出去。注意handle要和你定义的特征值索引对上填错了 Notify 发不出去。4.4 连接参数与吞吐量的关系BLE 的连接间隔直接决定透传的实时性。DA14531 默认的连接间隔可能是 30ms 到 50ms意味着手机发一包数据最快也要等下一个连接事件才能被 DA14531 处理。如果你要更快的响应可以在连接建立后请求更新连接参数比如把间隔降到 15ms 甚至 7.5ms。但连接间隔不是越小越好。间隔小功耗高而且有些手机不允许太小的间隔。我的经验是调试阶段用 30ms功能验证没问题后根据实际需求调整。如果只是传传感器数据30ms 完全够如果是遥控类应用可以试 15ms。5. 双向透传联调从能通到稳定5.1 分阶段验证的思路透传联调最忌讳一上来就双向全开出了问题根本不知道是哪一段。我一般分四步走第一步RA4M2 自发自收。把 RA4M2 的 TX 和 RX 短接发一串数据看能不能原样收回来验证 UART 驱动本身没问题。第二步RA4M2 和 DA14531 对发。RA4M2 定时发数据DA14531 收到后通过 Notify 推给手机手机 App 上看数据对不对。这一步验证 RA4M2 → DA14531 → 手机的方向。第三步手机发数据DA14531 通过 UART 转给 RA4M2RA4M2 收到后点灯或者回显。这一步验证手机 → DA14531 → RA4M2 的方向。第四步双向同时跑。手机发指令RA4M2 处理后回数据看会不会互相干扰。每一步都跑通了再合起来。这样出问题的时候你能快速定位是哪一段的毛病。5.2 数据粘包与分包的处理透传场景下UART 是字节流BLE 是包流两者之间必然存在粘包和分包的问题。比如手机连续发两条 10 字节的指令DA14531 的 UART 可能把它们合成 20 字节一次发给 RA4M2反过来RA4M2 发 50 字节DA14531 可能拆成 3 包 Notify 推给手机。解决这个问题的标准做法是在应用层加一个简单的帧协议。我常用的是帧头 长度 数据 校验的格式字段长度说明帧头2 字节固定 0xAA 0x55长度1 字节数据段长度最大 255数据N 字节实际载荷校验1 字节前面所有字节的异或RA4M2 侧收到数据后在环形缓冲区里找帧头找到后按长度取数据校验通过就处理不通过就丢弃并重新找帧头。这套逻辑不复杂但能解决 90% 的透传数据错乱问题。5.3 手机端 App 的选择调试阶段不用自己写 App用现成的 BLE 调试工具就行。安卓上我用得比较多的是 nRF Connect 和 LightBlueiOS 上 LightBlue 也很好用。这些工具能扫描、连接、读写特征值、订阅 Notify足够验证透传功能。用 nRF Connect 的时候连上设备后找到你的服务点写特征值旁边的上传箭头输入十六进制或者文本数据就能发。Notify 特征值点那个三个箭头的小图标订阅之后 DA14531 推的数据就会实时显示。注意有些 App 默认按 UTF-8 解析 Notify 数据如果你传的是二进制显示会乱码。在设置里改成十六进制显示就行。6. 稳定性优化那些跑久了才会暴露的问题6.1 断连重连的处理BLE 连接不是永久的手机走远、锁屏、切换 App 都可能导致断连。DA14531 在断连后要重新开始广告RA4M2 这边要检测到蓝牙断了并做相应处理。DA14531 的断连回调里我一般做三件事停止 Notify、重新启动广告、通过 UART 通知 RA4M2。RA4M2 收到断连通知后可以停止发送数据避免数据堆在 UART 缓冲区里溢出。重连的时候DA14531 会重新建立连接但之前订阅的 Notify 需要手机重新订阅。这是 BLE 协议的规定不是 bug。所以你的手机 App 或者调试工具在重连后要记得重新点订阅。6.2 低功耗模式的取舍DA14531 的一大卖点是低功耗但透传场景下低功耗和实时性是有矛盾的。如果 DA14531 进入 extended sleepUART 可能收不到数据或者收到数据后唤醒有延迟。我的做法是连接建立后保持 active 模式不做深睡眠断连后进入 extended sleep等广告事件唤醒。这样连接期间透传稳定断连后又能省电。如果你确实需要在连接期间也省电那就要接受一定的响应延迟并且把 UART 的唤醒配置好。6.3 长时间运行的看门狗RA4M2 和 DA14531 都应该开看门狗。RA4M2 的看门狗用 FSP 配置一下就行主循环里定期喂狗。DA14531 的看门狗在 SDK 里也有但要注意喂狗时机别在中断里喂容易掩盖主循环卡死的问题。我遇到过 RA4M2 因为 UART 接收缓冲区满了之后没处理导致主循环一直在等最后看门狗复位。后来加了缓冲区溢出的错误处理满了就清空重新开始问题就没了。所以看门狗不是万能的根本还是要处理好边界情况。7. 几个容易被忽略的实操细节7.1 DA14531 的 UART 波特率配置DA14531 的 UART 波特率是通过时钟分频算出来的不是随便填个数就行。SDK 里有个uart_init()函数里面会根据你选的时钟源计算分频值。如果你改了系统时钟波特率可能会偏。我一般用 16MHz 的时钟源115200 波特率下误差在 1% 以内通信很稳。如果你发现 UART 收到的数据偶尔错位先查波特率误差。用示波器量一下 TX 线上的位宽算一下实际波特率和理论值对比。误差超过 2% 就容易出问题。7.2 RA4M2 的引脚复用冲突RA4M2 的引脚功能很多是复用的FSP 配置的时候如果两个外设抢同一个引脚生成代码会报错。我建议在 Pins 标签页里先把所有用到的引脚列出来确认没有冲突再生成代码。特别是 UART 的 TX/RX 和 SWD 调试引脚有时候会撞。7.3 BLE 的 MTU 协商默认 MTU 是 23实际能传 20 字节。如果你要传更长的数据可以在连接后发起 MTU 协商DA14531 支持到 247 字节。协商成功后单包能传 244 字节透传效率会高很多。但 MTU 协商需要手机端配合不是所有 App 都支持。nRF Connect 支持你可以在连接后手动发起协商。自己写 App 的话在连接回调里调用协商接口就行。7.4 数据吞吐量的实测数据我在 115200 波特率、30ms 连接间隔、默认 MTU 的条件下实测单向透传的稳定吞吐量大约是 1.5KB/s。如果把连接间隔降到 15msMTU 协商到 247吞吐量能到 8KB/s 左右。这个数据供你参考实际会因环境和手机不同有差异。如果你的应用需要更高的吞吐量那 RA4M2 和 DA14531 之间的 UART 波特率也要相应提高否则 UART 会成为瓶颈。115200 的 UART 理论上限是 11.5KB/s实际有效载荷大概 8KB/s和 BLE 协商 MTU 后的吞吐量刚好匹配。8. 调试工具与排查手段8.1 逻辑分析仪抓 UARTUART 通信出问题的时候逻辑分析仪是最直接的工具。把探头夹在 TX、RX、GND 上设置波特率 115200触发方式选下降沿就能看到实际传输的字节。我一般会对比RA4M2 发的和DA14531 收的如果对不上就是波特率或者接线的问题。没有逻辑分析仪的话用 USB 转串口模块也行。把 RA4M2 的 TX 接到串口模块的 RX电脑上用串口助手看数据。这个方法便宜但只能看单向而且会占用一个串口。8.2 BLE 抓包BLE 空中包的分析需要专门的抓包工具比如 Nordic 的 Sniffer 或者 TI 的 Packet Sniffer。这些工具能抓到连接建立、特征值读写、Notify 这些事件帮你确认数据到底有没有发出去。不过抓包工具配置起来有点麻烦需要特定的硬件。调试初期我建议先用 App 层面的日志确认数据到了手机没有。如果 App 收到了但数据不对再上抓包工具查空中包。8.3 日志输出的取舍RA4M2 和 DA14531 都可以通过 UART 打日志但透传本身也占 UART两者会冲突。我的做法是调试阶段用另一个 UART 通道打日志或者用 SWO如果芯片支持量产阶段把日志关掉或者只在错误时打。DA14531 的日志可以通过 SDK 里的arch_printf输出但要注意它默认可能走 UART1和透传用的 UART 不是同一个。配置的时候看清楚通道号别搞混了。9. 从 Demo 到产品的距离把透传跑通只是第一步真要做成产品还有几件事要处理。第一是固件升级。DA14531 支持 OTA但 OTA 和透传会抢 BLE 连接需要设计好切换逻辑。RA4M2 这边如果要升级可以通过 DA14531 把固件传过来也可以留一个独立的升级接口。第二是配对与绑定。Demo 阶段通常不加密谁都能连。产品上要加配对绑定防止未授权设备连接。DA14531 的 SDK 支持配对配置一下就能开。第三是功耗优化。如果产品是电池供电要仔细算一下平均功耗。DA14531 在连接状态下的功耗和连接间隔强相关间隔越大越省电。RA4M2 也可以在空闲时降频或者进睡眠。第四是异常恢复。产品在现场跑什么异常都可能遇到。BLE 断连、UART 卡死、看门狗复位这些都要有恢复机制。我的经验是任何可能卡住的地方都要加超时超时就复位重来别指望它能自己恢复。这套 RA4M2 加 DA14531 的方案我从接线到透传稳定跑了大概两周中间踩的坑基本都写在上面了。最深的体会是透传本身不难难的是边界情况的处理。数据短了、长了、断了、重了每一种都要想到。你把上面这些边界都处理干净这套方案跑起来就很踏实了。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →