Hallo zusammen,
mit folgender privater Nachricht wand sich ein Mitglied unseres Forums an mich. Weil ich der Meinung bin, dass es auch andere interessieren könnte werde ich in diesem Thread auch eine Antwort auf die Frage geben.
ich habe Probleme die Programmierung deiner Füllstandsanzeige zu verstehen. Es geht mir um den Master / Slave Teil. Kannst du mir eine vereinfachte Zusammenstellung geben, wie ich Daten von einem AVR zum anderen schicke? Ich will 2 Atmega32 mit einem Bus verbinden und einer davon soll nur Steuern und Regeln.
Ich beantworte die Frage natürlich gerne wie folgt:
* Für die Verbindung beider ATmegas in meiner Schaltung verwende ich die HW RS232 die auf den Bausteinen via HW vorhanden und von BASCOM auch unterstützt wird.
* Ich übertrage die Daten mit einer Geschwindigkeit von 38400 Baud über jeweils COM1.
* Da beide Systeme asynchron arbeiten und es dadurch auch zu zeitlichen Verschiebungen kommen kann habe ich für den Master noch einen Empfangsbuffer für den seriellen Empfang von Slave-Daten aktiviert. Damit stelle ich sicher, dass ich auf jeden Fall die Antwort des Slaves mitbekomme. Gemacht wird das z.B. wie folgt:
CodeBox Bascom
' Hardware RS232 Kanal 1 konfigurieren = interne RS232
Config Com1 = 38400 , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Config Serialin = Buffered , Size = 128
Open "com1:" For Binary As #1
* Das Funktionsprinzip für den Datenaustausch ist ganz einfach. Alles was im System passiert wird vom Master gesteuert. Der Master sendet je nachdem was gerade gemacht wird Botschaften (Befehle die ich selbst definiert habe und die aus Byte-Werten (Buchstaben) bestehen) an den Slave.
* Der Slave empfängt die Botschaft vom Master. Da der Slave nur zur Abarbeitung der Master-Kommandos programmiert ist hört der Slave immer auf der RS232 in Empfangsrichtung nach Kommandos. Wird ein Kommando empfangen wird die jeweilige Aufgabe abgearbeitet und das Ergebnis erneut über RS232 vom Slave an den Master gesendet.
* Der Master empfängt die Ergebnisbytes in der Empfangsqueue. Nach dem Absenden der Kommandos vom Master zum Slave wartet der Master auf eine Antwort vom Slave und verarbeitet diese. Das Warten auf ein Zeichen vom Slave mache ich wie folgt über den Empfangsbuffer:
CodeBox Bascom
' RS232 Buffer lesen
Temp_byte_1 = Ischarwaiting(#1)
* Parallel ziehe ich einen Sekundentimer auf den ich für den fall setzte, dass der Slave nicht antwrotet. Bedeutet, ich warte nur einem bestimmte Zeit x auf den Empfang eines Zeichens vom Slave und verarbeite sonst den Fehlerfall.
* Das Senden von Botschaften vom Master zum Slave und vice versa funktioniert über den normalen Print-Befehlt. Z.B. so:
CodeBox Bascom
' Messkommando an Slave senden
Print "{001}" ' Füllstand messen
* Beim Messen des Füllstands übertrage ich z.B. nach Messwertanforderung durch den Master das gesamte Array vom Slave zum Master in dem ev. auch vorhadene Echos beinhaltet sind. Das mache ich z.B. so:
CodeBox Bascom
' Messwerte an Master übertragen
For Temp_byte_1 = 1 To 17
Print #1 , Srf_result_struct(temp_byte_1) ' Word-Werte
Next Temp_byte_1
Man sieht hier, dass auch das Array einfach als Print in einer For-Schleife zum Master gesendet wird.
* Da bei einem normalen Print noch Zeichen wie CR + LF übertragen werden behandle ich diese Zeichen separat. Weiter sendet der Print Zeichen und keine Ziffern. Bedeutet ein Bytewert 128 geht als text "128" über die Leitung und kann nicht direkt wieder in eine Byte-Variable geladen werden. Das mache ich im Programmcode so, dass ich die empfangenen Zeichen "parse" und mir meine Zahlen wieder zusammensetze. So:
CodeBox Bascom
Do ' Zeichen-Schleife
Temp_byte_2 = Waitkey(#1) ' Zeichen von Kanal #1 lesen
' Ist Zeichen <CR> oder <LF>
If Temp_byte_2 <> 10 And Temp_byte_2 <> 13 Then ' Auf CR und LF prüfen
' NEIN, Zeichen ist normales Zeichen
' Damit kann Zeichen dem Ergebisstring angehängt werden
Temp_string_1 = Temp_string_1 + Chr(temp_byte_2)
Else ' CR / LF Prüfung
' CR wird mit diesem Konstrukt überlesen und bei LF wird Datenübernahme
' gestartet
' Wurde <LF> erkannt?
If Temp_byte_2 = 10 Then
' JA
' Ergebnisstring in Integer-Variable wandeln und speichern
Temp_messwert = Val(temp_string_1)
' Ergebnisstring zurücksetzen
Temp_string_1 = ""
End If ' LF Prüfung
End If ' Cr / Lf Prüfung
Loop Until Temp_byte_2 = 10 ' Zeichenschleife wiederholen bis LF
* In BASCOM gibt es noch die Befehle PRINTBIN und INPUTBIN mit denen es möglich ist auch binäre Daen also direkte Variableninhalte zu senden. Das kann man machen, ich habe mich halt für diesen Lösungsweg entschieden.
Sooooo, ich glaube das ist das ganze Hexenwerk für das es sicherlich min. noch 5 andere Lösungen gibt. Ich betrachte meine Lösung als sehr einfach. Ich habe auch den vorteil, dass ich mit einem Tool wie z.B. Breakout usw. ganz einfach auf der RS232 mithören/mittracen kann, was gerade über die Lieutn geht. und dadurch dass ich Print verwende kann ich das auch gleich im Klartext lesen ohne es umrechnen zu müssen.
Ich hoffe damit die Frage geklärt und erklärt zu haben und wünsche allen weiter viel Spass beim tüfteln und basteln.
Grüße,
Markus