单片机模块化程序: 单片机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语句就是需要主循环不停的调用
结语
看过介绍之后,记得自己好好的使用下哈.