这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【瑞萨BLE/WIFI模块测评】DA14531

共1条 1/1 1 跳转至

【瑞萨BLE/WIFI模块测评】DA14531

菜鸟
2026-09-19 19:33:16     打赏

上一篇把 RA4M2 的板子定义从头抄了一遍,栽在晶振上(以为 12MHz 实际 24MHz,超频到 192MHz 直接 LOCKUP),最后 DA16200 的 WiFi 从 AT 握手跑到 TCP 收发。这篇换蓝牙模块。

image.png

本来以为这是最轻松的一篇——板子定义现成、Pmod 座现成、串口现成,把 WiFi 模块拔下来插上 BLE 模块就完事。结果是目前为止最曲折的一次

接线不用动,两个模块都是 Pmod 插同一个座。先翻 Zephyr 对这颗芯片的支持:

$ grep -rn "DA1453" zephyr/drivers/bluetooth/hci/Kconfig
208:config BT_DA1453X
209:    bool "DA1453x HCI driver"
211:    depends on DT_HAS_RENESAS_BT_HCI_DA1453X_ENABLED

$ grep -rln "bt-hci-da1453x" zephyr/boards/
boards/shields/renesas_us159_da14531evz/renesas_us159_da14531evz.overlay

驱动有,连 shield 定义都有——瑞萨官方的 US159-DA14531EVZ,Zephyr 上游直接支持。我当时很高兴,觉得这篇五分钟就能写完:挂 shield,CONFIG_BT=y,跑 beacon 示例,收工。然后看到 shield 文档里这句:

The DA14531 Module contained on the shield must be programmed with a binary
file that supports the HCI interface over UART, with hardware flow control enabled.

出厂固件不是 HCI,得自己用 SmartBond Flash Programmer 经 SWD 重烧。那就先探一探模块现在跑的到底是什么。两种可能一次问清:AT 固件会回 OK(ASCII),HCI 固件会回 Command Complete 事件(二进制)。写个探测程序,发 AT\r\n,再发 HCI Reset 的 01 03 0C 00,收到什么全按 hex + ASCII 打出来:

[1] boot output (module talking on its own, 3s)
    2 bytes (framing/overrun errors: 1)
    0000  00 00                                            |..|
[2] CodeLess AT probe: "AT\r\n"
    <nothing>
[3] HCI probe: 01 03 0c 00  (HCI_Reset)
    <nothing>

两个都静默。开机那 2 个字节 00 00 还伴随 1 个 framing error,是复位释放瞬间电平跳变造出来的假字节,不是数据。

引脚电平:一个我自己挖的坑

协议层问不出东西,往下走一层直接量引脚。UART 空闲时 TX 必须是高电平,所以只要模块 TX 脚是高的,至少说明串口初始化过了。读 PIDR(端口输入数据寄存器,即使引脚被复用成外设功能也反映真实电平):

40080086:  ffff

Port4 全高,包括模块 TX 所在的 P410。但这个读数一文不值——悬空的引脚配上 MCU 内部上拉也是高,「高电平」这个事实同时兼容「模块在驱动它」和「根本没人管它」两种情况。要分开得用内部上下拉去逼它:外部有低阻驱动的话内部上下拉都拗不过,pd 和 pu 读数相同;没有外部驱动的话引脚老实跟着内部走,pd=0 pu=1。

gpio_pin_configure(port4, 10, GPIO_INPUT | GPIO_PULL_DOWN);
k_msleep(5);
vd = gpio_pin_get_raw(port4, 10);
gpio_pin_configure(port4, 10, GPIO_INPUT | GPIO_PULL_UP);
k_msleep(5);
vu = gpio_pin_get_raw(port4, 10);

跑出来:

P410 as input, no pull : 0
P410 with pull-down    : 0
P410 with pull-up      : 1

悬空特征,上拉能拉高、下拉能拉低,对端一个驱动源都没有,第三行还顺手证明了引脚本身是好的、方法有效。我以为模块 UART 从未初始化,TX 高阻,和「flash 里没有固件」完全吻合,需要重烧。

这个结论是错的。

后来翻别人的测评帖,看到这么一句:BLE 模块中需要将 LPR 引脚拉高才能正常工作。同时找到模块原理图,J1 是 2x6 排针:

1 BOOT      7  CONNECT
2 RXD       8  RESET(经 SS8550)
3 TXD       9  LPR
4 NC        10 NC
5 GND       11 GND
6 GND       12 VCC

Pin9 = LPR。LPR 不拉高模块根本不跑,不跑 UART 就不初始化,不初始化 TX 就是高阻。我量到的一切都对,只是那个「因」我压根没想到:

LPR 悬空 → 模块不启动 → UART 不初始化 → TXD 高阻 → 我量到悬空 → 判定"没烧固件" → 冤案

「引脚没被驱动」是个现象不是原因,它至少有没供电、没使能、没固件三种成因,我当时只想到最后一种,因为那是文档里刚提醒过我的那种。刚读过的东西最容易成为默认答案。

接下来把 LPR 映射到 RA4M2 的脚上。我的 pmod2 映射从 my_ra6m4 继承:Pin2(RXD)=P411 正好是 sci0 的 TXD0,Pin3(TXD)=P410 正好是 RXD0,Pin8(RESET)=P608 正好是 DA16200 那个复位脚,三处独立吻合映射可信;LPR 落在 P609,正是我一直空着没接的那根。overlay 补上,串口一根线都不用改:

zephyr,user {
    lpr-gpios = <&ioport6 9 GPIO_ACTIVE_HIGH>;   /* Pmod Pin 9, P609 */
};


拉高 LPR,重新扫一遍全部 Pmod 脚:

[diag] which Pmod pins is the module driving?
    LPR Pin9 P609 (we drive it high): reads 1
    method check on P411: forced low=0 high=1 -> GPIO owns the pin, pull results valid
    Pin1  P413  expect BOOT     pd=0 pu=1  -> floating
    Pin2  P411  expect mod RXD  pd=1 pu=1  -> DRIVEN HIGH
    Pin3  P410  expect mod TXD  pd=1 pu=1  -> DRIVEN HIGH
    Pin4  P412  expect NC       pd=0 pu=1  -> floating
    Pin7  P414  expect CONNECT  pd=0 pu=0  -> DRIVEN LOW
    Pin8  P608  expect RESET    pd=1 pu=1  -> DRIVEN HIGH
    Pin10 P610  expect NC       pd=0 pu=1  -> floating

P410 从「悬空」变成「DRIVEN HIGH」,同一块板子、同一根线、同一段测试代码,只多拉高了一个脚。

CONNECT 被驱动低(未连接)、RESET 被 R1 上拉到高、TXD 空闲高,模块通电、固件在跑、UART 初始化完毕。然后我满怀信心发了 AT,没有回应。

从空口那边看

AT 不回,波特率全扫一遍(115200 / 230400 / 460800 / 57600 / 38400 / 19200 / 9600)也不回。卡住了。这时候想起来这是个蓝牙模块,它有第二条链路——串口问不出来的事可以从空口问。电脑上就有蓝牙:

$ timeout 30 bluetoothctl --timeout 22 scan le
[NEW] Device E0:E8:F6:3F:A4:C1 superflyBLE

superflyBLE 是 DA14531 出厂默认设备名,模块在正常广播。到这一步嫌疑范围瞬间从「整个模块」缩到「UART 这一层」——一条命令砍掉一半可能性。顺手把 GATT 也枚举了:

service0001  00001800  (GAP)
service0006  00001801  (GATT)
service000a  866d3b04-e674-40dc-9c05-b7f91bec6e83   ← CodeLess
    char000b   914f8fb9-e8cd-411d-b7d1-14594de45425  (write)
    char000d   3bb535aa-50b2-4fbe-aa09-6b06dc59a404  (notify)
service0010  0000fd00

CodeLess 服务在,而且有一对读写特征。CodeLess 是双向的,BLE 那头也能灌数据进去

先做个验证。CodeLess 在 BLE 连上时会把 CONNECT 脚拉起来,我让 MCU 监控这几个脚,同时用电脑去连它:

[  9] P410 edges=0  P411 edges=0  CONN=0
[ 10] P410 edges=0  P411 edges=0  CONN=1   ← 电脑连上
[ 11] P410 edges=0  P411 edges=0  CONN=1
[ 14] P410 edges=0  P411 edges=0  CONN=1
[ 15] P410 edges=0  P411 edges=0  CONN=0   ← 断开

CONNECT 脚精确跟随 BLE 连接状态。空口上那个 superflyBLE 就是我手上这块、Pmod 映射 Pin7=P414 正确、模块固件功能完全正常

但 P410 和 P411 在上面那轮里 edges 全是 0,而前面 pd/pu 测试说这两个脚都是 DRIVEN HIGH。这里发现 pd/pu 这把尺子有个盲区:模块的输出脚空闲高,读数 pd=1 pu=1;模块的输入脚带 10K 上拉,读数也是 pd=1 pu=1,两者完全一样。Pin8 那个 DRIVEN HIGH 就是 R1 的 10K 上拉造出来的,已经现身说法了。UART 引脚带上拉太常见,所以我根本分不清 Pin2/Pin3 谁是输出。

从 BLE 那头灌数据,CodeLess 是透传,BLE 写进去的字节会从 UART 吐出来。于是 MCU 把 P410、P411 都配成普通输入死循环采样 PIDR 数异或跳变,电脑连上 BLE 往 914f8fb9 这个 write 特征里写 AT\r\n:

[ 92] P410 edges=0    P411 edges=0  CONN=1   ← 连上
[ 93] P410 edges=26   P411 edges=0  CONN=1   ← ★ 我写入的瞬间
[ 94] P410 edges=0    P411 edges=0  CONN=1
[ 97] P410 edges=0    P411 edges=0  CONN=0   ← 断开

P410 翻转 26 次,P411 纹丝不动。P410 就是模块的 TXD,原理图标注正确、映射从头到尾都对,而且接收方向是通的

用一段已知的字节去量波特率

既然模块能按我的指令从 TX 吐出我指定内容的数据,那就有了一个标准信号源。拿它标波特率:让 BLE 那头反复写 AT\r\n,MCU 这头每 6 秒换一个波特率接收,波特率对解出来就是干净的 AT\r\n,不对就是一堆带 framing error 的垃圾。

--- now listening at 460800 baud ---
[ 19] 27 bytes, 18 errors | ascii: x....x.x....x.x.x.x.x....x. | hex: 78 00 f8 00 1e 78 fe ...
--- now listening at 115200 baud ---
[ 21] 8 bytes, 0 errors | ascii: AT\r\nAT\r\n | hex: 41 54 0d 0a 41 54 0d 0a
[ 22] 4 bytes, 0 errors | ascii: AT\r\n     | hex: 41 54 0d 0a
[ 23] 8 bytes, 0 errors | ascii: AT\r\nAT\r\n
--- now listening at 57600 baud ---
[ 24] 2 bytes, 0 errors | ascii: .. | hex: 06 c2
--- now listening at 38400 baud ---
[ 27] 2 bytes, 1 errors | ascii: j. | hex: 6a ff
--- now listening at 230400 baud ---
[ 36] 8 bytes, 6 errors | ascii: ..`f.... | hex: 06 98 60 66 1e 18 06 fe

115200 零错误完美解码,其余全是垃圾。这比查手册可靠,波特率是量出来的不是查出来的。

这里有个 RA 特有的坑必须交代。RA 的 SCI 一旦 ORER(溢出)置位接收器会直接停摆,而 Zephyr 的 uart_ra_sci_poll_in() 只看 RDRF、只读 RDR,从来不清 ORER/FER/PER:

static int uart_ra_sci_poll_in(const struct device *dev, unsigned char *c)
{
    ...
    if (... cfg->regs->SSR_b.RDRF == 0U) {
        return -1;
    }
    *c = ... cfg->regs->RDR;
    return 0;
}

波特率错的时候 framing error 成片来,不清标志的话采集几毫秒就彻底聋了,恰好在诊断最需要它的时候。得自己按硬件要求的「先读后写 0」清掉:

#define SCI0_SSR (*(volatile uint8_t *)(DT_REG_ADDR(DT_NODELABEL(sci0)) + 0x04))
#define SSR_ERR_MASK 0x38U /* ORER | FER | PER */

static void clear_rx_errors(void)
{
    uint8_t s = SCI0_SSR;
    if (s & SSR_ERR_MASK) {
        SCI0_SSR = (uint8_t)(s & ~SSR_ERR_MASK);
    }
}

另一个坑:CONFIG_UART_INTERRUPT_DRIVEN 必须关。板子 defconfig 默认开着,它会把 SCI0 的 ERI(错误中断)挂进 NVIC,一个 framing error 进来 ERI 触发,驱动因为没注册回调不清标志,中断立刻重入,CPU 卡死在 _isr_wrapper 里回不到 main。第一次遇到时现象是「程序跑到一半不动了」,halt 下来 PC 在 _isr_wrapper,NVIC 的 IABR0 是 0x08 正好是 SCI0 的第 4 个中断也就是 ERI。中断风暴的排查路子就是读 ICSR 的 VECTACTIVE 和 NVIC 的 active 位,能直接点名。

反向再验一次

接收通了,发送呢?这个也能用 BLE 验,CodeLess 双向,UART 灌进去的数据会转发到 BLE。让 MCU 每轮从 UART 发一句自带标识的 MCU2BLE\r\n,电脑这头订阅 notify 特征等着:

[CHG] Attribute .../service000a/char000d Value:
  4d 43 55 32 42 4c 45 0d 0a       MCU2BLE..
  4d 43 55 32 42 4c 45 0d 0a       MCU2BLE..
  4d 43 55 32 42 4c 45 0d 0a       MCU2BLE..
  ...(连收 10 次)

ASCII 完整无损连收十次。到这里 UART 两个方向、波特率、引脚映射、模块健康状况全部有实测证据,而我发的 AT 它就是不回。

它根本不认 AT

最后一个嫌疑犯是我自己的代码:前面几轮 AT 全是在波特率扫描里发的,每次发之前都调过 uart_configure(),而那次成功的 MCU2BLE 用的是 DT 默认配置没碰过 uart_configure。会不会是它把什么搞坏了?把扫描拆掉,用 DT 默认的 115200 直接发,顺便把能想到的格式都试一遍:

[  1] >>> AT\r\n            -
[  2] >>> ATI\r\n           -
[  3] >>> AT+GAPSTATUS\r\n  -
[  4] >>> ATE1\r\n          -
[  5] >>> AT\r              -
[  6] >>> AT\r\n            -

全部无响应,uart_configure 洗清嫌疑。这块模块出厂固件不解析 UART 侧的 AT 命令,它就是个纯透传。BLE 服务里确实枚举出了 CodeLess,但 UART 进去的字节只做转发不当命令。别人的帖子里能发 AT+NAME= 改名,说明存在响应 AT 的固件版本,只是和我手上这块烧的不是同一个。要 AT 控制,得用 SmartBond Flash Programmer 经 Pmod 板上的 SWD 头重烧。

最终测试结果:

项目结果
设备名 / 地址superflyBLE / E0:E8:F6:3F:A4:C1
串口参数115200 8N1(实测标定)
BLE 广播
BLE 连接 / 断开✅ CONNECT 脚同步翻转
GATT 服务✅ GAP / GATT / CodeLess / 0xFD00
透传 BLE→UART✅ 零 framing error
透传 UART→BLE✅ 连收 10 次无损
UART 侧 AT 指令❌ 全格式无响应




共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]