【瑞萨BLE模块测评】4.无线蓝牙能力的集成
本帖最后由 qintian0303 于 2026-10-3 13:06 编辑最终的无线能力实际上是给大多数MCU添加的能力,我们这次就是给RA-ECO-RA4M2 V2.0开发板添加这样的无线能力,开发板上已经提供了PMOD接口,我们看一下实际的连接效果:
我们通过开发板的原理图看一下直接连接的外设:
我们现在工程里面进行串口和必备引脚的控制,这里主要展示串口,因为其他引脚都是GPIO的基本操作,引脚配置:
添加串口外设:
串口配置如下:
接下来就是控制程序,这里包括了初始化以及透传指令的解析,我们实现的主要功能:
1、在初始化阶段通过AT指令询问是否有模块,通信正常测LED1以1Hz闪烁,通信错误就以5Hz闪烁;
2、解析透传指令控制LED2和LED3,指令的模式为“L2:1/r/n”模式,其中透传控制命令都以/r/n结尾,正文必须是 "L:" = 4 字节。
主要代码包括串口接收回调,使用中断方式:
void g_uart0_Callback(uart_callback_args_t * p_args)
{
switch (p_args->event)
{
case UART_EVENT_RX_COMPLETE:
break;
case UART_EVENT_RX_CHAR:
{
uint8_t b = (uint8_t) (p_args->data & 0xFFu);
if (g_rx_len >= BT_RX_BUF_SIZE)
{
g_rx_len = 0u;
g_rx_complete = false;
}
else if (g_rx_len >= BT_RX_BUF_LIMIT)
{
g_rx_len = 0u;
}
/* 帧结束识别 (兼容 DA14531 默认透传 LF 收尾):
* CRLF (\r\n) -> 完整帧
* 单 LF (\n)-> 完整帧 (DA14531 默认结尾)
*
* 同时识别两个,避免网页发 \r\n 时收不到,也避免 DA14531 发 \n 时漏掉。
*/
bool frame_end = false;
if (b == 0x0A)
{
if (g_rx_len > 0u && 0x0D == g_bt_rx_buf)
{
/* CRLF 帧结束 (含 \r) */
g_bt_rx_buf = b;
g_rx_len++;
frame_end = true;
}
else if (g_rx_len > 0u)
{
/* 单 LF 帧结束 (无 \r) */
g_bt_rx_buf = b;
g_rx_len++;
frame_end = true;
}
else
{
/* 空缓冲收到 \n: 当成新帧起始字符? 直接丢弃 */
g_rx_len = 0u;
}
}
if (frame_end)
{
g_rx_complete = true;
}
else
{
g_bt_rx_buf = b;
g_rx_len++;
}
/* DA14531 "AT?\r\n" 回包扫描: 累积器里任意相邻 'A','T' 都算命中 */
if (!g_at_rx_seen && g_rx_len >= 2u)
{
for (uint32_t i = 0u; i + 1u < g_rx_len; i++)
{
if ('A' == g_bt_rx_buf && 'T' == g_bt_rx_buf)
{
g_at_rx_seen = true;
break;
}
}
}
}
break;
case UART_EVENT_TX_COMPLETE:
g_tx_busy = false;
break;
case UART_EVENT_ERR_PARITY:
case UART_EVENT_ERR_FRAMING:
case UART_EVENT_ERR_OVERFLOW:
case UART_EVENT_BREAK_DETECT:
default:
break;
}
}
透传指令解析:
static void protocol_process(const uint8_t * p, uint32_t len)
{
/* 兼容两种帧结尾:
* CRLF (\r\n):"L2:1\r\n"(5 字节)
* LF (\n): "L2:1\n" (4 字节)
* DA14531 默认透传是单 LF 收尾,网页/串口助手默认是 CRLF,两种都识别。
*/
uint32_t body_len;
if (len >= 2u && 0x0D == p && 0x0A == p)
{
body_len = len - 2u; /* CRLF */
}
else if (len >= 1u && 0x0A == p)
{
body_len = len - 1u; /* 单 LF */
}
else
{
return; /* 帧结束符不对,忽略 */
}
/* 正文必须是 "L<n>:<state>" = 4 字节 */
if (body_len != 4u)
{
return;
}
/* 必须 "L<n>:<state>" */
if ('L' != p || ':' != p)
{
return;
}
char n = (char) p;
char state = (char) p;
if (!('0' == state || '1' == state))
{
return;
}
bool on = ('1' == state);
if ('2' == n)
{
R_IOPORT_PinWrite(&g_ioport_ctrl, LED2_PIN,
on ? BSP_IO_LEVEL_HIGH : BSP_IO_LEVEL_LOW);
}
else if ('3' == n)
{
R_IOPORT_PinWrite(&g_ioport_ctrl, LED3_PIN,
on ? BSP_IO_LEVEL_HIGH : BSP_IO_LEVEL_LOW);
}
}
接下来我们看一下效果:
页:
[1]