PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Verständnisfragen zu Rs485 Code



Blamaster
03.02.2008, 19:33
Hi,

ich hab einen Rs 485 Code in dem ich ein paar Zeilen nicht genau verstehe.

Sender:



$regfile = "m128def.dat"
$crystal = 16000000
$hwstack = 32
$swstack = 20
$framesize = 40
$baud = 9600

Config Pinc.6 = Output
Config Pine.2 = Output
Config Graphlcd = 240 * 64 , Dataport = Portd , Controlport = Portc , Ce = 2 , Cd = 3 , Wr = 0 , Rd = 1 , Reset = 4 , Fs = 5 , Mode = 6

Dim A(8) As Byte
Dim B As Byte

Bl Alias Portc.6
Rs485 Alias Porte.2

Bl = 1
Rs485 = 1
Cursor Off
Cls

Locate 1 , 1
Lcd "RS485 Sender"

A(1) = 128 'ID
A(2) = 254 'ID
A(3) = 1 'Absender
A(4) = 2 'Empfaenger

Do
For B = 0 To 255
A(5) = B
A(6) = Crc8(a(1) , 5) 'Checksumme
Locate 7 , 1
Lcd A(6) ; " "
Gosub Send_data
Waitms 250
Next B
Loop

End

Send_data:
Printbin A(1) ; 6
Return


Empfänger:



$regfile = "m128def.dat"
$crystal = 16000000
$hwstack = 32
$swstack = 20
$framesize = 40
$baud = 9600

Config Pinc.6 = Output
Config Pine.2 = Output
Config Graphlcd = 240 * 64 , Dataport = Portd , Controlport = Portc , Ce = 2 , Cd = 3 , Wr = 0 , Rd = 1 , Reset = 4 , Fs = 5 , Mode = 6
Rs485 Alias Porte.2
Enable Interrupts
Enable Urxc
On Urxc Isrlabel

Dim A As Bit
Dim B As Byte
Dim Zeiger As Byte
Dim Db1(6) As Byte
Dim Db2(6) As Byte

Bl Alias Portc.6
Bl = 1
A = 0
Zeiger = 1
Rs485 = 0

Cursor Off
Cls
Locate 1 , 1
Lcd "RS485 Empfaenger"

Do
If A = 1 Then
Locate 3 , 1
Lcd "Absender : " ; Db2(3) ; " "
Locate 4 , 1
Lcd "Empfaenger: " ; Db2(4) ; " "
Locate 5 , 1
Lcd "Datensatz : " ; Db2(5) ; " "
Locate 7 , 1
Lcd "Checksumme: " ; Db2(6) ; " "
A = 0
End If
Loop

End

Isrlabel:
Db1(zeiger) = Udr
If Zeiger = 6 Then
For B = 1 To 6
Db2(b) = Db1(b)
Db1(b) = 0
Next B
Zeiger = 1
A = 1
End If
If Db1(1) = 128 Then
Db2(1) = Db1(1)
Db1(1) = 0
Incr Zeiger
End If
If Db2(1) = 128 And Db1(2) = 254 Then Incr Zeiger
Return


So zu dem Code hab ich folgende Verständnisfragen:

For B = 0 To 255
A(5) = B
A(6) = Crc8(a(1) , 5) 'Checksumme
Locate 7 , 1
Lcd A(6) ; " "

Der Abschnitt ist doch nur für die Erstellung der Checksumme zuständig oder ?

Was bedeutet Printbin A(1) ; 6 (das ; 6) ?

Und beim empfänger:

Isrlabel:
Db1(zeiger) = Udr <----- Bedeutet das Db1 die 6 gesendeten Byte empfängt und zeiger die Zahl der empfangenen Bytes annimmt ?
If Zeiger = 6 Then
For B = 1 To 6 <---- Nicht ganz klar was hier passiert.
Db2(b) = Db1(b) <--- praktisch einfach ein umschaufeln des Inhalts von Db1(x) zu Db2(x) ?
Db1(b) = 0 <---- Leeren der Db1(x)
Next B <----- Sprich der Schritt wird sooft wiederholt bis das mit allen 6 Byte passiert ist ?
Zeiger = 1
A = 1
End If
If Db1(1) = 128 Then
Db2(1) = Db1(1)
Db1(1) = 0
Incr Zeiger
End If
If Db2(1) = 128 And Db1(2) = 254 Then Incr Zeiger
Return


Ich hoffe ihr könnt mir beim verstehen dieser codestücke etwas weiterhelfen.

mfg blamaster

PicNick
03.02.2008, 20:28
Isrlabel:
Schau, am Anfang is ja zeiger=1, und wenn die "If" nicht aufgehen, bleibt es dabei: Alles was kommt, kommt nach Db1(1)
Wird nun ein Byte 128 = &H80 empfangen, geht der zweite IF auf:
Das Byte (128) kommt nach DB2(1), Db1(1) wird gelöscht, Zeiger geht +1 auf eins.
Alles, was jetzt kommt, kommt nach DB1(2)
das erste If geht noch immer nicht, das zweite kann auch nicht.
Erst, wenn nun ein Byte 254 (&HFE) emfangen wird, steht:
In db2(1) das 128 von vorher,
In db2(2) das 254 von jetzt , also wird der Zeiger erhöht,
dieser letze If geht nun immer auf, es landen die Folge-Bytes also in
DB(3), DB(4) etc.
Ist nun Zeiger = 6, kommt das erste If dran:
Alle 6 Byte gehen nach DB2(1,2,3,4,5,6)
Zeiger = 1, und es geht von vorne los.
Damit die Hauptschleife das weiss, wird A=1 gesetzt.
Die fummelt rum, und setzt A=0

In dieser Zeit kann Isrlabel schon wieder die nächsten 6 Byte empfangen.

kurzum, es wird gewartet bis hintereinander ein &H80 u. &HFE kommen, dann werden weiter 4 BYte empfangen, das ganze nach DB2, und die Hauptschleife zeigts her


*schnauf*

Hilft das ?

PicNick
03.02.2008, 20:35
Zweiter Teil, gemeckert:
Isrlabel hat eine Schwachstelle: wenn erstmal &H80 u. &HFE empfangen wurden, und dann kommt die Sendestation in die Bredouille und kann die restslichen 4 Bytes nicht vollständig senden, wird es mit der Kommunikation NIE WIEDER was, ausser zufällig, da hilft dann nurmehr "RESET" aus alles *schnorch*

Blamaster
03.02.2008, 20:49
Hilft schonmal etwas vielen Dank :)

Allerdings hab ich dann doch noch ein paar Fragen. Wie könnte man den Code umändern, das erstmal alle 6 Bytes empfangen werden und in eine zweite variabele verschoben werden und erst dann ausgewertet ?

Edit. und das hab ich noch nicht verstanden:

Was bedeutet Printbin A(1) ; 6 (das ; 6) ?

PicNick
04.02.2008, 07:40
Printbin A(1) ; 6
heisst: beginnend mit A(1) sechs bytes bei der UART rauspusten



umändern

Wieso, das macht er doch ? Er empfängt im Array Db1 und kopiert das nach DB2, und erst dort zeigt er her

Blamaster
04.02.2008, 15:42
Sprich mit dem Code hier:

Senden von 5 Bytes
Sender:


Dim Daten(5) As Byte
Dim Minuten As Byte
Dim Sekunden As Byte

Rs485 Alias Porta.6

Config Timer1 = Timer , Prescale = 256
Const Timervorgabe = 3036
On Timer1 Timer_irq

Rs485 = 1
Minuten = 0
Sekunden = 0

Daten(1) = 128
Daten(2) = 255
Daten(3) = 1
Daten(4) = 1
Daten(5) = 20

Enable Timer1
Enable Interrupts

Do

If Minuten = 0 And Sekunden = 20 Then
Printbin Daten(1) ; 5
Porta.0 = 1
Waitms 5000
Porta.0 = 0
End If

Loop

Timer_irq:
Timer1 = Timervorgabe
Incr Sekunden
If Sekunden = 60 Then
Incr Minuten
Sekunden = 0
End If
Return


Empfänger:



Dim A As Bit
Dim B As Byte
Dim Daten(5) As Byte
Dim Datenspeicher(5) As Byte
A = 0

Rs485 = 0

Cursor Off
Cls
Locate 1 , 1
Lcd "RS485 Empfaenger"

Do
If A = 1 Then
Locate 2 , 1
Lcd Datenspeicher(3)
A = 0
End If
Loop

End

Isrlabel:
Daten = Udr
For B = 1 To 5
Datenspeicher(b) = Daten(b)
Daten(b) = 0
Next B
If Datenspeicher(1) = 128 And Datenspeicher(2) = 255 Then
A = 1
End If

Return


Müsste es so funktionieren ? Also meiner auffassung nach sendet der Sender jetzt hintereinander weg die 5 Byte. Der Empfänger bekommt sie und schreibt sie in die Variable Daten. Dann geht es zu for B = 1 To 5, sprich B bekommt den Wert 1 zugewiesen und damit wird Datenspeicher(1) der Wert von Daten(1) übergeben. Danach wird Daten 1 gelöscht. Bei next geht er wieder zum For nur das B diesmal 2 annimmt und das geht dann weiter bis 5. Wenn dann alle Bytes in den Datenspeicher geschrieben sind, geht die If Anweisung auf und damit wird dann A=1 gesetzt, womit dann die If in der Main aufgeht und Datenspeicher(3) auf dem Display ausgegeben wird.

Sehe ich das soweit richtig ?

PicNick
04.02.2008, 16:34
Erstmal der Sender:
If Minuten = 0 And Sekunden = 20 Then .....
Der schickt nur einmal, dann erst wieder nach > 6 Stunden (256 Minuten)

Empfänger: Du mußt bedenken, daß bei jedem aufruf von ISRLABEL nur EIN Byte daherkommt. Deswegen auch in der Originalsource der "zähler"
Du wirst ja bei JEDEM Byte lebendig

Blamaster
04.02.2008, 16:56
Gut dann nochmal ganz langsam und zum mitdenken. Sprich die 5Byte werden nicht als Paket gesendet und treffen gleichzeitig ein sondern hintereinander. Sprich wenn ich 5 Byte sende, wir die ISRLABEL auch 5 mal aufgerufen ?

Wenn dem so ist verstehe ich jetzt endlich die Sinnigkeit von dem code :)

PicNick
04.02.2008, 17:30
BIngo ! genau so isses

Blamaster
04.02.2008, 18:05
Aber ist es dann nicht so das wenn in der ISRLABEL was schief geht z.B. nur 4 Bytes anstelle von 5 ankommen, oder das erste Byte nicht 128 ist die nächsten Bytes die gesendet werden alle total falsch sind ? Also praktisch nach einem Fehler die ganze ISRLABEL nicht mehr läuft ?

PicNick
04.02.2008, 19:56
Richtig.
Mehrere Möglichkeiten, eine davon :


Die hast drei Zustände
Zustand 1: Warten auf 128 --> wenn kommt, zustand = 2 , sonst nicht
Zustand 2: Nächstes Zeichen = 255 ? Ja-> Zustand = 3, sonst = 1
Zustand 3:
Zeichen = 128 ?
Ja-> Zustand = 1
No-> Data (zähler) = UDR, Zähler + 1
zähler > 5 ? Ja --> A=1 und kopieren, dann Zustand = 1

Blamaster
04.02.2008, 22:13
Ich hatte den Empfängercode nochmal etwas abgeändert:

Isrlabel:

Incr E_id
Daten(e_id) = Udr

If E_id = 5 And Daten(1) = 128 And Daten(2) = 255 Then
For B = 1 To 5
Datenspeicher(b) = Daten(b)
Daten(b) = 0
Next B
A = 1
E_id = 0

Else
Waitms 100
E_id = 0
End If

Return

Es wird also wenn die If nicht erfüllt wird 100ms gewartet un E_id dann wieder auf 0 gesetzt. Gibt es da für meinen jetztigen code noch elegantere Arten das Problem zu lösen ?