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指令流格式化为数组下标,然后用数组下标

直接查表来得到解析函数。

        这个格式化的算法怎么设计,我目前还没有很好的思路,如果你有什么好的想法,请留言

给我。

2018.12.26

        最近有个NTC测温的项目,是另外一个同事负责,给出的温度和阻值对应曲线不是线性的。

于是这个同事就犯愁了,如果用传统的if/else和switch/case架构去做分段解析,那么精度要求高的

时候,段就会分很多;如果段分的少,精度又下降了。那有没有一种思路,既可以兼顾精度,又可以

使代码架构简单,降低体力活力度?于是有位老专家提出了一种“算法”,用折线去模拟曲线,同时

又没有if/else判断,我感觉思路很好,记录如下:

1、首先用折线去模拟曲线,这个没什么好办法,每段去选择合适的K和B的参数,这样就有一张参数表;

2、那么怎么知道现在读取的阻值是落到那一段呢?摒弃程序分支判断的方法就是查表法,就是说根据

阻值我就可以计算出目前在表里的位置,然后查表就得到了K和B;

3、这里取折线段的方法很重要,你可以用线性发(均分法),这样查表算法就是kx+b;如果采用非线性

方法,那个查表算法很可能是高次函数或者指数等高阶函数;

这里就设计到计算资源问题,当然根据精度,采用定点算法,实时性会大大提高。

2022.08.02

上面遗留了一个问题,一直没有写解决思路,现在把解决思路总结下。问题如下:

 这里说如果考虑拼包,就和协议绑定了,是因为原来的解决思路是需要知道用户协议,才能去接收数据里面去找数据帧,才能够知道一个APDU是否完整。这样的思路没有问题,但是用户协议和我的底层驱动绑定了,换种协议,我就得重写驱动。下面说下后来常用的做法:

1、我们思考下那些是“变化”的?

2、怎么把变化的部分分离?

从上可以看出,用户协议是变化的,那怎么分离呢?把它打包成函数,每次只改写这个函数,再进一步,把这个函数指针当成参数,传入到底层驱动。

1、check函数指针输入到此等驱动,可以如下写法:返回0:则表示没有找到,返回非零,则表示找到数据帧,并且代表数据帧长度,下面驱动出队这么多。

2、下层驱动接收到数据,则每次重置超时时间,超时时间到则全部出队。

以上就是最近几年经常用的架构。

  • 21
    点赞
  • 94
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值