Hallo zusammen
Habe ein Problem in BASCOM mit der HW UART und der Funktion Bytematch.
Mein Programm läuft auf einem ATmega328, und liest in der main loop
verschiedene Sensorwerte ein und verarbeitet diese entsprechend weiter.
Zusätzlich soll der AVR Daten von einem GPS verarbeiten, die über die HW
UART rein kommen. Ein GPS-Datensatz beginnt mit '$' und endet mit CRLF.
Um das ende zu erkennen habe ich die funktion Bytematch verwendet.
Soweit funktioniert auch alles, jedoch nach ca. 500 empfangenen
Datensätzen wird irgendwie das RAM oder der Stack durcheinander
gebracht, und der AVR macht dann irgend welchen komischen sachen.
Ohne GPS, also ohne empfangenen UART Daten, läuft der AVR stundenlang
ohne Probleme, der Fehler muss also irgendwo in der Empfangsroutine der
HW UART liegen.
Um mal die ganze GPS Datenverarbeitung auszuschliessen sende ich zum
testen '$TEST' an den AVR, und der soll dann mit '1234' antworten. Dies
funktioniert die ersten 500 mal, und irgendwann gerät im RAM oder Stack
etwas durcheinander...
Also hier mal ein Code Ausschnitt mit den UART relevanten Teilen (anbei
der ganze Code):
in der Bascom Hilfe steht, dass man bei Verwendung von Bytematch die
register selber sichern muss, habe ich bereits mit Pushall/popall
versucht, hat aber auch nichts genützt.
Hat jemand Erfahrungen mit dem Bytematch ? gibt es irgendwelche
speziellen eigenheit von Bascom die man berücksichtigen muss ?
'0011.BAS: Optimierter String-Empfang
$Regfile = "2313def.dat"
$Crystal = 3686400
$Baud = 9600
Dim s As String*10 At &H60
Dim b(11) As Byte At &H60 Overlay
Dim n As Byte
On URXC OnRxD
Enable URXC
Enable Interrupts
Main:
If n > 9 Then
Print s
n = 0
End If
Goto Main
OnRxD:
Incr n
b(n) = UDR
Return
Der String wird auf Adresse &H60 im AVR abgelegt. Dies ist die Adresse
des ersten Bytes im SRAM (da der AT90S2313 über 128 Bytes SRAM vefügt,
ist die höchste SRAM-Adresse &HDF). Quasi "darüber", also auf die selbe
Adresse, legen wir ein Feld, das genauso lang wie der String ist. Das
ist alles. Der Trick ist nur, daß wir beim Füllen des Strings in unserem
Anwendungsfall am effizientesten mit einem Feld arbeiten können, während
in anderen Fällen die Arbeit mit einem String günstiger sein kann.
Welche Wege man in der Praxis gehen will, hängt natürlich immer von der
Anwendung ab. Die Anwendung des Overlay-Tricks kostet weder zusätzlichen
Code, noch SRAM. Es ist vielleicht eher wie die Auswahl zwischen
Buddelschippe, Schaufel und Bagger bei ein und dem selben Haufen Sand.
Und noch ein drittes UART-Mißverständnis trat wiederholt auf: Der
UART-Empfangs-Interrupt meldet, daß ein Zeichen empfangen wurde. In der
Interrupt-Routine kann man deshalb auch immer nur ein Zeichen auslesen.
Zum Beispiel macht es daher keinen Sinn, in der Interrupt-Routine den
Bascom-Befehl Input einzusetzen, um doch mehrere Zeichen empfangen zu
können.
also ich habe den Fehler jetzt ziemlich gut eingrenzen können: es liegt
wie vermutet an der Bytematch routine, das Problem dabei ist, dass
dadurch die main loop zu stark ausgebremst wird.
In der Main loop werden per Soft-i2c sensoren ausgelesen. Es kann dann
passieren, dass eine fehlübertragung der messwerte erfolgt, und
dementsprechend bei der weiterverarbeitung krumme sachen rauskommen...
Frickelfinker schrieb:> Machs zu Fuß mit Overlay, das funz.
Dein beispiel sieht super aus, einfach und effektiv..
Wie muss ich den die UART Schnittstelle initialisieren ? Wird die
baudrate mit $baud automatisch in den registern gesetzt ? Und die
anderen Parameter 8,N,1 ? Oder sowiso per ASM einstellen und
initialisieren ?
Wie sieht es mit dem senden aus ? Hast du da auch so eine einfache
lösung parat mit dem TXCn Interrupt ;-) ?