最近单片机课讲到了守时计数器,在C语言中守时计数器的初值能够选用这种办法(假定计数10000次)TH0=(65536-10000)/256;TL0=(65536-10000)%256;这是通用的办法,65536-10000=55536=0xD8F0;赋值后TH0=0xD8,TL0=0xF0。我联想到补码的规矩,65536-10000的数值在核算机中和-10000数据存储是相同的,所以我就简略赋值为TH0=(-10000)/256.;TL0=(-10000)%256;能够少写一个数据,削减敲字的作业。我就这样给学生讲了。这两种办法都能够。
在一天李老师看到我的学生作业都是写TH0=(-10000)/256.;TL0=(-10000)%256;她说-10000或许运用不对。当天晚上的时分在QQ上发消息过来说,经验证,在Keil中,TH0=(65536-10000)/256;TL0=(65536-10000)%256;的赋值办法TH0=0xD8,TL0=0xF0。可是TH0=(-10000)/256.;TL0=(-10000)%256;的赋值办法TH0=0xD9,TL0=0xF0。TH0的数值总是要大1,并且取不同的数值验证均是这个成果,两种办法TH0总是相差1,而TL0数值是相同的。我翻开Keil,输入程序,然后调试检查汇编指令,得到如下成果:
8: TH0=(65536-10000)/256;
C:0x009B 758CD8 MOV TH0(0x8C),#0xD8
9: TH1=(-10000)/256;
C:0x009E 758DD9 MOV TH1(0x8D),#0xD9
发现汇编指令直接关于TH0和TH1进行赋值,没有通过任何的运算,可是便是相差1,这是为什么呢?我无法了解,后来在百度知道上发问,得到的答复是:这个和默许数据类型有关,TH0=(65536-10000)/256,默许unsigned char,即TH0=0xD8;TH0=(-10000)/256,默许signed char,二进制最高位为符号位,负数为1,所以TH0=0xD9 。
原来是Keil编译器核算数据的时分默许的数据类型不相同,65536-10000=55536是unsigned类型,55536/256=216=0xD8,而-10000是signed类型,(-10000)/256=-39=0xD9。原来如此,Keil的编译器预先处理的时分依据不同类型的数据进行了不同的运算,然后直接赋值。我又验证了一下,TH0=(unsigned int)(-10000)/256;发现先把-10000强制转换为unsigned类型后,得到的成果便是正确的了TH0=0xD8。得到答案后脸红了,不过多亏是在放假期间,没有学生看到。开学后立即在课堂上更正了。╮(╯▽╰)╭,这次糗大了。
我从头写了一个程序,#include
void main()
{
unsigned int i;
unsigned char j;
i= – 10000;
j=i/256;
while(1)
;
}
中心加一个变量,看Keil会怎样处理,成果发现
2: void main()
3: {
4: unsigned int i;
5: unsigned char j;
6: i=-10000;
C:0x000F 7ED8 MOV R6,#0xD8
7: j=i/256;
8:
C:0x0011 8E08 MOV 0x08,R6
9: while(1)
C:0x0013 80FE SJMP C:0013
仍是直接赋值,编译器太聪明晰,知道80C51关于数据运算十分十分的不拿手,所以直接处理完数据,然后用赋值的办法来写汇编的指令。并且还知道,i的低字节没有用到,在指令里底子没有呈现,这也太聪明晰吧。Keil软件是最盛行,最好用的编译器,不是浪得虚名的。
我再修正:
include
void main()
{
unsigned int i;
unsigned char j;
i=-10000;
i++;
j=i/256;
while(1)
;
}
成果发现代码只增加了一点。
2: void main()
3: {
4: unsigned int i;
5: unsigned char j;
6: i=-10000;
C:0x0003 7FF0 MOV R7,#B(0xF0)
C:0x0005 7ED8 MOV R6,#0xD8
7: i++;
C:0x0007 0F INC R7
C:0x0008 BF0001 CJNE R7,#0x00,C:000C
C:0x000B 0E INC R6
8: j=i/256;
9:
C:0x000C 8E08 MOV 0x08,R6
10: while(1)
C:0x000E 80FE SJMP C:000E
但关于j的运算仍是用赋值的办法。我再改,把i类型变成signed类型,成果大吃一惊:
include
void main()
{
int i;
unsigned char j;
i=-10000;
j=i/256;
while(1)
;
}