打印
[51单片机]

51单片机程序活见鬼,求解释!

[复制链接]
982|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
    现象比较奇葩。且听我细细将来。
    话说当前在keil(版本4.12)中编写51程序,用到switch()语句,其中用到按位左移<<。发现其中case跳转异常,发现和左移<<操作有关,但不知为何会这样,甚是郁闷(已经多天没吃饭了)。
    我将程序做了简化处理,但能反应问题。
    先看问题程序,见下图,其中使用了switch语句,注意在语句内部使用到了按位左移<<,且左移最大超过16位(不知道这个是不是原因)。
    问题的现象是:当channel=18时,switch会先跳转到case 17,再转到case 18,然后跳出switch。但switch执行完之后,标志寄存器没有预想中的被赋值为(1<<16),或(1<<17),仍然是0。

再看对应的汇编代码,其中选中部分,分别对应c程序中的case 16和case17两句,注意这两句的跳转地址是一样的,这也印证了为什跳转有问题。

但是,如果我把程序中的按位左移去掉,改为直接赋值,就不存在这个问题了,见下图改后的C程序。

下面这张是对应的汇编,注意其中case 16 和case 17两句的跳转地址已经正常了。

    现象显然和左移操作有关。并且程序中是对长整型l(32位)变量进行操作,如果改为char型变量就不存在这个现象了,我试过。注意其中左移位数最大17位,如果channel的值小于17,比如16,也不存在这个问题。
所以怀疑是不是keil中C51左移最大只能是16?但也不应该,没看到相关规定。
把程序源码附件附后,可下载调试看看。
源码.rar (38.27 KB)

相关帖子

沙发
diweo| | 2015-7-15 13:00 | 只看该作者
建议你先把1强制转型。比如
fla|=((unsigned long)1)<<17;

使用特权

评论回复
评论
datouyuan 2015-7-15 14:24 回复TA
正解!!! 
板凳
datouyuan| | 2015-7-15 14:17 | 只看该作者
本帖最后由 datouyuan 于 2015-7-15 14:29 编辑

正确的写法:
case 1        :       标志寄存器_ |=(1ul<<0);                break;
abc_ |=(1ul<<17);

未做特别说明,编译器把“1”看成是INT类型的常数,而51的INT是16bit的。


使用特权

评论回复
地板
dirtwillfly| | 2015-7-15 16:59 | 只看该作者
diweo 发表于 2015-7-15 13:00
建议你先把1强制转型。比如
fla|=((unsigned long)1)


正解。1默认的不是32位无符号数

使用特权

评论回复
5
ayb_ice| | 2015-7-15 21:09 | 只看该作者
有啥诡异的,数字默认是整型的,16位的

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

32

主题

114

帖子

2

粉丝