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?