[其他] (转)MM32W无线MCU系列产品应用笔记 —— 自定义AT指令

[复制链接]
 楼主| 两只袜子 发表于 2021-7-19 09:17 | 显示全部楼层 |阅读模式
MM32W0/3提供模组和开发板方式供客户使用,支持UART\SPI\IIC接口的AT指令,用户通过发送相关固定格式的指令方式可以实现对应功能。开发板上电后,模块会自动进行广播,移动设备的APP 会对其进行扫描和连接,连接成功之后可以通过BLE 在模块和移动设备之间进行数据传输。用户MCU 可通过模块的串口和移动设备进行双向通信,移动设备也可以通过APP 对模块进行写操作,写入的数据将通过串口发送给用户的MCU,模块收到来自用户MCU 串口的数据,将自动转发给移动设备。



AT 指令主要用于配置模块参数,比如广播间隔、设备名、等,也用于发送透传数据和断开BLE 连接。而对于AT指令,客户可以很方便的进行修改,添加自己需要的功能。

 楼主| 两只袜子 发表于 2021-7-19 09:18 | 显示全部楼层
通信流程


132820nmwik1fkml9img5n.png.thumb.jpg

图1 通信流程


 楼主| 两只袜子 发表于 2021-7-19 09:19 | 显示全部楼层
UART AT指令集
132821mlcbx9la2m05s4eq.png.thumb.jpg

表1 UART AT指令集


 楼主| 两只袜子 发表于 2021-7-19 09:20 | 显示全部楼层
在官方提供的程序中已经支持大部分的蓝牙设置等操作,可以实现透传、修改蓝牙参数等操作,如果用户需要单独开发AT指令集可以通过以下方式进行开发。
接收指令
首先是接收指令时的数据处理流程:
132821e9o37f7bv9g75g52.png.thumb.jpg

图2 接收指令流程图



 楼主| 两只袜子 发表于 2021-7-19 09:22 | 显示全部楼层
在每次蓝牙服务调用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;
 楼主| 两只袜子 发表于 2021-7-19 09:25 | 显示全部楼层
在例程中,收到AT指令要通过蓝牙发送数据时,使用的是sconn_noti€€Fydata()接口函数,这是一种不需要应答的蓝牙特征值,预设句柄为0x12,可以在发送前用set_notifyhandle()函数修改对应的句柄,或者直接修改变量u16 cur_notifyhandle。
发送数据

在例程中,通过UART发送数据都是通过moduleOutData()函数,往一个特定的缓存数组中写入数据。这个函数可以加在任何位置,可以加在AT指令处理函数中发送应答数据,也可以加到BLE服务中实现数据透传功能。
 楼主| 两只袜子 发表于 2021-7-19 09:25 | 显示全部楼层
在每次蓝牙服务调用UsrProcCallback()函数时检查缓存数组,若不为空,在休眠之前加入一个延时,开启发送缓冲空中断,并在中断中发送剩下的数据。

132822xdt8bzjdok420d8b.png.thumb.jpg

图3 发送数据流程图



 楼主| 两只袜子 发表于 2021-7-19 09:26 | 显示全部楼层
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等。
[url=] favorite.png [/url]0




littlelida 发表于 2021-7-19 13:24 | 显示全部楼层
一直以为,AT指令是固定 的
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2122

主题

8117

帖子

11

粉丝
快速回复 在线客服 返回列表 返回顶部