6.Pic单片机C语言程序SIM软件仿真技巧(2)
鉴于C 语言模拟仿真(SIM)在学习C 语言程序时十分有用,这里笔者再进一步讨论模拟仿真的更多功能。
⑴ 模拟仿真C 程序运行的全过程,如果想要仿真查看《PIC 单片机C 语言设计程序(8)》Pic07.C 中的程序的全部运行过程(0 ~ 99 的增量),是十分困难的,其原因是,主函数voidmain( ) 要调用显示函数display(x),而该显示函数为了完成X++ 的0 ~ 99 任意一个增量(△为1 秒)的显示,则要通过循环语句while(d>0)进行d-- 的100 次循环(因d=100),模拟仿真这种循环太费时。且在该循环语句while(d>0)中, 又要调用延时函数delay(200), 使仿真更复杂。尽管这种仿真可以在MPLAB IDE 中完全正常运行,但是操作者等待时间太长。解决上述问题的最佳方法, 是改写程序pic07.C 中的一些参数,以快速完成程序模拟仿真的全过程。改写程序仍在MPLAB IDE(较高版本)集成环境下进行,改写的原则是不能减少C 程序的代码数(量),仅改写其中少数参数值(值大的),即不改变程序的整体工作模式。比如,将pic07.C显示函数中说明语句unsigned int d=100, 的d 值改为3,d 值决定0 ~ 99 每个增量的时间,d=100,增量时间约1 秒, 同一循环操作时间大大减少,以便我们进入程序的其他运作。又如,将pic07.C 循环语句while(d>0) 中的延时( 调用)delay(200) ;改为delay(4), 将无限循环语句while(1) 中调用显示函数display(x) ;中的if(x==99) 改为if(x==4)。这样整个程序的逻辑功能操作,便可较快地通过模拟调试全部完成。经上述改写后的程序重新命名为pic07a.C,其清单如下:
改写后的pic07a.C 的功能,是0 ~ 03 的增量循环计数,其增量耗时很短( 不再是1 秒)。
将pic07a.C 按照《PIC 单片机C 语言设计程序(8)》和《PIC 单片机C 语言设计程序(9)》中所述, 在MPLAB IDE 中存盘, 再进行编译,编译成功生成目标码。hex 后,便能对其进行模拟仿真操作了。
(1) 根据《PIC 单片机C 语言设计程序(10)》所述,建立模拟仿真调试环境,pic07a.C 源程序编译成功, 在MPLABIDE 窗口中, 点击Debugger( 调试命令)→ Selec TooL…… 的方法, 把pic07a.C 设置成仿真调试状态,再快速点击模拟调试快捷图标中的Animate( 动画运行) 和Hate( 停止), 则在pic07a.C 主函数main( ) 以下的TRISA=0X10 ;的左边,会出现一黄色箭头,如图53 所示。该箭头是C 程序运行的起始位,即程序运行总是从主函数开始的。
图53
(2)程序运行全过程,点击图53 中模拟调试快捷图标的step lnto(单步运行),你会观察到,鼠标每点击一次step lnto 命令,图53 中的黄色箭头会沿着C 程序代码运行一次,我们只需用鼠标一次一次地点击step lnto 命令,黄色箭头就沿着主函数以下的C 代码一步一步地运行。
当点击step lnto,使黄色箭头到达while(1)语句时,程序的运行就进入到while(1) 语句的无限循环区域,这时,程序仅在while(1) 区域运行,不再返回主函数(除非复位)。下面看看,程序在while(1) 中是如何运行的。
继续用鼠标一步一步点击step lnto, 一旦黄色箭头到达调用显示函数display(x) ;,黄色箭头就会跳转到显示函数void display(unsignedint x)的说明语句中运行。注意:按上述单步运行,当黄色箭头到达unit_bit=x%10;(送个位数显示)时,因它和下一条代码ten_bit=x/10%10(送十位数显示)的操作耗时太长,用step lnto 命令难以进行,应改用模拟调试快捷图标中的命令stepover(单步越过),即点击两次step over,黄色箭头就运行到while(d>0) 语句。然后又用steplnto(单步运行),即一步一步点击step lnto,黄色箭头就沿着while(d>0) 中的C 代码运行。当运行到调用延时delay(4) ;时再点击step lnto,黄色箭头转到延时函数Void delay(unsignedlong int k) 中进行延时功能操作。因delay(4);的形参数为4,所以标点击step lnto 命令应4 次,才能跳出延时操作功能,此后黄色箭头又回到RA3=1 ;代码,依序用鼠标一步一步点击steplnto 运行,黄色箭头又运行到调用延时delay(4)时,又转到前述延时函数进行延时功能操作,也是点击step lnto 命令,又是 4 次,才能跳出延时函数。按上述规律,当黄色光标箭头运行到自减量d-- ;时,d 值从3 减1 得2,while(d>0)语句中d 仍大于0, 黄色光标箭头再次回到whila(d>0) 中的代码中, 点击step lnto 命令重复上述程序运行过程,直到d-- ;从3 减到0,黄色箭头跳出while(d>0) 语句, 回到while(1)语句中的x++ ;使x 值从0 增量到1。再用鼠标点击step lnto,黄色光标箭头到达if(x==4) 语句,判断x 是否等于4,若不为4(此时x 等于1),黄色光标箭头随鼠标点击step lnto 又回到调用显示函数display(x) ;中运行。按上述方法重复操作,当x++; 自增量等于4 时,由if(x==4) 条件语句引导给x 赋值0,即x=0 ;pic07a.C 程序中的x++ 的0-4 增量计数全部完成。上述C 程序运行全过程,读者应反复熟练操作。
⑵ 模拟仿真找出pic07.C 程序的错误pic07.C 的功能, 是0 ~ 99 增量计数( △ 为1 秒)。初看程序while(1) 中的x++ ;条件是if(x==99) 时给x 赋值0(x=0;),即能完成0 ~ 99的计数功能。可事实上,如果将pic07.C 进行编译生成目标码。hex,再用PIC编程器将该目标码烧写到PIC16F84A芯片中, 用《PIC 单片机C 语言设计程序(4)》中的电路图3 的实验板通电观察两位数码管显示时,循环计数显示的是0 ~ 98 而不是0 ~ 99(约1 秒)计数。实验说明,pic07.C 程序没有达到设计要求,程序中有错误。
下面我们一起来通过模拟仿真找到该错误点并进行修正。
具体操作过程如下:
在MPLAB IDE 中, 按照《PIC 单片机C 语言设计程序(11)》中介绍的方法, 点击debugger, 在下拉菜单中将stop watch( 跑表)调到图53 的窗口中(时钟频率为4HZ),再点击MPLAB IDE 中的View, 在下拉菜单中点击Locals(局部变量), 将Locals 界面也调到图53 窗口中,用鼠标调整各界面后的显示界面如图54 所示。图54 中的Locals 界面上显示有Address(地址)、SymbolName( 符号名或参数名) 和Valua(取值)。
图54
在进行下面的模拟调试时注意观察,会看到Locals 界面各参数随调试运行显示。按照前述方法,对图54 中的程序(pic07a.C)进行全过程运行。用鼠标一步一步点击模拟调试快捷图标中的step lnto,一旦程序旁边的黄色箭头运行到显示函数Void display(unsigned int x) 以下代码时,图54 中的Locals(局部变量)就会出现pic07a.C 参数相关的显示值,见图55。
图55
symbol Name(符号名)为ten_bit(显示十位数),unit_bit( 显示个位数、d(unsignenint d)、SEG7(7 段码) 和X( 自增量) 的Address( 地址) 分别为0010、0012、0014、0016 和000E。这些Value(值)由程序运行决定。Locals(局部变量)界面显示的,实际上是pic07a.C 程序主要参数,可帮助用户了解程序的重要功能参数随程序运行(黄色光标指示)的变化,而这些功能参数正是增量计数时所需的数据。只要按照上述方法,对该程序进行全功能运行, 直到X++ ;自增量为4, 即满足了if(x=4)的条件,此时X=0 ;(给X 赋值0), 再用鼠标点击step lnto,Locals 的界面演变成图56。从图54 可清楚看出:只要X++ ;(自增量)满足if 语句的条件,就会给X 赋值0,这里X++ ;一旦为4,就给X 赋值0,所以程序再运行时,回到调用显示函数display(x),其中X 已为0,再运行,其个位unit_bit 显示即为0,而不会是X++ ;的4 值, 如图56 中的unit_pit(个位)只能为3。
图56
程序再运行,显示又从0 开始直到0 ~ 03 为止。
由此可见,对于pic07a.C,当X++ ;自增量为4 时,会立刻因it(x==4) 的条件而导致X=0,所以程序运行显示时,只会从unit_bit ;的3 回到0,而不可能使个位显示X++ ;自增的4 值。按上述逻辑过程,对Pic07.C,当其中的X++ ;自增为99 时,同样会由if(x==99) 的条件满足而使X=0 ;程序运行时,只能是显示98 后即清零,不可能显示99。如果想满足0 ~ 99 的增量显示,必须将条件语句if(x==99) 改为if(X==100)⑶ 模拟仿真优化C 程序代码利用模拟仿真,可对C 程序中的代码进行优化(即去掉多余的代码),以简化程序而不改变其功能。当然,优化后的程序还应通过最后的实验验证。例如pic07.C 的延时函数Void delay(unsighed long int k)可优化为Void delay(unsighed int k) 而不需要long 的条件,因为int k 的定义范围已满足了程序中delay(200); 即K=200 的要求。受版面限制,笔者不再介绍此程序的优化过程。总之,利用MPLAB IDE 7.40 开发环境进行程序的SIM 模拟仿真,对初学C 语言是十分有用的,大家必须熟练掌握其操作方法。