SMARTWATCH 学习手册有 C 基础 · 嵌入式从零开始
支线二 / CH582M 开发与蓝牙桥接 / 02

用熟悉的串口,接上另一颗主控

无线功能先放在一边。CH582M 与 STM32 之间仍然是已经学过的串口:发送脚接接收脚、共地,并约定相同格式。先把这一段对应清楚。

接续上一篇:打开 CH 工程:编译、下载与入口

1 · 先看接线,再看函数

发送端接收端方向
STM32 PA9 / LPUART1_TXCH582M PA8 / UART1_RX主控 → 蓝牙芯片
CH582M PA9 / UART1_TXSTM32 PA10 / LPUART1_RX蓝牙芯片 → 主控

两边相同的 PA9 名字属于不同芯片,不是同一根管脚。项目串口配置为 115200、8 个数据位、无校验、1 个停止位。板上已有连接;使用外置调试工具时还需核对电平和供电,避免两个输出同时接到一条线上。

2 · 把初始化拆成三个动作

摘自 app_uart_init · 保留实际引脚操作

GPIOPinRemap(DISABLE, RB_PIN_UART1);
GPIOA_SetBits(GPIO_Pin_9);
GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP_5mA);
GPIOA_SetBits(GPIO_Pin_8);
GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeIN_PU);
UART1_DefInit();
UART1_BaudRateCfg(115200);

第一行选 UART1 的这组默认管脚;接着为发送和接收脚选择模式;最后建立串口默认格式并明确波特率。SetBits 是设置对应输出位,ModeCfg 才是选择模式。遇到一个陌生函数,先沿声明找到实现,再把它归回“引脚、格式、收发”中的一项。

3 · 收到字节,为什么要有中断和数组

接在上面的初始化之后 · 开启 UART1 中断来源与处理器响应

UART1_INTCfg(ENABLE, RB_IER_RECV_RDY | RB_IER_LINE_STAT);
PFIC_EnableIRQ(UART1_IRQn);

外设能够提出中断请求,处理器也要允许这个请求进入处理函数,这两处都要开启。UART1_IRQHandler 在收到数据或接收超时时,把硬件接收缓冲中的字节放入软件循环队列,再设置 uart_rx_flag。

这个中断没有立即发送蓝牙,也没有解析完整应用帧。原因很具体:一次串口中断中的字节数不等于一条完整消息,蓝牙此时也可能正忙。先保存字节,回到主循环再处理更合适。

4 · 队列名字里的收发,以 CH 串口为观察点

软件队列保存什么后续交给谁
app_uart_rx_fifo,4096 字节从 STM32 串口收到的字节蓝牙通知发送
app_uart_tx_fifo,512 字节手机写入后,等待串口发送的字节UART1 发送寄存器

循环队列的结构已在主线讲过,这里只辨认数据方向。不要把手机的“接收”与 CH 串口的“接收”混用。主循环根据串口硬件发送缓冲的剩余空间,逐批把软件发送队列中的字节写出去。

5 · 先验证串口原样传递

UART1 已经承载应用数据,生产配置禁止把调试 PRINT 输出放在这个接口上。否则手机收到的既有协议字节,又有日志文本,帧解析自然会失败。

动手观察

对照 实际初始化与中断函数,找出两处中断使能、两个队列和发送寄存器 R8_UART1_THR。联调时先观察两端串口的原始十六进制字节;暂时不根据界面是否更新判断这一段是否正常。

资料与代码