参考帖子:
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,这几个地址不一定能进去,在我参与的帖子中也有
在救火车的文章中讨论的比较有技术些。