欢迎大家来到IT世界,在知识的湖畔探索吧!
说明:前面讲到用通讯解析框架,一般mcu或者其他的嵌入式系统或多或少涉及到通讯。不光有各种各样的字节指令,还有字符串指令比如本文要讲的AT指令,很多模块都涉及使用at指令作为指令集去做命令,比如电话模块,wifi模块,蓝牙模块等等,一般at指令解析比较繁琐,如果用到统一的框架做解析呢?
注:通讯解析框架的介绍可以看之前我写的文章内容,这里不再赘述。
下面我们着重讲解使用通讯解析框架解析at指令
以汉枫wifi模块为例
h框架文件:
typedef struct
{
U8 *Readbuf;//读内容
U16 BufLen;//读内容长度
U8 isUp;//主动上传还是下载
int YAL_WifiCmdPos;//其他命令位置
}YAL_WifiCmdPM;//读数据地址
typedef struct
{
const char *Buf;//at内容
U8 (*Handle)(YAL_WifiCmdPM *);//buf长度
U16 GetID;//获取的CMDId
}YAL_WifiCMDHandle;//读数据框架结构
enum
{
YAL_WIFICMD_GET_ENTERAT = 1,//进入AT
YAL_WIFICMD_GET_ANAENTERAT,//应答进入AT
YAL_WIFICMD_SET_CLOSESHOWAT,//关闭回显
…
};
C内容文件:
U8 Get_YAL_WIFI_EnterAt(YAL_WifiCmdPM *CmdPm);
U8 Get_YAL_WIFI_AckEnterAt(YAL_WifiCmdPM *CmdPm);
U8 Get_YAL_WIFI_CloseShowAt(YAL_WifiCmdPM *CmdPm);
…
U8 YAL_WIFI_LINK_END[] = { “\r” };//结尾
//获取指令
const U8 YAL_WIFI_REQ[] = { “AT+” };
const YAL_YAL_WifiCMDHandle YAL_WIFI_Cmd_handle[] = {
“+++”, Get_YAL_WIFI_EnterAt, YAL_WIFICMD_GET_ENTERAT,//进入AT
“a”, Get_YAL_WIFI_AckEnterAt, YAL_WIFICMD_GET_ANAENTERAT,//应答AT
“E”, Get_YAL_WIFI_CloseShowAt, YAL_WIFICMD_SET_CLOSESHOWAT,//关闭回显
…
}
int YAL_WifiCMD_findCmdPos(U16 Cmd)
{
int i;
U8 CmdCt = sizeof(YAL_WIFI_Cmd_handle) / sizeof(YAL_WIFI_Cmd_handle[0]);
for (i = 0; i < CmdCt; i++)
{
if (Cmd == YAL_WIFI_Cmd_handle[i].GetID) return i;
}
return -1;
}
/***********************************************************************
* 函数名称 : Get_YAL_WIFI_MacID
* 描述 : 获取WiFi版本号和MAC ID
* 输入形参 :
* 返回值 : 无
************************************************************************/
U8 Get_YAL_WIFI_EnterAt(YAL_WifiCmdPM *CmdPm)
{
u8 err = 1;
if (CmdPm->isGet){
return YAL_WIFI_ReadCMD(CmdPm->YAL_WifiCmdPos);//
}
else{
if (Str_cmp(CmdPm->Readbuf, (U8 *)”a”) == 1){
err = 0;
}
}
return err;
}
/***********************************************************************
* 函数名称 : Get_YAL_WIFI_MacID
* 描述 : 获取WiFi版本号和MAC ID
* 输入形参 :
* 返回值 : 无
************************************************************************/
U8 Get_YAL_WIFI_AckEnterAt(YAL_WifiCmdPM *CmdPm)
{
u8 err = 1;
if (CmdPm->isGet){
return YAL_WIFI_ReadCMD(CmdPm->YAL_WifiCmdPos);//
}
else{
if (YAL_WifiCmd_isOk(CmdPm->Readbuf)){
SetAtMode(1);
err = 0;
}
}
return err;
}
/***********************************************************************
* 函数名称 : Get_YAL_WIFI_CloseShowAt
* 描述 : 关闭回显
* 输入形参 :
* 返回值 : 无
************************************************************************/
U8 Get_YAL_WIFI_CloseShowAt(YAL_WifiCmdPM *CmdPm)
{
u8 err = 1;
if (CmdPm->isGet){
U8 info_str[10];
//转义字符处理
memset(info_str, 0, sizeof(info_str));
sprintf_s((char *)info_str, sizeof(info_str), “=off%s”, YAL_WIFI_LINK_END);
//strcat((char *)info_str,(char *)YAL_WIFI_LINK_END);
return YAL_WIFI_ReadWriteCMD(CmdPm->YAL_WifiCmdPos, info_str);//
}
else{
if (YAL_WifiCmd_isOk(CmdPm->Readbuf)){
err = 0;
}
}
return err;
}
/***********************************************************************
* 函数名称: YAL_WIFI_ReadCMD
* 描述 : 读WiFi指令
* 输入形参: YAL_WifiCmdPos 列表位置
* 返回值 : 0成功 1失败
************************************************************************/
u8 YAL_WIFI_ReadCMD(int YAL_WifiCmdPos)
{
if (CheckCmdPos(YAL_WifiCmdPos)) return 0;
…
memcpy(SENDBUF, YAL_WIFI_Cmd_handle[YAL_WifiCmdPos].Buf, strlen((char *)YAL_WIFI_Cmd_handle[YAL_WifiCmdPos].Buf));
USART1_SendString(SENDBUF, strlen((char *)SENDBUF));
…
return 0;
}
int YAL_WifiCMD_findCmdPos(U16 Cmd)
{
int i;
U8 CmdCt = sizeof(YAL_WIFI_Cmd_handle) / sizeof(YAL_WIFI_Cmd_handle[0]);
for (i = 0; i < CmdCt; i++)
{
if (Cmd == YAL_WIFI_Cmd_handle[i].GetID) return i;
}
return -1;
}
//解析at指令:将字符串数据内容解析到该函数中
U8 YAL_AnaData_revcmd(U8 *Buf, U16 BufLen)
{
int YAL_WifiCmdPos;
YAL_WifiCmdPM cmdPm;
YAL_WifiCmdPos = YAL_WifiCMD_findCmdPos(GetLastCmdId());//上一次请求的内容
if (CheckCmdPos(YAL_WifiCmdPos))return 1;
cmdPm.Readbuf = Buf;
cmdPm.BufLen = BufLen;
cmdPm.YAL_WifiCmdPos = YAL_WifiCmdPos;
cmdPm.isGet = 0;
return YAL_WIFI_Cmd_handle[YAL_WifiCmdPos].Handle(&cmdPm);//回调函数
}
//发送cmd消息:通过CMDId请求对应的at指令
void YAL_WifiCMD_SetCmd(U16 Cmd)
{
int WifiCmdPos;
YAL_WifiCmdPM cmdPm;
cmdPm.Readbuf = SendBuf;
cmdPm.BufLen = 0;
cmdPm.isGet = 1;
WifiCmdPos = WifiCMD_findCmdPos(Cmd);
if (WifiCmdPos == -1)return;
if (CheckCmdPos(WifiCmdPos))return;
cmdPm.WifiCmdPos = WifiCmdPos;
YAL_WIFI_Cmd_handle[WifiCmdPos].Handle(&cmdPm);
SetLastCmdId(YAL_WIFI_Cmd_handle[WifiCmdPos].GetID);
}
总结:通过框架将AT指令的头尾等公共部分作为框架一部分,可变的内容部分作为识别的内容实体,用于解析和发送,比如”+++”作为识别码,“AT+E”中的“E”作为识别码
识别解析的内容通过各种的handle回调处理,当发送一条AT指令,对应的回一条AT指令,解析和发送对应LastCmdId的关系去解对应的回应的AT指令内容,当然AT指令多变,本文只是
抛砖引玉,可相互交流,欢迎评论转发加关注。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/73888.html