给单片机增加手机通信功能,可以采用"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、参数配置及连接状态提示。
这些结果验证了基本功能链路;持续吞吐、远距离通信、断线重连和长时间稳定性,还需要分别设计测试。