一线研发之声 https://passport2.21ic.com/?567930 [收藏] [复制] [RSS] ------最底层、最深邃、最负重的编程之歌

日志

一线研发之声 之 跑马灯变形记(五)

热度 15已有 10851 次阅读2014-11-8 07:23 |个人分类:一线研发之声|系统分类:嵌入式系统


   跑马灯的第四次变形:修改模块间的依赖关系

是的,只有把前面的三个诘问解决了,我们才能得到一个相对完美的跑马灯。最终,我们要的是一个干净清爽的关系依赖图,如下。

要实现这样的依赖关系,就需要明白上一次变形中存在的几个“思维误区”。

1)        LIGHT_INTERVAL_TIME这个参数调整跑马灯的间隔时间,最终影响跑马灯的循环闪烁速度,可快可慢。它本质上是属于用户的,如同街上的广告轮廓灯,它的样式和闪烁方式,是由订购者决定的。广告灯的供应商只需给出使用方法即可。

因此LIGHT_INTERVAL_TIME这个参数是不属于设备层的,它归使用者,归main.c设备层必须得给出一个接口实现方式,让使用者得以传递LIGHT_INTERVAL_TIME的数值,使“用户”可以灵活地控制跑马灯的运行速度。如何实现呢?这里介绍一种较为符合当前应用的方法。为此,我们需要将timer模块改装如下。

2)        
led_turn.h中的端口定义“#define  LED_PORT         P1。许多单片机的工程师喜欢将平台相关的东西定义在.h档里面,其本意是为了移植方便,想着届时只需要修改.h档即可。但这样的话,led_turn.h模块就得依赖文件,不然就无法识别到端口P1。最终造成了所有依赖led_turn.h的模块,会间接依赖。因此,这个P1,必须放到led_turn.c的模块内部。

不要轻视这样的小细节,当系统较为庞大时,这样操作很容易就会造成二次、三次、多次间接依赖,像病毒一样“污染扩散”,牵一发就会动全身,最终使整个系统陷入永沦之地。正所谓,勿以恶小而为之,勿以善小而不为。

3)        
上次变形中,我们把timer模块中的全局变量flag_80ms,通过timer.h,开发给main.c读写。在当前这个小小跑马灯系统中,也许问题不大。但对于构建商业软件系统,这是一个极为危险的做法。全局变量本身就是一个需要极力避免的东西,更何况还把写权限开放给外界,这如同将家中大门拆除一般令人心悸。关于全局变量的危害性及处理方法,详见本书章节《全局变量猛于虎》。此处我们用函数get_and_clr_timer_evt()进行了规避,详见上述代码。

多年来,我总结了一个经验,.h档里面,最好都是纯洁无瑕的函数声明。我一直尽力做到这一点,本书的后续章节,会陆续提到这一原则的带来的种种妙处,及其各种实现技巧。

综上,我们得到这样的一个依赖清晰的main.c文件,如下:

     这样,我们的跑马灯完成了第四次变身,成为了一个具备良好移植性、可阅读性的商业系统。如果这个跑马灯要移植到M3/M0或者AVR等平台上,只需要修改“设备层”的led_trun.ctimer.c文件即可。而应用层的三个文件无需任何修改,因为它们没有依赖任何平台相关的文件。

一线研发之声 之 跑马灯变形记(六)



路过

鸡蛋
14

鲜花

握手

雷人

刚表态过的朋友 (14 人)

发表评论 评论 (4 个评论)

回复 sedatefire 2014-12-25 16:09
我自己重新看了一遍,发现这样的行文方式,对于没有耐心的读者,很难“入戏”。
太长了,还是要再增加图表来降低阅读难度。
在这样的快餐时代,作者要去迎合读者。

当然,对于有深度的读者,他会希望能够得到更详细的细节。这样的读者还算是少数。
回复 wlc824136 2014-12-27 09:45
sedatefire: 我自己重新看了一遍,发现这样的行文方式,对于没有耐心的读者,很难“入戏”。
太长了,还是要再增加图表来降低阅读难度。
在这样的快餐时代,作者要去迎合读者 ...
看完大大的文章,也想学学将程序分层,我想问一下,我用定时器来做延时,需要多个时间标志位,我现在想的是将每个时间标志return出来,然后再其他函数要用到时读一下好?还是用全局变量好?还有没有其他方法,求指教!!!
回复 sedatefire 2014-12-28 12:08
wlc824136: 看完大大的文章,也想学学将程序分层,我想问一下,我用定时器来做延时,需要多个时间标志位,我现在想的是将每个时间标志return出来,然后再其他函数要用到时读 ...
用事件机制吧
回复 GZZXB 2015-10-13 13:47
很想听听不把端口定义放在h文件中的利与弊。