天天看點

AT指令代碼與實作方法(基于C語言)

WiFi、藍牙、4G等多種通信子產品均需使用AT指令進行配置和通信。基于μCOSIII作業系統,寫了個AT指令的代碼,也可以簡單修改後用于裸奔系統。簡單介紹一下,完整代碼下載下傳連結為:

https://download.csdn.net/download/hnxyxiaomeng/10815656

1、AT配置結構體

設計了一個結構體stcATConfig,可以對發送的每個指令分别進行配置。

typedef struct
{
uint16_t        resp_time100ms;//發送後查詢傳回資訊的延時,100ms為機關。可設為指令最大響應時間。
uint8_t         try_delay1ms; //發送失敗後再次發送時的延時,1ms為機關
uint8_t         max_try_times; //最大重試次數
uint8_t         max_reset_times; //最大重新開機次數
} stcATConfig;
           

2、AT指令注冊函數

在發送AT指令之前,需要先注冊AT指令的運作環境,包括如下4項。

void AT_RegisterHandler(SendMsgFunc_t func, char* recv_buf, OS_SEM* recv_sem, OS_MUTEX* buf_mutex)
{
	SendMsgCallback=func;             //序列槽發送資料的函數
	pRecvAckSem = (OS_SEM*)recv_sem;  //序列槽收到AT指令回令的信号量,可在序列槽接收空閑後發出
	pAckBufMux=(OS_MUTEX*)buf_mutex;  //序列槽接收緩沖區互斥信号量
	atAckBuf = (char*)recv_buf;		  //序列槽接收緩沖區
	return;
}
           

3、發送AT指令函數和發送AT字元數組函數

二者的主要差別是:

(1)發送AT指令函數主要用于發送AT配置指令,發送的都是字元串,發送函數遇到"\0"時就停止。發送AT字元數組函數主要用于發送資料,發送的時char型數組,遇到"\0"時不停止,且需指定發送的數組長度。比如,用EC20子產品釋出MQTT消息時,發完PUB指令後,就需要直接發送一個數組作為資料。

(2)發送AT指令函數在多次發送失敗後,可以根據設定多次重新開機硬體。發送AT字元數組函數不重新開機硬體。

/*****************************************************************
* 功能:發送AT指令
* 輸入: send_buf:發送的字元串
		recv_str:期待回令中包含的子字元串
        p_at_config:AT配置
* 輸出:執行結果代碼
******************************************************************/
uint8_t AT_SendCmd(const char *send_str,const char *recv_str,stcATConfig *p_at_config)
{
    ......
}

/*****************************************************************
* 功能:發送數組資料
* 輸入: send_buf:發送的數組
		buf_len:數組長度
		recv_str:期待回令中包含的子字元串
        p_at_config:AT配置
* 輸出:執行結果代碼
******************************************************************/
uint8_t AT_SendData(const char *send_buf,const uint16_t buf_len,const char *recv_str,stcATConfig *p_at_config)
{
    ......
}
           

4、清空接收緩沖區和搜尋響應字元串函數

均是局部函數,清空接收緩沖區函數在每次發送AT指令或資料前調用,搜尋響應字元串函數在發送AT指令後調用。

/*****************************************************************
* 功能:查詢AT指令的回令中是否有需要的字元串
* 輸入: recv_str:期待輸出字元串中需要含有的子字元串,如"OK\r\n"
        max_resp_time:指令最大響應時間,機關100ms
* 輸出:查找到的子字元串指針
******************************************************************/
char* AT_SearchRecvBuf(const char* recv_str,uint16_t max_resp_time)
{
	...
}
/******************************************
* 功能:清空序列槽接收緩沖區
******************************************/
void AT_ClearAckBuff(void)
{
    ...
}
           

5、舉個例子

(1)先注冊AT指令運作環境

AT_RegisterHandler(Uart_SendData,atAckBuf,&ATRecvAckSem,&ATRecvAckMux);
           

其中Uart_SendData是序列槽發送函數,符合typedef void (*SendMsgFunc_t)(uint8_t * buf, uint32_t len);的形式即可。

atAckBuf是序列槽接收數組char[],ATRecvAckSem和ATRecvAckMux分别是序列槽接收資料信号量和序列槽接收數組互斥信号量。

OSSemCreate((OS_SEM*)&ATRecvAckSem,"ATRecvAckSem",0,&_err);
OSMutexCreate((OS_MUTEX*)&ATRecvAckMux,"ATRecvAckMux",&_err);
           

(2)發送AT指令

stcATConfig iotATConfig;
stcATConfig * pATConfig = &iotATConfig;

pATConfig->resp_time100ms = 1; //最大響應時間100ms
pATConfig->try_delay1ms = 100; //響應失敗後再次發送時延時100ms
pATConfig->max_try_times = 10; //最大重試次數:10
pATConfig->max_reset_times =0; //最大重新開機次數:0

_ret = AT_SendCmd("ATI\r\n","OK\r\n",pATConfig);//發送"ATI\r\n"後,響應中包含"OK\r\n"才算響應正常

....

pATConfig->resp_time100ms = 500; //最大響應時間50s
pATConfig->try_delay1ms = 100; //響應失敗後再次發送時延時100ms
pATConfig->max_try_times = 10; //最大重試次數:10
pATConfig->max_reset_times =0; //最大重新開機次數:10
_ret = AT_SendCmd("******\r\n","\r\n+QMTOPEN:",p_AT_Config);//發送"***\r\n"後,響應中包含"\r\n+QMTOPEN:"才算響應正常
           

(3)發送AT資料

與發送AT指令類似,更簡單,不舉例了。