玩转单片机有几年的时间了,从接触51开始就走上了看不到尽头的程序员之路。也许大多会认为,敲了几天几夜代码将作品或者项目完美完成的那一刻是最开心最得意的时候。我却认为,真正快乐的是与Bug斗争的过程,最后完成作品或项目只是这种快乐的终点。那么我们该怎么去对待Bug才能做到,游走在Bug世界里享受无尽的快乐。
本文引用地址:http://www.eepw.com.cn/article/158899.htm。
一些高手在程序的编写方面都有了自己的风格,可以将程序做很好的规划。以缜密的思维构造程序架构,以编程规范来打造程序的外观。Bug已经在高手面前无所遁形。所以Bug只是高手们用来愉悦的玩物。用来享受那一刻的征服感。为了让菜鸟也能享受其中的快乐,我分享一下自己的经验,让大家能在程序员这条路上走的快乐,而不是整天熬夜带来的孤独感,菜鸟入门通常以89c52单片机入门,那么我就针对这个讲讲如何破Bug。
1.装上摄像头定点监控
找出Bug就像找小偷一样,我们需要在程序中装上多个摄像头,当程序出现问题时我们可以知道是在哪一个地方。这点是相当的实用,对于无法仿真的51单片机,要了解程序内部运行的状态和变量现在的值,就显得很无语,简直束手无策。那么就请加入串口程序的代码,利用串口将一些重要变量的值或者信息发送到上位机上进行观测。这样就像是在各点装上了摄像头,而监控画面就是我们的上位机软件。串口的收发程序都有成熟的模块所以初学者也不用担心用不了的问题。现阶段如果写不出来就直接COPY来用用反正也不用钱,所以在调试的时候要充分发挥串口的作用,让问题变得清晰明了。用的最多就是发送字符串,发送16进制数据和十进制数据。列举一个小小的例子:
例一:感觉程序中是没运行到子函数A中。
那么就不要只感觉了,就在A中放上一个摄像头用来监控此处。在子函数A的开头加一句发送字符串的程序:
UartSendString(“现在进入函数A了哦!\n”); //发送到上位机看是否运行了函数A。
这样大家体会到摄像头的作用了吧,时刻掌握程序运行的状况。让Bug逃不出手掌心。
2. 清晰的路标
所谓清晰的路标的第一个意思就是在程序中加入详细的注释,在追捕Bug中我们要看路标,分析他会逃串到哪里。单片机编程就是一个逻辑思维。我一直将89C52单片机看作是一个没头没脑只有几十个脚的小笨蛋。这个小笨蛋能完成各种小制作是靠什么呢?当然是靠我们伟大的程序员来给他灌输思想,告诉他如何去运用自己的几十个脚。当测试当中这个小笨蛋没有按照我们的想法去做事,那么就肯定是哪里的逻辑出现了问题。这个时候程序的注释就体现出了优势。我们按照自己写下的路标来将整个路程走一遍,看是否有什么漏洞导致迷路。那么整个运行过程就无法逃离自己的掌握之中。这点就不举例了,大家在实践中体会吧。只需要将程序看作一条路,自己在头脑中走一边就行。
清晰的路标除了指程序中的注释还指每个变量和每个函数的命名清晰明了。这就是所说的程序规范。如果程序规范了,就好像是给了程序一个铁的纪律。程序可读性提高,看起来也美观。可以说每个人写程序都有自己的风格,如果是刚接触单片机的童鞋就不一定了。变量总是i和j或者来几个k , y , z。函数名都有可能是void abc(); 如果真这样,那就悲剧了。这样调试的时候很迷茫,程序的直观性不好。在调试中还要不停的跳转到对应的函数来看看这个到底完成的是个什么功能。我给大家两个小建议吧,如果现在还没有规范自己程序的童鞋可以借鉴一下:
(1)函数名和变量名尽量用英文单词组成或者其缩写组成。我列举几个ucGUI里的一些函数名:GUI_DispStringAt(); GUI_DrawHLine(); GUI_Clear(); GUI_SetColor(); 有了很规范的命名,大家只学要看到函数名就知道这个函数是什么功能。变量名我也列举ucGUI里面的几个GUI_RED ,GUI_TM_NORMAL。大家看变量名也可以知道是什么意思。这个就是规范了函数名和变量名的好处
(2)如果是指针变量前面加个p,如果是全局变量前面加个g。变量名由几个单词组成的中间加上“_”来隔开。
说到这里,我们只是做了对抗Bug的一个前期准备。只要做好上面几步,那么亲爱的菜鸟就可以不用对51单片机的Bug产生恐惧,接下来就是你玩弄Bug的过程了。有人说些程序的人本身就有一种霸气,一种渴望征服的愉悦感。因为程序员可以控制一样东西完全按照自己的思维去运行。我个人也是这么认为的。所以做好上面几步,你就可以将程序看作是你手中的玩物。我总结了几条针对51单片机对抗Bug的技巧:
(1)在重要的点放上摄像头UartSendString(“提示的内容”);
(2)对于变量的观察就将数据发送到上位机观察。
(3)碰到卡死现象可以按照(1)的方法,将发送提示信息的函数多放几个地方来了解程序运行的情况
(4)如果是逻辑上的错误就好好回顾一下程序,通过注释再来理清思路,找Bug游戏不能心急。
(5)要定点检查一个地方可以加入强制卡死while(1);
3. 后续工作
通过上面的两点基本上可以找出程序中的Bug,既然找出来了,只要对症下药,除掉他必然不是难事。如果自己除不掉也可以找度娘和各种论坛,因为你现在知道了明确的问题,可以有针对性的去找解决的办法。那么程序都调试完成了,但是程序中还余留下一些我们调试时候的残渣,这个怎么办的。那么就要使用一些小技巧怎么一次性清楚所有的摄像头呢?
在程序中可以这样写:
在程序的开头或者头文件里定义:#define HAPPY_DEBUG
在程序调试时加入摄像头就按照如下的格式:
#ifdef HAPPY_DEBUG
UartSendString(“现在进入函数A了哦!\n”);
#endif
写程序是很短的时间,调试程序是一个漫长的过程。只有做好前期的准备后面依靠自己的调试技巧,就能玩弄Bug于鼓掌之中,而不是被Bug搞的头昏脑胀。找出Bug的那一瞬间就是快乐,解决Bug的那一刻更是兴奋。这就是与Bug斗争的快乐所在。在孤独的程序员道路上我们也要寻求自己的快乐,这就是其中之一。