手机c51编程语言,对“C51语言应用编程的若干问题”

1 对C51中定时/计数器赋初值算法的补充

《力源电子工程》1999年第3期《C51语言应用编程的若干问题》一文的例3中,用下述方法为T0赋初值,使T0在启动后满1000个机器周期时产生中断申请:

TMOD = 0X01

/*T0工件在定时器方式1,为16位*/

TH0 = -(1000/256)

TL0 = -(1000%256)

1.1 赋初值算法问题的验证

这种算法(以下称其为新算法)比较新颖而且方便,不同于传统的算法。但经过验算,发现这种算法有一个漏洞,会引起定时或计数的严重错误,仍以本例进行验证如下:

新算法:

TH0

=-(1000/256)

=-(3)

= 0XFD

TL0

=-(1000%256)

=-(232)

= 0X18

传统算法:

2^16 – 1000 = 64536 = 0XFC18

即:

TH0 = 0XFC

TL0 = 0X18

两种算法得出的TH0值相差1。

若使T0在启动后1024个机器周期时产生中断申请。

新算法:

TH0

=-(1024/256)

=-(4)

= 0XFC

TL0

=-(1024%256)

=-(0)

= 0X00

传统算法:

2^16 – 1024 = 64512 = 0XFC00

即:

TH0 = 0XFC

TL0 = 0X00

则两种算法得出的值完全相同。

经观察发现,当TL0 = 0X00 时,新算法得出的结果是正确的,否则,必须将新算法得出的TH0的值减去1,才能得出正确的结果。

在所需机器周期数大于256时,这种错误将使中断提早到达256个机器周期;

在所需机器周期数小于256时,TH0应为0XFF,新算法得出TH0=0X00,将会使中断迟到(0XFF-0X00)* 256=65280个机器周期。

在所需机器周期数等于0时最甚(当然,在实际编程中不会出现这种情况,但为严谨起见,对其进行论述),中断将会迟到65536个机器周期。

证明:

为方便理解,仍以16位的定时/计数器为例,对13位的定时/计数器仍可以用下述方法进行证明(见1.3适用范围一节)。

设X表示定时/计数所需的机器周期数

设A = X/256(本文中X/256均指X除以256舍尾取整);B = X%256。

1. 当X>256时

新算法的计算过程中

TH0 =-(X/256),实际上是TH0 = 256-(X/256),因为TH0是8位长度,它的值不超过255。

TL0 =-(X%256)是同样道理。

则新算法的计算过程可表示为:

TH0TL0 =(256-X/256)* 256 +(256-X%256)

=(256-A)* 256 +(256-B)

= 65536-256A +(256-B)    (1)

式(1)中(256 – B)即 TL0 的值。

传统算法的计算过程可表示为:

TH0 TL0 = 65536-X

= 65536-[(X/256)* 256 + X%256]

= 65536-256A-B   (2)

可以看出,新算法确实比传统算法的正确值多了256,也就是说,TH0的值应减去1,只有当式(2)中B=0时,在新算法中则:TL0 =-(B)=0,即式(1)中的(256-B)=0,此时式(2)与式(1)才相等。

2. 当X<256时(A=0)

新算法的计算过程可表示为:

TH0TL0 =-(X/256) * 256 + 256-X%256

= 256-B     (3)

传统算法的计算过程可表示为:

TH0TL0 = 65536-B      (4)

新算法的结果比传统算法结果小65280,若将其TH0减去1变为0XFF,则为正确结果。

3. 特例,当X=0时(A=B=0)

新算法的计算结果为:

TH0TL0 = 0X0000      (5)

传统算法的计算结果为:

TH0TL0 = 0X10000(实际上不可能) (6)

两者相差65536。

1.2 产生问题的原因分析

(1) 分析产生这个问题的原因,可先从定时/计数器的工作过程入手。

新算法中

TH0 =-(X / 256)

TL0 =-(X % 256)

其主观意图是在TH0中装入0X100H(即256)减去X/256的整数部分得出的差ΔTH0,使TH0控制计数ΔTH0* 256个机器周期T(或输入ΔTH0* 256个计数脉冲),TL0也同理;然而当TL0≠0时,定时/计数器在启动后的(256-TL0)个机器周期T后即向TH0进位。按前面所说的主观意图来理解,则是在TH0中记录下“已计满256个机器周期T的时间或256个输入脉冲”的信息。也就是说:TL0所设定的(256-TL0)个机器周期T,错误地使TH0(应记录整数个256T)“跳数”(加1),将使定时/计数器产生非预期的中断申请。

所以当TL0≠0时新算法得出的TH0值应减去1,则可以避免此错误的发生。程序应以如下形式:

TH0 =-(X / 256)

TL0 =-(X % 256)

if (TL0<>0) TH0- -;

相反,当TL0=0时,TL0计数满后向TH0进位正是新算法的本意,所以不会发生定时/计数错误。

上面分析了当X>256时的情况(A>0),当X<256时,A=0,新算法得出TH0=0,显而易见应为TH0=0XFF。

(2) 简单地说:新算法是把传统算法的0X10000-hhll(hhll=X)当作(0X100-hh)赋给TH0,(0X100-ll)赋给TL0来计算,当ll=0时,(0X100-ll)=0X100,没用向0X100的最高位“1”即TH0借位;当ll≠0时,要发生借位,传统算法中有这一过程,而新算法则丢失了这个借位,所以会在TH0中多出1来。

之所以要从不同角度进行分析,是因为在实际编程中,我们可能会从不同角度出发确定算法,经过上述分析,可以避免类似失误的发生。

1.3 适用范围

当定时/计数器工作在模式0时,将算法中的256替换为32,使用如下语句:

TH0 =-(X/32)

TL0 =(-(X%32))& 0X1F

if(TL0<>0) TH0--;

则同样适用上述结论。文中以定时/计数器0 的定时器方式为例,但对定时/计数器1以及它们工作在计数器方式时也是适用的。

2 对C51条件编译语句#if…用法的订正

《力源电子工程》1999年3期《C51语言应用编程的若干问题》一文中有下述宏定义与条件编译例子(例1):

#define flag 1

#ifdef flag==1

#define fosc 6M

delay=10;

#elif flag==0

#define fosc 8M

delay=12;

#else

#define fosc 12M

delay=20;

#endif

main()

{

for(I=0;I

}

经实际运行,发现“#ifdef flag==1”一句似有不妥,为叙述方便起见,设有如下情形。

1. 情形1

#ifdef 标识符

该条件编译语句当并且仅当 “标识符” 曾被“#define”语句定义过(如果有“# undef 标识符”语句则在其前面)时为TRUE,即使如下形式也是如此:

#ifdef 标识符 == 常量 亦即:#ifdef 常量表达式。

2. 情形2

#if 标识符 == 常量 亦即:#if 常量表达式

该条件编译语句当并且仅当 “标识符 == 常

量”为TRUE时,为TRUE。

所以在上述例子中“#ifdef flag == 1”的值将永远为TRUE,不论“flag == 1”是否为TRUE。

根据程序目的可知,这一句应为:

“#if flag ==1”。

另外,在Franklin C51 V3.20编译系统目录OMF51\EXAMPLES\DCLOCK.C 中有如下一段:

#ifdef CPU==8051

#define SECOND (4000/(12/FREQ))

#else

#define SECOND (200/(12/FREQ))

#endif

在此段前没有出现对“CPU”的定义,实际上, #ifdef CPU==8051

一句是不合理的。其值等于 #ifdef CPU

而非

(#ifdef CPU) && (#if CPU==8051)

特别指出,在参考文献2第128页的例子中,也出现了

#ifdef CPU==8051,这一语句。

上述结论作者经过Franklin C51 V3.20编译验证。

参 考 文 献

1 张毅刚, 修林成, 胡振江. MCS-51单片机应用设计. 哈尔滨:哈尔滨工业大学出版社, 1990

2 徐爱钧, 彭秀华. 单片机高级语言C51应用程序设计. 北京:电子工业出版社, 1998

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值