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.
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.
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.