PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] UART senden zwischen zwei ATMega8: ||| wird String vorangestellt



jcrypter
28.05.2013, 09:05
Guten Morgen,

ich beschäftige mich mit dem Senden von Daten zwischen zwei ATMega8.
Ich habe den Quelltext jetzt nicht hier, den liefere ich nach.

Ich arbeite mir config serialin und serialout.
Versuche also so zu arbeiten, dass ich den Chip nicht durch warten auf Empfang blockiere.

Die beiden Programme sind komplett identisch. Nur der eine Chip sendet als Auslöser der Kommunikation eine "0".

Der Ablauf ist wie folgt:
Chip1 sendet eine "0".
Chip2 wartet auf einen String.
In der Interrupt Routine wird eine flag gesetzt, dass ein String empfangen wurde, gleichzeitig wird der Inhalt des Puffers in eine Variable geschrieben.
Beim nächsten Durchlauf der Hauptschleife wird geprüft ob ein String empfangen wurde, wenn ja wird der String mit Val() in eine Integer umgewandelt, eine 1 hinzugerechnet und mit print an Chip1 zurückgesandt.
Es erfolgt eine Ausgabe des empfangenen und des gesendeten Strings auf einem LCD.
Das gleiche passiert dann auf Chip1.
Theoretisch sollten sich die beiden Chips einen immer um 1 erhöhten Wert zusenden.

Jetzt tritt aber folgendes auf:
Der erste Versandt, und die Addition funktionieren dann allerdings wird dem String ein Zeichen vorangestellt (eins, oder mehrere, das weiß ich nicht): auf dem LCD wird es so ausgegeben ||| , dahinter steht dann noch eine 1.
Die Ausgabe ist also |||1

Wenn ich das ganze mit einem Computer und einem Chip mache funktioniert es einwandfrei!
Es ist das selbe Programm auf dem Chip und ich sende per Hyperterminal eine Zahl, dann bekomme ich immer eine um 1 erhöhte zurück!!!


Ich verstehe absolut nicht wo das Problem liegen könnte.
Das ganze läuft auf 1Mhz ohne externen Quarz bei 4800Baut.

danke für eure Hilfe!
Quelltext folgt!

Crypi

sysrun
28.05.2013, 15:09
Standardfrage: Hast du die RX/TX Leitungen vertauscht?

for_ro
28.05.2013, 15:22
@sysrun: Das kann ja nicht die Ursache sein, er empfängt ja seine Strings.

@jcrypter: Ohne dein Programm kann man nicht genau sagen, wo das Problem liegt. Ich nehme an, dass dies dadurch hervorgerufen wird, dass ein Teil des CR+LF noch in deinem String bleibt und dann auf dem LCD ausgegeben wird. Wahrscheinlich benutzt du Bytematch=10 oder =13, damit du nach dem Empfang in eine ISR springst.

jcrypter
28.05.2013, 15:42
Danke für die Antworten!
Ein vertauschen der Leitung kann ich ausschließen!
ja, ich nutze bytematch = 13.
Ich vermute auch, dass etwas darin bleibt, aber wie behebe ich das?

Quellcode folgt heute Abend!

Crypi

HeXPloreR
28.05.2013, 15:57
Hallo Crypi,

benutze zum Empfang mal z.B. das Terminal von Br@y++.
Dort kannst Du den Empfangen String genauer ansehen - ich habe den Bereich für Dich markiert in dem die info zu sehen sein sollte.

Wenn es keine "1" oder "kleines l" kannes nur noch "vertical bar" sein...was auch immer das ist. Die Ascii Tabelle zeigt oben wie die Angaben zu lesen sind.

Ich hoffe das hilft Dir etwas weiter.

Ich vermute sonst noch das du das "nullzeichen" - also das nede vom String vielleicht mitwandelst? - vielleicht hilft es dem String die Null-Terminierung abzuschneiden und das dann in integer zu speichern?

25616

oh sorry sehe grade Du sagst senden auf PC geht richtig ....

... aber die Variable muss ein LONG sein. Deshalb wird es wohl aufgefüllt.

jcrypter
28.05.2013, 16:07
Hi Hexplorer,

ich vermute, dass es die vertical bar ist.

Gibts eine Methode die Nullterminierung zu entfernen?
Ich habe via google nichts gefunden.

Blöd wenn man nicht "am Gerät" sitzt ums auszuprobieren :)

Crypi

HeXPloreR
28.05.2013, 16:14
Kanns sein das Bascom das beim umwandeln schon macht - macht mehr sinn als das man es erst noch selbst machen muss - aber ich kann's nicht sagen


... aber die Variable muss ein LONG sein. Deshalb wird es wohl aufgefüllt.

Probier das mal, laut Bascom hilfe zum serin.

EDIT: Hat man sowas schon gesehen ... ein Bascom-Forum (http://bascom-forum.de/forum.php) ;)

jcrypter
28.05.2013, 17:57
in ordnung, wird alles nachher ausprobiert!

Danke, mal wieder ;)

Crypi

- - - Aktualisiert - - -

so, ein problem gelöst.
Die seltsamen Zeichen verschwinden.
Ich habe alles auf long geändert.
Wie gesagt, die beiden Programme sind identisch bis auf die gekennzeichneten Zeilen am Anfang.




$regfile = "m8adef.dat"
$framesize = 32
$swstack = 32
$hwstack = 32
$crystal = 1000000

$baud = 4800

Declare Sub Serial0charmatch()

Config Serialin = Buffered , Size = 30 , Bytematch = 13
Config Serialout = Buffered , Size = 30
Enable Interrupts

Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , _
Db7 = Portd.7 , E = Portd.3 , Rs = Portb.6
Config Lcd = 16 * 1a

Dim Empfangenedaten As Long
Dim Umrechnen As Long
Dim Datenempfangen As Long


Cls
Lcd "start"
Empfangenedaten = 10
Datenempfangen = 0

Waitms 1000 '<--- bei einem chip auskommentiert
Print Empfangenedaten '<--- bei einem chip auskommentiert


Do
If Datenempfangen = 1 Then
Waitms 100
'Cls
Lcd Empfangenedaten

Umrechnen = Empfangenedaten + 1

Datenempfangen = 0
Print Umrechnen
lcd umrechnen
End If


Loop
End


Sub Serial0charmatch()
Local Incoming_data As Long
Input Incoming_data Noecho
Empfangenedaten = Incoming_data
Datenempfangen = 1
End Sub

End


Auf dem LCD, das an den Chip der die KOmmunikation startet angeschlossen ist wird folgendes angezeigt:

start
1112
01
01
01
01....

da als erstes eine 10 geschickt wird und dann eine 11 zu dem Chip zurückkommt, muss die Kommunikation einmal funktionieren.
Dann wird die 12 geschickt und ab da.... da verliert sich die Spur.

Mich verlässt gerade der Glaube in meine Programmierfähigkeiten.

Crypi

HeXPloreR
28.05.2013, 20:33
Jetzt sendest Du aber keinen String mehr, oder?

Schau mal in der Bascom hilfe bei "suchen" nach Serialin. Im index finde ich es nicht. Oder hast Du schon da geguckt?

Dort schreiben sie man soll den Speicher nicht selbst löschen sondern "Clearserialin" benutzen. CTS und RTS werden auch benötigt?
Sonst quatschen die durcheinander, weil kein timing vorhanden ist.

jcrypter
28.05.2013, 20:47
Die Variablen sind keine Strings mehr, nein.
Aber so wie ich das verstehe wandelt er beim senden via print auch eine Zahl in ein Zeichen um.


Dieser Code

PRINT 1

übermittelt das Zeichen "1" und nicht die Zahl 1
entnommen aus http://halvar.at/elektronik/kleiner_bascom_avr_kurs/uart_rs232_vom_computer/

Und einen type-cast macht er ja ganz offenbar hier automatisch:



Sub Serial0charmatch()
Local Incoming_data As Long
Input Incoming_data Noecho
Empfangenedaten = Incoming_data
Datenempfangen = 1
End Sub

denn es funktioniert ja zweimal was man an der empfangenen 11 erkennt, die mit einer 12 beantwortet wird.

Ich denke nicht, dass ich die Interrups deaktivieren darf!
Ich brauche sie ja um auf den Empfang eines Zeichens zu warten. Da bin ich mir sicher!

Durcheinander quatschen können sie nicht, denn jeder reagiert nur dann, wenn er ein Zeichen empfängt.
Es wird ja nicht in der ISR geantwortet, sondern erst im Ablauf der Schleife.


Der Ablauf ist folgender:

Chip 1: wartet 1 Sekunde (um sicher zu gehen, das beide Chips laufen)
Chip 1: sendet 10
Chip 1: tut nichts und läuft die schleife durch, "wartet" auf das flag "datenempfangen", solange tut er gar nichts
Chip 2: empfängt die 10 -> ISR ->setzt "datenempfangen" und "empfangenedaten"
Chip 2: addiert eine 1
Chip 2: sendet 11
Chip 2: tut nichts
Chip 1: empfängt die 11
...
Chip 1: sendet 12
jetzt kommt das große Mysterium.... und sendet eine 0, bzw Chip 1 interpretiert es als 0, sendet eine 1 und ab da werden angeblich nur noch 0 und 1 verschickt.


ich = ratlos


edit:

gerade gesehen, Du hast deine Antwort nochmal verändert.

Ich leere den Puffer eigentlich auch nicht selbst, das mache ich an keiner Stelle.
Allerdings hatte ich im Netz gefunden, dass man von den Puffern besser die Finger läßt und also das clear serialin nicht benutzt.
Ich hatte darüber nachgedacht, aber nach dem Fund wieder verworfen.
Ich probiere es mal aus.

- - - Aktualisiert - - -

ich habe mal in die isr ein clear serialin gesetzt, ändert nichts.

das größte Mysterium ist auch noch, dass es bei der Kommunikation mit einem Computer ohne Probleme funktioniert.

HeXPloreR
28.05.2013, 20:51
Ja, sorry....wollte eigentlich kompett löschen da ich Dir eher ungenügend helfen kann, aber dann habe ich gesehen das Du schon wieder drin bist und habe sinngemäss wieder geschrieben.

EDIT: wenn du eine 12 vom terminal sendest kommt eine 13 zurück? sendest du eine 13 kommt eine 14 zurück?

Nimm mal das datenempfangen komplett raus-ich denke laut dem Teil 2 von Gerold passt es nicht so gut rein. Und ändere incoming_data zu string*30

jcrypter
28.05.2013, 21:53
Ja, vom Computer aus funktioniert es genau wie es soll!

- - - Aktualisiert - - -

Soooooooooooooooooooooooooooooooooo erstmal geschafft!!!


für alle: wenn man UART über Interrups also config serialin / config serialout nutzen will, dann muss man sich offenbar doch um den Puffer kümmern!
Zumindest um serialin!
Es ist notwendig diesen zu leeren!
Warum Bascom das nicht selber macht, weiß ich nicht, dafür reicht mein Verständnis nicht.
Ob es sich bei serialout als notwenidig erweisen wird, weiß ich noch nicht. Bisher geht es ohne.

Das clear serialin, an der richtigen Stellen, nämlich nicht in der ISR, hat dafür gesorgt, dass es jetzt geht.

Meine Lösung für eine einfache Kommunikation zwischen zwei Microcontrollern oder einem und einem Computer:

$regfile = "m8adef.dat"
$framesize = 32
$swstack = 32
$hwstack = 32
$crystal = 1000000

$baud = 4800

Declare Sub Serial0charmatch()

Config Serialin = Buffered , Size = 30 , Bytematch = 13
Config Serialout = Buffered , Size = 30
Enable Interrupts

Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , _
Db7 = Portd.7 , E = Portd.3 , Rs = Portb.6
Config Lcd = 16 * 1a

Dim Empfangenedaten As Long
Dim Umrechnen As Long
Dim Datenempfangen As Long


Cls
Lcd "start"
Empfangenedaten = 10
Datenempfangen = 0


'als Start der KOmmunikation muss ein Chip die ersten Daten schicken, etwas Wartezeit, um sicher zustellen, das beide Chips laufen
Waitms 1000 ' beim zweiten chip auskommentieren
Print Empfangenedaten ' beim zweiten chip auskommentieren


Do
If Datenempfangen = 1 Then 'nur wenn Daten empfangen wurden, wird etwas damit getan
Waitms 1000
Cls
Lcd Empfangenedaten 'die Daten werden unverändert auf einem LCD ausgegeben

Umrechnen = Empfangenedaten + 1
Print Umrechnen ' die veränderten Daten werden zurückgeschickt
Lcd Umrechnen

Datenempfangen = 0
Clear Serialin 'der empfangspuffer muss geleert werden
End If

Loop
End


Sub Serial0charmatch()
Local Incoming_data As Long
Input Incoming_data Noecho

Empfangenedaten = Incoming_data
Datenempfangen = 1 'hinweis: es wurden daten empfangen, tue etwas

End Sub


End



Dieser Code tut nichts anderes als eine jeweils um 1 erhöhte Zahl zwischen zwei Chips hin und her zu schicken.


danke für all eure Hilfe!
Wenn ich nichts übersehen habe, war es das erstmal :)
Vielleicht hilft dies ja dem einen oder anderen.

edit: soviel zu "ich mach heute noch sport.. muss nur kurz das problemchen lösen"

Crypi

HeXPloreR
29.05.2013, 08:45
Mir ist noch eingefallen wenn Du mit Bytematch = 13 (Eingabe/enter) arbeitest, dann müsstest du das auch mitsenden.
Ich würde bei eine µC<>µC Kommunikation vielleicht "Inkey" nehmen. Und vielleicht eine LED an jeden µC zur Kontrolle togglen lassen -falls man keine wzei LCD's hat.

jcrypter
29.05.2013, 09:41
Moin,

bytematch = 13 reagiert auf carriage return, als CR


Dieser Code

PRINT "Hallo Welt!"

übermittelt die Zeichenfolge "Hallo Welt!" und fügt die unsichtbaren Zeichen CR und LF an.
http://halvar.at/elektronik/kleiner_bascom_avr_kurs/uart_rs232_vom_computer/

Das CR wird also bei jedem print sowieso mit angehängt.
Darum muss ich mich nicht kümmern.

Ich bevorzuge diese Lösung:
- ich kann sicher sein, dass meine Nachricht komplett angekommen ist, da CR angekommen ist und nur dann die ISR aufgerufen wird
- ich blockiere die Hauptschleife nicht durch das warten auf Nachrichten

Wie störanfällig das ganze ist, kann ich überhaupt nicht beurteilen aber im jetzigen Zustand funktioniert es hervorragend.

Crypi