关于溢出中止不管是哪个单片机都是不断累加,使其寄存器溢出触发中止,然后跳转到中止函数处履行中止服务程序。关于守时器初值的设定能够加深对守时器的作业原理的了解。
ATMega16 里边有8位和16位两种守时器,他们何时会溢出这个是固定的,也便是抵达他们的计数规模的最大值就会发生中止,8位的守时器的最大计数规模是0~256(2的8次方),便是累加到256后他就会发生中止,16位的守时器最大计数规模是0~65536(2的16次方),累加到65536时他就会发生中止。
而咱们所谓的计数初值是便是要设定守时器在什么地方开端计数,以8位守时器为例比方:初值为100,所以守时器从100开端累加,累加了156次,加到256后发生中止,这便是中心耗费的时刻和指令周期便是咱们要去设定的时刻;再比方:初值是200,所以守时器从200开端累加,累加了56次,加到256后发生中止,能够看到榜首守时要累加156次才会中止而第2次只需累加56次就会发生中止,明显榜首次设定的时刻要比第2次的长。
守时器不只能够守时,并且咱们用到守时器的时分往往是需求准确守时的时分。咱们能够核算出咱们设定的初值会在多长时刻后进入中止。
下面的是8位守时器设定的时分需求用的寄存器:
试验渠道:ATMega16
晶振: 11.0592 MHz
对初值的核算:
1,11059200 / 1024 = 10800 设定为1024倍分频 ,得到每1秒需求进行多少次累加
2,10800 / 100 = 108 得到10ms 的守时需求进行多少次累加 。
3,256 – 108 = 148 核算规模最大值减去要累加的时刻,得到初值,即从哪里开端累加才能在溢出时为10ms的时刻。
4,148 <==> 0x94 得到十六进制值,赋值给TCNT0
试验代码: 守时10ms
#include
unsigned char flag = 0;
void timer_init(void)
{
TCCR0 = 0x05; //进行1024分频
TCNT0 = 0x94; //赋计数初值
TIMSK_TOIE0 = 1; //开使能
SREG_I = 1; //开总中止
}
#pragma vector = TIMER0_OVF_vect
__interrupt void time0_normal(void)
{
TCNT0 = 0x94; //从头赋初值
flag++;
}
void main(void)
{
timer_init();
DDRB_Bit0 = 1;
while(1)
{
if(flag == 100) //10ms 重复100次,即为1秒
{
PORTB_Bit0 = ~PORTB_Bit0; //让LED闪耀
flag = 0;
}
}
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
试验渠道:ATMega16
晶振:11.0592
16位守时器初值设定:
1,11059200 / 256 = 43200 设定256倍分频,得到每1秒需求进行多少次累加
2,65536 – 43200 = 22336 核算规模最大值减去要累加的时刻,得到初值,即从哪里开端累加才能在溢出时为1s的时刻。
3,22336 <==> 0x57 0x40 得到十六进制值,赋值给TCNT1H , TCNT1L
试验代码: 守时1s
#include
unsigned char flag = 0;
void timer_init(void)
{
TCCR1B = 0x04;
TCNT1H = 0x57;
TCNT1L = 0x40;
TIMSK_TOIE1 = 1;
SREG_I = 1;
}
#pragma vector = TIMER1_OVF_vect
__interrupt void time1_normal(void)
{
TCNT1H = 0x57;
TCNT1L = 0x40;
flag++;
}
void main(void)
{
timer_init();
DDRB_Bit0 = 1;
while(1)
{
if(flag == 1)
{
PORTB_Bit0 = ~PORTB_Bit0;
flag = 0;
}
}
}