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
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.
Eine Wartezeit wie ein Waitus 2000 sollte nicht im Interrupts sein. Auch die Ausgabe auf das LCD ist ggf. ein Problem, auch wenn das wohl eher eine HIlfe zur Fehlersuche ist. So wie es jetzt gemacht ist, wird die Wartezeit gebraucht damit in der Zeit die zur Verarbeitung von 1 byte schon das Nächste byte ankommt. Entsprechend sollte die Wartezeit zusammen mit der Laufzeit auf die Bautrate abgestimmt sein. Dabei kann der recht langsame LCD Befehl ggf. die extra Wartezeit auch ganz ersetzen, was vor allem Zeigt das man LCD(...) in der ISR vermeiden sollte.
Die Interrupt Routine sollte so schnell sein, das immer nur 1 Byte verarbeitet wird - die while Schleife ist also eigentlich überflüssig. Damit muss natürlich dann auch die Abfrage auf das vorzeitige Ende eines Datenblocks anders gelöst werden, z.B. in die IF Abfrage mit ASC(endzeichen).
Was an sich meine erste Vermutung dann bestätigen würde...
nämlich das die abarbeitung zu schnell abläuft und das nächste zeichen noch garnicht im Buff vorliegt.
Wenn das dann so stimmt weiss ich ja, wo ich ansetzen muss...
JAAAA... Microchips kann man essen... aber der Geschmack ist furchtbar.
Da ist auch ein Wait 1 in der isr...
So würde ich es wohl probieren: (ungetestet, da nur Laptop hier und keine Hardware)
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 = 40 'Standardwert $swstack = 40 'Standardwert $framesize = 20 '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 Enable Interrupts '------------------------------------------------------------------------------- 'Variablen '------------------------------------------------------------------------------- Dim Temp_byte As Byte Dim Datenblock(16) As Byte Dim Indexposition As Byte Const Startzeichen = 123 Const Endzeichen = 125 Const Datenblock_laenge = 16 Dim Datenblock_komplett As Bit Dim Lcd_position As Byte Dim Datenblock_string As String * 16 Dim Datenblock_byte(16) As Byte At Datenblock_string Overlay '------------------------------------------------------------------------------- 'Hauptprogramm '------------------------------------------------------------------------------- Cls Waitms 100 Do If Ischarwaiting() = 1 Then Gosub Empfangen End If If Datenblock_komplett = 1 Then Reset Datenblock_komplett Gosub Anzeige End If Loop End Anzeige: 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 Return Empfangen: Temp_byte = Inkey() If Temp_byte > 12 Then 'unter 13 sind nur Sonderzeichen If Temp_byte = Startzeichen Then Indexposition = 0 Elseif Temp_byte = Endzeichen Then Gosub Auswerten Else Incr Indexposition Datenblock(indexposition) = Temp_byte End If If Indexposition = Datenblock_laenge Then Gosub Auswerten End If End If Return Auswerten: Dim Dummy As Byte Datenblock_string = String(datenblock_laenge , 0) Dummy = Memcopy(datenblock(1) , Datenblock_byte(1) , Indexposition) Datenblock(1) = String(datenblock_laenge , 22) 'Wozu? Indexposition = 0 Set Datenblock_komplett Return
Wenn das Herz involviert ist, steht die Logik außen vor! \/
Wie schon gesagt, das ganze Konzept ist kompletter Käse, Du hast das Prinzip Interrupt-gesteuerter Verarbeitung überhaupt nicht verstanden.
Der BYTEMATCH ist normalerweise dafür vorgesehen, das Ende einer Übertragung zu erkennen. Es ist nicht dafür gedacht den Anfang zu erkennen und dann solange in der ISR rumzurödeln und alles andere zu blockieren, bis man die Zeichenkette empfangen hat. Wofür soll dann der gepufferte Empfang überhaupt noch gut sein?
Das hier ist jetzt in ein paar Minuten entstanden und sollte eigentlich funktionieren. "Eigentlich", weil nicht auf Hardware getestet, aber vielleicht siehst Du die Idee.
Code:$regfile = "m8def.dat" $crystal = 8000000 $hwstack = 100 $swstack = 100 $framesize = 100 $baud = 9600 Const block_wait = 0 Const block_receive = 1 Const block_length = 16 Const False = 0 Const True = 1 Dim rx_state As Byte Dim buff(block_length) As Byte Dim data_block(block_length) As Byte Dim db_index As Byte Dim rcvd_char As Byte Dim rcv_complete As Bit Dim tmp As Byte rx_state = block_wait db_index = 0 rcv_complete = False On URXC UART_Get_Char Enable URXC Enable Interrupts Do If rcv_complete = True Then Printbin data_block(1) rcv_complete = False End If Loop UART_Get_Char: rcvd_char = UDR Select Case rx_state Case block_wait: If rcvd_char = "{" Then rx_state = block_receive Case block_receive: If rcvd_char <> "}" Then If db_index < block_length Then Incr db_index buff(db_index) = rcvd_char Else db_index = 0 rx_state = block_wait End If Else If db_index > 0 Then tmp = memcopy(buff(1) , data_block(1) , db_index) rcv_complete = True End If db_index = 0 rx_state = block_wait End If End Select Return
Lesezeichen