Start, Endzeichen und Datenblocklänge würde ich als Konstante hinterlegen. Spart Laufzeit.
Ich habe für mein aktuelles Projekt Datenpakete per UART zu empfangen.
Vorgabe ist das empfangen von 16Byte für die weiterverarbeitung im Hauptprogramm.
Aktuell ist es so gelöst, das die Pakete jeweils mit einem vorgegebenen Startzeichen beginnen müssen.
Diese sind dann entweder bis 16Byte begrenzt oder werden durch ein vorgegebenes Endzeichen abgeschlossen.
Ich möchte mir damit eine art Universelle Übertragung schaffen, die ich für weitere Projekte einfach anpassen kann.
Der Code sieht so aus:
Funktioniert soweit auch zufriedenstellend.Code:'------------------------------------------------------------------------------- 'Variablen '------------------------------------------------------------------------------- Dim Temp_byte As Byte Dim Datenblock(16) As Byte Dim Indexposition As Byte Dim Startzeichen As String * 1 Startzeichen = "{" Dim Endzeichen As String * 1 Endzeichen = "}" Dim Datenblock_komplett As Bit Dim Datenblock_laenge As Byte Datenblock_laenge = 16 Dim Datenblock_string As String * 16 '------------------------------------------------------------------------------- 'Hauptprogramm '------------------------------------------------------------------------------- Do If Datenblock_komplett = 1 Then For Indexposition = 1 To Datenblock_laenge Step 1 Insertchar Datenblock_string , Indexposition , Datenblock(indexposition) Next Print Datenblock_string Datenblock_string = "" Datenblock_komplett = 0 End If Loop End '------------------------------------------------------------------------------- 'Interrupt '------------------------------------------------------------------------------- Serial0charmatch: While Ischarwaiting() = 1 Temp_byte = Inkey() waitus 2000 If Temp_byte = Asc(startzeichen) Then Indexposition = 0 Datenblock_komplett = 0 Elseif Temp_byte = Asc(endzeichen) Then Datenblock_komplett = 1 Else Indexposition = Indexposition + 1 Datenblock(indexposition) = Temp_byte End If If Indexposition = Datenblock_laenge Then Datenblock_komplett = 1 Clear Serialin End If Wend If Indexposition < Datenblock_laenge Then Do Indexposition = Indexposition + 1 Datenblock(indexposition) = 0 Loop Until Indexposition = Datenblock_laenge Datenblock_komplett = 1 End If Return
Kurz noch Beispiele...
Allerdings möchte ich gerne eure Meinung hören, inwieweit es da zu Problemem kommen kann,Code:{1234567890123456} ergibt 1234567890123456 {123456 ergibt 123456 {123456} ergibt 123456 123456 ergibt "nix" (weil kein Startzeichen)
oder ob man das noch optimieren könnte (speziell wegen der Abarbeitungszeit im Interupt).
Derzeit wird per Kabel übertragen... soll aber die nächsten Tage durch ein Funkmodul (APC220) ersetzt werden.
P.S. ... sorry, das es nicht auskommentiert ist... sollte aber trotzdem leicht überschaubar sein.
Geändert von JoeM1978 (03.03.2013 um 20:39 Uhr)
JAAAA... Microchips kann man essen... aber der Geschmack ist furchtbar.
Start, Endzeichen und Datenblocklänge würde ich als Konstante hinterlegen. Spart Laufzeit.
Wenn das Herz involviert ist, steht die Logik außen vor! \/
Joa... hast du recht. werd ich noch anpassen.
Generell geht es mir aber mehr um das einlesen der Bytes in das Array... und späther um das Entschlüsseln
in einzelne "Komandos" ... bzw was ich da jetzt schon für Probleme vermeiden könnte.
In die Gegenrichtung (also senden) werde ich ebenso ein System einfügen mit vermutlich16byte-paketen.
Damit werden dann sensordaten zum pc (zur auswertung) gesendet.
EDIT:
Nachdem gestern das Programm im test funktionierte... heute auf einmal nicht... musste ich fehlersuche betreiben.
Anscheinend ist die Routine für meine derzeitige Baudrate (9600) ZU SCHNELL.
Ich hatte im test hier 2 printbefehle drinn. Dann hats funktioniert.
Also... Ich habs getestet... es werden rund 1500 bis 2000 us Wartezeit benötigt bis überhaupt die Zeichen aus dem
Serial-buff verwendbar sind. Dann geht es wieder
Geändert von JoeM1978 (03.03.2013 um 20:38 Uhr)
JAAAA... Microchips kann man essen... aber der Geschmack ist furchtbar.
Das ist mir noch nicht passiert. Allerdings arbeite ich mit ischarwaiting() in der Hauptschleife. Die Interruptroutine nutze ich nur bei Softuart. Pausen brauchte ich bisher aber nie einbauen.
Wenn das Herz involviert ist, steht die Logik außen vor! \/
Zitat Bascom Hilfe:
When using the BYTEMATCH option, you must preserve the registers you alter.Ich versteh nicht so recht, was das werden soll, aber 2ms in einem Interrupt zu warten, funktioniert gar nicht.oder ob man das noch optimieren könnte
Ist da vielleicht ein BYTEMATCH = ALL in der Config drin ? Dann führt der Code in Verbindung mit dem gepufferte Serialin in's Leere, kurz macht die ganze Sache sinnlos.
Da baut man sich besser selbst 'ne Routine auf Basis des URXC-Interrupts auf.
Halte ich für ein Gerücht, wenn der Code nur mit Delay funktioniert, ist der Wurm drin.Anscheinend ist die Routine für meine derzeitige Baudrate (9600) ZU SCHNELL.
Mein Gefühl von der ganzen Konstruktion ist, die ist reif für die Tonne
Geändert von MagicWSmoke (03.03.2013 um 23:06 Uhr)
Ich kann dir nur empfehlen, die Lib von P.Fleury zu benutzen. Das spart dir viel Ärger und Sucherei und die Lib funktioniert.
http://homepage.hispeed.ch/peterfleu...-software.html
Gruss Hambone
Hallo Hambone,
kannst du bitte noch kurz erklären, wie man die in Bascom einbindet?Ich kann dir nur empfehlen, die Lib von P.Fleury zu benutzen.
@Joe:
wenn du deinen ganzen Code posten würdest, bräuchte man nichts vermuten.Ist da vielleicht ein BYTEMATCH = ALL in der Config drin ?
Gruß, Michael
Oh, das weiss ich nicht, da ich Bascom nicht benutze. Ich arbeite mit GCC. GCC ist auch nicht schwerer als Basic. Ich habe früher mit verschiedenen Basic-dialekten gearbeitet und finde C auf Dauer besser, wenn auch an manchen Stellen gewöhnungsbedürftig (wie Kurzschreibwesen i++ --> i=i+1, wobei das noch harmlos ist.) . Aber es müsste im Forum etwas ähnliches geben. Der Vorteil der Fleury Lib ist, daß die von vielen Usern getestet ist und funktioniert.
Ich kann mich erinnern, dass es früher bei Turbo-Pascal die Möglichkeit gab, C- und / oder Assembler Routinen in den Code einzubinden möglicherweise auch in Bascom?
Gruss Hambone
Inline ASM geht. C-Code lässt sich nicht so einfach einbinden. Ich habe unter Bascom mit dem UART keinerlei Probleme. Das hier beschriebene Problem kann überall liegen, da der Code nicht komplett da steht. Auch möglich, dass der AVR ins Nirvana läuft und dann neustartet und daher die Ausgabe passt.
Ich nutze wie gesagt die IsCharWaiting() Methode ohne Interrupts. Evlt. noch buffered Empfang einstellen. Dann geht nichts verloren. Mein X300T Programm lässt nach dem Starten erstmal eine Meldung mehrere Sekunden übers Display laufen bevor es in die Mainloop geht und trotzdem kann ich einfach schon Daten losschicken. Da geht nichts verloren.
Wenn das Herz involviert ist, steht die Logik außen vor! \/
So... der komplette code wäre dann:
Es ist ohne diese Verzögerung in serial0charmatch.
Das Funkmodul ist an sich schon in betrieb und ich kann dann wahlweise über Kabel oder Funk die Verbindung testen.
Der Hinweis auf die Register ist von mir noch nicht geprüft...
Da muss ich mich erst noch bissl einarbeiten... hab mich mit den Registern noch nicht wirklich beschäftigt.
Was ich auch etwas seltsam finde...
Wenn ich vom pc aus den port öffne und sende... ok. kommt an wie gedacht"... wenn ich den port aber trenne und
ein zweites mal öffne sind irgendwelche "zeichen" im buffer, die mir das ganze array zerschiessen.
wird beim trennen des ports auf der tx/rx-leitung noch was gesendet ??
Das bytematch ist 123 (also wie das Startzeichen { )Code:'------------------------------------------------------------------------------- '------------------------------------------------------------------------------- '------------------------------------------------------------------------------- 'Programmname: UART-Schnittstelle.bas 'Letzte Änderung: 03.03.2013 'Funktion: Empfang von gesamt 18Byte, ' ausgabe als echo über seriell und lcd zur kontrolle 'Mikrocontroller: Mega8 ' 'Input: 'Output: '------------------------------------------------------------------------------- '------------------------------------------------------------------------------- '------------------------------------------------------------------------------- 'Den Atmega mit den passenden Daten füttern. '------------------------------------------------------------------------------- $regfile = "m8def.dat" 'eingesetzter Mikrocontroller $crystal = 8000000 'eingestellte Taktfrequenz (8MHz) $hwstack = 100 'Standardwert $swstack = 100 'Standardwert $framesize = 100 'Standardwert $baud = 9600 '------------------------------------------------------------------------------- 'Ports/Pins/Configs '------------------------------------------------------------------------------- '------------------------------------------------------------------------------- 'Timer/OCR/PWM/ISR usw. setzen '------------------------------------------------------------------------------- Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2 Config Lcd = 16 * 2 Config Serialin = Buffered , Size = 18 , Bytematch = 123 '123={ Enable Interrupts '------------------------------------------------------------------------------- 'Variablen '------------------------------------------------------------------------------- Dim Temp_byte As Byte Dim Datenblock(16) As Byte Dim Indexposition As Byte Dim Startzeichen As String * 1 Startzeichen = "{" Dim Endzeichen As String * 1 Endzeichen = "}" Dim Datenblock_komplett As Bit Dim Datenblock_laenge As Byte Datenblock_laenge = 16 Dim Lcd_position As Byte Dim Datenblock_string As String * 16 '------------------------------------------------------------------------------- 'Hauptprogramm '------------------------------------------------------------------------------- Cls Waitms 100 Do If Datenblock_komplett = 1 Then 'UART-Datenblock in String füllen For Indexposition = 1 To Datenblock_laenge Step 1 Insertchar Datenblock_string , Indexposition , Datenblock(indexposition) Next Disable Interrupts 'Ausgabe/Abarbeiten des UART-Datenblock Cls Waitms 100 For Indexposition = 1 To 3 Step 1 Lcd_position = Indexposition Locate 1 , Lcd_position Lcd Chr(datenblock(indexposition)) Next For Indexposition = 3 To Datenblock_laenge Step 1 Lcd_position = Indexposition - 8 Locate 2 , Lcd_position Lcd Chr(datenblock(indexposition)) Next 'Echo zurücksenden zur Kontrolle Print Datenblock_string Datenblock_string = "" Datenblock_komplett = 0 Enable Interrupts End If Loop End '------------------------------------------------------------------------------- 'Interrupt '------------------------------------------------------------------------------- Serial0charmatch: While Ischarwaiting() = 1 Temp_byte = Inkey() Waitus 2000 Locate 2 , 13 Lcd Chr(temp_byte) Wait 1 If Temp_byte = Asc(startzeichen) Then Indexposition = 0 Datenblock_komplett = 0 Elseif Temp_byte = Asc(endzeichen) Then Datenblock_komplett = 1 Else Indexposition = Indexposition + 1 Datenblock(indexposition) = Temp_byte End If If Indexposition = Datenblock_laenge Then Datenblock_komplett = 1 Clear Serialin End If Wend If Indexposition < Datenblock_laenge Then Do Indexposition = Indexposition + 1 Datenblock(indexposition) = 22 Loop Until Indexposition = Datenblock_laenge Datenblock_komplett = 1 Clear Serialin End If Return
Nachtrag: ... bei dem jetzigen code... wenn ich die verzögerung rausnehm...
Ich sende {xyz1234567890123}
es kommt die ersten 2 vorgänge nur "leerstellen" ins array... ab dem dritten dritten mal ist dann
"y} " im Array
Geändert von JoeM1978 (04.03.2013 um 19:05 Uhr)
JAAAA... Microchips kann man essen... aber der Geschmack ist furchtbar.
Lesezeichen