打印

PICC编译器BUG求助

[复制链接]
6073|25
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
gx_huang|  楼主 | 2011-10-28 08:48 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
C编译器是PICC 9.65
722芯片
简化程序:
void main(void)
{
do
{
  led=1;
}while(1);
}
//10MS定时器中断
void  interrupt isr(void)
{
根据led的值显示到数码管上,0对应0,1对应1....
}
按道理数码管应该稳定显示1,但是会闪烁,有显示0的痕迹。
检查led=1的汇编代码翻译成C就是:
led=0;
led++;
倒霉呀,在led=0时产生中断的话,中断程序就错误的显示0了。
还没有发现有任何其它的编译器会出现PICC 9.65这么弱智的错误。
其它编译器,对于8位的MCU,单字节赋值不需要保护,
只有双字节赋值才需要考虑保护一下。

不知道是否更高版本的没有这个BUG?
沙发
gx_huang|  楼主 | 2011-10-28 08:56 | 只看该作者
临时措施是在主程序里定义一个临时变量led_temp

led_temp=1;
led=led_temp;

但是这么搞,太累了。

使用特权

评论回复
板凳
l4157| | 2011-10-28 09:41 | 只看该作者
如果led不是全局变量,那么就不全算PICC的BUG

使用特权

评论回复
地板
gx_huang|  楼主 | 2011-10-28 10:30 | 只看该作者
led是全局变量

使用特权

评论回复
5
gx_huang|  楼主 | 2011-10-28 12:13 | 只看该作者
已经解决,改用9.80版本的编译器就可以了。

使用特权

评论回复
6
gx_huang|  楼主 | 2011-10-28 13:09 | 只看该作者
还是不行。
led=1编译的结果是:
led=0;
led++;

但是led=0xff是对的:
ACC=0xff;
led=ACC;

使用特权

评论回复
7
gx_huang|  楼主 | 2011-10-28 13:16 | 只看该作者
错误1:
  1376                           ;isr.c: 56: rcv_cnt=1;
  1377  021C  01F6                       clrf        _rcv_cnt
  1378  021D  0AF6                       incf        _rcv_cnt,f

错误2:
   921                           ;Radar_722_v00.c: 109: if(i>=200) radar_alm=1;
   922  01A4  30C8                       movlw        200
   923  01A5  0236                       subwf        dis_radar@i,w
   924  01A6  1C03                       skipc
   925  01A7  29AB                       goto        l2438
   926  01A8  01FD                       clrf        _radar_alm
   927  01A9  0AFD                       incf        _radar_alm,f

以上2处,想赋值1,编译结果都是先清零,再加1。导致中断里引用该数据就错了。

以下赋值2就是对的:
   931                           ;Radar_722_v00.c: 110: else if(i>=120) radar_alm=2;
   932  01AB  3078                       movlw        120
   933  01AC  0236                       subwf        dis_radar@i,w
   934  01AD  1C03                       skipc
   935  01AE  29B2                       goto        l2442
   936  01AF  3002                       movlw        2
   937  01B0  00FD                       movwf        _radar_alm
通过累加器赋值,中断里引用就不会出现错误的中间值。

使用特权

评论回复
8
gx_huang|  楼主 | 2011-10-28 13:17 | 只看该作者
唉,PICC怎么这么弱智呢?
用KEIL C51,从来不会出现类似问题,只有双字节以上的赋值才有可能出错,需要软件引用前特别处理。

使用特权

评论回复
9
ayb_ice| | 2011-10-28 16:05 | 只看该作者
这是编程的基本问题,还怪这怪那

使用特权

评论回复
10
jack_shine| | 2011-10-28 16:12 | 只看该作者
还是不行。
led=1编译的结果是:
led=0;
led++;

gx_huang 发表于 2011-10-28 13:09
此编译的结果不也是led=1吗

使用特权

评论回复
11
yewuyi| | 2011-10-28 21:17 | 只看该作者
此不能算是BUG,该变量应该做中断现场保护才对,即使在C51+KEIL上也应该要做,否则也是可能会出一些问题的。

使用特权

评论回复
12
bobo1957| | 2011-10-28 21:58 | 只看该作者
显示效果最好应该是静态,刷屏都会有抖动,你得想办法消除抖动,不要随便怀疑编译器,人家是要用来卖钱的,这么容易就有bug,那怎么卖呢

使用特权

评论回复
13
gx_huang|  楼主 | 2011-10-29 07:17 | 只看该作者
你们没有彻底理解我的意思。
主程序里对显示变量赋值,定时中断里显示该变量,我这里举例的是一个显示变量,
实际上显示变量很多,和数码管的个数一样。
我可以保证,在有中断的系统里,凡是对单个字节类型的变量赋值,keil c51绝对不会出现问题。
当主程序想赋值1的时候,我希望显示的也是1,但是主程序赋值1的指令,被分解成2个指令,
如果先赋值0,刚好产生中断,则瞬间显示0,在下一个中断,显示才恢复到正确的1。
如果主程序里循环赋值1,则显示就在0和1之间反复闪烁。

使用特权

评论回复
14
gx_huang|  楼主 | 2011-10-29 07:24 | 只看该作者
对于8bit的系统中,主程序对单个字节的变量赋值,中断程序不应该出现问题。
类似的,对于16位系统,对单字节和双字节变量赋值,中断程序也不应该异常。
因为,赋值操作应该在单个指令中完成。
如果编译系统对于如此简单的赋值操作都不考虑中断程序的正常调用,这不是BUG是什么?

使用特权

评论回复
15
headwolf_83| | 2011-10-29 09:44 | 只看该作者
你具体是用什么版本,LITE?HEXIE的PRO?
如果是用LITE版,一切皆有可能。

使用特权

评论回复
16
ayb_ice| | 2011-10-29 09:55 | 只看该作者
对于8bit的系统中,主程序对单个字节的变量赋值,中断程序不应该出现问题。
类似的,对于16位系统,对单字节和双字节变量赋值,中断程序也不应该异常。
因为,赋值操作应该在单个指令中完成。
如果编译系统对于如此 ...
gx_huang 发表于 2011-10-29 07:24

谁定义的这些结论,我看是你自己定义的吧
像ARM,根本不能直接对内存操作,必须先通过加载指令将内存数据送到寄存器才能操作那怎么办,类似51的XRAM空间

使用特权

评论回复
17
gx_huang|  楼主 | 2011-10-30 13:19 | 只看该作者
回15L:
是9.80,**版的。9.65**版也有问题。

回LS兄弟:
是我这么定义的,你看懂我的问题了吗?
好像你很懂的,连ARM的RAM读取都知道。

请问,在主程序里对LED赋值1,编译器先赋值0,再加1,这样好吗?

使用特权

评论回复
18
l4157| | 2011-11-2 09:31 | 只看该作者
1.编译器先赋值0,再加1"在代码和执行速度上是有优势的;2.做程序有时是要主意中断的变量保护,这样才能写出好代码;3.在这里,编译器优化是有点过了,不过一般正常程序也不会这样写;4.不要相互攻击,讨论一下而已

使用特权

评论回复
19
yewuyi| | 2011-11-2 09:57 | 只看该作者
小黄有些理解确实是错误的。

使用特权

评论回复
20
gx_huang|  楼主 | 2011-11-3 12:13 | 只看该作者
18# l4157

PIC的上述指令,只要不跳转,指令速度是一样的。

使用特权

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

本版积分规则

50

主题

9037

帖子

79

粉丝