gpt4 book ai didi

c - AVR编程如何激活16位定时器

转载 作者:太空宇宙 更新时间:2023-11-04 02:10:06 25 4
gpt4 key购买 nike

我有一个 atmega168a 芯片。我用 Counter 0切换 PORTC通过使用 ISR(TIMER0_COMPA_vect)ISR(TIMERB_COMPA_vect)中断子程序。我想激活 16-bit timer什么时候if条件为真。所以,我使用 TIMSK1 = (1<<OCIE1A) , 但此行调用 ISR(TIMER1_COMPA_vect)立即中断我希望 16 位定时器仅在计数器 reaches 时被中断至 OCR1A值(value)。如何在运行时激活 16 位定时器而不引起即时中断?

这是我的代码:

#define F_CPU 8000000
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>

volatile uint8_t counter;

int main (void){
DDRC = 0xFF; //sets PORTC as output
PORTC = 0xFF; //initial output value
/*COUNTER0 settings*/
TIMSK0 = ((1<<OCIE0A) | (1<<OCIE0B)); // Enable Interrupt TimerCounter0 Compare Match A & B
TCCR0A = (1<<WGM01); // Mode = CTC
TCCR0B = (1<<CS01) | (1<<CS00); // Clock/64, 1/(8000000/64)= 0.000008 seconds per tick
OCR0A = 200; // 0.000008 *230 = 1.6 ms
OCR0B = 100; // 0.8 ms

/*16bit timer - counter1 settings*/
TIMSK1 &= ~(1<<OCIE1A); // Disable Interrupt Counter 1, output compare A (TIMER1_CMPA_vect)
TCCR1B = ((1<<CS12) | (1<<CS10) | (1<<WGM12)); // Clock/1024, 1/(8000000/1024) = 0.000128 seconds per tick, Mode=CTC
OCR1A = 40; // 0.000128*40 ~= 5.12 milliseconds

sei(); //interrupts are globally switched on
counter =0;
while(1){
if(counter >= 4){
TCNT1 = 0; // clear the counter 1
TIMSK1 = (1<<OCIE1A);// Enables the interrupt for Counter 1,(TIMER1_CMPA_vect)
TIMSK0 &= ~((1<<OCIE0A) | (1<<OCIE0B)); //disables the Counter 0's interrupts
counter = 0;
}
}
return 0;
}

ISR(TIMER0_COMPA_vect){ //1.6ms
PORTC = 0xFF;
counter++;
}

ISR(TIMER0_COMPB_vect){ //0.8 ms
PORTC = ~PORTC;
}

ISR(TIMER1_COMPA_vect){ // 5.2 milisecond interrupt
PORTC = 0x00;
TCNT0 = 0; //clear the counter of counter0
// TIMSK0 = ((1<<OCIE0A) | (1<<OCIE0B)); //Enable the Counter 0 interrupts
// TIMSK1 &= ~(1<<OCIE1A);// Disable Interrupt Counter 1, output compare A (TIMER1_CMPA_vect)
}

这是一个示波器输出,显示了为什么我不想立即设置中断,因为它会立即设置信号 0。 enter image description here

最佳答案

我认为问题可能是在 CTC 模式下,当设置 OCF1A 标志时(在 TIFR 中)会产生中断。由于您的计时器始终在运行,只是不产生中断,因此它设置了永远不会被清除的 OCF1A 标志。在数据表的第 142 页上,它说:

OCF1B is automatically cleared when the Output Compare Match B Interrupt Vector is executed. Alternatively, OCF1B can be cleared by writing a logic one to its bit location.

这意味着当你设置定时器1时,你还需要清除OCF1A:

TIFR1 &= ~(1<<OCF1A)

但是,我认为您可以做得更好。您可以在不需要时停止计时器,并在需要时启动它,而不是摆弄 TIMSK 并让计时器 1 始终运行。如果将 TCCR1B 设置为零,则会清除 CS12CS11CS10,根据数据表表示“计时器停止”。然后,当您的计数器达到 4 时,您可以像上面那样打开定时器 1:

TCCR1B = ((1<<CS12) | (1<<CS10) | (1<<WGM12));

如果这样做,则不需要打开和关闭定时器 1 中断:只需让它们打开,并且只在需要时打开计数。

我还想知道是否真的有必要触发两个中断来切换 PORTC 上的引脚?您是否为此不使用 PWM,因为它不能为您提供足够精确的脉冲长度?

关于c - AVR编程如何激活16位定时器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15314326/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com