1. 程式人生 > >AT指令的一種解析想法

AT指令的一種解析想法

       最近一直在忙著做NBlot模組,話說部落格也好久沒有更新了,最近整理下思路,

做下總結,權當是一片部落格吧。

AT指令大家很熟悉了,這裡不再做介紹(不熟悉的,請參考《GSM Rec.07.07標準AT命令》)。

一個命令型別最多分為四類:
1、設定型別,CMD=設定引數,回覆OK或者ERROR;        可用通用模式解析
2、讀取型別,CMD?讀取引數當前值,回覆+CMD:引數列表;解析返回字串,可能做命令轉變
3、測試型別,CMD=?讀取預設引數值和可設定範圍;       解析返回字串,可能做命令轉變,也有可能返回OK
4、執行型別,CMD  讀取不可設定引數值;              解析返回字串,可能做命令轉變

這裡解析主要運用到訊息地圖的方法,同時為了減小地圖的大小,每個命令位元組不具體細分是那個

命令類別,交給具體的命令解析函式去處理。如下:

//! 訊息地圖
const static msg_t c_tMSGMap[]  =  {
    {"AT",              JZQ_AT_CMD_AT},
    {"ATE0",            JZQ_AT_CMD_ATE0},
    {"AT$MYGMR",        JZQ_AT_CMD_MYGMR},
    {"AT$MYTYPE",       JZQ_AT_CMD_MYTYPE},
    {"ATI",             JZQ_AT_CMD_ATI},
    {"AT$MYCCID",       JZQ_AT_CMD_MYCCID},
    {"AT+CSQ",          JZQ_AT_CMD_CSQ},
    {"AT+CREG",         JZQ_AT_CMD_CREG},
    {"AT+CIMI",         JZQ_AT_CMD_CIMI},
};

在具體的命令解析函式裡面,都次都可以指定NBlot模組的資料返回解析函式,做到每個命令和命令

的回覆處理函式一 一對應。如下:

傳送給NBlot模組命令:

    user_nblot_send(get_byte_pipe_buffer(&tBytePipe),get_byte_pipe_num(&tBytePipe));
    s_tNblotAppBuffer.pRxCallBack = JZQ_AT_CMD_MYNETWRITE_ACK; 

NBlot模組的命令接收解析:

    switch(s_tState){
        case FSM_NBLOT_PROTOCOL_START:
            s_tState = FSM_NBLOT_PROTOCOL_WAIT_DATA;
            s_tNBlotAppBuffer.hwBufferSize = 0;
            //break;
        case FSM_NBLOT_PROTOCOL_WAIT_DATA:
            if(nblot_rx_buffer_is_empty()){
                break;
            }
            s_tState = FSM_NBLOT_PROTOCOL_REV_FRAME;
            //break;
        case FSM_NBLOT_PROTOCOL_REV_FRAME:
            tFsmRt = nblot_protocol_revice_frame();
            if(fsm_rt_cpl ==  tFsmRt|| fsm_rt_buffer_full == tFsmRt){
                s_tState = FSM_NBLOT_PROTOCOL_HANDLE;
            }else if(fsm_rt_err == tFsmRt){
                RESET_FSM_NBLOT_PROTOCOL();
                return fsm_rt_err;
            }
            break;
        case FSM_NBLOT_PROTOCOL_HANDLE:
            if(NULL != s_ptRxCallBack){
                s_ptRxCallBack(s_tNBlotAppBuffer.chBuffer,s_tNBlotAppBuffer.hwBufferSize);
            }
            RESET_FSM_NBLOT_PROTOCOL();
            return fsm_rt_cpl;
        default:
            FSM_DEFAULT_ACTION();
    }

至此一個大體的AT命令解析架構介紹完畢了,但是這個架構會有一個問題,

就是如果僅僅考慮問答式命令形式,這個架構再加一個超時無效處理的維護

執行緒就可以(維護執行緒就幹一件事情,傳送命令後,啟動維護執行緒,設定超

時命令,如果在設定的超時時間內回覆,則通過傳送命令時候指定的處理函

數解析,如果超時了,就把指標清NULL,同時傳送超時訊息)。如果還要考

慮主動上報,那麼上面的架構就需要在(每個)處理函式裡面加入主動上報

的處理邏輯,否則邏輯上就不對。這樣就會產生很多“髒程式碼”,處理方法是利

用行為繼承,在FSM_NBLOT_PROTOCOL_HANDLE前面增加一個DEFULT_HANDLE

處理,把一些通用或者主動上報的(每個命令幀都需要考慮的情況)打包成一個處理函式。

到目前為止,AT指令解析,基本講完了,說些題外話:

1、下行資料可能要考慮拼包問題,因為在測試過程中發現主站下發一個APDU,在模組

      端會被分為兩個socket包,並且時間間隔還很長(目前監控到最長30S);這裡有一

      個問題,如果考慮拼包,那麼就和協議關聯了。

2、socket會自己斷開,一定要有重建機制;

 

2018.10.23

       前幾天和一位老工程師交流這個AT指令解析方法,有一些心得,記錄下,也算是一種

思想上的提高。

        這個解析方法有個確實,就是當指令閱讀,訊息地圖越大,檢索時間越長。如果系統

要求這個檢索時間和地圖大小無關,時間是“確定”的,怎麼解決?

        首先我們就想到是什麼?什麼情況下檢索時間和資料表大小無關?我們是不是想到了

陣列下標,查表的方法。沒錯,查表的時間確定,並且和表的大小無關。那麼我們怎麼進行

查表呢?首先我們需要有一個格式化演算法,把AT指令流格式化為陣列下標,然後用陣列下標

直接查表來得到解析函式。

        這個格式化的演算法怎麼設計,我目前還沒有很好的思路,如果你有什麼好的想法,請留言

給我。