AVR ATmega644p: no se puede borrar el pin OC0A en modo CTC

1

Hice una pistola de infrarrojos para controlar la TV (encendida y apagada) basada en ATmega644p. Estoy usando Timer0 en modo CTC para generar una forma de onda de 38 kHz. Este es el código:

#include <mega644p.h>
#include <delay.h>

void start_waveform(void);
void stop_waveform(void);

// IR singal pattern
int ir_signal[] = { 
    1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, -1,
    1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, -1,
    1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, -1,
    1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 2  
};
int index;

void main(void) 
{
    // Pin input for button (PB0)
    DDRB &= ~(1 << 0);
    // Pin output for IR LED (OC0A) (PB3)  
    DDRB |= (1 << 3);  

    TCCR0A |= 
        // Toggle OC0A at compare match
        (1 << COM0A0) |
        // Mode 2 CTC
        (1 << WGM01);

    // Make 38kHz output frequency (F_CPU = 16MHz, Prescaler = 8)   
    OCR0A = 25;     

    while (1)
    {
        // If button is pressed
        if (!(PINB & (1 << 0))) 
        {
            // Transmitt IR signal   
            for (index = 0; index < 64; index++) 
            {
                if (ir_signal[index] == -1)
                {
                    start_waveform();
                    delay_us(280);   
                    stop_waveform();
                    delay_ms(45); 
                } 
                else if (ir_signal[index] == 0) 
                {
                    start_waveform();
                    delay_us(280);   
                    stop_waveform();   
                    delay_us(760);
                }
                else if (ir_signal[index] == 1) 
                {
                    start_waveform();
                    delay_us(280);   
                    stop_waveform();  
                    delay_us(1780);
                }
                else if (ir_signal[index] == 2) 
                {
                    start_waveform();
                    delay_us(280);   
                    stop_waveform();
                }
            }

            delay_ms(500);     
        }
    }
}

void start_waveform()
{
    // Start waveform at prescaler = 8    
    TCCR0B |= (1 << CS01);  
}

void stop_waveform()
{
    // Stop waveform  
    TCCR0B &= ~(1 << CS01);
}

Este código funciona para encender y apagar el televisor, pero el problema es; A veces, después de que finaliza la señal IR, el LED IR sigue encendido. He intentado agregar código para asegurarme de que el PB3 esté apagado usando este código, pero no funciona:

void stop_waveform()
{
    // Stop waveform
    TCCR0B &= ~(1 << CS01);
    // Make sure PB3 is turn off
    PORTB &= ~(1 << 3);
}

Tengo curiosidad por saber qué hay de malo con este código?

    
pregunta Yohanes Erwin

1 respuesta

1

Es posible que hayas quemado algo alrededor de la salida de MCU.

Siempre debes leer la hoja de datos. Todos los dispositivos electrónicos tienen un rango de operación máximo. Para su MCU esto se explica en la página 316, una tabla llamada: Máximas calificaciones absolutas . Aquí encontrará una corriente DC por pin de E / S que le indica el límite superior de la cantidad de pines de E / S que puede generar / hundir la corriente. En general, no querría más de 20 mA por pin.

Usted dijo que está manejando el LED directamente desde el pin MCU a través de una resistencia de 27 ohmios. Incluso si está alimentando la MCU desde 3.3V y el voltaje a través del LED es 1.3V, la corriente es de alrededor de 70 mA, lo que está muy por encima del límite superior (seguro que lo está manejando con PWM pero siempre debe asumir el peor de los casos).

Por lo tanto, lo que recomendaría es que primero intentes conducir el LED a través de un transistor, hay un montón de tutoriales por ahí sobre cómo hacerlo. Si eso no funciona, también intentaría reemplazar la MCU.

    
respondido por el Golaž

Lea otras preguntas en las etiquetas