分享一年的程序调试经验

不知不觉已经出来工作一年,经过一年的工作,使我学了不少东西,从而使我认识到以前很多不足之处,也想把自己的程序调试经验跟大家分享下。

首先是软件的编写环境,选择一个编译平台对于编写代码效率是至关重要的,在实际开发中,基本上使用Source Insight这个软件上编写和根改程序代码,本人现在使用的的是Source Insight3.5,这个软件功能非常强大,可以帮你快速定位代码、查看代码变量使用及各位置调用情况等信息。颜色管理也非常出色,根据颜色可以判断各个信息,比如变量是否定义、是局部变量还是全局变量等,可以说只要你使用过了就决不会再想在KEIL环境下编写代码了,当然程序很小有点感觉不出来,而对于程序量较大,且充分使用程序模块化,就是头文件的使用,定位程序的速度可以达到想到哪里就定位到哪里。熟悉后基本是使用各个快捷键进行操作,到那时KEIL就是当作一个编译器使用了。
KEIL建工程还是很有讲究的,假如代码比较大时,而工程全部又放在同一个文件里,那这个文件里的东西就像杂货间,找一个东西都难。如下建立一个工程简单keil工程,这样建的工程,在keil设置相关的头文件调用路径,清单与工程存放文件等设置后,整个工程的程序代码就跟keil工程文件独立了,这样就对代码的移植及备份带来很大的方便,当然还有分得更细的工程了。这样一来Source Insight工程里添加文件,SVN版本管理代码就方便了。
 
变量及函数的定义在一个工程里命名习惯是非常重要的,做到看到函数或变量名就可以知道变量和函数的意义及作用。我一般命令根据函数功能相关的关键字进行命名,而关键字与关键字之间用大小写区分,我英语也很差,但语法可以不懂,但专业英语的单词还是要会使用的。而变量定义能用结构体的尽量使用,比如时间就可以构建一个时间结构体变量,里面包含年、月、日、时、分、秒、星期,这样定义了一个时间就非常容易操作而且直观。
 
程序的调试是写程序最重要的环节,好的调试方法可以快速完成程序调试。以前调试就是要在板上设置一盏灯,不然程序跑到哪里出了问题都不知道,所以以前没灯都不知道怎么样去调试,但即使有灯调试,这样效率也是很低的而且实际中也不太现实。使用串口打印信息来调试程序,可以完全跟TUBRO C 2.0下的printf函数格式进行信息打印,如使用%d,%s、%f、%c打印各类型变量值,而这个功能函数就是debug.c和debug.h模块文件,在这里预编译发挥着重要的作用,可以根据自己配置的定义去控制打印的信息,当程序调试结束后就关闭打印信息,这样编译器就不会编译调试信息,这有就不用一个一个把调试代码删掉了,当要更改程序时,可以重新打开编译信息,这就充分使用了C语言里的预编译和DUBUG的使用,这就是为什么程序里存在调试版和释放版,而调试版程序运行时,往往在串口可以看到相关的信息。断言(assert (条件))也是检测程序里关键参数一个重要调试方式,但条件不成立时打印出错所在的文件下的第几行和错误条件信息。串口调试环境构建当使能调试时要开销一部分资源,不过现在单片机基本上有外扩RAM,从而使串口调试在51单片机上调试成为可能。
 
附:本人调试keil51时遇到打印char 类型出现了一些问题,比如char a=0X01,用printf(“a=%c\n”,a),串口会打印出a=0100, 用printf(“a=%d\n”,a),串口会打印出a=512,而keilARM里没出现,应该是51keil标准库的问题。
 
程序的屏蔽,以前最常用的是 “ // ”和”/**/”来注释掉程序,//是屏蔽掉一行的代码,当要屏蔽一段代码时就会使用/**/来屏蔽,但往往一些注释也用/**/来注释,如果在屏蔽段代码中刚好用/**/的注释,那是问题就出现了,以前就会把代码段里/**/该成//注释。现在就我们可以使用#if <条件> 一段代码 #endif来屏蔽一段代码,当条件为真时编译器编译代码,如为0则不编译代码,这样就容易多了。
 
前后台系统,写程序中处理单个任务在难的功能只算是一个功能,代码多容易写,当任务多个给且任务看似实时的,如数码管显示,按键操作、流水灯、点阵显示灯这样的任务放在一起的时候,就存在时间调配问题。这些我们按键按下时要马上反应、数码显示、点阵显示、流水灯都是要实时处理的,比如按键按下不能及时反应,要麻处理按键时显示停在某个状态,而这些现象在实际中是完全可以同时出现的,而你是看不的上面的现象,而处理这样的事件往往是*前后台系统运行起来的,而前后台系统就是看定时器来构建这个程序的软中断一样,比如单片机里的中断就是一个机器周期去查询中断的状态位,如符合中断,程序就会放下当前代码去执行中断代码,但按键、数码显示、点阵这些对人来说是时间很短的,但对于单片机来说是很长的,有了这样的思维后我们就可以构建一个由我们自己定的模拟软件中断查询周期,这个周期就是*定时器来设置中断间隔时间,而这个在定时器里处理的事件最好是占用时间短,比如计数、少数个赋值、状态判断及标记,然后后台(main()函数里的代码)就根据前台(TimerTnterrupt()函数里的代码)返回的标记状态进行处理相应事件。这就有点像操作系统的系统节拍,简称为系统的心脏。
永不止步步 发表于11-24 09:46 浏览65535次
分享到:

已有0条评论

暂时还没有回复哟,快来抢沙发吧

添加一条新评论

只有登录用户才能评论,请先登录注册哦!

话题作者

永不止步步
金币:67417个|学分:364041个
立即注册
畅学电子网,带你进入电子开发学习世界
专业电子工程技术学习交流社区,加入畅学一起充电加油吧!

x

畅学电子网订阅号