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:
Ist bisschen mehr dieses mal. Werden wahrscheinlich auch noch einige Fehler drin sein.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![]()
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?!







Zitieren

Lesezeichen