原创 SIM模块驱动程序的巧妙编写思路

2012-12-21 15:05 1966 17 30 分类: 消费电子

           单片机控制SIM模块实现GPRS联网是实现远程监控的基本方式。般的做法都是通过串口发送AT指令来实现对SIM模块的控制。

 

原理然简单,但是要编写一套稳定、可靠的程序就要采用合适的设计思路,比如:发送AT指令后我们需要对AT指令的返回值进行断,如果采用固定延时的做法也未尝不可,但是有些情况下比如联网时CONNECT OK的返回时间就跟环境有很大关系,所以采用固定延时的做法编写的程序适应性很差。

 

还存在另一种情况,比如发送完AT指令后模块返回错误代码,这时候我们最好的做法就是重发,而不是略过。

 

基于上面这两点的考虑我采用了超时重发的机制来保证程序的可靠性、适应性从而避免程序在执行错误之后出现崩溃。

 

下面讲一下我的具体思路:我采用的是STM8L系列的低功耗单片机控制SIM模块的,要实现超时和重发的机制,我们需要一个基础定时器和串口。从发送AT指令后开始开启定时器计时,设置一个最大定时值,在设定时间到来之前如果收到正确的返回值就跳出定时等待,否则在最大等待时间到来后跳出循环,执行有限次的重发,在这种实现策略中必须要设定定时器中断的优先级比串口接收中断优先级要低,以便实现中断嵌套。通过这种手段我们可以将超时值和重发次数作为函数入口参数,只要更改这两个值便可以增强程序的适应性和可靠性。

PARTNER CONTENT

文章评论13条评论)

登录后参与讨论

462629051_256703759 2013-9-6 09:12

多谢allen_zhan您对这篇博客的仔细研究,不过说实在的我还确实没想到这么多,只是觉得定时器监控CPU的运行可以实现对CPU的管理,进而或许可以实现任务调度!不过还是非常感谢allen_zhan您的持续关注的!

allen_zhan_752827529 2013-9-5 12:57

继续上面3点的设计 rule, 我想, 对于第三点的补充就是, 这个 flag 是中断禁止的. 正如同软件喂狗一般, 对 flag(针对本次 AT 指令的设定, 要求代码前后禁止 interrupt). 比方说: diasable interrupt; set at_flag true; send at cmd; enable intrerupt again; 这应将对这个 flag 起到保护作用.

allen_zhan_752827529 2013-9-5 11:20

再次无意浏览到这份文章, 我修正我之前的回帖. ARM7TDMI-s 是不支持嵌套终端, 而在 cortex-M series(举例说 m0, 架构 v6M) 是支持嵌套中断的. 重新理清你的计划完成的项目, 我想, 是否可以说, 你在定时器中断与uart 中断"并行"发生感到困扰. 我所谓的"并行", 正是嵌套之意. 在前一个 AT 指令的结果收到后, 你可能开始设计下一个 AT 指令定时器发送机制, 但是你担心, 比方说, 在发送AT 的 timer ISR 中, 突然已经收到了上个 AT 成功返回的 result. 明明不需要重发, 但是你的现在这个 ISR 却还在继续运行中? 或者其他类似这样的时序问题? -- 你想到了实时OS, 如 RTX 之类的, 都是OK的, 我明白你试图引入一个在多任务中的定时器机制(它不是中断). 但是又如何保证在执行这个多任务中的重发时, 来自 uart 的 isr 不会打断它的执行呢? -- 所以, 其实无论是否嵌套中断, 还是你计划使用os的多任务定时器(它可能不是定时器中断), 其实你简单在 superloop 中, 计算 timer count 也可以模拟出多任务定时器的功能(这是题外话). -- 我想无论是上述哪种方式, 都应该进行逻辑简化. 你的 AT 重发机制, 应该被 uart iar 进行管理. 也就是, (1)每个新的 AT 开始, 都必须是上一个 AT 成功的结束. (2)每个AT 都是可重发的, 有等待时间的, 依赖 uart isr 返回值的. (3) 理论上, 任何一个被发送的 AT CMD 都不应该被中断 ISR 干扰, 但是, 事实上, 由于你的超时定义, 就算被干扰, 应该在重发任何一个 AT 指令之前, 使用 flag 标志新的发送事件开始, 并等待新的 uart 结果. -- 这个意义上, 是否嵌套, 是否任务定时器都可能不重要了, 就算多进行一次 AT 指令又何妨呢?...

allen_zhan_752827529 2013-4-9 13:34

啊, 不好意思, 过了这几个月又无意看到了这个回帖, 我考虑给 EETC 提建议. 不仅仅是论坛, blog 的回复也应该提醒...我差不多明白你提及的核心, 毫无疑问, 你在实现一种机制, 这种机制, 是一个非阻塞形式的, 可执行指定次数或者无限循环的, 可根据某个外部 interrput 的协议分析结果进行自行中止的. 并可以自组织执行逻辑与步骤的一个软件逻辑. 我们这里想说的就是, 这个逻辑, 似乎不应该用"中断嵌套"来称呼. 因为"中断嵌套"应该是一个专有属于. 在 ARM 的世界里, 是不被支持的. 但是很多工程师, 在挑战这个用法. 他们依靠在一个中断例程中, 主动关闭中断 flag, 开启新的中断 falg 的方式, (请原谅我说的含糊, 因为我没有仔细跟进去做重复实验), 在实现"中断嵌套"只目的. 在EETC 的砖家blog 中, 有个博主"下家山", 曾经发表过一份 blog, 验证了"中断嵌套"的实现方式. 我有这个印象. 但是, 因为复杂的中断嵌套逻辑为我个人不喜, 担心增加系统的可维护性, 而没有认真了解. 所以, 我想你这里要实现的软件逻辑, 应与"中断嵌套"这个专业术语无关. 想想看, 你关闭自己的 timer interrpt, 然后等待 uart interrupt, 但是你还在 timer interrupt isr 中! 处理了 uart isr, 然后恢复 timer ist? 多想想, 我都觉得脑细胞大量死亡中... 所以, 是否在实际project 中使用中断嵌套, 应该是仁者见仁智者见智吧.

用户1413766 2013-1-15 09:13

这是最基本的实现方式。

462629051_256703759 2013-1-7 17:16

allen zhan你好!其实我觉得这篇博客最重要的是一种等待超时的一种实现机制。这种机制对于多任务来说是有很大的帮助的,比如ucos II操作系统就提供了好多非阻塞形式的函数,这些函数都会允许用户设定一个最长的等待时间。我没有研究ucos II实现这种超时等待的原理,但是在STM32移植ucos II的时候会有一个Systick定时器的驱动,我猜想ucos II在应用层实现的超时判断就是依靠Systick定时器监控程序执行来实现的。从这个方面来说ARM是可以实现中断嵌套的!

allen_zhan_752827529 2013-1-7 16:42

不好意思, 无意浏览帖子, 看到你的回应. 我找不到blog 的短信提示参与讨论的帖子的提示, 所以往往是发帖后, 就石沉大海, 刚才无意中点击这个帖子出来了吧. 我印象里面, 中断嵌套, 至少 ARM 是不支持的. 很多人说, 执行中断嵌套, 应配合使用 EXTINT 操作中断标志, 在中断例程中, 清除中断标志等方式实现嵌套. 我想你的 original ideal 是不去理会这种复杂的代码实现与测试的. 在这个基础上, 我理解中断触发应该不存在你想象的"抢占"和"实时"的概念. 可能你设计的, 应该就是一个定时器的反复发送逻辑, 只不过是可以被runtime 中的某个 flag 中止而已. 而这个 flag , 可以如你说的来自 uart interruput 或是其他 any interrput or machine.

462629051_256703759 2013-1-7 10:52

allen zhan你好,可能我的表述不太清楚,我所说的中断嵌套正如你所理解的,存在两个中断:定时器中断和串口接收中断,定时器中断的作用是超时时间的计数,用来监控串口是否在设定超时时间到来之前收到有效回应,要想实现这样的功能就需要同时开启串口中断和定时器中断,而且定时器中断优先级要低于串口中断,一旦判断出串口收到有效回应,就退出超时等待,这样的做法可以保证一定的实时性,而且只要修改超时时间就可以保证程序的适应性。至于重发则是由CPU来实现的,比如,一次超时到来之后没有收到有效回应,CPU启动重发程序,再次发送AT指令等待有效回应,至于超时值和重发次数的设置可以以环境条件而设置。最后我还有个全新的想法,为了提高程序的适应性,我们设置可以通过AT指令获取当前信道的拥堵情况,并以此构造一个超时值和重发值的拟合函数,保证程序可以自动判断超时值和重发次数,我曾利用AT+CSQ获取过信号电平,但是后来发现信号电平和信道拥堵并不成正比,所以由信号电平来决定超时值和重发次数并不非常合理,也希望各位网友如果有更好的主意可以共同讨论!

用户1241444 2013-1-5 15:29

STATUS ATcmd_send(char cmd[], int timeout, char *exp_retstr, char **pRcv)

用户557499 2013-1-5 12:29

不错 不错
相关推荐阅读
462629051_256703759 2014-06-08 21:56
产品研发的一点想法
        产品研发的核心是产品,研发是为了实现产品,所以能够快速设计出稳定的产品才是研发的目的。通过对比自己身边的一些项目产生了一些想法,总体来说就是尽可能采用半导体厂商的最成熟方案尽可能和...
462629051_256703759 2014-03-01 12:34
LED子系统
        Linux驱动中已经将led驱动作为一个子系统来实现了,针对Tiny210采用通用IO口来控制led的情况,linux采用platform驱动来实现led子系统,因此我们可以通过l...
462629051_256703759 2014-02-27 22:47
git入门
15.1、安装git $sudo apt-get install git $sudo apt-get install git-core 更新git $git clone git:/...
462629051_256703759 2014-02-27 15:05
Vim + Ctags + Taglist组合
12.1、Ctags和Taglist插件的安装: 12.1.1、Ctags插件的安装:sudo apt-get install ctags 12.1.2、Taglist插件的安装:首先下载...
462629051_256703759 2013-09-23 15:57
改善电源负载瞬态响应性能的设计方法
        以前对电源芯片的理解停留在输出电压是否满足需求、输出电流是否满足负载等一些静态的参数上,但是后来发现即使这些参数满足要求所选用的电源芯片有可能还是不能满足负载瞬变时的波动,所以就查...
462629051_256703759 2013-09-05 14:33
MSP430两种串口升级方式对比
        早上收到网友咨询MSP430单片机串口升级问题的邮件,因为不是第一次收到这样的帮助请求,于是便把自己做过的两种串口升级方式做一对比希望对此问题感兴趣的工程师朋友可以从中受益,也希望...
EE直播间
更多
我要评论
13
17
关闭 站长推荐上一条 /3 下一条