Use AVR Timer1 para comparar interrupciones Y PWM al mismo tiempo

1

¿Es posible usar Timer1 en un ATMega para generar una interrupción de comparación en OCR1A y PWM en OCR1B? Lo he intentado de forma similar a la siguiente, pero ninguno funciona con todo lo que he intentado.

TCCR1A = _BV(COM1B1) | _BV(WGM11) | _BV(WGM10);
TCCR1B = PRESCALE1_8;
OCR1B = 0;


// set compare match register for 1000Hz 
OCR1A = 2000;
// turn on CTC mode
TCCR1B |= _BV(WGM12);

Nota al margen: Sé que esto es extremadamente similar a otra pregunta mía , pero eso fue con respecto a PWM en un temporizador e interrupciones en otro. Esta vez tengo problemas para sacar ambos del mismo temporizador.

    
pregunta Adam Haile

1 respuesta

2

Su código configura el contador para la operación PWM de fase correcta con el valor superior 0x3FF, por lo que el primer problema que enfrentará es que las interrupciones de comparación de coincidencia no se activarán en intervalos iguales debido a la forma en que funciona este modo, que se cuenta para la parte superior y luego cambiar de dirección y contar hacia atrás.

El otro problema es que el contador cuenta hasta 1023 (0x3ff) y vuelve a 0, por lo que no hay forma de obtener una interrupción de coincidencia para un valor de 2000 (OCR1A = 2000)

operación PWM de fase correcta:

Este es un código mínimo para mega328 corriendo a 16MHz que configura el temporizador 1 para generar un PWM rápido con una frecuencia de aproximadamente 1 kHz (frecuencia establecida por ICR1 y servicio establecida por OCR1B) y también proporciona una interrupción de desbordamiento del temporizador 1 con 1 kHz tasa

#include <avr/io.h>
#include <avr/interrupt.h>

// Timer1 overflow interrupt service routine
ISR(TIMER1_OVF_vect)
{
    PORTB ^= 1; // invert PORTB.0
}

int main(void)
{

    // Port B initialization
    // Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=Out Bit1=In Bit0=Out
    DDRB = 0x05;

    // Timer/Counter 1 initialization
    // Clock source: System Clock
    // Clock value: 2000,000 kHz
    // Mode: Fast PWM top=ICR1
    // OC1A output: Disconnected
    // OC1B output: Non-Inverted PWM
    // Noise Canceler: Off
    // Input Capture on Falling Edge
    // Timer Period: 1,0245 ms
    // Output Pulse(s):
    // OC1B Period: 1,0245 ms Width: 0,12806 ms
    // Timer1 Overflow Interrupt: On
    // Input Capture Interrupt: Off
    // Compare A Match Interrupt: Off
    // Compare B Match Interrupt: Off
    TCCR1A = (0 << COM1A1) | (0 << COM1A0) | (1 << COM1B1) | (0 << COM1B0) | (1 << WGM11) | (0 << WGM10);
    TCCR1B = (0 << ICNC1) | (0 << ICES1) | (1 << WGM13) | (1 << WGM12) | (0 << CS12) | (1 << CS11) | (0 << CS10);
    TCNT1 = 0;
    ICR1 = 2048;
    OCR1A = 0;
    OCR1B = 256;

    // Timer/Counter 1 Interrupt(s) initialization
    TIMSK1 = (0 << ICIE1) | (0 << OCIE1B) | (0 << OCIE1A) | (1 << TOIE1);

    // Global enable interrupts
    sei();

    while(1)
    {
        // Place your code here

    }
}
    
respondido por el alexan_e

Lea otras preguntas en las etiquetas