GD32 蓝牙模块调试记录
本篇博文介绍一下PB-03F蓝牙模组与GD32通信的调试过程。
蓝牙模块介绍
PB-03 是由深圳市安信可科技有限公司开发的蓝牙块。该模块核心处理器芯片PHY6252(SSOP24)是一款高集成度的低功耗蓝牙系统级芯片(SoC),专为物联网(IoT)、移动设备、可穿戴电子设备、智能家居等各种应用而设计。
PHY6252(SSOP24)芯片具有行业领先的低功耗性能和射频性能,支持蓝牙 BLE 5.2。芯片内置64 KB SRAM,256KB fash,96 KB ROM,256bitefse。芯片支持多种低功耗工作状态,能够满足各种应用场景的功耗需求。射频输出功率可调节功能等特性,可以实现通信距离、通信速率和功耗之间的最佳平衡。
PB-03 模块提供丰富的外设接口,包括 UART,PWM,ADC,I2C,SPIPDM,DMA 和多达 19个 I0 口。
PB-03 模块具有多种特有的硬件安全机制。硬件加密加速器支持 AES 算法。
PB-03 模块支持低功耗蓝牙:Bluetooth5.2,Bluetoothmesh。蓝牙速率支持:125Kbps,500Kbps,1Mbps,2Mbps。支持广播扩展,多广播,信道选择。

芯片硬件连接

PB-03得管脚功能定义如下图所示,芯片供电3.3V,然后通过串口与MCU进行通信。

注意:需要在TX&RX串口线路上,预留2个电阻,串联在线路中。用于防止串口自带的3.3V电压会影响到模组的复位。
程序
基本AT指令
基本AT指令,本博文就介绍几个常用的指令,有其需要可以参考《pb系列模组通用at_v1006版本指令_v1.1.3》
1、AT+BLEMODE 查询和设置蓝牙模式

bash
AT+RST
AT+BLEMODE?
AT+BLEMODE=9
AT+BLEMODE?
AT+BLEMODE=0
AT+BLEMODE?

2、AT+BLESTATE 查询连接状态


未连接

已连接

模块反馈

断开连接

从机指令
1、设置蓝牙名称

bash
AT+RST
AT+BLENAME?
AT+BLENAME=GW7001
AT+RST
AT+BLENAME?

2、AT+BLESERUUID 查询或者设置服务 UUID

bash
AT+RST
AT+BLESERUUID?
AT+BLESERUUID=55535343fe7d50010000120230500001
AT+BLEMODE=0
AT+BLESERUUID?
更改UUID前

更改查询操作

更改UUID后

3、 AT+BLEAUTH 查询或设置蓝牙配对码

bash
AT+RST
AT+BLEAUTH?
AT+BLEAUTH=123456
AT+BLEAUTH?

GD32程序
配置
1、读写
c
static uint8_t Proto_BLE_Cmd(char* str, const char *ExpRcvStr, uint32_t timeOutMs)
{
uint8_t i, buf[100], length=0;
do
{
uint8_t tmpbuf[32];
if(0 == drv_usart_read(BLE_COM , tmpbuf, 32, 10))
{
break;
}
}while(1);//串口读空
for(i=0; i<1; i++)
{
if(drv_usart_write(BLE_COM, (uint8_t*)str, strlen(str), 10))
{
memset(buf,0,sizeof(buf));
length = drv_usart_read(BLE_COM, buf, 100, timeOutMs);
if((length)&&(length<100))
{
if(strstr((char *)buf, ExpRcvStr) !=NULL)
{
return 1;
}
}
}
}
return 0;
}
2、配置流程
c
/**
* @brief 蓝牙模块初始化
* @param pName 蓝牙名称
* @retval
*/
uint8_t Proto_ble_init(uint8_t *pName, uint32_t pPin)
{
static uint8_t init_step = 0, recount = 0, reSetCnt = 0;
static uint32_t waitConnect = 0;
char cmd[128];
if(recount>5)
{
init_step++;
}
switch(init_step)
{
case 0: //进入AT命令模式并确保成功
{
Proto_BLE_Cmd("+++", "OK\r\n", 200);
//osDelay(1000);
//Proto_BLE_Cmd("ATE1\r\n", "OK\r\n", 200);//关闭回显
recount = 0;
init_step = 2;
break;
}
case 1: //进入AT命令模式并确保成功
{
recount++;
if(1 == Proto_BLE_Cmd("AT+BLEDISCON\r\n", "OK\r\n", 200))//重连时确保断开了连接
{
recount = 0;
init_step = 2;
}
break;
}
case 2: //进入AT命令模式并确保成功
{
recount++;
if(1 == Proto_BLE_Cmd("AT\r\n", "OK\r\n", 200))
{
recount = 0;
init_step = 3;
}
break;
}
case 3: //设置从机模式
{
recount++;
if(1 == Proto_BLE_Cmd("AT+BLEMODE=0\r\n", "OK\r\n", 200))
{
recount = 0;
init_step = 4;
}
break;
}
case 4: //设置名称
{
recount++;
sprintf(cmd, "AT+BLENAME=%s\r\n\r\n", pName);
if(1 == Proto_BLE_Cmd(cmd, "OK\r\n", 200))
{
recount = 0;
init_step = 5;
}
break;
}
case 5: //设置配对码
{
recount++;
sprintf(cmd, "AT+BLEAUTH=%d\r\n", pPin);
if(1 == Proto_BLE_Cmd(cmd, "OK\r\n", 200))
{
recount = 0;
init_step = 6;
}
break;
}
case 6: //确认蓝牙是否连接
{
recount++;
if(1 == Proto_BLE_Cmd("AT+BLESTATE?\r\n", "OK\r\n", 200))
{
recount = 0;
init_step = 7;
}
break;
}
case 7: //进入透传模式
{
uint8_t buf[100], length=0;
memset(buf,0,sizeof(buf));
length = drv_usart_read(BLE_COM, buf, 100, 200);
if((length)&&(length<100))
{
if(strstr((char *)buf, "+EVENT:BLE_CONNECTED") != NULL)
{
recount = 0;
init_step = 0;
reSetCnt = 0;
waitConnect = 0;
return 1;
}
}
else
{
waitConnect++;
//1-上电1分钟重设一次,再连不上5分钟重设一次,再连不上10分钟重设一次,最后还是连不上就等待连接或者手动下电尝试/每15分钟重设一次
if((0 == reSetCnt)&&(waitConnect>(60000/500))) //500ms周期 60000/500
{
recount = 0;
init_step = 0;
reSetCnt = 1;
waitConnect = 0;
}
else if((1 == reSetCnt)&&(waitConnect>(5*60000/500))) //500ms周期 5*60000/500
{
recount = 0;
init_step = 0;
reSetCnt = 2;
waitConnect = 0;
}
else if((2 == reSetCnt)&&(waitConnect>(15*60000/500))) //500ms周期 15*60000/500
{
recount = 0;
init_step = 0;
reSetCnt = 3;
waitConnect = 0;
}
}
break;
}
default:
{
recount = 0;
init_step = 0;
waitConnect = 0;
break;
}
}
osDelay(300); /* AT指令之间时间定位500ms, 后续再优化重连时间 */
return 0;
}
3、调用配置
c
if(1==Proto_ble_init((uint8_t *)"GWDC7000", 123456))
{
bleLoginStatus = 2;
}
蓝牙连接
根据我们前面从机命令介绍的反馈,调试助手接收到的连接状态返回,蓝牙模块就进入了连接状态。所以判断连接如下:
c
memset(rcvBuf, 0, sizeof(rcvBuf));
rdvLen = Proto_ble_recv(rcvBuf, 100, 100);
if(rdvLen>0)
{
if(strstr((char *)rcvBuf, "+EVENT:BLE_CONNECTED") != NULL)
{
bleLoginStatus = 2;
}
}
断开连接
同理,断开连接判断
c
if(Tick_Out(&heartbeatMs, 1000)) //10s周期发送数据 - 后续再完善心跳超时 重连机制
{
Tick_Out(&heartbeatMs, TICK_OUT_RESTART);
Proto_ble_send((uint8_t*) "TEST MSG FROM DC7000", strlen("TEST MSG FROM DC7000"), 100);
}
memset(rcvBuf, 0, sizeof(rcvBuf));
rdvLen = Proto_ble_recv(rcvBuf, 100, 100); //根据协议最长字节确定接收长度
if(rdvLen>0)
{
if(strstr((char *)rcvBuf, "+EVENT:BLE_DISCONNECT") !=NULL)
{
bleLoginStatus = 1;
}
Proto_ble_send((uint8_t*) rcvBuf, rdvLen, 100);
}
蓝牙通信任务
c
/**
* @brief 蓝牙通信任务
* @param 无
* @retval 无
*/
void BLE_Com_Thread(void const * argument)
{
static uint32_t heartbeatMs = 0;
uint8_t rdvLen = 0;
uint8_t rcvBuf[128];
for( ; ; )
{
switch(bleLoginStatus)
{
case 0://配置-等待连接
{
if(1==Proto_ble_init((uint8_t *)"GWDC7000", 123456))
{
bleLoginStatus = 2;
}
break;
}
case 1://等待连接 - 考虑后续再等待一定时间后重新配置
{
memset(rcvBuf, 0, sizeof(rcvBuf));
rdvLen = Proto_ble_recv(rcvBuf, 100, 100);
if(rdvLen>0)
{
if(strstr((char *)rcvBuf, "+EVENT:BLE_CONNECTED") != NULL)
{
bleLoginStatus = 2;
}
}
break;
}
case 2://通信
{
if(Tick_Out(&heartbeatMs, 1000)) //10s周期发送数据 - 后续再完善心跳超时 重连机制
{
Tick_Out(&heartbeatMs, TICK_OUT_RESTART);
Proto_ble_send((uint8_t*) "TEST MSG FROM DC7000", strlen("TEST MSG FROM DC7000"), 100);
}
memset(rcvBuf, 0, sizeof(rcvBuf));
rdvLen = Proto_ble_recv(rcvBuf, 100, 100); //根据协议最长字节确定接收长度
if(rdvLen>0)
{
if(strstr((char *)rcvBuf, "+EVENT:BLE_DISCONNECT") !=NULL)
{
bleLoginStatus = 1;
}
Proto_ble_send((uint8_t*) rcvBuf, rdvLen, 100);
}
break;
}
default:break;
}
osDelay(50);
}
}
运行结果

上位机测试

上位机接收数据

上位机发送数据

蓝牙模块接收透传给MCU

总结
本博文记录了PB-03蓝牙模块调试开发过程。实际调试过程中,和资料文档中的描述稍有差入。可能是固件版本的不一样。该模块还支持二次开发,提供二次开发SDK和文档, 有兴趣的同学可以学习尝试。
参考安可信官网资料
官方官网:https://www.ai-thinker.com