PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Uart-Abfrage mit Atmega128 - Mit Lösung!



Jimmy23
23.11.2010, 20:24
Hallo,

Ich versuche mit einem ATmega128 und daran angeschlossenem Funkmodul Daten zu empfangen. Die Daten werden von einem weiteren Prozessor (A32) über ein Funkmodul gleichen Typs gesendet.

Aber leider funktioniert das Auswerten und Beschreiben des Strings nicht.

Als Daten werden gesendet: "Chr(15)" und danach ""Hallo!""
Schließe ich das Sendeboard direkt an das Display an, wird das auch korrekt angezeigt, dort kann der Fehler nicht liegen.


Bitte guckt einmal meinen Programmcode durch:




$regfile = "m128def.dat" ' Bei Mega 128 "
$framesize = 40
$swstack = 40
$hwstack = 40
$crystal = 16000000 'Quarzfrequenz
$baud = 19200 'Baudrate für Funkmodul
$baud1 = 19200


Config Pine.2 = Output
Rdy_hostempfangsbereit Alias Porte.2

Open "com2:" For Binary As #2
Config Serialin = Buffered , Size = 50 , Bytematch = 15

Enable Interrupts
' ---------------------------------------------------
Dim Z As Byte
Dim Text As String * 6

Print #2 , "RN Mega128Funk"

Rdy_hostempfangsbereit = 0

Echo Off

Do
Print #2 , Text
Waitms 500
Loop



Serial0charmatch:
Text = Inkey()
Return




Wem die 2te konfigurierte RS232-Schnittstelle auffällt:
Dort habe ich ein Display angeschlossen(RN KeyLCD), das die gleiche Funktion eines Terminalprogramms hat.


Das Ergebnis was dann im Display angezeigt wird sind nur einzelne 'H's, keine 6 Zeichen "Hallo!"



Bitte versucht meinen Fehler zu finden!

Mit freundlichen Grüßen
Jimmy

Che Guevara
23.11.2010, 21:06
Hallo Jimmy,

in dem Serial0charmatch Unterprogramm ist dein Fehler. In deinem Programm überschreibt die Zeile "Text = Inkey()" nämlich immer die Variable Text mit dem neuesten UART "Textzeichen".
Du musst folgendes Schreiben:


Serial0charmatch:
buffer = inkey()
text = text + buffer
return


Wobei ich mir momentan nicht sicher bin, ob inkey() hier richtig ist oder man besser "udr" nehmen soll....
buffer ist hier eine zusätzliche Variable als Zwischenspeicher, welche vom gleichen Typ wie Text sein sollte.

Gruß
Chris

for_ro
23.11.2010, 21:12
Hallo Jimmy,
Inkey() liest nur ein einzelnes Zeichen aus dem Input Buffer. Daher bleibt es immer bei dem "H".
Wenn hinter dem "!" ein <CR> kommt, dann schreib doch mal
Input Text, Noecho

Ansonsten wäre es besser, du würdest nach deinem Text ein bestimmtes Zeichen, wie z.B. CHR(15) senden.
Wenn jetzt der SerialCharMatch kommt, dann sind schon alle Zeichen im Puffer und das Programm braucht nicht mehr auf das Eintreffen zu warten.

Jimmy23
23.11.2010, 21:20
Hi Chris,

Danke für deine konstruktive Antwort!

Meinst du das weil der Inkey-Befehl immer nur ein Zeichen aufnehmen kann?
Ich habs in der Library nachgelesen, man kann auch den ganzen String damit befüllen.


Ich habe deinen Vorschlag trotzdem mal ausprobiert und siehe da, nun zeigt er nicht nur eine Stelle "H" an, sondern "Ha".
Ich müsste also das "text = text + buffer" nur für jede Stelle die der String hat wiederholen und hätte dann die ganze Nachricht.

Aber plötzlich resettet sich der Controller immer nach einigen Sekunden selbständig, nur nach diesem Einschub...

Läuft da eventuell "text" über?

Jimmy23
23.11.2010, 21:27
Hallo for_ro,

Auch dir danke ich für deinen Beitrag!

Du meinst man kann zwar einen String mit "Inkey" beschreiben, dieser wird aber dann imer nur ein Zeichen haben?
Warum steht aber dann in der Bascom-Library ein Beispiel mit einem 2-Zeichen-String?

Über die Reihenfolge von Erkennunsgzeichen und den eigentlichen Daten habe ich schon nachgedacht, doch ich kam zu dem Schluss dass die Funktion ab dem Erkennunsgzeichen alle x viele Zeichen liest.

Danke dass du mich darüber nochmal aufgeklärt hast!

for_ro
23.11.2010, 21:42
In der Library ist aber doch ein Loop drinnen, der Inkey immer wieder aufruft.
SerialCharMatch funktioniert so, dass zu dem Label gesprungen wird, wenn das Zeichen empfangen wurde, welches du vorgegeben hast.
Dort fragst du mit Inkey das erste Zeichen des Puffers ab. Danach geht das Programm wieder zurück zu dem befehl, wo es unterbrochen wurde.
Dies ist bei dir die Do..Loop mit dem Print alle 500ms. D.h. du kannst so nur ein Zeichen einlesen. Überleg es dir noch einmal.
Du könntest es auch so machen:


Serial0charmatch:
While IsCharWaiting() = 1
Text = Text + Inkey()
Wend
Return

Jimmy23
25.11.2010, 16:06
Ich habe die Änderungen eingebaut, eine gute Idee mit der while-Schleife, doch nun gibt der Controller gar nichts mehr aus, sondern resettet sich sofort.

Sobald der Atmega etwas empfängt setzt er sich selbst zurück.

Wenn ich das Sendeboard ausmache läuft das Programm weiter durch, nur kann es dann natürlich nichts mehr empfangen.

Hier nochmal mein Programmcode:



$regfile = "m128def.dat" ' Bei Mega 128 "
$framesize = 40
$swstack = 40
$hwstack = 40
$crystal = 16000000 'Quarzfrequenz
$baud = 19200 'Baudrate für Funkmodul
$baud1 = 19200


Config Pine.2 = Output
Rdy_hostempfangsbereit Alias Porte.2

Open "com2:" For Binary As #2
Config Serialin = Buffered , Size = 10 , Bytematch = 15


Enable Interrupts
' ---------------------------------------------------
Dim Text As String * 6
Dim Buffer As String * 1

Print #2 , "RN Mega128Funk"
Rdy_hostempfangsbereit = 0


Echo Off

Do
Print #2 , Text
Waitms 500
Loop




Serial0charmatch:
While Ischarwaiting() = 1

Buffer = Inkey()
Text = Text + Buffer
Wend

Return


Übrigens hat die Buffergröße keinerlei Einfluss auf die Zeit bis zum Reset, auch wenn ich sie erhöhe.

for_ro
25.11.2010, 19:36
Ich verstehe zwar nicht, warum du unbedingt bei der Version mit Startzeichen bleiben willst, aber sei's drum.
Mach mal in die Sub ein Pushall und ein Popall, so wie es in der Hilfe steht.
Nach dem Printen würde ich die Variable Text leeren, sonst wird sie immer größer.

Jimmy23
26.11.2010, 18:22
Ich habe die Änderungen eingebaut, doch leider tat sich nach wie vor nichts, außer dem periodischen Selbst-Reset des Controllers.

Dann habe ich nach einem anderen Weg gesucht und bin schließlich auf einen Thread gestoßen, wo du in der gleichen Frage Jemandem anders geantwortet hast.

Damit klappt es!!! \:D/

Hier mein endgültiger Code:


$regfile = "m128def.dat" ' Bei Mega 128 "
$framesize = 40
$swstack = 40
$hwstack = 40
$crystal = 16000000 'Quarzfrequenz
$baud = 19200 'Baudrate für Funkmodul
$baud1 = 19200

Config Pine.2 = Output
Rdy_hostempfangsbereit Alias Porte.2 'Auf Low setzen wenn Empfangsbereit für Daten vom Funkmodul

Open "com2:" For Binary As #2
Config Serialin = Buffered , Size = 20 , Bytematch = 13

Enable Interrupts
' ---------------------------------------------------
Dim Command_key As Byte
Dim Command_count As Byte
Dim Command_string As String * 12
Dim Empfang As Bit
Empfang = 0
Rdy_hostempfangsbereit = 0

Echo Off

Do

If Empfang = 1 Then
Sound Portg.2 , 200 , 650

Waitms 1
Print #2 , Command_string
Empfang = 0
Command_string = ""

End If
Loop


Serial0charmatch:
Empfang = 1
Command_count = 0
Command_string = ""
While Ischarwaiting() = 1
Command_key = Inkey()
If Command_key <> Chr(13) Then
Incr Command_count
If Command_count < 12 Then
Command_string = Command_string + Chr(command_key)
End If
End If
Wend
Clear Serialin
Return



Der String ist 12 Zeichen lang, wer eine andere Länge haben will muss sie oben bei "Dim String as" und unten bei "If Command_count" ändern.

Wer ein anderes Erkennungszeichen als Chr(13) nehmen will, muss es oben bei "Config Serialin [...] Bytematch=" und unten bei "If command_key" ändern.


Das Bit "Empfang" sorgt dafür dass nur dann Text ausgegeben wird, wenn neue Daten empfangen wurden.


Die Geschwindigkeit ist super! Mein Sender sendet im Abstand von 200 Millisekunden "Hallo" mit einer Zählvariable die von 1 bis 9 läuft und jede Message wird korrekt angezeigt.

Hier noch der Link zum Original-Thread:

https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=42559&highlight=input+string

Viel Spaß mit dem Programm und nochmals Danke an dich Rolf! =D>