比较隐秘的中断所带来的危害

参考帖子:

http://bbs.21ic.com/club/bbs/bbsView.asp?action=topicwithme

程序的源代码是:

#include <iom48.h>
#include <inavr.h>

unsigned int count;
unsigned long sum;
unsigned long error;
unsigned char flag;

#pragma vector = TIMER1_COMPA_vect
__interrupt void my_interrupt_routine(void) //定时中断
{
    count++;        //count = 251~260
    
    if(count > 260)
    {
        count = 251;
    }
    
    flag = 1;
    
}

void tmr1_ini() 定时中断初始化
{
    TCNT1  = 0x00;
    
    OCR1A  = 80;
    TIMSK1 = 0x02;
    
    TCCR1A = 0x00;
    TCCR1B = 0x09;
}

void main(void)
{
    count = 251;
    sum = 0;
    error = 0;
    
    tmr1_ini();
    __enable_interrupt();
    
    while(sum < 100000)
    {
        if(flag > 0)
        {
            sum++;
            flag = 0;
        }
        
        if(count > 250)         //count = 251~260
        {
            __delay_cycles(2);  //按理一定执行这句话
        }
        else
        {
            error++;            //但实际上有一定的机率会执行这句话
        }
    }
    
    
    while(1)                    //下断点,看error的数值
    {
        __delay_cycles(2);
        __delay_cycles(2);
        __delay_cycles(2);
    }
}


大家想这程序出问题的原因是什么
想想这个程序改进的方法是什么
想通了这个也许对大家有点帮助

呵呵,讨论一下,帖子上面都有的啊!

问题最容易出在

if(count > 250)         //count = 251~260

因为 unsigned int count;,所以比较会汇编成两个CMP语句:

                 R     MOV     A,count+01H ;------(1)
                       SUBB    A,#00H
                 R     MOV     A,count     ;------(2)
                       SUBB    A,#0FAH
                 R     xJLT    ?C0546

如果在(1)和(2)之间发生了 count 255到256的变化,如果是little endian参考Programming Embedded Systems with C and GNU Development Tools, 2nd Edition (OReilly, 2006).chm 6.3节的介绍,可以得到,其实作比较的数据是A和00。当然会导致 

error++;            

的执行啊!

其实这个问题是 救火车竟选文章《一个容易忽略的错误》最先提出的可是不知道为何这么多人也来讨论了

http://bbs.21ic.com/club/bbs/bbsView.asp

http://bbs.21ic.com/club/bbs/showEssence.asp?id=8512,这几个地址不一定能进去,在我参与的帖子中也有

在救火车的文章中讨论的比较有技术些。
 

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值