Nuoeriris · 2020年07月13日

MM32W无线MCU系列产品应用笔记 —— 数据透传

在前面一个章节中我们详细介绍到了基于MM32W系列芯片开发的使用场景非常丰富的简易蓝牙智能锁方案,在本章节我们将继续给大家介绍一个蓝牙案例——基于MM32W系列开发的数据透传应用。

1.jpg
图1 透传应用连接传输图

说到低功耗蓝牙模块的工作方式,少不了要介绍低功耗蓝牙模块中最简单、最常见的通讯方式——数据透传。透传也叫串口透传,就是透明传输的意思,透传是一种工作方式,不是一种功能,一般出现在串口模块中。灵动MM32W系列MCU为了让用户更好的开发蓝牙无线传输产品,而不需要关心内部蓝牙协议栈如何实现,可以很快地实现串口模块的功能。串口模块具体的工作机制就是不对MCU要传输的数据做任何处理,也不需要自己增加什么协议,用户可以控制数据包的大小与APP之间进行双向传输。

硬件资源如下:

本方案基于MM32 BLE\_Test Board进行测试验证,配套使用一条Micro usb数据线作为与上位机串口助手通讯方式的载体。在硬件原理上,本方案Demo板载了USB转串口芯片,通过跳线帽连接到MCU的UART2功能引脚,USB转串口芯片的RXD连接到了TX2(PA2)上,TXD连接到了RX2(PA3)上,且在通讯引脚上都分别并联了不同颜色的LED作为数据收发情况的指示;使用PB1连接到绿色LED指示灯,可作为蓝牙连接状态的指示;低功耗唤醒引脚选择PA0配置为上拉输入;蓝牙相关的功能引脚与前面介绍的方案一致,此处不做过多展开。以下为USB-TTL串口转换原理图:
2.jpg
图2 原理图

软件资源如下:

结合上述使用到的硬件资源,下面我们着重介绍软件实现流程以及相关配置代码。由于本应用方案BLE芯片与APP与之间为数据透传,为了避免其它数据干扰把应用层的广播报文取消,且不需要设置配对模式;由于本方案使用的是MCU的UART2,在使用printf调试打印功能时需将fputc和fgetc两个库函数内部使用的串口切换为UART2,且使用的是查询方式打印数据,与本案中透传发送至APP的方式不同(中断方式);另外再对连接状态指示灯的引脚进行配置,从而更为直观地对应用效果进行观测和验证,且使能看门狗复位功能来保证蓝牙服务的稳定性能;由于方案应用对低功耗的需要,本方案低功耗采用SLEEP和STOP双模式切换,根据不同的超时时间进入不同的低功耗模式。

以下为主函数初始化配置内容,主要将所有的外设资源和蓝牙协议栈初始化,并且以中断服务程序的方式运行蓝牙,主函数的循环中主要实现的功能为判断是否进入低功耗模式、根据串口接收和发送数据的超时时间进入何种低功耗模式,代码如下:
3.jpg
下面着重介绍一下串口2操作相关的几个函数:

 /***串口2发送数据接口,当MCU接收到蓝牙透传数据后程序会调用该接口函数,该函数主要实现把要发送的数据装载到TX BUFF中,等待串口中断服务程序处理发送***/
void moduleOutData(u8*data, u8 len) 
{
unsigned char i;
if ((txLen+len)<MAX_SIZE)//发送BUFF没有溢出
{
for (i=0;i<len;i++) {
txBuf[txLen+i] = *(data+i);//往发送BUFF中装载数据
}
txLen += len;
}
}
/***重定义printf实现库函数,UART2的POLLING方式发送数据避免与透传产生冲突***/
int fputc(int ch, FILE *f)
{
UART_SendData(UART2, (uint16_t) ch);
while(1) {
if(UART_GetITStatus(UART2, UART_IT_TXIEN)) {
UART_ClearITPendingBit(UART2, UART_IT_TXIEN);
break;
}
}
return ch;
}
int fgetc(FILE *f)
while(1) {
if(UART_GetITStatus(UART2, UART_IT_RXIEN)) {
UART_ClearITPendingBit(UART2, UART_IT_RXIEN);
break;
}
}
return (int)UART_ReceiveData(UART2);
}
/***当收到来自串口助手的数据时,中断服务程序处理接收BUFF装载数据,在蓝牙协议的周期性回调函数中调用该函数来把串口助手的数据发送至APP***/
void CheckComPortInData(void) //at cmd NOT supported
{
u16 send;
if(comrxbuf_wr_pos != comrxbuf_rd_pos)//接收BUFF不为空{
if(!GetConnectedStatus())//蓝牙未连接{
comrxbuf_rd_pos = comrxbuf_wr_pos; //清空接收BUFF
}
else //蓝牙正常连接{
if(comrxbuf_wr_pos > comrxbuf_rd_pos)//当前串口接收到的数据长度大于接收BUFF索引号{
//调用sconn_notifydata函数主动通过蓝牙发送数据
send = sconn_notifydata(rxBuf+comrxbuf_rd_pos,comrxbuf_wr_pos - comrxbuf_rd_pos);
comrxbuf_rd_pos += send;
}
else {//调用sconn_notifydata函数主动通过蓝牙发送数据
send = sconn_notifydata(rxBuf+comrxbuf_rd_pos,MAX_SIZE - comrxbuf_rd_pos);                         comrxbuf_rd_pos += send;
comrxbuf_rd_pos %= MAX_SIZE;//定义MAX_SIZE为接收BUFF最大长度,这里为200
}
}
}
}

在UsrProcCallback()处理函数中做了喂狗操作,且处理串口2透传数据的接收和发送操作,蓝牙协议会周期性回调本函数,无论是在广播状态还是连接状态;在串口2中断服务程序中主要实现了发送BUFF和接收BUFF的数据装载以及触发发送功能。以下为代码实现内容:

4.jpg
5.jpg
//蓝牙连接成功后协议在空闲的时候会调用本回调函数
 void gatt\_user\_send\_notify\_data\_callback(void)
{
static u8 LockFlagBak = 1;
if (LockFlagBak != LockFlag) {
LockFlagBak = LockFlag;//LockFlag标志位会在MOTOR\_Proc()中清零和置位
sconn\_notifydata(&LockFlagBak,1);
}
}



下面着重介绍一下蓝牙服务操作相关的几个函数和特征值定义:

//APP获取蓝牙设备名称信息
u8* getDeviceInfoData(u8* len) ;
//APP设置并更新蓝牙设备名称信息
void updateDeviceInfoData(u8* name, u8 len) ;
//APP获取蓝牙设备固件版本号
u8* getsoftwareversion(void) ;
//判断蓝牙连接状态,并且通过状态指示灯显示
void ConnectStausUpdate(unsigned char IsConnectedFlag) ;
//APP查询蓝牙及MCU串口波特率信息回复函数
void server\_rd\_rsp(u8 attOpcode, u16 attHandle, u8 pdu\_type) ;
//APP发送数据到MCU及设置串口波特率响应函数,在此实现上位机到下位机数据的透传
void ser\_write\_rsp() ;

除了上述关键的蓝牙服务函数外,下面再简单介绍一些与蓝牙相关的特征值定义:

在const BLE\_CHAR AttCharList[] 中定义了本案中的四个特征值:
{TYPE\_CHAR,0x0011, {ATT\_CHAR\_PROP\_NTF, 0x12,0, 0,0}, 1/*uuid128-idx1*/ },// RxNotify
{TYPE\_CHAR\,0x0014\, {ATT\_CHAR\_PROP\_W|ATT\_CHAR\_PROP\_W\_NORSP\, 0x15\,0\, 0\,0}\, 2/*uuid128-idx2*/ }\,// Tx
{TYPE\_CHAR\,0x0017\, {ATT\_CHAR\_PROP\_W|ATT\_CHAR\_PROP\_RD\, 0x18\,0\, 0\,0}\, 3/*uuid128-idx3*/ }\,// BaudRate 设置
{TYPE\_INFO,0x0019, {ATT\_CHAR\_PROP\_RD}}// BaudRate 回复
在void att\_server\_rdByGrType( u8 pdu\_type, u8 attOpcode, u16 st\_hd, u16 end\_hd, u16 att\_type )中实现自定义特征值服务声明;
手机操作流程如下:

手机App使用nRF UART v2.0 App(安卓版本的App安装包nRFUART\_Googlev2.apk,也可以从360手机助手查找和下载);

打开nRF UART v2.0 App,点击Connect开始搜索ble设备,选择对应名称(MM32\_UART2)的蓝牙设备并进行配对,等待连接成功。连接成功后会有相应提示,按钮Connect名字会变成Disconnect;

连接成功后,在App内可以输入数据,然后点Send,手机发送的数据会通过蓝牙透传至测试demo板接收,并通过UART2发送到PC端的串口助手上显示:为了演示方便,可以短接串口2的TX2和RX2引脚,这样demo板接收到手机App发送的数据后会把同样的数据内容发给手机App上显示出来。

6.jpg
7.jpg
图3 手机APP图和PC端串口助手图

推荐阅读
关注数
6152
内容数
276
灵动MM32 MCU相关技术知识,欢迎关注~
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息