2007年7月毕业后,我嵌入深圳,在一家公司做软件方面的研发工作。一直刻苦努力学习,兢兢业业工作。
2008年春节刚过,我经历了的一个小小的项目,经过了一些挫折和错误,终于完成了任务。于是赛一赛自我总结,算是一个备忘,若还能给某些人提供一些参考价值,那就更是好上加好啦。(大家好才是真的好)
闲话少说,直奔主题。
那是2008年2月14日,过年后的第一天上班(情人节就开始上班,大家打工容易么?虽然没我啥事:)),小组直接领导找到我们,让我们接手一个关于键盘的事。此键盘非PC键盘,除了数字、字符键外,还有旋钮(编码器)、滑杆(需获取滑动电阻AD转换数值)、按键高亮、蜂鸣器等特殊应用。功能需满足在键盘上操作按键、旋钮、滑竿向上位机发送正确数据,并从上位机接收数据控制按键LED高亮和蜂鸣器响铃。是整个研发项目中的一小部分。因为负责该部分的同事另谋高就了,领导考虑到开年一时半会儿招不到人,招到人也得有一个熟悉过程,不如直接让项目组的我们熟悉。拜托,我写应用程序,硬件的,不咋会啊。。。
从同事那儿交接的资料包括:键盘设计说明书一份,已通电的键盘板,电路图,程序,芯片及其它资料若干。同事向我们展示了软件、仿真器、键盘板的连接方法,和现在已经实现的功能。他将键盘连接在PC上,打开记事本,按下数个数字键和字符键,好使;断点调试查看变量值,发现旋转编码器、滑杆也好使;接收数据部分只有程序,没有测试过。我暗自庆幸中,还好硬件已经调通,只用关心软件部分,这还较为拿手(卖瓜一个:))。可是,等等,怎么按键死机了呢?回头一看,同事早已消失了无痕。。。(挥一挥手,不带走一片云彩)
没法子,看程序吧。也许是搞硬件的人轻视软件,又也许是我的理解能力太差,我觉得这位老兄写的程序有些混乱:主程序里包含很多子程序、无缩进、数字常量遍地开花,重复代码也很多,出错也不知道是哪儿啊。但由于我对硬件编程不熟,还是修改程序吧。(悔恨与眼泪齐飞,激动共苍天一色。以后领导若让我带新人,我一定要让他/她看《高质量C++编程指南》先!)
首先,屏蔽其他子程序,单独测试数字、字符键盘矩阵扫描,挨个按键测试,发现按下Q键后,在按下其它键就出现莫名其妙的东东啦。于是打开《PS2协议中英文版》附录表PS2第二套扫描码,对比查看Q键对应的扫描码。发现这位老兄的扫描码矩阵是10进制数字表示滴(附录表为16进制),且跟硬件连接矩阵行列倒置,对照看得我有些难受,我改!VC里行列倒置、16进制输出,复制、查看。这下爽啦,三方对照,发现程序扫描码矩阵里有重复键1对,附录表里找不到而矩阵里出现的扫描码2个,Q键扫描码为0x15(10进制21)。附录上Q键扫描码为0x14,0x15是Ctrl键的扫描码,再看程序按键时发通码,弹起时啥也不发,按Q键后就相当于按下Ctrl键+其它键,而且Ctrl键永不弹起!难怪会出现好多没用过的系统键。《PS2协议中英文版》明确告诉我们一个键要发送通码和断码啊。我改!加入断码按键测试搞定。
接下来单独测试编码器扫描,老兄程序的状态机做的还是不错,从变量数值来查看,捕捉状态良好。但调试时,难道要领导看变量里一个个数值来判断正确与否?这太不体恤领导的时间和精力啦,呵呵。于是我加上编码器字符测试,左旋输出字符‘-’,右旋输出‘+’,打开记事本,旋转编码器,“---”、“+++”,不错,很直观。接下来测试接着AD转换,老兄毕竟是搞硬件的,考虑了滑动电阻AD转换的毛刺,所以采样后要与前一次采样比较,大于阈值才发送。(学到知识啦,以前写应用程序丁是丁,卯是卯,赋值为50圆怎么也不会自动变化为100圆。光知道有个volatile类型,也不知何时何地用)我如法炮制AD转换,以字符形式输出AD通道编号和AD转换数值,打开记事本,运行程序,插上键盘,拨动滑竿,记事本里飞速地输出字符。我晕,这速度,我不知道发了啥东东啊。想了想,加了0.2s延时,此时输出就好看多啦,比较拨动前后的两次发送,数值还真是有区别!(:)没区别就惨啦)组合起来测试一下,也能行。嗯,目前上位机还在调试中,不能向键盘发送数据,我也不知道在Window或Linux里如何发送数据给键盘,没法控制高亮啦。拨打内线888,请小领导莅临审核。
小领导踱着方步,缓缓入来,我先演示如何测试,小领导一看可以在记事本直接查看测试结果,也来了兴致。按键,好使;编码器,好使;滑竿,好使。我在旁边正暗自兴奋,这短时间能弄出来,鼓励与赞美之词应有两句吧。想时迟,手动快,领导的手在编码器上滴溜溜一转,“+”,n次旋转只出现一个状态。折子!我赶紧检查程序,发现我处理AD转换时延时了0.2s,这不把编码器扫描时间给占用了吗?我只好让领导也来单个模块测试啦。测试后领导说,编码器扫描要快,按键和AD转换扫描较慢,不必每次循环都扫描,得改进,而且要考虑接收上位机数据来控制LED和蜂鸣器。我汗,为图省事每次都扫描所有模块,确实霸道,但冲突也很多。(回忆起来,不是领导要求这么做的么?想到一个面试问题,如果你和你的上司在工作上有了冲突,你咋办?)我改!:b
在领导走后,我修改程序,使得每次循环扫描编码器,用定时器控制0.1s扫描一次按键,0.3s扫描一次AD转换。又加入按键按下LED高亮、弹起不高亮的测试,这样,不进记事本,我也能知道按键是否好使啦。键盘发送数据搞定啦,该考虑接收数据的事,可是没有上位机,无法向键盘发送数据啊。干脆接收PC启动检测键盘时发送的数据好啦。说干就干,循环发送键盘自检成功命令0xaa到PC,PC接收到后,采用老兄编写的程序接收。结果Windows系统启动后没有检测到键盘,且此时按键导致死机。有时还会连累USB接口的仿真器不能识别,据老兄告之,每次要先打开仿真器电源,再打开键盘电源,仿真器才能被识别。(我:/,起床还管别人先穿裤子还是先穿外套?后来才明白,这个比喻不对,这是一个先穿内裤还是先穿外裤的问题,一般是必须先穿内裤,才能套上外裤。当然也有先穿外裤,再穿内裤的,不过那是超人!)
看来问题在老兄写的接收模块程序没有作用,于是准备重写接收模块。打开《PS2协议中英文版》开始参考(这里先表扬翻译PS2协议的老兄,毕竟让中国人人可看中文版PS2协议;在这里也要批评一下这位老兄,您找的翻译校对不厚道啊,错字忒多),按照推荐方法写了个接收模块,结果还是收不到。为什么呢?继续检查程序,发现老兄写的延时子程序有些问题,没有考虑使用循环带来的额外时间开销,你想啊,一条指令耗时1us,用for (i=0; i<5; i++)来延时5us,这明显多了,光循环加上子函数调用就有6us。于是重新写延时函数,再看老兄写的发送模块,用他的延时函数却也能发送数据,这又是为什么呢?不管啦,把发送模块和接收模块按照推荐方法重写。先测试发送,正常。再重启及其测试接收,启动后查看接收变量数组,呵呵,收到了主机发送的数据。在我发送一次0xaa后,一直不理睬主机的情况下,主机还是发来了十数条信息(以后给未来的她发信息,打电话,她却一直不理睬时,我也能像主机那样坚持吗?)。
再次欢迎领导光临现场做测试示范,在我解释了修改和补充的东东,及何谓数据接收成功后,领导进行了测试,结果那是相当的成功!领导讲话:“接下来要定义好每个操作的扫描码,并准备好接收数据定义格式,提供给上位机,应用程序也要结合定义的扫描码做相应的消息修改,等到上位机可测试后进行联调,到时肯定还会再调试的。”呵呵,应用程序的消息机制同事已经把宏定义弄好,换个键码而已。倒是和调试上位机的领导沟通一下接收数据定义格式和应用程序写数据格式较为重要,还要根据上位机与键盘合作方式发送和接收数据。(沟通很重要噢,不管跟领导,还是跟那个谁)
联调中,前端板、数字板、键盘板、应用程序一起上阵,那是一个历史性的时刻,何其壮观(大家鼓掌)。键盘发送数据没啥问题,我抽空测试了键盘接收数据。领导的经验果然丰富,问题出现。上位机发送多于1个字节的数据,键盘只能接收到1个字节。这是为什么呢?我有经验啦,应是延时问题。让上位机每次发送1字节数据延时1s测试,果然都能收到。(键盘慢啊,有哲人说思维比键盘还慢!)最后调试到上位机每次发送1字节数据延时0.1s,键盘也能正确收到数据。LED高亮也能控制啦,蜂鸣器也好使啦。就是键盘下面顶着一个仿真器,操作时难受啊,而且也不方便调试其它部分。于是申请烧片。(房子、车子、票子都准备好了吧,咱领证去。)
一切准备妥当,生成bin文件,烧片,上电,按键正常,旋钮正常,滑竿正常,LED灯高亮,蜂鸣器响铃,键盘正常,中国正常,地球正常。那一刻,我感到无比激动与骄傲。在半边天节日到来的前夕,我要将我的成功献给她们,祝愿所有认识和不认识的妇女节日快乐!那一刻,我不是一个人在战斗!
小领导走过来,拍了拍我的肩膀,道:“小z,干得不错!下个版本的键盘设计文档,你就用这个键盘敲入好了。”看着一脸坏笑的领导,想起没有机打功能、没有系统功能键、只响应单个按键、每次按键嘟嘟响、手感不咋地的硅胶按键,我*&^%$#@*
后记:为了测试键盘的稳定性和健壮性,为了迎合领导,为了练就‘一指残’神功,我花了72小时,用那个键盘敲入了上面这些文字。键盘仍旧默默的工作着,我的一指打字神功也修炼到了第九九八十一层。。。:)
断断续续3周,通过修改程序,调试键盘,觉得学到了不少东东。最后总结道:有项目做真幸福啊!