Hi, Ich erhalte via simplem AM Denodulator/Slicer bits an P2.3. Die Bitrate ist etwa 160kbps. Eingeleitet wird ein Transfer über eine „Päambel“ bei der der Eingang für eine bestimmte Zeit auf 0 geht und dann 1 und 0 (Das Protokoll könnte ich ggf. anpassen ... PWM, Manchester code etc geht aber eher nicht). Was ist der eleganteste Weg so einen Receiver zu implementieren? 1.) Einfach von P2IN lesen und versuchen das timing mit NOPs hinzubekommen? 2.) I/O interrupt auf edges? Aber was wenn ich keine garantierte Transition per bit habe? 3.) Timer A? Welcher Mode? Wenn ich zuerst den I/O interrupt nehme und auf eine fallende Flanke warte dann habe ich den „asynchronen“ Start gefunden. Hier könnte ich SMCLK auf 16 MHz setzen und den Counter bis 100 zählen lassen („up Mode“). Das gäbe mir 160kbps. Allerdings sample ich dann am Ende des Bits was nicht optimal ist. Wie bekomme ich das reliable zusammen sodass die Bits möglichst in der Mitte ausgelesen werden? LG, Peter
Leider zeigst du uns kein komplettes Datentelegramm. Von dem, was du beschreibst, könnte ein UART die Lösung sein, das es in den G2xx3 bis G2xx5 zwar gibt, aber nicht auf P2. Ich habe zwar eine Idee, wie ich das (in Assembler) machen würde, aber bevor ich mich auslasse, um dann festzustellen, dass das in deiner Situation doch nicht geht, hätte ich gerne die vollständige Beschreibung des Telegramms.
Mit Timer_A im Compare-Modus findest du den Zustand des Eingangs zum Ablaufzeitpunkt im SCCI-Bit. Peter M schrieb: > Allerdings sample ich dann am Ende des Bits was nicht optimal ist. Direkt nach der ersten Flanke setzt du CCRx ein mal auf den halben (or 3/2) Wert, dann landest du in der Mitte.
:
Bearbeitet durch User
Hi Der Zahn der Zeit & Clemens,
Danke! Erstmal sorry, ich glaub ich war da etwas unklar da jemand den
Titel nach MSP430P2 geaendert hat. Mit P2 meinte ich Port 2 (Port 2.3
konkret). Die Hardware ist vorhanden, ich moechte hardwareseitig nichts
aendern und deswegen wollte ich das erwaehnen fuer den Fall dass es
ueber UARTs etc. an anderen Pins moeglich waere.
Mein exaktes Device ist MSP430FR5969.
> Leider zeigst du uns kein komplettes Datentelegramm.
1 | (Delimiter,12.5us) 1 0 1 1 1 0 0 1 1 ... |
2 | ___ __ ______ ___ |
3 | \_________________/ \__/ \____/ \__ |
Das Signal ist "active high" und die Uebertragung beginnt mit einem Delimitter das ca. 12.5us ist. In diesem Delimiter geht das signal auf low. Danach folgen 2-3 Bits Preambel (z.B. 1 0 aber das kann geaendert werden). Dann folgen die Datenbits, im oberen Beispiel 1 1 1 0 0 1 1. Jedes Bit ist etwa 1/160kHz=6.25us lang. > Ich habe zwar eine Idee, wie ich das (in Assembler) machen würde, aber > bevor ich mich auslasse, um dann festzustellen, dass das in deiner > Situation doch nicht geht, hätte ich gerne die vollständige Beschreibung > des Telegramms. Wunderbar. > Mit Timer_A im Compare-Modus findest du den Zustand des Eingangs zum > Ablaufzeitpunkt im SCCI-Bit. Der Zustand des Einganssignals ist ob mein Port 2.3 signal 0 oder 1 ist? Gut, dann brauche ich ja gar nicht explizit von P2IN zu lesen? > Direkt nach der ersten Flanke setzt du CCRx ein mal auf den halben (or > 3/2) Wert, dann landest du in der Mitte. Ja, gute Idee. Ist folgende Strategie die richtige?
1 | 1.) Interrupt auf fallende Flanke von P2.3 |
2 | 2.) In der ISR mit NOPs zaehlen ob der Delimiter etwa 12.5us lang ist. Falls nein --> return |
3 | 3.) Falls ja, warten auf die naechste fallende Flanke (die nach dem ersten "1"). |
4 | 4.) Timer A im compare Modus starten: |
5 | a) P2.3 auf "primary module selection" aendern (via P2SEL0/P2SEL1) |
6 | b) TA0CCR auf 16MHz/160kHz = 100 setzen. |
7 | c) Counter (TA0CR) auf -50 setzen und timer starten |
8 | d) Der erste compare interrupt sollte nach 150 timer zyklen kommen, also inter Mitte vom zweiten "1" bit. |
9 | e) Folgende interrupts kommen in der Mitte der folgenden Bits |
10 | f) Bit via TA0CCTL (bit SCCI) auslesen und speichern |
11 | g) Abbruch wenn genuegens Bits gelesen sind. |
Peter M schrieb: > Mit P2 meinte ich Port 2 (Port 2.3 konkret) Das hatte ich auch genau so verstanden... > Die Hardware ist vorhanden, ich moechte hardwareseitig nichts > aendern ... und davon bin ich ausgegangen. Was in deinem Datentelegramm vielleicht noch fehlt, ist die Anzahl der Datenbits und/oder wo dran man das Ende des Telegramms erkennt und ggf. wie lange das Ende vom nächsten Anfang entfernt ist. Aber wahrscheinlich geht es auch so: Idle: Einen Interrupt auf die neg. Flanke P2.3 einrichten. Wenn Delimiter low: Mit Pollen oder einem weiteren Interrupt auf die pos. Flanke warten. Wenn Delimiter high: Timer (CCR0) auf eine halbe Bitzeit (~3.12 µs) setzen. Z. B. Bitzähler setzen Bei jedem Timerinterrupt: - Bit einlesen - Bit in ein Schieberegister - Timer (CCR0) auf eine ganze Bitzeit (~6.25 µs) setzen Letzteres ist prinzipiell nur beim ersten mal nötig. Das zu sparen ist möglich, dürfte aber unnötig umständlich sein. Interrupt-Routine Bit einlesen und ins Schieberegister:
1 | TA_Int:
|
2 | bit.b #BIT3,&P2IN ;Setzt auch Carry = .not. Zero |
3 | rrc Rx ;Rx = Eins der Register, max. 16 Bit |
4 | mov #99,&TACCR0 ;(oder muss es 100 sein?) |
5 | ;Jetzt noch irgendwas zur Ende-Erkennung, z. B. |
6 | dec Ry ;Bits zählen |
7 | jnz RetInt |
8 | clr #GIE,&SR ;(Global) Interrupt disable |
9 | RetInt
|
10 | reti
|
In der Hauptroutine wird nachgesehen, ob Ry 0 ist, wenn ja, ausgewertet. Dann wieder Idle, also alles von vorne: Ry wieder auf Anzahl der Bits gestellt, Interrupt auf Flanke, GIE wieder gesetzt, warten auf Delimiter etc.. Ich neige dazu, auch bei wenigen Zeilen mal Blödsinn zu schreiben. Es ist doch angenehm, wenn man weniger Probleme als ein Chirurg bekommt, wenn man mal einen Fehler macht...
Peter M schrieb: > 1.) Interrupt auf fallende Flanke von P2.3 > 2.) In der ISR mit NOPs zaehlen ob der Delimiter etwa 12.5us lang ist. > Falls nein --> return NOPs in der ISR sind pfuibäh. DAnn kannst du auch gleich in der Main Loop pollen. Folgenden Ansatz würde ich verwenden: * Interrupt auf fallende Flanke von P2.3 * Timer starten und nach 11 und 14 µs jeweils die ISR triggern lassen (das geht bequem über TACCR0 und TACCR1 - Achtung, zwei verschiedene ISR). Dann kannst du schauen, ob dazwischen eine steigende Flanke war. * Nun den Timer so einstellen, dass die ISR ganz gemütlich immer in der Mitte des Bits (oder auch in der zweiten Bithälfte) zurückliest. Der Rest ist ein bisschen Bitschieberei. Timer im Capture Mode geht natürlich auch, dann muss man aber 1. in der ISR jeweils die Triggerbedingung zwischen steigend und fallend umschalten 2. bei mehreren aufeinander folgenden gleichen Bits (wo der Flankenwechsel ja fehlt) dann in der ISR die Anzahl der Bits rückrechnen 3. eine Lösung für das Ende des Datenpakets finden - wenn Idle = High und die letzten Bits ebenfalls High sind, triggert die ISR ja nicht. Gruß, Max
Peter M schrieb: > Ist folgende Strategie die richtige? Grundsätzlich ja. > 1.) Interrupt auf fallende Flanke von P2.3 Das ginge auch mit dem Timer im Capture-Modus. Dann hast du den genauen Zeitpunkt der Flanke und kannst so die folgenden Zeiten für die Bit-Mitten genauer festlegen. > 2.) In der ISR mit NOPs zaehlen ob der Delimiter etwa 12.5us lang ist. > Falls nein --> return > 3.) Falls ja, warten auf die naechste fallende Flanke (die nach dem > ersten "1"). Du könntest auch für die zweite fallende Flanke noch Capture-Modus benutzen, dann musst du nur prüfen, ob der Abstand ca. 18.75 µs ist. > b) TA0CCR auf 16MHz/160kHz = 100 setzen. Wenn du mit Capture-Modus anfängst, dann benutzt du Continuous-Modus, und musst auf CCR den entsprechenden Abstand immer wieder dazuaddieren.
Hi Der Zahn der Zeit, Max, Clemens, Danke das hilft sehr weiter! Ich werde mit der dem Flankentrigger und der TA_Int routine beginnen. Ende ist einfach nach N bits. Also genau wie du geschrieben hast (dec Ry, jnz retInt). Peter
Peter M schrieb: > (Delimiter,12.5us) 1 0 1 1 1 0 0 1 1 ... > __ __ _____ ___ > \_________________/ \__/ \____/ \__ Das erinnert mich an was, mmmhh ... Wie konstant ist die Bitzeit? Wie lang ist ein Datentelegramm? Die Darstellung trügt, den Delimiter ist nur 2 Bit lang; es könnten auch zwei '0' mitten im Telegramm sein. Wie wird zwischen den Teilnehmern synchronisiert?
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.