单片机模块化程序: 单片机AT指令配置模块程序模板(非阻塞版)

 

说明

在单片机开发中会遇到使用串口发送指令给模组,然后模组返回以后再发送其它指令给模组.

为了便于实现这种功能,我封装了一套框架.

这套框架是非阻塞形式的,不会耽搁主循环运行.

 

先来测试体验下

1.把以下文件放到自己的工程

 

 

 

2.把ConfigModuleNoBlockCnt++; 放到1ms定时器中断函数里面

 

 

 

3.替换自己的串口发送函数,假设是使用串口1和模组通信

 

 

 

4.把以下内容放到主循环,并按照提示修改

 

 

 

5.提示

我的程序代码是使用的环形队列接收的数据,然后打开了单片机自带的串口空闲中断

关于空闲中断和环形队列请用户参考前面的文章.

 

 

 

6.所以修改如下

其实就是把ConfigModuleNoBlock();放到主循环里面,然后把模组返回的数据送给

ConfigConnectDispose(char *data,int len) 函数

我的串口接收数据(模组返回的数据)是存储到了环形队列,所以是从环形队列里取数据而已.

然后把取出来的数据送给ConfigConnectDispose(char *data,int len) 函数

 

 

 

 

测试1 

1.发送AT命令给模组,模组返回OK以后,发送AT+RST给模组,模组返回OK以后配置完成

在以下位置增加以下程序

SendConfigFunction("AT\r\n",NULL,"OK",NULL,FunctionParseCompare,CompareValue);

SendConfigFunction("AT+RST\r\n",NULL,"OK",NULL,FunctionParseCompare,CompareValue);

 

 

 

2,使用串口调试助手模拟为模组

当收到单片机发送的AT命令以后发送OK给单片机,

会发现单片机会执行下一条AT+RST,然后再发送OK给单片机,整个配置结束.

 

 

 

 

现在咱们来看一下框架是如何运行的

1. ConfigModuleNoBlock 函数就是放到主循环里面进行轮训

 

 

 

2.不过多少时间进入if 语句内部执行是靠这个时间控制的

咱给模组发送每一条命令需要的间隔时间将就是靠 CompareValue 这个参数来控制的.

不过呢,这个时间是模组没有返回咱想要的数据之后的最长等待时间,

咱在发送完指令以后如果模组返回了想要的数据,是可以立即发送下一条.

 

 

 

3.以下红框部分

如果发送的上一条指令模组返回了咱想要的数据,就执行下一个case语句

如果执行某个case语句,模组没有返回相应的数据,就会再接着执行该case 两次,

如果模组还是没有返回,就从case 0 重新执行.

 

 

 

4.下面的是用户需要根据模组进行改动的程序

 

 

 

 

来看下主要的函数 SendConfigFunction 的工作过程

1.以 SendConfigFunction("AT\r\n",NULL,"OK",NULL,FunctionParseCompare,CompareValue); 为例子说明

 

 

 

2.要发送的AT\r\n 呢直接通过串口发送了出去

 

 

 

 

3.希望返回的数据 OK 拷贝到了 HopeReturnData1 数组里面

因为咱配置模组的时候很多地方都是比较判断返回的数据,所以框架里面默认把

比较判断返回数据封装了进去.

 

 

 

 

 

 

 

4.接着就是需要接收处理模组返回的数据

接收处理数据的参数是一个函数指针

 

 

 

函数内部把函数指针传给了 ConfigConnectDispose

 

 

 

5.例程里面把 FunctionParseCompare 函数传递了过去

 

 

 

 

 

 

6.其实就是

 

 

 

7.关于为啥要这样子做

因为发送不同的指令可能需要不同的函数接收处理数据,我上面只不过是把比较判断函数写好了.

咱大部分时候需要的是比较判断,有些情况不只是比较判断,用户发送完指令需要对返回的数据

做其它操作的时候,可以把相应的处理函数指针传递过去就可以.

 

8.关于比较判断

单片机发送完AT以后,模组返回OK.然后传递给了 FunctionParseCompare 函数

函数里面判断了如果返回了期望返回的数据就置一  DataReturnFlage=1;

注:后面的 ConfigModuleNoBlockCnt = (SendNextDelay == 0 ? ConfigModuleNoBlockCnt:SendNextDelay);

是控制发送下一条数据的间隔时间,这个后面会说明

 

 

 

 

下一个轮训过来,程序里面判断了 DataReturnFlage 是1之后便会执行下一条

 

 

 

9.关于最后一个参数

咱们从前面知道ConfigModuleNoBlockCnt如果累加到大于 CompareValue 才会再次进入函数里面执行case语句执行

下面就是为了给 ConfigModuleNoBlockCnt 重新赋值而做的,注意后面的参数最终传递给了 SendNextDelay

 

 

 

 

下面这个地方就是把数据赋值给 ConfigModuleNoBlockCnt

改变 ConfigModuleNoBlockCnt 的值就能控制发送下一条数据的时间间隔

 

 

 

 

现在开始看看使用的好几种方式

为了能够应对各种情况,该框架不仅仅只是上面的发送命令和判断返回

 

 

判断返回的数据其实有两个

 

 

 

 

假设模组返回OK 或者 ready 的时候执行下一条

 

 

 

自定义函数解析模组返回的数据

函数参数注意需要是char *data,int len 

然后最后判断或者提取完成以后记得写上ConfigModuleRunNext(CompareValue);

这句话其实就是控制发送下一条数据的时间

 

 

 

 

 

 

假设并不是发送普通指令

可以自定义一个函数,然后在里面编写发送的数据,然后使用串口发送出去

然后把函数名称放到SendConfigFunction 函数的第二个参数上就可以.

注意:我只是简单的发送了个AT命令,实际中根据自己的情况使用串口发送数据就可以.

 

 

 

先组合字符串然后再发送

把要发送的数据使用sprintf组合进main_buff数组

main_buff[main_len]=0;设置下字符串的结尾位置

 

 

 

假设一开始的时候用引脚控制模组重启

 

 

 

假设有的模组需要延时更长的时间

则这就需要更改 CompareValue的值

 

在主循环里面判断是否配置完成

一般咱都是用此框架配置一遍模组,然后再接着做其它事情

可以在主循环里面判断 ConfigModuleNoBlockFlage

 

 

 

假设检测到模组一些问题需要重新配置模组

让框架重新配置模组只需要 ConfigModuleNoBlockFlage=0; ConfigModuleNoBlockCaseValue=0;

 

 

 

如果用户不希望程序一运行的时候就配置模组

可以直接写上 ConfigModuleNoBlockFlage = 1; 

当需要配置的时候再写上 ConfigModuleNoBlockFlage=0; ConfigModuleNoBlockCaseValue=0;

 

 

 

假设某一个case语句就是需要主循环不停的调用

 

 

 

 

结语

看过介绍之后,记得自己好好的使用下哈.

 

posted on 2019-10-14 23:06  广源时代  阅读(7202)  评论(0编辑  收藏  举报

导航

支付宝 QQ群