Pepisoft ich hab jetzt nochmal zwei Funktionen, mit denen man ein Byte, bitweise senden kann. Das 36kHz Signal wird immer noch mit PWM und Timer1 erzeugt. Timer2 wird für das senden und empfangen verwendet.
Beide Funktionen benutzen die Timer so das sie nur währen der Funktion gebraucht werden. Man könnte also auch noch z.B. srf04 Messung auch mit Timer1 machen.
Hier der Code:
Code:
// Wieder für 8 Mhz
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
// Eins auswählen
#define send
// #define receive
// Wie lange die verschiedenen Signale dauern in X_SIGNAL*0,128us
#define START_SIGNAL 250 // z.B. 250*0,128us=32ms langes Start Signal
#define HIGH_SIGNAL 200 // 25,6ms
#define LOW_SIGNAL 100 // 12,8ms
// Ein Byte zu senden dauert somit max. 32ms+8*25,6ms=236,8ms, für die Zahl 256
// Pin an dem der TSOP Ausgang angeschlossen ist
#define rc5_pin // z.B. PINA
#define rc5_bit // z.B. PA1
// Für PWM 36kHz Signal
#define PWM_PORT DDRD // PWM Pin1 von Timer1, beim ATmega16 z.B. PD5
#define PWM_BIT PD5
#ifdef send
void rc5_send(unsigned char byte)
{
volatile unsigned char byte_flag,x;
// Timer1 Fast PWM Prescaler 1, 36kHz Träger,
TCCR1A = (1<<COM1A1) | (1<<COM1A0) | (1<<WGM11);
TCCR1B = (1<<WGM12) | (1<<WGM13) | (1<<CS10);
OCR1A = 111;
ICR1 = 222;
byte_flag=0;
/* Sendet Start Signal */
// Lädt Timer2 Register mit 5 vor ein 250*128us=32ms langes Startsignal zu senden
TCNT2 = 255 - START_SIGNAL;
// Prescaler 1024 Frequenz 7,8125kHz Tackt von 128us , Timer an
TCCR2= (1<<CS22) | (1<<CS21) | (1<<CS20);
PWM_PORT |= (1<<PWM_BIT); // Der Pin mit dem 36kHz Siganl wird auf Ausgang geschaltet
// Warten bis Overflow2 nach 32ms
while(!(TIFR & (1<<TOV2))) asm volatile ("nop");
PWM_PORT &= ~(1<<PWM_BIT); // 36kHz Signal aus
TCCR2= ~(1<<CS22) & ~(1<<CS21) & ~(1<<CS20); // Timer2 aus
for(x=0;x<=200;x++) asm volatile ("nop"); // Kleine Pause
/* Sendet nun das byte, bitweise */
// high=25,6ms lang, low=12,8ms lang
for(byte_flag;byte_flag<=7;byte_flag++)
{
if(byte & (1<<byte_flag)) // Ist bit(byte_flag) in byte high
TCNT2=255-HIGH_SIGNAL; // Wenn ja TCNT2 vorladen für high senden
else
TCNT2=255-LOW_SIGNAL;
TCCR2= (1<<CS22) | (1<<CS21) | (1<<CS20); // Timer an
PWM_PORT |= (1<<PWM_BIT); // 36kHz Signal an
while(!(TIFR & (1<<TOV2))) asm volatile ("nop"); // Warten bis Overlow2, -> Bit gesendet
PWM_PORT &= ~(1<<PWM_BIT); // 36kHz Signal aus
TCCR2= ~(1<<CS22) & ~(1<<CS21) & ~(1<<CS20); // Timer2 aus
for(x=0;x<=200;x++) asm volatile ("nop"); // Kleine Pause
}
// Timer1 wieder aus, kein PWM mehr
TCCR1A = ~(1<<COM1A1) & ~(1<<COM1A0) & ~(1<<WGM11);
TCCR1B = ~(1<<WGM12) & ~(1<<WGM13) & ~(1<<CS10);
OCR1A = 0;
ICR1 = 0;
}
#endif
#ifdef recieve
unsigned char rc5_recieve(void)
{
volatile unsigned char byte,byte_flag,wert,x;
x=0;
byte_flag=0;
// Solange messen bis Startsignal empfangen, aber max. 9 mal damit nicht in endlosschleife
// galls garkein Signal
do{
TCNT2=0; // Timerregister auf 0
// Warten bis rc5/tsop1736 Pin auf high
while (!(rc5_pin & (1<<rc5_bit))) asm volatile ("nop");
TCCR2= (1<<CS22) | (1<<CS21) | (1<<CS20); // Timer2 starten, Prescaler 1024
// Warten bis rc5/tsop1736 Pin auf low
while (rc5_pin & (1<<rc5_bit)) asm volatile ("nop");
wert=TCNT2; // byte = Timer1
TCCR2= ~(1<<CS22) & ~(1<<CS21) & ~(1<<CS20); // Timer2 aus
x++;
// Wert nicht genau auf STAR_SIGNAL prüfen um eine Fehlertoleranz zu haben
}while((!((wert > STAR_SIGNAL - 10)&&(wert < START_SIGNAL + 5)))|| x!=9);
// Wenn Startsignal empfangen
if((wert > STAR_SIGNAL - 10) && (wert < START_SIGNAL + 5))
{
// Schleife um einzelne Bits zu empfangen
for(byte_flag;byte_flag<=7;byte_flag++)
{
TCNT2=0; // Timerregister auf 0
// Warten bis rc5/tsop1736 Pin auf high
while (!(rc5_pin & (1<<rc5_bit))) asm volatile ("nop");
TCCR2= (1<<CS22) | (1<<CS21) | (1<<CS20); // Timer2 starten, Prescaler 1024
// Warten bis rc5/tsop1736 Pin auf low
while (rc5_pin & (1<<rc5_bit)) asm volatile ("nop");
wert=TCNT2;
TCCR2= ~(1<<CS22) & ~(1<<CS21) & ~(1<<CS20); // Timer2 aus
// Wieder Fehlertoleranz für HIGH_SIGNAL und LOW_SIGNAL, diesmal +/- 20
if((wert > HIGH_SIGNAL - 20) && (wert < HIGH_SIGNAL + 20))
byte|=(1<<byte_flag); // Bit ist high, entsprechendes bit in byte high setzen
else if(wert>80 && wert<120)
byte&= ~(1<<byte_flag); // Bit low setzen
}
return byte;
}
// Wenn kein Startsignal empfangen
else
return 0;
}
#endif
Ist bisschen mehr dieses mal. Werden wahrscheinlich auch noch einige Fehler drin sein.
Vielleicht kannst/musst du auch mal mit den Zeiten für die einzelnen SIGNALE rumspielen, und mit deren Toleranzen in der recieve Funktion.
Und noch was zur rc5_recieve(), sie versucht erst neun mal ein Startsignal zu empfangen. Hat sie ein Startsignal empfangen beginnt sie mit dem empfang der einzelnen Bits. In der rc5_send(byte) ist nach dem Startsignal und nach jedem einzelnen Bit eine kleine Sendepause, mit
for(x=0;x<=200;x++) asm volatile ("nop");
Theoretisch müsste es funktionieren.
Gruß Muraad
EDIT: Hab schon wieder was verbessert 
EDIT: Ich hab nochmal was verändert. Vielleicht funktioniert er ja jetzt?!
Lesezeichen