MM32W0/3提供模组和开发板方式供客户使用,支持UART\SPI\IIC接口的AT指令,用户通过发送相关固定格式的指令方式可以实现对应功能。开发板上电后,模块会自动进行广播,移动设备的APP 会对其进行扫描和连接,连接成功之后可以通过BLE 在模块和移动设备之间进行数据传输。用户MCU 可通过模块的串口和移动设备进行双向通信,移动设备也可以通过APP 对模块进行写操作,写入的数据将通过串口发送给用户的MCU,模块收到来自用户MCU 串口的数据,将自动转发给移动设备。
AT 指令主要用于配置模块参数,比如广播间隔、设备名、等,也用于发送透传数据和断开BLE 连接。而对于AT指令,客户可以很方便的进行修改,添加自己需要的功能。
通信流程
图1 通信流程
UART AT指令集
表1 UART AT指令集
在官方提供的程序中已经支持大部分的蓝牙设置等操作,可以实现透传、修改蓝牙参数等操作,如果用户需要单独开发AT指令集可以通过以下方式进行开发。
接收指令
首先是接收指令时的数据处理流程:
图2 接收指令流程图
在每次蓝牙服务调用UsrProcCallback()函数时,使用CheckAtCmdInfo()函数检查是否收到数据,如果有,在进入休眠之前加入一个可以接收20个字节的延时,在接收中断中接收剩下的数据,通过判断最后一位是否是0x0d或是0x0a来获得一条完整的指令,调用AtCmdPreParser()函数处理数据。检查数组开始的“AT+”和后面的指令名称,在at\_func\_list[]中查找并调用对应的函数对数据中后续的参数进行处理。
从流程中可以看到,如果只是简单的加减指令的话,只需要修改at\_func\_list数组就可以了,结构体AT\_CMD\_FUNC的两个成员变量分别是函数名称和对应的字符串。
注:处理时间不宜太长,更不能阻塞
typedef void (*ATCMDFUNC)(u8* cmd,u8 len);
typedef struct _tagATCMD
{
ATCMDFUNC func;
u8 name[MAX_AT_CMD_NAME_SIZE]; //max len is 11 bytes
}AT_CMD_FUNC;
在例程中,收到AT指令要通过蓝牙发送数据时,使用的是sconn\_notifydata()接口函数,这是一种不需要应答的蓝牙特征值,预设句柄为0x12,可以在发送前用set\_notifyhandle()函数修改对应的句柄,或者直接修改变量u16 cur\_notifyhandle。
发送数据
在例程中,通过UART发送数据都是通过moduleOutData()函数,往一个特定的缓存数组中写入数据。这个函数可以加在任何位置,可以加在AT指令处理函数中发送应答数据,也可以加到BLE服务中实现数据透传功能。
在每次蓝牙服务调用UsrProcCallback()函数时检查缓存数组,若不为空,在休眠之前加入一个延时,开启发送缓冲空中断,并在中断中发送剩下的数据。
图3 发送数据流程图
void moduleOutData(u8*data, u8 len) //api
{
unsigned char i;
if ((txLen+len)<MAX_SIZE)//buff not overflow
{
for (i=0;i<len;i++){
txBuf[txLen+i] = *(data+i);
}
txLen += len;
}
}
#ifdef MM32W0NTB//NTB 32Pin UART1
void UART1_IRQHandler(void) //串口1中断服务程序
#else //PFB 48Pin UART2
void UART2_IRQHandler(void) //串口2中断服务程序
#endif
{
if(UART_GetITStatus(UART_BLE, UART_IT_TXIEN) != RESET){
UART_ClearITPendingBit(UART_BLE,UART_IT_TXIEN);
TxTimeout = SysTick_Count + (20000/BaudRate);
if (PosW < txLen){
UART_SendData(UART_BLE,txBuf[PosW++]);
if (PosW == txLen){
txLen = 0;
PosW = 0;
}
}
else{
UART_ITConfig(UART_BLE, UART_IT_TXIEN, DISABLE);
}
}
}
以上例程使用的是UART接口的自定义AT指令实现方式,用户可以根据需要自行修改为其他接口,如SPI、IIC、CAN、USB等。