原创 Keil C51 总线外设操作问题的深入分析

2009-8-13 19:30 1572 6 6 分类: 医疗电子

阅读了《单片机与嵌入式系统应用》2005年第10期杂志《经验交流》栏目的一篇文章《Keil C5l对同一端口的连续读取方法》(原文)后,笔者认为该文并未就此问题进行深入准确的分析。文章中提到的两种解决方法并不直接和简单。笔者认为这并非是 Keil C51中不能处理对一个端口进行连续读写的问题,而是对Keil C51的使用不够熟悉和设计不够细致的问题,因此特撰写本文。电子园51单片机学习网%s'u|zk$u,zR
电子园51单片机学习网)Q\x Z_z:[ RT
    本文中对原文提到的问题,提出了三种不同于原文的解决方法。每种方法都比原文中提到的方法更直接和简单,设计也更规范。(无意批评,请原文作者见谅)电子园51单片机学习网(aj+f.\,N]



HAiE+h S5M'zk2G446061 问题回顾和分析
r D'x"h;D\ va44606    原文中提到:在实际工作中遇到对同一端口反复连续读取,Keil C5l编译并未达到预期的结果。原文作者对C编译出来的汇编程序进行分析发现,对同一端口的第二次读取语句并未被编译。但可惜原文作者并未分析没有被编译的原因,而是匆忙地采用一些不太规范的方法试验出了两种解决办法。电子园51单片机学习网N2w5@.aw)\
电子园51单片机学习网ZoMg3G:HN ~
    对此问题,翻阅Keil C51的手册很容易发现:KellC51的编译器有一个优化设置,不同的优化设置,会产生不同的编译结果。一般情况缺省编译优化设置被设定为8级优化,实际最高可设定为9级优化:
4~1O.PML#n0}p44606    ①Dead code elimination。
W? C V*b:D44606    ②Data overlaymg。
K#MAs/QiLTN44606    ③Peephole optimization。电子园51单片机学习网 W3fA2q3\XW9J5G7C$|-g
    ④Register variables。
/z'W+OS? _+uo`44606    ⑤Common subexpression elimination。电子园51单片机学习网w6ksqi(z_2ys
    ⑥Loop rotation。
0f d+SL9pt44606    ⑦Extended Index Access 0ptimizing。
*D"D5[ud44606    ⑧Reuse Common。Entry Code。电子园51单片机学习网,}aY p]-n ?:S
    ⑨Common Block Subroutines。
*D zd F {/sD44606电子园51单片机学习网5k|y~ b4I0]7L H
    而以上的问题,正是由于KeiI C5l编译优化产生的。因为在原文程序中将外设地址直接按如下定义:电子园51单片机学习网 T.U7[&?W*^
    unsigned char xdata MAXl97_at_Ox8000;
!kiu X"i5Z5D44606电子园51单片机学习网`g L0[,lL"A
    采用_at_将变量MAXl97定义到外部扩展RAM指定地址Ox8OOO。因此,Keil C51优化编译理所当然认为重复读第二次是没有用的,直接用第一次读取的结果就可以了,因此编译器跳过了第二条读取语句。至此,问题就一目了然了。电子园51单片机学习网8HxOJ[ _2Ps



p+k\4pjuvM446062  解决方法
6g0hV,cE$rI(M44606    由以上分析很容易就能提出很好的解决办法。
:Sx;p!_+B/Xf44606电子园51单片机学习网l|e;p1s2h p6P
2.1  最简单最直接的办法

N8B2N#kSh1U:a44606    程序一点都不用修改,将Keil C5l的编译优化选择设置为0(不优化)就可以了。
|8bq:r+HHhqGfc44606    选择project窗口的Target,然后打开“Options forTarget”设置对话框,选择“C5l”选项卡,将“Code Optimiztaion”中的“Level”选择为“0:Costant folding”。再次编译后,大家会发现编译结果为:电子园51单片机学习网!c0e*_2L.Kb,qN ^Oas"J
    CLR MAXHBEN
X#[~"]`t44606    MOV DPTR,#M.AXl97
R \^ D7~ A"B:CMm44606    MOVX A,@DPTR
_:e vEL#wf5["cE F44606    MOV R7.A电子园51单片机学习网2q dXI*S:v
    MOV down8.R7电子园51单片机学习网.wq#qfw ^h+\0n
    SETB MAXHBEN
9X;K)Nn{B!LY U%r@44606    MOV DPTR,#MAXl97
W8lCm#nD44606    MOVX A,@DPTR电子园51单片机学习网3u"@:` x#s I!H Fxnq
    MOV R7.A
X;N.@&SA3lb,P/W44606    MOV uD4.R7
iA Cd2_4M/D44606    两次读取操作都被编译出来了。
9^%An4\E%e'|X)Z44606
qU4H(~0h*Zc446062.2  最好的方法
电子园51单片机学习网F/G/nj3B6RE
    告诉Keil C51,这个地址不是一般的扩展RAM,而是连接的设备,具有“挥发”特性,每次读取都是有意义的。电子园51单片机学习网-z3W3M;p x9^ l[

*}8Ja1WJbhn%CH!B8L44606    可以修改变量定义,增加“volatile”关键字说明其特征:
|~c!A/O z44606    unsigned char volatile xdata MAXl97_at_Ox8000;
9[~ s N1jC!A8aAP44606电子园51单片机学习网:h^$R*w|K
    也可以在程序中包含系统头文件:“#incIude<ab—sacc.h>”,然后在程序中修改变量,定义为直接地址:
S+cbqC1^)k44606    #defme MAXl97 XBYTE[Ox8000]

yZ}.h#J$uM'w^6w44606


;\,a7?Xv1g[44606    这样,。Keil C51的设置仍然可以保留高级优化,且编译结果中,同样两次读取并不会被优化跳过。电子园51单片机学习网%Q(|#{2vLD jz

$IP&o2h0zKCNu446062.3  硬件解决方法
电子园51单片机学习网6z*zU-z R%[J3QG^
    原文中将MAXl97的数据直接连接到数据总线,而对地址总线并未使用,采用一根端口线选择操作高低字节。很简单的修改方法就是使用一根地址线选择操作高低字节即可。比如:将P2.0(A8)连接到原来P1.O连接的HBEN脚(MAXl97的5脚),在程序中分别定义高低字节的操作地址:电子园51单片机学习网 d'B-|.c;l!e CG1p'b
    unsigned char volatile xdata MAXl97_L_aI_Ox8000;电子园51单片机学习网1FH)^ [:ss9v
    unsigned char volatile xdata MAXl97 H at 0.x8100;
|Vn0W9zl/K4KJ[44606    将原来的程序:
N-@5c5U J.z5sx}kA44606    MAXHBEN="O"; //读取低8位
IM lt{l^1I44606    down8=MAXl97:电子园51单片机学习网p$U2nP9SI6F
    MAXHBEN="1"; //读取高4位
{;[yv&FO%l:I44606    up4=MAXl97:
${7?v'VX!y"GAs6c5q44606    改为以下两句即可:电子园51单片机学习网[~ D&P7]_
    down8=MAXl97_L; //读取低8位
L1e2LR`z44606    up4=MAXl97_H; //读取高4位

9V {LXR2QRI44606


yO yQ}*`%m0g446063  小结电子园51单片机学习网;J-xkI H1@p
    Keil C51经过长期考验和改进以及大量开发人员的实际使用,已经克服了绝大多数的问题,并且其编译效率也非常高。对于一般的使用,很难再发现什么问题。笔者曾经粗略研究过一下Keil C51优化编译的结果,非常佩服Keil C51设计者的智慧,一些C程序编译产生的汇编代码,甚至比一般程序员直接用汇编编写的代码还要优秀和简练。通过研读KeilC51编译产生的汇编代码,对提高汇编语言编写程序的水平都是很有帮助的。
d(@` iF7E44606电子园51单片机学习网r*t?Ru;Wsh
    由本文中的问题可以看出:在设计中遇到问题时,一定不要被表面现象蒙蔽,不要急于解决。应该认真分析,找出问题的原因,这样才能从根本上彻底解决问题。上不会出现不必要的干扰,防止了数据不一致的发生。

p!{v{Z&Lh&C1G44606
PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
6
关闭 站长推荐上一条 /3 下一条