Nerb
26.05.2008, 22:15
hallo zusammen,
ich habe vor einiger Zeit den code für eine 4 Kanal Fernbedienung mit Tiny13 porgrammiert. Da ich das ganze erst in geraumer Zeit testen kann, wollte ich hier den code mal in die Runde werfen, in der Hoffnung das eventuelle Fehler aufgedeckt werden.
Nun ein paar Daten zum selbstausgedachten code:
Der 8 bit Timer (einziger timer im Tiny13) erzeugt die Trägerfrequenz von 38khz. An Pin PB2 ist eine IR Leuchtdiode über Vorwiderstand und Treiber angeschlossen.
Als Taster werden normale 2 Schließer benutzt. Je ein Schließer eines Tasters hängt an PB0,PB3,PB4 und PB5. Der zweite Schließer jedes Tasters hängt zusammen mit den anderen an PB1 dem externen Interrupt, was den avr aus dem Sleep modus aufwecken soll.
Gesendet wird zuerst ein 3 Bit Header, dann ein 4 Bit Befehlsschlüssel. Alles wäre natürlich auch mit weniger Bits ausgekommen, aber so ist das Ganze meines Erachtens störsicherer. Der Zeitabstand zwischen jedem gesendeten Bit ist 2ms. Dazu wird die delay Funktion benutzt. Ob die Genauigkeit dazu ausreicht, weiß ich nicht. Nach jedem Bitblock wird 160ms gewartet.
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#define F_CPU 1000000UL
#include <util/delay.h>
int main (void) {
DDRB|=(1<<PB2);
PORTB=0x3b; //Pullups an (außer PB2)
TIMSK0 |= (1<<TOIE0); //Timer Overflow Interrupt freischalten
ACSR = 0x80; //Analog Comparator ausschalten
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sei();
while(1) { //Hauptschleife,
do { //Interrupt pin gedrückt (low)
//header 101
TCCR0B = 0x1; //Timer starten
_delay_ms(2); //1
TCCR0B = 0; //Timer stoppen
_delay_ms(2); //0
TCCR0B = 0x1; //Timer starten
_delay_ms(2); //1
if ((PINB & (1<<PINB0))==0) { //code 1: 1010
_delay_ms(2); //1
TCCR0B = 0;
_delay_ms(2); //0
TCCR0B = 0x1;
_delay_ms(2); //1
TCCR0B = 0;
_delay_ms(2); //0
}
if ((PINB & (1<<PINB3))==0) { //code 2: 1101
_delay_ms(4); //11
TCCR0B = 0;
_delay_ms(2); //0
TCCR0B = 0x1;
_delay_ms(2); //1
}
if ((PINB & (1<<PINB4))==0) { //code 3: 0101
TCCR0B = 0;
_delay_ms(2); //0
TCCR0B = 0x1;
_delay_ms(2); //1
TCCR0B = 0;
_delay_ms(2); //0
TCCR0B = 0x1;
_delay_ms(2); //1
}
if ((PINB & (1<<PINB5))==0) { //code 4: 1011
_delay_ms(2); //1
TCCR0B = 0;
_delay_ms(2); //0
TCCR0B = 0x1;
_delay_ms(4); //11
}
TCCR0B = 0;
_delay_ms(160);
} while((PINB & (1<<PINB1))==0);
PORTB &= ~(1<<PB2); //IR LED ausschalten
sleep_mode(); //in den Schlafmodus wechseln
}
}
ISR (INT0_vect) {
_delay_ms(50); //Tasten entprellen
}
ISR (TIM0_OVF_vect ) { //Erzeugung der 38Khz Trägerfrequenz
cli();
PORTB ^= (1<<PB2); //PB2 toggeln
TCNT0 = 0xe5; //Vorladen auf 229 -> 26 Schritte
sei();
}
mfg Philip
ich habe vor einiger Zeit den code für eine 4 Kanal Fernbedienung mit Tiny13 porgrammiert. Da ich das ganze erst in geraumer Zeit testen kann, wollte ich hier den code mal in die Runde werfen, in der Hoffnung das eventuelle Fehler aufgedeckt werden.
Nun ein paar Daten zum selbstausgedachten code:
Der 8 bit Timer (einziger timer im Tiny13) erzeugt die Trägerfrequenz von 38khz. An Pin PB2 ist eine IR Leuchtdiode über Vorwiderstand und Treiber angeschlossen.
Als Taster werden normale 2 Schließer benutzt. Je ein Schließer eines Tasters hängt an PB0,PB3,PB4 und PB5. Der zweite Schließer jedes Tasters hängt zusammen mit den anderen an PB1 dem externen Interrupt, was den avr aus dem Sleep modus aufwecken soll.
Gesendet wird zuerst ein 3 Bit Header, dann ein 4 Bit Befehlsschlüssel. Alles wäre natürlich auch mit weniger Bits ausgekommen, aber so ist das Ganze meines Erachtens störsicherer. Der Zeitabstand zwischen jedem gesendeten Bit ist 2ms. Dazu wird die delay Funktion benutzt. Ob die Genauigkeit dazu ausreicht, weiß ich nicht. Nach jedem Bitblock wird 160ms gewartet.
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#define F_CPU 1000000UL
#include <util/delay.h>
int main (void) {
DDRB|=(1<<PB2);
PORTB=0x3b; //Pullups an (außer PB2)
TIMSK0 |= (1<<TOIE0); //Timer Overflow Interrupt freischalten
ACSR = 0x80; //Analog Comparator ausschalten
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sei();
while(1) { //Hauptschleife,
do { //Interrupt pin gedrückt (low)
//header 101
TCCR0B = 0x1; //Timer starten
_delay_ms(2); //1
TCCR0B = 0; //Timer stoppen
_delay_ms(2); //0
TCCR0B = 0x1; //Timer starten
_delay_ms(2); //1
if ((PINB & (1<<PINB0))==0) { //code 1: 1010
_delay_ms(2); //1
TCCR0B = 0;
_delay_ms(2); //0
TCCR0B = 0x1;
_delay_ms(2); //1
TCCR0B = 0;
_delay_ms(2); //0
}
if ((PINB & (1<<PINB3))==0) { //code 2: 1101
_delay_ms(4); //11
TCCR0B = 0;
_delay_ms(2); //0
TCCR0B = 0x1;
_delay_ms(2); //1
}
if ((PINB & (1<<PINB4))==0) { //code 3: 0101
TCCR0B = 0;
_delay_ms(2); //0
TCCR0B = 0x1;
_delay_ms(2); //1
TCCR0B = 0;
_delay_ms(2); //0
TCCR0B = 0x1;
_delay_ms(2); //1
}
if ((PINB & (1<<PINB5))==0) { //code 4: 1011
_delay_ms(2); //1
TCCR0B = 0;
_delay_ms(2); //0
TCCR0B = 0x1;
_delay_ms(4); //11
}
TCCR0B = 0;
_delay_ms(160);
} while((PINB & (1<<PINB1))==0);
PORTB &= ~(1<<PB2); //IR LED ausschalten
sleep_mode(); //in den Schlafmodus wechseln
}
}
ISR (INT0_vect) {
_delay_ms(50); //Tasten entprellen
}
ISR (TIM0_OVF_vect ) { //Erzeugung der 38Khz Trägerfrequenz
cli();
PORTB ^= (1<<PB2); //PB2 toggeln
TCNT0 = 0xe5; //Vorladen auf 229 -> 26 Schritte
sei();
}
mfg Philip