RA4M2 + DA14531 蓝牙开发实战:从 UART 驱动到手机 BLE 双向透传

给单片机增加手机通信功能,可以采用"MCU + 蓝牙模块"的方案:MCU 负责业务逻辑,通过串口与蓝牙模块交换数据,模块负责广播、连接及无线数据传输。

本文记录在 RA-Eco-RA4M2 开发板 上,通过 PMOD1 接口连接 DA14531 蓝牙模块,实现 AT 指令查询及手机双向透传的过程。

最终完成了两条通信链路:

text 复制代码
RA4M2 → DA14531 → 手机:发送 hello
手机 → DA14531 → RA4M2:接收 HelloWorld

文章重点介绍通信原理、硬件连接、驱动实现和分阶段测试方法。

本文的控制脚定义、J3 供电选择及复位电路,对应本次使用的 DA14531 PMOD RevA 模块板;AT 指令对应实测的 superflyBLE、版本 V0.0 固件。其他 DA14531 模块或固件应以各自资料为准。

一、系统组成与通信原理

1. 硬件与软件环境

项目 本次使用的配置
主控开发板 RA-Eco-RA4M2-100PIN-V2.0
主控芯片 R7FA4M2AD3CFP
蓝牙模块 DA14531 PMOD 模块板
模块接口 PMOD1,SCI4
模块串口参数 115200、8 位数据、无校验、1 位停止位
PC 调试接口 CH340,SCI9
命令行组件 MicroShell
编译工具链 ARM LLVM、CMake、Ninja
手机工具 BLE 调试助手

这里使用了两个相互独立的串口:

text 复制代码
PC 串口终端
    │
    │ USB / CH340
    ▼
RA4M2 SCI9
    │
    │ Shell 命令解析
    ▼
RA4M2 SCI4
    │
    │ UART
    ▼
DA14531
    │
    │ BLE
    ▼
手机 BLE 调试助手

SCI9 用于输入测试命令和查看日志,SCI4 用于与蓝牙模块通信。分开使用可以避免模块数据和调试信息混在同一条串口链路中。

2. DA14531 在系统中负责什么?

本项目使用的是已经运行 BLE/UART 透传及 AT 指令固件的模块。

RA4M2 不需要在本工程中实现完整的蓝牙协议栈,而是通过 UART 完成两类操作:

操作 用途 示例
AT 指令交互 查询模块信息 查询版本、广播名称
数据透传 与手机交换业务数据 发送 hello,接收 HelloWorld

需要注意,AT 指令是模块固件提供的功能,不是使用 DA14531 芯片就必然支持同一套命令。

更换模块固件后,命令格式、默认波特率、服务 UUID 和透传方式都有可能变化。

3. BLE 为什么需要"服务"和"特征"?

手机连接模块后,调试助手通常先显示服务列表,而不是直接出现类似串口助手的接收窗口。

这是因为 BLE 数据访问基于 GATT。设备通过服务组织功能,通过特征暴露具体数据及读写操作。相关概念可以参考 Bluetooth SIG 的 GATT 入门资料。

在本项目的透传测试中,需要关注两类特征:

特征属性 在本次测试中的用途
Notify 模块向手机推送数据
Write / Write Without Response 手机向模块写入数据

实际固件可能把这两类能力放在同一个特征中,也可能使用不同特征,应以手机发现的属性为准。

因此,测试时需要完成:

text 复制代码
扫描设备 → 建立连接 → 发现服务 → 展开特征 → 开启通知 → 收发数据

连接成功,并不表示手机已经订阅了数据通知。

二、硬件连接:先把接口和控制脚对应好

1. PMOD1 与模块的引脚关系

本工程最终使用 PMOD1 / SCI4。

PMOD1 脚号 RA4M2 引脚 模块侧功能 MCU 侧配置
1 P401 BOOT 输入,保持模块自身偏置
2 P205 / TXD4 模块 RXD SCI4 发送
3 P206 / RXD4 模块 TXD SCI4 接收
5、11 GND 地 共地
6、12 3.3V 电源输入 供电
7 P008 CONNECT 输入
8 P403 复位控制 输出
9 P402 LPR 输出高电平

UART 的信号方向是:

text 复制代码
RA4M2 P205 / TXD4 ─────→ 模块 RXD
RA4M2 P206 / RXD4 ←───── 模块 TXD

开发板原理图中,PMOD1 接收路径经过 SB12。如果在 MCU 引脚处回环成功,却在 PMOD1 插座处失败,应检查这段连接路径。

2. J3 是模块电源选择接口

本次模块板的 J3 用于选择供电来源:

J3 脚号 功能
pin1 PMOD 电源输入
pin2 模块实际 VCC
pin3 电池 VB+

使用开发板供电时,需要接通:

text 复制代码
J3 pin1 ───── pin2

可以安装跳线帽,也可以使用接触可靠的杜邦线连接。连接应在断电状态下完成,不能同时短接三个脚。

本次调试中,补齐 J3 供电连接后,确认模块实际 VCC 为 3.3V,为后续正常启动建立了条件。

这个细节容易被忽略:PMOD 插座有电源,不代表经过电源选择接口后的模块 VCC 已经接通。

3. 复位极性必须结合模块板电路判断

模块板上的 J1 pin8 并不是直接接到芯片复位端,中间还有一个 SS8550 PNP 三极管反相电路。

因此,在本次模块板上:

MCU 输出到 J1 pin8 的电平 作用
低电平 通过反相电路使模块复位有效
高电平 释放复位,允许模块运行

程序使用的复位过程为:

text 复制代码
P403 拉低 → 保持 20ms → P403 拉高 → 等待模块启动

正常运行时保持:

text 复制代码
P403 = HIGH
P402 = HIGH

其中 P402 对应 LPR,按本次参考工程的使用方式保持高电平,使模块 UART 可用。

三、RA4M2 程序设计

1. 驱动分层

为了把硬件控制、串口收发和测试命令分开,程序主要划分为以下文件:

文件 职责
pmod1_uart.c SCI4 配置、中断接收、缓冲管理、回环测试
ble_uart.c 模块复位、控制脚、启动信息捕获
sci9_uart.c PC 调试串口及系统毫秒计时
uart_shell.c ble、pmod1 等测试命令

BLE 通信和 PMOD1 回环测试共用同一个 SCI4 驱动,避免两个模块分别初始化、读取同一个外设。

2. 配置 SCI4 引脚复用

P205、P206 需要配置为对应的 SCI 外设功能:

c 复制代码
uint32_t cfg =
    (uint32_t) IOPORT_CFG_PERIPHERAL_PIN |
    (uint32_t) IOPORT_PERIPHERAL_SCI0_2_4_6_8;

R_IOPORT_PinCfg(&g_ioport_ctrl,
                BSP_IO_PORT_02_PIN_05,
                cfg);

R_IOPORT_PinCfg(&g_ioport_ctrl,
                BSP_IO_PORT_02_PIN_06,
                cfg);

仅在软件中选择 SCI4 通道还不够,外部引脚也必须切换到正确的复用功能。

3. 波特率计算要使用真实外设时钟

本工程中,RA4M2 的 SCI 时钟来自:

text 复制代码
PCLKA = 100 MHz

对于当前采用的配置:

text 复制代码
BGDM = 0
ABCS = 0
ABCSE = 0
BRME = 1

波特率计算为:

text 复制代码
baud = PCLK / [32 × 4^CKS × (BRR + 1)] × MDDR / 256

115200 档使用:

text 复制代码
CKS  = 0
BRR  = 26
MDDR = 255

对应实际波特率约为:

text 复制代码
115288.63 baud

相对误差约为:

text 复制代码
+0.077%

分频和调制参数的关系可以对照 Renesas FSP SCI UART 驱动源码。

这里有一个值得记录的细节:旧注释曾写成"PCLKB=50MHz、分频系数16",虽然两者都不符合实际配置,但在部分档位上计算结果恰好与"100MHz、分频系数32"相同。

因此,排查波特率时,应核对实际时钟树和寄存器组合,不能只看代码注释。

4. 使用接收中断和环形缓冲

模块可能在启动时连续输出名称和 MAC,也可能在手机写入后突发发送一串数据。

如果只在主循环中偶尔读取 UART,打印日志或处理命令期间就可能来不及取走数据。

本工程采用:

text 复制代码
SCI4 RXI 中断
      ↓
读取接收字节
      ↓
写入环形缓冲
      ↓
Shell 命令读取并显示

接收缓冲数组大小为 1024 字节,采用预留一个位置区分空满的方式,可用容量为 1023 字节。

缓冲满时丢弃新字节并增加 dropped 计数。这样不会静默覆盖尚未读取的数据,也方便通过状态命令观察应用层是否读取不及时。

5. 接收错误也要正确恢复

程序记录了以下状态:

计数项 含义
RX 接收数据计数
ORER 硬件接收溢出
FER 帧错误
PER 奇偶校验错误
dropped 软件缓冲满导致的丢弃
TX_timeout 发送等待超时

错误恢复时,不能只依赖 RDRF 是否置位。

参照 FSP 的错误处理流程,发生接收错误时也需要读取、丢弃错误数据,再清除错误标志。简化逻辑如下:

c 复制代码
uint8_t ssr = R_SCI4->SSR;

if (ssr & (0x40U | 0x38U))
{
    uint8_t data = R_SCI4->RDR;

    /* 正常数据进入接收缓冲;
       错误数据用于诊断,不作为有效业务数据。 */
    (void) data;
}

if (ssr & 0x38U)
{
    R_SCI4->SSR =
        (uint8_t) (R_SCI4->SSR & (uint8_t) ~0x38U);
}

上面的代码仅用于说明处理顺序,实际工程还包含缓冲操作、错误分类和临界区保护。

6. 先开启接收,再释放模块复位

模块启动信息往往只发送一次。如果先复位、等待很久,最后才打开串口接收,就可能错过这段信息。

本工程采用的初始化顺序是:

text 复制代码
配置控制脚
    ↓
初始化 SCI4,开启接收
    ↓
发出模块复位脉冲
    ↓
等待启动,同时持续接收
    ↓
保存启动信息,供 ble read 查看

系统计时使用 1ms SysTick 中断,保证串口输出及等待模块启动期间,超时计时仍能正常推进。

四、为调试增加 Shell 命令

PC 端串口配置为:

text 复制代码
115200、8N1、无流控

主要命令如下:

命令 功能
pmod1 loopback PMOD1 串口回环测试
ble status 查看连接状态、控制脚及错误计数
ble diag 观察 RX 电平及短时间内的错误增量
ble reset 复位模块
ble banner 复位并捕获启动信息
ble at <命令> 发送 AT 指令并等待响应
ble test 自动探测常见波特率和有效应答
ble send <文本> 向模块发送文本,追加 CRLF
ble read 读取模块发来的数据

这组命令可以把测试分成硬件通路、模块启动、AT 交互和无线透传几个阶段。

五、第一阶段:验证 PMOD1 串口回环

测试前断电拔下蓝牙模块,在 PMOD1 插座处短接 pin2 与 pin3,再上电执行:

text 复制代码
pmod1 loopback

实际输出:

text 复制代码
[RA4M2 /]$ pmod1 loopback
PMOD1 loopback PASS; remove jumper before attaching module

随后执行:

text 复制代码
ble diag

测试时得到:

text 复制代码
Observe 100ms (no TX/reset):
samples=80178 P206_high=80178 RXDMON_high=80178 edges=0 TX(P205)=1

delta: RX=0 FER=0 break_low=0 clear_failed=0
RX stayed HIGH during sampling (normal idle, or disconnected/pulled high).

回环通过说明当前波特率下,MCU 发出的测试字节可以经插座连接回到接收端。

由于测试在 PMOD1 插座处完成,也覆盖了 MCU 到该插座的收发路径。

回环只验证 MCU 侧 UART 通路,不验证蓝牙模块是否上电、是否运行,也不验证无线通信。

测试结束后,应断电移除短接线,再接入模块。

六、第二阶段:捕获模块启动信息

接好模块及 J3 电源选择后,重新上电,执行:

text 复制代码
ble read

实际输出:

text 复制代码
[RA4M2 /]$ ble read
RX: \xC0DEVICE_NAME:superflyBLE MAC:A197B1FEC8C4\n
remaining=0

再执行启动信息捕获:

text 复制代码
[RA4M2 /]$ ble banner
Boot RX (current baud): \xFEDEVICE_NAME:superflyBLE MAC:A197B1FEC8C4\n
Boot RX proves module->MCU only; use ble test for AT round-trip.

从完整可读的文本可以确认:

text 复制代码
设备名称:superflyBLE
MAC:A197B1FEC8C4

这说明模块应用已经启动,并且模块到 MCU 的 UART 接收通路正常,当前 115200 波特率能够正确接收文本。

日志开头的 \xC0、\xFE 是捕获到的非打印字节,可能与复位阶段的信号变化有关,不应当作设备名称的一部分。

另外,启动信息只证明:

text 复制代码
模块 TX → MCU RX

要验证 MCU 到模块的发送方向,还需要 AT 应答测试。

七、第三阶段:验证 AT 指令交互

测试 AT 指令时,先保持手机断开,避免固件连接后的透传行为影响判断。

本工程的 ble at 命令会自动追加:

text 复制代码
\r\n

因此不需要在 Shell 中手动输入转义字符。

1. 基础查询

text 复制代码
[RA4M2 /]$ ble at AT?
AT RX: AT\n

2. 查询固件版本

text 复制代码
[RA4M2 /]$ ble at AT+VER?
AT RX: OK+VER=V0.0\n

3. 查询设备名称

text 复制代码
[RA4M2 /]$ ble at AT+NAME?
AT RX: OK+NAME=superflyBLE\n

版本和名称查询已经形成了完整的请求---应答链路:

text 复制代码
RA4M2 发送查询
       ↓
模块解析 AT 指令
       ↓
模块返回查询结果
       ↓
RA4M2 接收并显示

到这里,双向 UART 通信已经验证通过。

4. 自动测试必须适配真实应答格式

本次固件的应答并不总是单独一行:

text 复制代码
OK

例如版本查询返回:

text 复制代码
OK+VER=V0.0

如果自动测试只判断是否存在独立的 OK 行,就会把已经正常工作的模块误判为无有效应答。

因此,最终程序将版本查询作为探测命令之一,并识别完整的:

text 复制代码
OK+VER=<非空版本字符串>

同时保留对独立 OK 行的支持。

普通命令回显、随机乱码或仅收到某个字符,都不作为测试成功的依据。

八、第四阶段:手机连接与 Notify 订阅

1. 扫描并连接模块

打开手机 BLE 调试助手,扫描:

text 复制代码
superflyBLE

连接后展开服务列表,再查看各服务下的特征。

本文未将某个 UUID 写死,因为实际服务和特征由模块固件决定。应根据当前设备展示的 UUID、描述和属性选择对应的透传特征。

2. 找到 Notify 特征并开启通知

在特征列表中查找包含:

text 复制代码
Notify

属性的条目,点击"开启通知""订阅"或对应图标。

如果手机工具只有服务浏览能力,操作不方便,也可以使用支持特征读写和通知订阅的 nRF Connect for Mobile。

本次测试中,手机已经能够连接模块,但最初只显示服务信息。展开特征并开启通知后,才完成了接收数据的操作。

需要注意:

应先订阅,再发送测试数据。未订阅时已经发送的内容,不保证在订阅后补发。

九、第五阶段:完成双向透传测试

1. RA4M2 向手机发送

手机连接并开启通知后,在 PC 串口终端执行:

text 复制代码
[RA4M2 /]$ ble send hello
UART sent; verify reception on phone

手机端成功接收到测试内容,验证了以下路径:

text 复制代码
RA4M2 SCI4 TX
      ↓
DA14531 UART RX
      ↓
BLE 通知
      ↓
手机

本工程的 ble send 会追加 CRLF,因此发送的字节内容为:

text 复制代码
hello\r\n

如果手机工具使用十六进制显示,对应:

text 复制代码
68 65 6C 6C 6F 0D 0A

终端打印 UART sent 只说明 MCU 已完成串口发送;确认无线链路成功,还要以手机实际收到数据为准。

2. 手机向 RA4M2 发送

在手机端找到具有:

text 复制代码
Write

或:

text 复制代码
Write Without Response

属性的透传特征,选择文本格式,发送:

text 复制代码
HelloWorld

随后在 PC 串口终端执行:

text 复制代码
[RA4M2 /]$ ble read
RX: HelloWorld
remaining=0

这验证了反方向链路:

text 复制代码
手机写入 BLE 特征
      ↓
DA14531 接收
      ↓
模块 UART TX
      ↓
RA4M2 SCI4 RX
      ↓
接收缓冲
      ↓
PC 串口终端显示

remaining=0 表示本次读取后,软件接收缓冲中没有剩余待读数据。

至此,RA4M2 与手机之间的双向透传完成。

十、本次调试中值得保留的经验

1. 回环通过后,要继续验证模块控制条件

回环可以证明 MCU 的 UART 通路可用,但模块正常通信还依赖供电、复位、LPR 和固件运行状态。

按照下面的顺序验证,可以更快缩小问题范围:

text 复制代码
UART 回环
    ↓
模块实际供电与控制脚
    ↓
启动信息
    ↓
AT 查询应答
    ↓
手机连接和特征订阅
    ↓
双向透传

2. 接口名称、UART 通道和引脚必须统一

本工程曾存在 BLE 命令使用 PMOD2/SCI0,而实际模块测试使用 PMOD1/SCI4 的情况。

修改时必须同时核对:

  • UART 外设通道;
  • TX/RX 引脚复用;
  • 复位、LPR、CONNECT 控制脚;
  • Shell 显示的引脚说明;
  • 回环命令实际使用的驱动。

只改日志里的"PMOD1",或者只改 UART 通道,都不能完成正确迁移。

3. 接口侧复位极性不一定等于芯片复位极性

模块板可能加入三极管、逻辑门等电路。

本次模块板的插座复位控制端经过反相,因此 MCU 应输出低脉冲复位、高电平运行。应从 MCU 到模块芯片沿信号路径检查整条电路。

4. 看错误增量比只看累计值更有帮助

FER 等统计项是累计值,可能包含启动、复位或扫描波特率期间产生的错误。

判断当前通信是否仍异常,应该观察固定时间窗口内是否继续增长。

因此,程序增加了 ble diag,观察 100ms 内的 RX 电平和错误增量。它适合判断持续低电平、空闲高电平及错误是否继续发生,但不能替代示波器或逻辑分析仪分析波形。

5. BLE 透传仍需要应用层协议

本次验证的是短文本双向通信。

如果后续用于传感器数据、控制指令或较长消息,还需要定义帧格式,例如:

text 复制代码
帧头 + 命令字 + 长度 + 数据 + 校验

接收程序不能默认"一次串口读取"或"一次 BLE 通知"就一定是一条完整业务消息,应支持拆包、拼包和长度校验。

十一、测试结果与后续扩展

本次完成的验证项目如下:

测试项目 结果
PMOD1 插座处 UART 回环 通过
模块启动信息接收 通过
AT 固件版本查询 V0.0
AT 设备名称查询 superflyBLE
手机扫描并连接 通过
RA4M2 → 手机发送 hello 通过
手机 → RA4M2 发送 HelloWorld 通过

当前工程已经具备模块初始化、UART 中断接收、AT 查询、状态诊断及双向透传能力。后续可以在此基础上加入传感器数据上报、手机控制 LED、参数配置及连接状态提示。

这些结果验证了基本功能链路;持续吞吐、远距离通信、断线重连和长时间稳定性,还需要分别设计测试。

相关推荐
开开心心_Every4 小时前
文件夹批量创建工具支持同级和多层级
运维·服务器·游戏·jupyter·智能手机·pdf·postman
ii_best16 小时前
按键精灵手机端开发安卓版实战:手写一个可最小化、可拖动的「运行日志悬浮窗」(附完整 源码 + 踩坑记录)
android·ios·智能手机·自动化·ai编程·按键精灵
终端安全笔记16 小时前
安卓做 MDM 管控,先分清三种注册入口
android·安全·智能手机
乌萨达17 小时前
手机模拟器安卓怎么用?电脑安装应用、玩手游与账号同步指南
android·智能手机·电脑·雷电模拟器
ycvv20 小时前
手机启动失败后的数据提取评估:系统状态、加密条件与文件验收
服务器·数据库·智能手机
wulechun1 天前
基于Python实现的开源缠论量化分析框架:深入解析chan.py项目架构、可视化绘图与策略回测实战指南
智能手机
hongyangcao1 天前
运营商下线手机分期:一条消费信贷风控链路的关闭
智能手机
wulechun1 天前
跨越传统搜索引擎的信息壁垒:深度解析Last30Days-skill开源项目架构、信号评分体系与实战使用方法
智能手机
PiaoKe___1 天前
云手机原理与 Python 自动化实战:从虚拟化、ADB 到设备池管理
python·智能手机·自动化