ATmega16单片机定时器停止不了

这个问题纠结我好长时间。
前段时间想用ATmega16单片机的定时器1做个99秒倒计时的装置。发现时间到0后定时器关闭不了。
用的8MHz晶振,数码管显示。编译器是iccavr v6.31a,程序中定义char time=99;来计时。
定时器初始化函数如下:
void T1_init()
{
TCCR1B=0X04;
TCNT1H=0X85;
TCNT1L=0XED;
TIMSK |= BIT(2);
SREG |= BIT(7);
}
定时器的中断服务程序如下:
#pragma interrupt_handler T1:9
void T1()
{
TCNT1H=0X85;
TCNT1L=0XED;
time--;
if (time <= 0)
TIMSK &= ~BIT(2);
}
这样发现时间到0后,定时器没能停止,不过继续显示的是乱码。
如果把中断服务程序里判断时间是否为零的语句改成if (time ==0)定时器就可以正常停止。这是为啥啊?哪位大师指点一下小弟?

if (time <= 0)你的time 是全局变量,char型(-128~127)??那么time可以为负了,应该是if (time == 0)表示倒计时结束,为了可循环,可以做以下调整if (time <= 0){
TIMSK &= ~BIT(2); time=99;//重新赋值
} 上一个我写的代码 #include<iom16v.h>
#include"MacroAndConst.h"//自定义函数
#include<Macros.h>
int8 count;
int8 ge;
int8 shi;
uchar table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0X7d,0X07,0x7f,0x6f};
/*软件延时函数定义*/
void delay(uint ms) //误差 -0.651041666667us
{
int8 a,b,i;
for(i=0;i<ms;i++)
for(b=102;b>0;b--)
for(a=3;a>0;a--);
}
/*T/C1定时初始化设置*/
void Timer1_init(void)
{
TCCR1B=0X04;//256分频
TCNT1H=0X85;//1s
TCNT1L=0Xee;
TIMSK|=BIT(2);//T/C1 interrupt
SREG|=BIT(7);
}
/*端口初始化设置*/
void Port_Init(void)
{
DDRA=0XFF;
PORTA=0XFF;
DDRB=0XFF;
PORTB=0XFF;
DDRC=0XFF;
PORTC=0XFF;
DDRD=0XFF;
PORTD=0XFF;
}
/*数码管显示程序*/
void display(int8 wela,int8 dula)
{
PORTB=table[dula];//send dula
PORTC&=~BIT(wela);//开启显示的位
delay(10);
PORTC|=BIT(wela);//开启显示的位
}
/******************************************
作者: prodigal功能介绍:用T/C1普通模式实现秒表程序,并用
数码管显示出来。

创作日期:20110809
版本�0.01
******************************************/
void main()
{
Port_Init();
Timer1_init();
while(1)
{
display(1,shi);
display(2,ge);
}
}
/*中断服务程序*/
#pragma interrupt_handler timer1_isr:9
void timer1_isr(void)
{

count++;
if(count==60)count=0;
shi=count/10;
ge =count%10;

TCNT1H=0X85;
TCNT1L=0Xee;
} 直奔→嵌入式团员为你解答,希望能帮助到你
温馨提示:答案为网友推荐,仅供参考
第1个回答  2013-12-09
我不用这款编译器,我建议你看下反汇编的代码,看看编译器是怎么处理的。
如果是我,我会写成if (!time) 这样效率高。
第2个回答  2013-12-09
还是用51的方法啊,呵呵可以试试把TIMSK &= ~BIT(2);修改成TCCR1B &= ~0X04; 要定时器停止是CS2~CS0都写成0,你那个是关中断欢迎追问
第3个回答  2020-02-05
atmega的单片机没有运行控制位,停止不了,不像51,可以给一个TR0=0就可以停止了!