据说,在中国,当老板的一般都有这么一个心态:花最少的钱,办最多的事!
客户大爷不能慢待,因为开源和节流不可偏废。政府机关必须打点,毕竟“有关部门”掌握着生杀大权。于是,这“节流之道”便落在了员工的头顶上。
只是,人心惟危,道心惟微,被教育多年的打工者都不想做活雷锋。节流手段过于明显的话,无异于杀鸡取卵。于是,老板们八仙过海,各显神通。
有的呢,深入落实我党的群众路线,和群众们打成一片,很好地实现了“到群众中去,让人民服务”的目的。
有的呢,摆出一副义薄云天的架势,和员工们勾肩搭背、称兄道弟,以“情”感人,成功地将老实厚道的员工们加薪的请求扼杀在了萌芽状态。
有的呢,善用权谋,假惺惺地放权,让手下人产生“主人翁”意识,同时搞制衡之道,效仿春秋二桃杀三士的故事,让员工们争相效忠,总之,靠着厚黑之道,将风筝背后的那根线牢牢地掌控在自己手中。
也许是深知惹毛工程师的惨痛下场,电子类公司的老板对待工程师们更有人性一些。在画大饼、吊胡萝卜一段时间后也会忍着心痛犒赏犒赏大家伙。但是,开公司毕竟不是请客吃饭,还得有钱赚。
于是,不能拿人开刀的老板们就把目光放到了物料上面。
如果一件产品的物料成本能节省10块,卖出去1万件便是10万,10万件便是100万。数学运算算得贼溜的老板们就这样对物料清单下手了。
一
在小公司里面,老板们亲自参与硬件设计不算什么稀罕事。老板经常赤膊上阵,对硬件元器件选型指手画脚。
作为一名软件工程师,好整以暇地在旁边欣赏硬件工程师被老板虐得敢怒不敢言的画风固然很惬意,但是一旦老板的魔爪伸向MCU这颗关键物料之时,我辈也难以事不关己高高挂起了。
那一日,晴空万里,艳阳高照,不才正沐浴在午后的阳光中,品着茶香,感叹着岁月静好:“其香悠远兮扶摇登宵,其味空静兮潜藏于窍!”
不才摇着头,晃着脑,感觉到欢快的自我就快要出窍,全然没有发现悄悄来到面前的领导。
“咳咳”,一声短促的咳嗽,带着熟悉的压迫感将我从浮生若梦中惊醒。不才赶紧从半躺的姿势中坐起,差点闪着媳妇所言“用进废退”的老腰。
“马步君,看看我手里这个板子。”领导带着看似神秘莫测、其实没有什么意义的微笑,把一个电路板递给了我。
不消说,来任务了!从天堂掉落人间的我心中一个咯噔,看着手里的电路板,内心荡漾个不停:“这板子看着不算复杂,这等小活一般是不会安排给我的,莫非领导开恩?”
这边厢,不才心中火光电闪,转个不停,那边厢,领导打开了话匣子,讲起了原委。
原来,这是别的公司给我司一个客户批量供货的产品,现在客户要求对产品进行升级,希望在硬件电路基本不改动的情况下,添加一些功能,客户为了保证供货安全,把我司列入了备胎供应商之列。
具体情况交代完之后,领导把不知从哪里搞来的原产品电路图发给了我,让我评估一下不改电路、完全抄板的情况下,能不能实现产品升级。
二
“我真傻,真的,”事后,我经常抬起帅气逼人的眼睛来,祥林嫂似对同事说。“我单知道在设计新产品的时候为了控制成本,领导会插手MCU的选型;我不知道升级别人产品的时候也会这样。”
当我把“不需要改电路,只需要换一下引脚兼容、资源更丰富一点的MCU”的结论告诉领导时,领导及时地制止了我的“无理要求”。
“客户是把产品升级了,但是产品的价格基本未动,加的功能也不算太多,MCU就不要换了吧。想想办法,能省一块是一块嘛!”
看着领导那副欠揍的笑脸,我据理力争,“天之道,损有余而补不足......”
“别吊书袋子了,硬件资源不够,软件功底来凑。所以才把这么艰巨的任务交给你嘛!”
得,认命吧!
资源受限,编程自然处处是挑战。具体到这个产品上,我发现挑战最大的一点便是:定时应用特别多,MCU的定时器又特别地少。
硬件定时器的数量远远少于定时应用的数量,显然无法为每一个定时应用单独分配一个硬件定时器。本来一个萝卜一个坑最好办,现在资源不够怎么办?
不才就不卖关子了,方案当然是用软件的有余弥补硬件的不足了。
为了各个定时应用的起点相同、步调一致,同时为了编程的统一,最好的方式便是在单个硬件定时器的基础上模拟实现多个软件定时器,以前台硬件定时器中断服务程序和后台软件定时器管理程序相结合,实现单次定时、多次定时和循环定时应用。
三
不才不屑藏私,下面就把具体的方案设计给各位看官们分享出来。
先跟大家建立这么一个概念:
程序设计=数据结构+运算
具体到这里,数据结构便是“软件定时器”,运算便是中断服务程序(ISR)和定时管理程序。
软件定时器是“结构体”形式,根据定时应用的特点及分类,设计一种涵盖单次定时、多次定时和循环定时三种类型定时的软件定时器节点的数据结构,使用一个静态分配的软件定时器节点数组来定义所有的定时任务。
这个结构体有以下几个成员变量:软件定时器ID、激活状态、定时次数、超时次数, 循环标识,定时值, 计时值, 回调函数,这些成员变量的意义大多数可以“顾名思义”,这里便不赘述了。
下面开始叨ISR和定时管理程序。
ISR和定时管理程序是靠一个叫“相对计时时间”(记为Timer_TIcked)的信使扭结在一起的,它表示未被软件定时器计时的时间。
MCU上电初始化时,设置硬件定时器的中断周期为T并使能中断,硬件定时器以T为时间间隔,触发MCU执行ISR。在ISR中,累加相对计时时间的数值,累加值为T,即TImer_TIcked += T。
定时器管理程序完成对软件定时器节点数组的操作后,清零相对计时时间,所以,只要程序设计地合理,TImer_ticked不会很大,超过20ms基本可以确定您的程序设计有毛病了。
总之,通过相对计时时间,保证了所有软件定时器节点的同步计时和准确计时。
ISR当然简单,接下来便是稍微复杂一些的定时管理程序了。
定时管理程序是管理所有定时应用的,每个定时应用对应上述结构体数组里的一个成员,可以以“节点”来称呼它。
定时管理程序是在后台循环执行的,它每次都会检查所有定时器节点的状态,如果该定时器节点处于空闲状态,它就跳过它不做处理,如果处于激活状态,它就增加该定时器节点的计时值(累加值为Timer_ticked)。
然后判断计时值是否超过了所设定的定时值。如果没超过,那就跳过它不做处理,如果超过了,先调用它的定时回调函数,然后判断该节点是否为循环定时器。
如果不是循环定时,跳过它不做处理,如果是,则需要重启本定时器节点。
按照这种方法处理完所有定时器节点之后,便可以退出本次定时管理程序了。
讲到这里,各位看官应该看明白了吧.
四
小米手机物美价廉,没来由地担上了“低价误国”的骂名。国外的MCU厂商倒是鸡贼得很,一分钱一分货,资源丰富一点,价格就涨上去了,赤果果的资本家嘴脸。
所以,在成本的约束以及领导的威严下,在一个资源受限的MCU上捣鼓代码成了嵌入式软件工程师日常工作的常态。不过,不要抱怨,也不用忧虑和焦心,办法总比困难多。
总的原则就是:硬件不够,软件来凑。
比如对于多个定时应用,单定时器就足够!