Hallo zusammen. Ich bastle schon lange an einer Routine zum einlesen von NEC IR Protokoll. Verwendet wird ein TSOP1738 entsprechend entstört direkt am INT1 eingang eines Atmega8. (Signal invertiert). Nun zu meinem Problem. Via dem Interrupt INT1 wird auf die entsprechenden Flanken getriggert (ISR). Immer nach einer steigenden Flanke deaktiviere ich den Interrupt Int1 und aktiviere den Interrupt Zählerüberlauf vom Zähler 2. Der läuft nach 814us ab und tastet mir das Signal am Eingang INT1 ab. Nach Abtastung deaktiviere ich den Interrupt Zählerüberlauf lösche das Flag vom Int1 und aktiviere den Interrupt INT1 wieder und warte auf die nächste Flanke. Den Sync erkenne ich. Aber die Bit's kann ich nicht einlesen. Bzw. immer ein HIGH am Eingang. Zeiten: Interrupt steigende Flanke bis Zählerüberlauf aktiviert 13us Bis Abtastung 814us Abtastung und Interrupt flanke aktiviert 18us Sonst habe ich alle sonstigen Interrupts deaktiviert. (UART,Timer1) Anbei der Code: SIGNAL (SIG_INTERRUPT1) //Interruptroutine Interrupt1 { if(IR_sperr) //Sperrconter damit Zeit zum auslesen des Codes { IR_sperr--; } else { GIFR |= 0x80; //Flag rücksetzen switch (Sync) { case 0: //Wenn noch nicht Sync erkannt TCNT2 = 0; MCUCR |= 0x04; // on rising edge Sync = 1; break; case 1: //Wenn Sync erkannt 9ms Puls if (((TCNT2 >0x00)) && ((TCNT2 <= 0x08))) //4Tick Toleranz //Wenn 16T langer Sync !!!//!Achtung Zähler überläuft funktioiert //nur mit 8Bit Zähler 9000us / 34.7us = 258! { MCUCR &= ~0x04; // on faling edge TCNT2 = 0; Sync = 2; } else { MCUCR &= ~0x04; // on faling edge Sync = 0; shiftreg(0,1); //Lösche Schieberegister } break; case 2: //Wenn 4ms erkannt if (((TCNT2 >0x36)) && ((TCNT2 <= 0x44))) //4Tick Toleranz //Wenn 4T langer Sync !!!// { MCUCR |= 0x04; // on rising edge Sync = 3; } else { MCUCR &= ~0x04; // on faling edge Sync = 0; shiftreg(0,1); //Lösche Schieberegister } break; case 3: //Im Decodiermodus if(!(MCUCR & 0x04))//Wenn falling Edge { MCUCR |= 0x04; // on rising edge } else { TCNT2 = -24; // in 840us ein Zählerüberlauf TIMSK |= 0x40; //Setze Timer Overflow Interrupt GICR &= ~0x80; // ext. Int1 disable } break; } } GIFR |= 0x80; //Flag rücksetzen } ********************************************************************* SIGNAL (SIG_OVERFLOW2) //Interruptroutine Zählerüberlauf { static unsigned char In_Port,stat; In_Port = IR_PP1; //Lese Wert von Port ein if(In_Port == 1) //Wenn Input High { //Setze Bit auf 1 TIMSK &= ~0x40; //Lösche Timer Overflow Interrupt GICR |= 0x80; // ext. Int1 enable MCUCR &= ~0x04; // on falling edge } else { //Setze Bit auf 0 TIMSK &= ~0x40; //Lösche Timer Overflow Interrupt GICR |= 0x80; // ext. Int1 enable MCUCR |= 0x04; // on rising edge } stat = shiftreg(In_Port,0); if(stat == 1 ||stat == 2 ) { Sync = 0; shiftreg(0,1); //Lösche Schieberegister MCUCR &= ~0x04; // on faling edge GICR |= 0x80; // ext. Int1 enable } GIFR |= 0x80; // clear Int0-Flag } **************************************************** in .h File #define IR_PP1 ((PIND & 0x8) >> 3) ******************************************************** //Init des Zählers bzw. vorteiler TCCR2 = 0x06; // 0x6 == 1/256 Timer2 auf 28.8kHz --> 34.7us ( bei 7.3728Mhz Osz.) ************************************************************* Was mache ich falsch? Danke im voraus Grüsse Michael
Hallo Michael, schau mal hier: http://www.sbprojects.com/projects/ircontrol/picir/nec.htm Zwar mit Pic aber leicht übertragbar. gruß Hans
Danke Hans Diesen Link habe ich auch gefunden. Anhand von diesem und anderen Links habe ich die Routine geschrieben. Habe auch schon mit dem AVR Smulator einen ganzen Durchgang durchgespielt, also eigentlich sollte es klappen. Mein Problem liegt vermutlich dort das die Interruptrutine nicht das macht was sie soll, oder ein Fehler beim Porteinlesen. Also vermutlich ein AVR Problem. Gruss Michael
Vielleicht ist NEC so nett, dir den Programmcode zu überlassen? http://www.necel.com/en/faq/mi_com/__com_remo.html
Hallo zusammen Bin mir sicher es ist ein Timingproblem oder ein Problem beim enlesen des Port's. Denn ich lese immer High ein Ist es überhaupt möglich den externen Interrupt sowohl als Flankentrigger wie auch als Eingangsport zu nuzen? Mache ich beim Einlesen einen Fehler? In_Port = IR_PP1; //Lese Wert von Port ein #define IR_PP1 ((PIND & 0x8) >> 3) Gruss und Dank Michael
Viel zu kompliziert. FÜr die kurze zeit, in der das IR-Signal empfangen wird habe ich eine komplett interruptfreie Lösung. Das spart das ganze hin-und her konfigurieren des Interrupts. Ein Timer lasse ich mit 8khz laufen, und vergleiche dann die vergangene Zeit mit meinen Preset-Werten. Läuft sehr stabil. Habe noch eine art überlauf mit eingebaut, das heisst, falls mal mist empfangen wird, und die Übertragung mittendrin aufhört, kann ich sicher sein, dass die Routine zuende geführt wird. (die bytes sind dann=ff) Nimm mal ein Scope und schau dir an, was der TSOP rausgibt, die machen manchmal mist, wenn Energiesparlampen oder Sonnenlicht einfallen.
Hallo Sebastian, wenn du bereits eine funktionierende Lösung hast, kannst du uns dann evtl. den Source zur Vefügung stellen??? MfG
Mein Tip: erstmal ohne interrupts etc, dann kannst du immernoch schauen wie du es abänderst Ist aber Bascom: der timer ist eingestellt auf 8khz und macht folgendes: Timer_irq: Timer0 = Timervorgabe Incr Count Return Do Loop Until I = 1 'normzustand 'Disable Timer0 O1 = 1 Ena = 0 Do 'hier mache ich nen Powerdown oder ähnliches, solange bis ein signal vom tsop kommt Loop Until I = 0 Count = 0 Enable Timer0 Do Loop Until I = 1 Disable Timer0 If Count > 60 Then Count = 0 Enable Timer0 Do Loop Until I = 0 Or Count > 40 Disable Timer0 Byte1 = 0 Byte2 = 0 Byte3 = 0 Byte4 = 0 'byte 1 wird eingelesen For B = 0 To 7 Count = 0 Do Loop Until I = 1 Enable Timer0 O1 = 1 Do Loop Until I = 0 Or Count > 40 Disable Timer0 If Count > 40 Then byte1=255 Else If Count > 7 Then Byte1.b = 1 Next . . . . .
Hallo Michael, hier aus einem Projekt rausgeschnitten mein Code. Wenn Daten empfangen ist ir_daten gesetzt, bei Repeat zusätzlich ir_repeat. Läuft mit Int1 und Timer0 (Timer 1 und 2 waren belegt). Die Daten sind in der Union irdaten als long oder Byteweise verfügbar. Einige Einstellungen liegen an restlichen Programmteilen ;). Gruß Hans
Danke euch beiden. Habe den Fehler mittlerweile gefunden. Saublöd sag ich nur. Hatte nicht daran gedacht das der Zähler ja schon lösläuft und einen Overflow INT Flag setzt. Sobald ich den interrupt enable schalte wird der Interrupt ausgeführt. Deswegen las er immer eine 1 ein. Das findet man aber mit dem Simulator erst raus wenn mann den Simulator ein bisschen laufen lässt bevor man simuliert. Na Ja, viel gelernt! Grüsse Michael
Hi hans, unter welcher Lizenz steht dein Code (nec_x.c)? Ich würde ihn gerne grob modifiziert in ein GPL-Projekt packen, "Public Domain" (soweit es das in Deutschland denn gibt) oder GPL wäre gut. Gruß Seb
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.