Hallo, im Zuge meine Ausbildung zum Elektroniker für Geräte und Systeme arbeite ich im Moment an einem PIC Projekt. Ich habe mir bereits angesehen wie ich den UART im PIC auswerte und Daten über RS232 empfange und sende. Jetzt habe ich jedoch das Problem das ich 4 Variablen von 0-255 von einem PIC zum anderen übergeben möchte. Wie kann ich dem PIC beibringen welches empfangene Byte zu welcher Variablen gehört? Ich habe erst wenige Monate Erfahrung mit der Programmierung weshalb ich mich freuen könnte wenn sich jemand kurz Zeit nimmt um mir zu erklären wie ich eine solche Auswertung prinzipiell zu Stande bekomme. Google konnte mir leider nicht wirklich helfen... vielen Dank schon mal im voraus
Marcel Meyer schrieb: > 4 Variablen von 0-255 Wenn es nicht um Geschwindigkeit geht, wäre ein ASCII Kodierung am einfachsten, z.B.: <STX> <High-Nibble Var.1> <Low-Nibble Var.1> <High-Nibble Var.2> .... wobei "High Nibble" und "Low Nibbel" die beiden ASCII-kodierten Stellen der Hexadezimalzahl der Variablen sind. Der Empfänger wartet dann auf <STX> und die nächsten 8 Zeichen sind die 4 Variablen. Wenn man am Ende dann noch <CR> und <LF> sendet, kann man sich die Daten auch einfach mit einem Terminalprogramm in Listenform ansehen. Gruß Dietrich
Marcel Meyer schrieb: > das ich 4 Variablen von 0-255 von > einem PIC zum anderen übergeben möchte a) Billige Möglichkeit, Vorsicht Bitfummelei und nicht erweiterbar: Teile die Variablen auf in 8 Nibbles zu 4 Bit. Die restlichen 4 bit dienen der Darstellung, zu welchem Nibble jetzt die gerade gesendete Information gehört. Wenn zu einer 8Bit Variable zwei Nibbles eingetroffen sind, wird sie in die Datenhaltung übernommen. Das eine verbleibende Bit kann für ein Toggle genutzt werden, um einfachst sicherzustellen, dass die gerade gesendeten Nibbles einer Variable auch zum selben Zeitpunkt beim Sender gesampled wurden. b) Ein Protokoll aufsetzen, dazu eignet sich z.B. ein vorhandenes wie Modbus oder ähnliches.
OK also das mit der ASCII Kodierung hört sich sinnvoll an. Jetzt wäre nur die Frage, wie ich so etwas in Assembler umsetzen kann. Als erstes Stelle ich mir die Frage wie ich aus einem Nibble ein ASCII Zeichen erstellen kann, das ich dann ausgebe?
Marcel Meyer schrieb: > Als erstes Stelle ich mir die Frage wie ich aus einem Nibble ein ASCII > Zeichen erstellen kann, das ich dann ausgebe? Google sagt mir auf die Schnelle: http://www.piclist.com/techref/microchip/math/radix/b2ah-8b2a-sd.htm (ohne Garantie!) Gruß Dietrich
Du könntest auch ein Escape-Zeichen (z.b. 0x1B) definieren, das kennzeichnet, dass das darauf folgende Zeichen ein Kommando darstellt. Ein Kommando könnte dann bedeuten "Beginn der Übertragung" (z.B. 0x02). Es kann aber natürlich passieren, dass man das Escape-Zeichen 0x1B auch mal als Nutzdaten braucht. Ein "Kommando" muss also sein "Das Escape-Zeichen ist in den Nutzdaten" (z.B. 0x01). Beispiel 1: Die Variablen sollen die Werte 0x11, 0x12, 0x13, 014 bekommen. Die Übertragung sieht folgendermaßen aus: 0x1B (Escape-Zeichen: Das folgende Zeichen ist ein Kommando) 0x02 (Kommando: Beginn der Übertragung) 0x11 (Wert für Variable 1) 0x12 (Wert für Variable 2) 0x13 (Wert für Variable 3) 0x14 (Wert für Variable 4) Beispiel 2: Die Variablen sollen die Werte 0x1A, 0x1B, 0x1C, 0x1D bekommen. Die Übertragung sieht folgendermaßen aus: 0x1B (Escape-Zeichen: Das folgende Zeichen ist ein Kommando) 0x02 (Kommando: Beginn der Übertragung) 0x1A (Wert für Variable 1) 0x1B (Escape-Zeichen: Das folgende Zeichen ist ein Kommando) 0x01 (Kommando: "Das Escape-Zeichen ist in den Nutzdaten": Wert für Variable 2 = 0x1B) 0x1C (Wert für Variable 3) 0x1D (Wert für Variable 4) Beim Empfangen der Daten muss man also den Datenstrom immer auf das Escape-Zeichen 0x1B hin prüfen. Wenn es auftaucht, sagt das darauf folgende Zeichen, was zu tun ist. Nur wenn die Kombination 0x1B, 0x02 auftaucht, handelt es sich um einen gültigen Übertragungsbeginn.
:
Bearbeitet durch User
Okay also nochmal zum Verständnis: ich suche mir ein Escape Byte aus und ein Kommande Byte z.B ASCII STX und ETX. Dann sende ich meine Variablen in aufgeteilten Nibbles von ASCII 0-F . Damit umgehe ich das STX und ETX in den Nutzdaten vorkommt. Somit ist das Datenpaket immer eindeutig oder? Und im Empfänger prüfe ich immer auf STX und habe daraufhin eine eindeutige Zuordnung der Daten die ankommen Soweit alles richtig verstanden? Macht es sinn noch ein schluss Zeichen zu senden und da nach eine kurze Pause einzulegen? Da ich immer genau vier Variablen übertrage brauche ich kein Schlussbit oder?
Marcel Meyer schrieb: > ich suche mir ein Escape Byte aus und ein Kommande Byte z.B ASCII STX > und ETX. Dann sende ich meine Variablen in aufgeteilten Nibbles von > ASCII 0-F . Damit umgehe ich das STX und ETX in den Nutzdaten vorkommt. > Somit ist das Datenpaket immer eindeutig oder? Das ist doppelt gemoppelt. Wenn Du die Daten in Nibbles sendest, brauchst Du nichts escapen. Jedes gesendete Byte besteht aus 4 Bit Kommando und 4 Bit Nutzdaten. Die Kommandos könnten z.B. sein: 0x0: Variable 1, Low-Nibble 0x1: Variable 1, High-Nibble 0x2: Variable 2, Low-Nibble 0x3: Variable 2, High-Nibble 0x4: Variable 3, Low-Nibble 0x5: Variable 3, High-Nibble 0x6: Variable 4, Low-Nibble 0x7: Variable 4, High-Nibble Wenn Du dann den Variablen die Werte 0x3A, 0x4B, 0x5C, 0x6D zuweisen willst, ist die gesendete Folge: 0x0A: Variable 1, Low-Nibble = 0xA | 0x13: Variable 1, High-Nibble = 0x3 -> Variable 1 = 0x3A 0x2B: Variable 2, Low-Nibble = 0xB | 0x34: Variable 2, High-Nibble = 0x4 -> Variable 2 = 0x4B 0x4C: Variable 3, Low-Nibble = 0xC | 0x55: Variable 3, High-Nibble = 0x5 -> Variable 3 = 0x5C 0x6D: Variable 4, Low-Nibble = 0xD | 0x76: Variable 4, High-Nibble = 0x6 -> Variable 4 = 0x6D Bei meinem Vorschlag benutzt Du dagegen ein Escape-Zeichen, um Kommandos wie "Übertragungsbeginn" im Datenstrom "hervorzuheben". Die Werte können dann (abgesehen vom Fall, dass das Escape-Zeichen in den Nutzdaten vorkommt) unverändert byteweise übertragen werden. Marcel Meyer schrieb: > Macht es sinn noch ein schluss Zeichen zu senden und da nach eine kurze > Pause einzulegen? Da ich immer genau vier Variablen übertrage brauche > ich kein Schlussbit oder? Eine Kommando "Übertragungsende" kannst Du natürlich einfügen, ist aber nicht unbedingt nötig, genau wie eine Pause. Bei beiden Verfahren kannst Du in einem Datenstrom mit beliebigem Beginn ohne Zeitinformation den Beginn der Übertragung eindeutig erkennen. Das Ende ergibt sich von alleine daraus, dass Du ja weißt, dass Du genau vier Variablen befüllen willst. Bei der Version mit den Nibbles könntest Du sogar nur einzelne Variablen ändern. Es ist allerdings schlechter um weitere Kommandos erweiterbar.
:
Bearbeitet durch User
Marcel Meyer schrieb: > Soweit alles richtig verstanden? Ja. > Macht es sinn noch ein schluss Zeichen zu senden und da nach eine kurze > Pause einzulegen? Da ich immer genau vier Variablen übertrage brauche > ich kein Schlussbit oder? Nein, ein Schlusszeichen brauchst Du nicht. Aber eine Pause ist ggf. ganz sinnvoll, damit der Empfänger Zeit hat das empfangene Telegramm auszuwerten, bevor er wieder empfangsbereit ist für das nächste Telegramm. Das hängt natürlich ab von Übertragungsgeschwindigkeit und von der Realisierung der SW (Polling, interruptgesteuert, ...). Gruß Dietrich
Ok kurzes Verständnis Problem: wenn ich eine 8Bit breite Variable übertragen möchte, ist es doch notwendig diese in zwei nibbles zu zerlegen damit ich sie sinnvoll aus zwei ASCII Zeichen von 0-F übertragen kann. wenn ich den Wert nur als High Nibble sende habe ich doch nur noch einen 4Bit breiten Wert für den Inhalt der Variable zur Verfügung? Dann macht es doch sinn das mit Escape und Kommand zu machen?
Mal ganz grundsätzlich: Du willst vier 8-Bit-Wörter übertragen und hast dafür einen Strom aus 8-Bit-Wörtern zur Verfügung. Das Problem ist, dass Du noch mindestens die Steuerinformation übertragen musst, wo Deine Übertragung beginnt, damit Du die vier Werte den korrekten Variablen zuordnen kannst. Wenn Du 8 Bit in 8-Bit-Wörtern direkt kodierst, sind allerdings keine freien Wörter für die Steuerdaten mehr übrig. Es gibt jetzt verschiedene Möglichkeiten, diese Steuerinformation mit in den Datenstrom zu kodieren: 1) Du kodierst ein 8-Bit-Wort in 8 Bit. Für die Kommandos nutzt Du ein Escape-Zeichen mit besonderer Bedeutung. Wenn dieses Zeichen in den Nutzdaten auftritt, muss es gesondert behandelt werden. Das habe ich im Beitrag um 16:37 beschrieben. 2) Du kodierst ein 8-Bit-Wort in zwei 8-Bit-Worten. 2a) Du nutzt jeweils 4 Bit innerhalb eines Bytes für das Kommando und die anderen 4 Bit für die Daten. Man braucht dann keine zusätzlichen Steuerzeichen, weil die Kommandos in 4 Bit jedes übertragenen Bytes stehen. Das habe ich im Beitrag um 17:08 beschrieben. 2b) Du überträgst jeweils 4 Bit als ASCII-Zeichen (das 8 Bit braucht). Dann hast Du noch eine Menge anderer Zeichen als Steuerzeichen zur Verfügung. Eine Übertragung könnte also aus einem Startzeichen und 8 ASCII-Zeichen ('0' bis 'F') bestehen. Es gibt bestimmt auch noch viele andere Möglichkeiten. Welche Du nimmst, musst Du entscheiden. Der Platzbedarf auf dem Bus ist unterschiedlich, aber für Dich vermutlich nicht relevant. Der Programmieraufwand ist bei allen recht ähnlich. Im Prinzip also reine Geschmackssache.
Ok ich denke jetzt habe ich verstanden wie du es gemeint hast. =) Ich werde mich morgen mal an den Quellcode geben und das gannze mal testen. Sollte ich dabei noch auf weitere Probleme stoßen muss ich nochmal fragen an sonnsten gebe ich zeitnah nochmal Feedback ob alles geklappt hat =) Auf jedenfall schonmal vielen Dank für die detailierte Beschreibung!
Normalerweise benutzt man dazu 9bit uart. bit9 gesetzt ist Addresse, sprich FSR und nicht gesetzt ist Daten, sprich INDF
So, also das hier wäre jetzt mein Quellcode: mainloop call PWM_R_ASCII call PWM_G_ASCII call PWM_B_ASCII call DMX_Adress_ASCII call RS232senden goto mainloop PWM_R_ASCII movfw PWM_R call umwandeln_B2ASCII movwf PWM_RL movfw high_nibble_senden movwf PWM_RH return PWM_G_ASCII movfw PWM_G call umwandeln_B2ASCII movwf PWM_GL movfw high_nibble_senden movwf PWM_GH return PWM_B_ASCII movfw PWM_B call umwandeln_B2ASCII movwf PWM_BL movfw high_nibble_senden movwf PWM_BH return DMX_Adress_ASCII movfw DMX_Adress call umwandeln_B2ASCII movwf DMX_AdressL movfw high_nibble_senden movwf DMX_AdressH return RS232senden btfss PIR1,TXIF ; Prüfe ob senden erlaubt goto RS232senden movlw D'2' ; Entspricht dem ASCII "STX" movwf TXREG movfw PWM_RH movwf TXREG ; Register zur Ausgabe auf UART movfw PWM_RL movwf TXREG movfw PWM_GH movwf TXREG ; Register zur Ausgabe auf UART movfw PWM_GL movwf TXREG movfw PWM_BH movwf TXREG ; Register zur Ausgabe auf UART movfw PWM_BL movwf TXREG movfw DMX_AdressH movwf TXREG ; Register zur Ausgabe auf UART movfw DMX_AdressL movwf TXREG return ;----------------------------------------------------------------------- ; Konvertiert ein byte in w in zwei ASCII Zeichen von 0-F! Gibt das obere ; Nibble in char_hi aus und das untere Nibble in W ;----------------------------------------------------------------------- umwandeln_B2ASCII movwf high_nibble_senden swapf high_nibble_senden,w andlw 0x0f addlw 6 skpndc addlw 'A'-('9'+1) addlw '0'-6 xorwf high_nibble_senden,w xorwf high_nibble_senden,f xorwf high_nibble_senden,w andlw 0x0f addlw 6 skpndc addlw 'A'-('9'+1) addlw '0'-6 return Jetzt denke ich mir das das so eigentlich klappen müsste. Anzumerken habe ich nur das ich keine Idee gefunden habe mehrere Variablen mit einer Funktion auszugeben. Ich habe mich ja hier im Quellcode oft wiederholt. Gibt es da eine Möglichkeit der Vereinfachung? Was sagt das ExpertenAuge zu meinem Programm. Ist wie gesagt die Variante mir ESCAPE Byte am Anfang...
das ganze scheint auch irgendwie nicht zu funktionieren =( HyperTerminal zeigt nur LLLLL..... an
Wieso du aber binary mit ascii mischt, ist mir unverstàndlich. Da kannst du genausogut die Daten direkt senden, und wenn du die Daten mit 0xAA (anstelle von 2, ist sicherer) veroderst, dann kommt auch kein 0xAA in den Daten vor. so z.B. sendrs232 movlw 0xAA call rs232TX movfw data xorlw 0xaa call rs232TX ... und beim empfang, machst du ;empfang von Zeichen in W xorlw 0xaa bz stx_empfangfen movwf INDF btfss FSR,?? ; verhindert overflow, man muss aber ; dazu die Variablen planen incf FSR Du kònntest genauso z.B. '\n' als Endzeichen nehmen. Es setzte dir den Pointer wieder auf null und nach RS232senden btfss PIR1,TXIF ; Prüfe ob senden erlaubt goto RS232senden movwf TXREG return DatensatzSenden movlw D'2' ; Entspricht dem ASCII "STX" call RS232senden swapf PWM_B,w call nibble2hex call RS232senden movfw PWM_B call nibble2hex call RS232senden ... return ;----------------------------------------------------------------------- ; Konvertiert ein byte in w in zwei ASCII Zeichen von 0-F! Gibt das obere ; Nibble in char_hi aus und das untere Nibble in W ;----------------------------------------------------------------------- nibble2hex andlw 0x0f addlw 6 skpndc addlw 'A'-('0'-6) addlw '0'-6 return
OK also das Grundprogramm läuft jetzt soweit Fehlerfrei. Ich muss mich jetzt nochmal damit befassen wie ich das ganze mit dem FSR und INDF etwas kompakter gestalten kann. Wenn da jemand einen Tipp hat wäre ich froh, werde mich aber parallel da mal einlesen
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.