PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Homeautomatisierung mit RS485



Ramer
29.12.2009, 15:22
Moin Moin

Cooles Forum/Wiki habt ihr hier!
Hat mir mit dem Grundeinstieg sehr geholfen.

Nun aber zum eigentlichen Thread^^

Habe folgende Schaltungen entworfen:

Master/Szenenmodul:
http://www.corit-lan.ch/ramer/projekte/Master.jpg
Slave/Schaltmodul:
http://www.corit-lan.ch/ramer/projekte/Slave.jpg

Ich erkläre mal was die Schaltung soll und wie es funktionieren sollte:

Master/Szenenmodul:
Dieses Modul kann an sich nicht schalten, es hat nur 8 Tastereingänge sowie eine RS485 Schnittstelle für den BUS und ne RS232 Schnittstelle für Datenaustausch mit dem Server(Auslesung der Schaltzustände, Schalten per Software)
Die Taster sind für Szenen gedacht sprich das Mehrere Relais von verschiedenen Modulen einschalten. z.B. Modul01 PD5 und PD6, Modul03 PB3 einschalten/ausschalten.

Slave/Schaltmodul:
Dieses Modul soll Schalten.
Sprich wenn Taster 01 vom gleichen Modul gedrückt wird soll Relais 01 schalten.
Aber auch die Befehle vom Master/Szenenmodul entgegennehmen und entsprechend schalten.

Das ganze wird über einen RS485 Bus realisiert.

Die Hardware habe ich mal probeweise auf nem Steckbrett aufgebaut und die Hardware würde funktionieren.

Aber da ich erst vor 1 Woche mit Bascom proggen angefangen habe, bin ich bereits jetzt aufm Holzpfad.

Fragen:
1. Wie realisiere ich das mit dem BUS?
Ich weis das RS485 nur die Hardware beschreibt und nicht das Protokoll. bin aber trotzdem nicht schlau geworden. SNAP und so habe ich schon ein bisschen durchgeackert bin aber nicht schlau geworden.
2. Ich arbeite ja mit Tastern, also arbeitet der Ausgang eigentlich nur tastend, wie kann ich das Softwaremässig anpassen dass der Ausgang rastend ist?(Schrittschalterprinzip)

Ich hoffe ihr könnt mir helfen und ein paar Starttipps geben!

Greez Ramer

Vitis
30.12.2009, 09:29
na da hast Du Dir aber was vorgenommen für den Anfang.
Meine Empfehlung ist:

Erstmal klein anfangen. LED an Ausgang blinken lassen (Port-Register, timer, interrupt),
Taster abfragen und entprellen (Pin-Register / Debounce).
Dann UART ansprechen, lesen / schreiben auf selbige (print, inkey, input, config print).
Zwischendurch noch Programmstrukturen (Sub, Function, Call, Gosub)
Dann Auswertung der UART-Events, Befehlsauswertung schreiben (if-Then, Case, watchdog, left, mid, right, overlay, rxc, txc).
Danach dann Adressierungsmodell Deiner Konstruktion erarbeiten.
Dann noch zu den Grundlagen der Hausinstallation, VDE0100
Isolationsabstände usw.
Ach so, bei den A-B-Kanälen noch Pullup / Pulldown vorsehen.
Manche Bausteine brauchens, andere nicht.

Ramer
25.02.2010, 15:18
Moin moin

so hab mir ein bisschen deine Tipps zu herze genommen.
Habe mal klein angefangen^^
Zu den Vorschriften bezüglich der Hausinstallation ist kein Problem, da ich als Elektiker arbeite bin ich mit dennen bestens vertraut^^

Frage 2 hat sich komplett erledigt.
Allerdings ist das mit dem Bus noch so ne sache... Grundsätzlich ist mir es egal was für ich ein Busprotokoll ich nehmen werde, aber so vom Lesen her ist der Modbus sehr einfach aufgebaut. Allerdings bin ich mir da auch nicht so sicher wie ich das implementieren soll. Könnt ihr mir einen Tipp geben und vielleicht auch nen Beispiel in Bascom? Also nur für den Bus mit Master und Slave.
Die Adressen möchte ich gerne per Software lösen sprich direkt in den AVR programmieren.

Hoffe ihr habt was nützliches für mich^^

Greez Ramer

Vitis
25.02.2010, 18:18
RS485 hat prinzipiell kein Protokoll, das beschreibt nur die Hardware.
Für Protokolle gibts verschiedene Beispiele, das von Dir erwähnte Modbus
oder auch Profibus

für Modbus hat Bascom schon n paar kleine Gimmiks dabei:

http://avrhelp.mcselec.com/makemodbus.htm

Also das Konvertieren eines Modbusbefehlst kann schon mal zum Senden.
Die Auswertung scheinbar noch nicht ... ich schau mal ob ich noch was finde.

Ramer
25.02.2010, 18:40
Danke für die Antwort.
Das RS485 nur die Hardware beschreibt ist mir klar, hatte ich im ersten Post geschrieben.

Die Seite kenne ich vom Modbus, allerdings weis ich nicht genau wie ich den Slave implementieren soll.
Irgendwie komisch finde ich, dass ich nicht intelliegentes zu einem Modbus Slave finde...
Bin ich zu Dumm um zu suchen?!?^^
Ja Profibus habe ich mir auch angeschaut bin aber ehrlichgesagt nicht weit gekommen, da er schon ein bisschen komplexer aufgebaut ist. Aber ich denke mit nem gescheiten Bsp. Master/Slave würde ich es hinbekommen.
Wille und Interesse sind vorhanden.^^
Ich finde ich lerne am besten mit Beispielen^^ und ne kleine Anleitung dazu.

Aber was meinst du wäre Profibus für meine Anwendung besser geeignet?
Werde nochmals ein bisschen über Profibus googlen.
Aber wenn ihr schneller seit oder besser gesagt mit Erfahrungen kommen könnt, nur her damit!^^

Greez Ramer

Ramer
26.02.2010, 17:57
Hmm habe zum Profibus in Bascon kein gescheites Beispiel gefunden.
Hat einer von euch ein Beispiel für mich?

Vitis
26.02.2010, 21:30
Hab weder für Modbus, noch für Profibus was gescheites gefunden ...

mal schaun, vielleicht mach ich da mal was.

Richard
27.02.2010, 08:44
RS485 arbeitet eher mit den CAN Protokoll, ist aber auch etwas aufwändig,
dafür aber auch sehr sicher (Autos, Busse u.s.w.). Es gibt spezielle IC's
die einen einiges an Arbeiten abnehmen können.

Gruß Richard

Vitis
27.02.2010, 09:11
CAN hat auch kein festes Protokoll. Gut, Kollisionen erkennen die
Schnittstellenbausteine von selbst und Prioritäten gibts auch,
was welche Adresse, welcher Befehl macht ist aber auch nicht
standardisiert, und darum gehts bei Protokollen wie Modbus oder
Profibus.
Gleiche Schnittstellen.

Richard
27.02.2010, 09:55
Wenn es keine Adressen gibt, wie wird verhindert das anstatt das Bremslicht
z.b. ABS ausgeschaltet wird? Es ist eher so, alle Busteilnehmer lesen alles mit,
nutzen aber nur was für sie selber (Adresse) gedacht (adressiert) ist. CAN
Bus Teilnehmer (die teurere Version) schalten sich sogar selbständig vom Bus
wenn sie merken das sie diese blockieren.

Gruß Richard

Vitis
27.02.2010, 10:14
Ja, genau, das nennt sich Protokoll, das der Motor nicht auf das Bremslicht
reagiert, aber da braut jeder Autohersteller sein eigenes Süppchen.
Welcher Befehl was bewirkt ist im CAN nicht festgelegt.
Die Adressaten haben Adressen und bekommen Datenpakete geschickt,
das kann dann das Autoradio sein oder das Fernlicht.
Ob der Adressat Steuergerät Licht nun Fernlicht oder Abblendlicht versteht
hängt von der übermittelten Information ab.
Profibus oder Modbus machen nix Anderes, ein Befehl kommt an, wird
ausgewertet, was der Adressat damit macht ist wieder was Anderes, aber
die Befehlssyntax ist "genormt"

reinhars
27.02.2010, 14:35
Der Code funktioniert, ist aber nicht komplett kommentiert und auch nicht aufgeräumt, da ich ihn nur schnell aus einem unfertigen projekt rauskopiert habe.
Aber als start sollte das reichen. Der Master ist auch "unbeffered".

Es wäre natürlich nett wenn wir auch wieder was von dem Hausautomationsprojekt hören oder quellcode bekommen.

Viel Spaß

Grüße Stefan

Master:



' *********** Snap ***********************************
Dim Temp1 As Byte ' Temporäre Variable
Dim Temp2 As Byte ' Temporäre Variable
Dim Tmpw1 As Word
Dim Tmpw2 As Word
Dim Crc As Word ' CRC Word
' *********** Snap Ende ******************************

'################################################# ###########################################
'################################### S.N.A.P. ###############################################
'################################################# ###########################################

' -----[ Title ]------------------------------------------------------
'
' File......: SNAP-IO.BAS
' Purpose...: Turns LEDs on and off
' Author....: Christer Johansson
' Version...: 1.01
' Started...: 980503
' Updated...: 980918
' Modified..: 991229 by Claus Kuehnel
' -----[ Program Description ]----------------------------------------
'
' This program shows how to implement the S.N.A.P protocol in
' BASCOM-AVR and is an simple example to turn LEDs ON or OFF.
' This example uses 16-bit CRC-CCITT as error detection method which
' gives secure data transfer.
'
' The packet structure is defined in the received packets first two
' bytes (HDB2 and HDB1). The following packet structure is used.
'
' DD=01 - 1 Byte destination address
' SS=01 - 1 Byte source address
' PP=00 - No protocol specific flags
' AA=01 - Acknowledge is required
' D=0 - No Command Mode
' EEE=100 - 16-bit CRC-CCITT
' NNNN=0010 - 2 Byte data
'
' Overview of header definition bytes (HDB2 and HDB1)
'
' HDB2 HDB1
' +-----------------+-----------------+
' | D D S S P P A A | D E E E N N N N |
' +-----------------+-----------------+
'
'


' -----[ Initialization ]---------------------------------------------

Function Slave(command As Byte , Transfer As String , Adresse As Byte , Timeout As Byte)as String
Const Crcpoly = &H1021 ' CRC-CCITT

Const Preamble_x = &B01001101 ' Preamble byte
Const Sbyte_x = &B01010100 ' Synchronisation byte

Const Hdb2_x = &H52 '01010010
Const Hdb1_x = &H48 '10010000
Const Myaddress = 1 ' Node - Adresse
Const Empfangen = 1
Const Senden = 0
Local Preamble As Byte ' Preamble byte
Local Sbyte As Byte ' Sync byte
Local Hdb1 As Byte ' Header Definition Byte 1
Local Hdb2 As Byte ' Header Definition Byte 2
Local Dab1 As Byte ' Für welche Node-ID ist das Paket
Local Sab1 As Byte ' Wer sendet das Paket
Local Db1 As Byte ' Paket Data Byte 1
Local Db2 As Byte ' Paket Data Byte 2
Local Db3 As Byte ' Paket Data Byte 3
Local Db4 As Byte ' Paket Data Byte 4
Local Db5 As Byte ' Paket Data Byte 5
Local Db6 As Byte ' Paket Data Byte 6
Local Db7 As Byte ' Paket Data Byte 7
Local Db8 As Byte ' Paket Data Byte 8
Local Crc2 As Byte ' Paket CRC Hi_Byte
Local Crc1 As Byte ' Paket CRC Lo_Byte
Local Received As Byte
Local Dummy As String * 1

Adresse = 100 + Adresse

Db1 = Command
Dummy = Mid(transfer , 1 , 1)
Db2 = Asc(dummy)
Dummy = Mid(transfer , 2 , 1)
Db3 = Asc(dummy)
Dummy = Mid(transfer , 3 , 1)
Db4 = Asc(dummy)
Dummy = Mid(transfer , 4 , 1)
Db5 = Asc(dummy)
Dummy = Mid(transfer , 5 , 1)
Db6 = Asc(dummy)
Dummy = Mid(transfer , 6 , 1)
Db7 = Asc(dummy)
Dummy = Mid(transfer , 7 , 1)
Db8 = Asc(dummy)

Select Case Timeout
Case 1:
$timeout = 1000000
Case 2:
$timeout = 2000000
Case 3:
$timeout = 3000000
Case 4:
$timeout = 4000000
Case Else
$timeout = 5000000
End Select

Preamble = Preamble_x
Sbyte = Sbyte_x
Sab1 = Myaddress
Dab1 = Adresse
Hdb1 = Hdb1_x
Hdb2 = Hdb2_x

Crc = 0
Temp1 = Hdb2
Gosub Calc_crc
Temp1 = Hdb1
Gosub Calc_crc
Temp1 = Dab1
Gosub Calc_crc
Temp1 = Sab1
Gosub Calc_crc
Temp1 = Db8
Gosub Calc_crc
Temp1 = Db7
Gosub Calc_crc
Temp1 = Db6
Gosub Calc_crc
Temp1 = Db5
Gosub Calc_crc
Temp1 = Db4
Gosub Calc_crc
Temp1 = Db3
Gosub Calc_crc
Temp1 = Db2
Gosub Calc_crc
Temp1 = Db1
Gosub Calc_crc
Crc2 = High(crc) ' Move calculated Hi_CRC value to outgoing packet
Crc1 = Low(crc) ' Move calculated Lo_CRC value to outgoing packet

Waitms 10

' Send packet to master, including the preamble and SYNC byte
Printbin #2 , Preamble ; Sbyte ; Hdb2 ; Hdb1 ; Dab1 ; Sab1
Printbin #2 , Db8 ; Db7 ; Db6 ; Db5 ; Db4 ; Db3 ; Db2 ; Db1
Printbin #2 , Crc2 ; Crc1

Do
Received = Waitkey(#2)
If Received = 0 Then Exit Function
If Received = Sbyte_x Then
Inputbin #2 , Hdb2 , Hdb1 , Dab1 , Sab1 , Db8 , Db7 , Db6 , Db5 , Db4 , Db3 , Db2 , Db1 , Crc2 , Crc1 ' Get packet in binary mode
Goto Packet
Else
Preamble = Received
End If
Loop

Packet:
If Hdb2 <> Hdb2_x Then
Locate 3 , 1
Lcd "hdb2 nicht ok"
Exit Function
End If
If Hdb1 <> Hdb1_x Then
Locate 3 , 1
Lcd "hdb1 nicht ok"
Exit Function
End If
If Dab1 <> Myaddress Then
Locate 3 , 1
Lcd "adresse nicht ok"
Exit Function
End If
Locate 3 , 1
Lcd "crccheck"
Crc = 0
Temp1 = Hdb2
Gosub Calc_crc
Temp1 = Hdb1
Gosub Calc_crc
Temp1 = Dab1
Gosub Calc_crc
Temp1 = Sab1
Gosub Calc_crc
Temp1 = Db8
Gosub Calc_crc
Temp1 = Db7
Gosub Calc_crc
Temp1 = Db6
Gosub Calc_crc
Temp1 = Db5
Gosub Calc_crc
Temp1 = Db4
Gosub Calc_crc
Temp1 = Db3
Gosub Calc_crc
Temp1 = Db2
Gosub Calc_crc
Temp1 = Db1
Gosub Calc_crc
Temp1 = Crc2
Gosub Calc_crc
Temp1 = Crc1
Gosub Calc_crc
If Crc <> 0 Then
Locate 3 , 1
Lcd "crc nok"
Exit Function
' Goto Nak ' Check if there was any CRC errors, if so send NAK
End If

'+++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++



Ack_:
' Send ACK (i.e tell master that packet was OK)
Hdb2 = Hdb2 Or &B00000010 ' Set ACKs bit in HDB2 (xxxxxx10)
Hdb2 = Hdb2 And &B11111110
Goto Send

Nak:
' Send NAK (i.e tell master that packet was bad)
Hdb2 = Hdb2 Or &B00000011 ' Set ACK bits in HDB2 (xxxxxx11)
Goto Send

Send:
Waitms 50
' Swap SAB1 <-> DAB1 address bytes
Temp2 = Sab1
Sab1 = Dab1
Dab1 = Temp2

Check_crc , Senden

Crc2 = High(crc) ' Move calculated Hi_CRC value to outgoing packet
Crc1 = Low(crc) ' Move calculated Lo_CRC value to outgoing packet

' Send packet to master, including the preamble and SYNC byte
Preamble = Preamble_x
Printbin Preamble ; Sbyte ; Hdb2 ; Hdb1 ; Dab1 ; Sab1
Printbin Db8 ; Db7 ; Db6 ; Db5 ; Db4 ; Db3 ; Db2 ; Db1
Printbin Crc2 ; Crc1

' Goto _start ' Done, go back to Start and wait for a new packet

Slave = Chr(db1) + Chr(db2) + Chr(db3) + Chr(db4) + Chr(db5) + Chr(db6) + Chr(db7) + Chr(db8)

End Function



slave:



' -----[ Title ]------------------------------------------------------
'
' File......: SNAP-IO.BAS
' Purpose...: Turns LEDs on and off
' Author....: Christer Johansson
' Version...: 1.01
' Started...: 980503
' Updated...: 980918
' Modified..: 991229 by Claus Kuehnel
' -----[ Program Description ]----------------------------------------
'
' This program shows how to implement the S.N.A.P protocol in
' BASCOM-AVR and is an simple example to turn LEDs ON or OFF.
' This example uses 16-bit CRC-CCITT as error detection method which
' gives secure data transfer.
'
' The packet structure is defined in the received packets first two
' bytes (HDB2 and HDB1). The following packet structure is used.
'
' DD=01 - 1 Byte destination address
' SS=01 - 1 Byte source address
' PP=00 - No protocol specific flags
' AA=01 - Acknowledge is required
' C=0 - No Command Mode
' EEE=100 - 16-bit CRC-CCITT
' NNNN=1000 - 8 Byte data
'
' Overview of header definition bytes (HDB2 and HDB1)
'
' HDB2 HDB1
' +-----------------+-----------------+
' | D D S S P P A A | C E E E N N N N |
' +-----------------+-----------------+
'
'
' *********** SNAP **********************************
Const Preamble_x = &B01010011 ' Preamble byte
Const Sbyte = &B01010100 ' Synchronisation byte
Const Crcpoly = &H1021 ' CRC-CCITT
Const Hdb2_x = &H52 '01010010
Const Hdb1_x = &H48 '01001000
Const Empfangen = 1
Const Senden = 0

' *********** 1-Wire Sensoren ************************
Dim Temp_aussen As Integer
' *********** Ende 1-Wire Sensoren *******************

Dim A As Byte 'Zähler für For...Next und die Bus-Arrays
Dim Bytearray(4) As Byte 'Bytearray für allgemeine Nutzung

Dim Transfer As String * 8

'*********** SNAP ************************************
Dim Adresse As Byte ' Node - Adresse
Dim Preamble As Byte ' Preamble byte
Dim Lastbyte As Byte
Dim Hdb1 As Byte ' Header Definition Byte 1
Dim Hdb2 As Byte ' Header Definition Byte 2
Dim Dab1 As Byte ' Für welche Node-ID ist das Paket
Dim Sab1 As Byte ' Wer sendet das Paket
Dim Db1 As Byte ' Paket Data Byte 1
Dim Db2 As Byte ' Paket Data Byte 2
Dim Db3 As Byte ' Paket Data Byte 3
Dim Db4 As Byte ' Paket Data Byte 4
Dim Db5 As Byte ' Paket Data Byte 5
Dim Db6 As Byte ' Paket Data Byte 6
Dim Db7 As Byte ' Paket Data Byte 7
Dim Db8 As Byte ' Paket Data Byte 8
Dim Crc2 As Byte ' Paket CRC Hi_Byte
Dim Crc1 As Byte ' Paket CRC Lo_Byte
Dim Received As Byte ' Temporäre Variable
Dim Temp1 As Byte
Dim Temp2 As Byte ' Temporäre Variable
Dim Crc As Word ' CRC Word
Dim Tmpw1 As Word
Dim Tmpw2 As Word
Dim I As Integer
Dim Dummy As String * 1

Declare Sub Check_crc(byval Modus As Byte)

'******************* Schnittstellen, LCD, usw ********
Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0 ' MUST MATCH THE SLAVE
Rs485dir Alias Portd.2
Config Print = Portd.2 , Mode = Set ' use portb.1 for the direction
Config Rs485dir = Output
Rs485dir = 0 ' go to receive mode



Config Portc.0 = Input
Config Portc.1 = Input
Config Portc.2 = Input
Portc.0 = 1
Portc.1 = 1
Portc.2 = 1


If Adresse = 0 Then
Adresse = 100
If Pinc.0 = 0 Then Adresse = Adresse + 2
If Pinc.1 = 0 Then Adresse = Adresse + 4
If Pinc.2 = 0 Then Adresse = Adresse + 8
End If

'------[ Program ]----------------------------------------------------
Print "node up"

Do
Received = Waitkey()
If Received = Sbyte Then
Inputbin Hdb2 , Hdb1 , Dab1 , Sab1 , Db8 , Db7 , Db6 , Db5 , Db4 , Db3 , Db2 , Db1 , Crc2 , Crc1 ' Get packet in binary mode
Gosub Packet
Else
Preamble = Received
End If
Loop
End

Packet:
If Hdb2 <> Hdb2_x Then
Print "hdb2 nicht ok"
Return
End If

If Hdb1 <> Hdb1_x Then
Print "hdb1 nicht ok"
Return
End If

If Dab1 <> Adresse Then
Print "adresse nicht ok"
Return
End If

Print "crccheck"
Check_crc , Empfangen ' Check CRC for all the received bytes
If Crc <> 0 Then
Print "crc nok"
Goto Nak ' Check if there was any CRC errors, if so send NAK
End If
' No CRC errors in packet so check what to do.
' Associated Function (place it between +++ lines)
'+++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++
Transfer = Chr(db2) + Chr(db3) + Chr(db4) + Chr(db5) + Chr(db6) + Chr(db7) + Chr(db8)
Select Case Db1
Print "prepare data"
Case 50:
Goto $0c00

Case 10:
#if Devel
Print "Temperatur!!!"
'Gosub Temperatur
Print "TWI:" ; Twi
Print "Register:" ; Str(register)
Print "twi_btw:" ; Str(twi_btw)
#endif
Gosub Temperatur
' Transfer = Temperatur$
Case Else
Print "command: " ; Db1
End Select


Dummy = Mid(transfer , 1 , 1)
Db1 = Asc(dummy)
Dummy = Mid(transfer , 2 , 1)
Db2 = Asc(dummy)
Dummy = Mid(transfer , 3 , 1)
Db3 = Asc(dummy)
Dummy = Mid(transfer , 4 , 1)
Db4 = Asc(dummy)
Dummy = Mid(transfer , 5 , 1)
Db5 = Asc(dummy)
Dummy = Mid(transfer , 6 , 1)
Db6 = Asc(dummy)
Dummy = Mid(transfer , 7 , 1)
Db7 = Asc(dummy)
Dummy = Mid(transfer , 8 , 1)
Db8 = Asc(dummy)


'+++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++

Ack_:
' Send ACK (i.e tell master that packet was OK)
Hdb2 = Hdb2 Or &B00000010 ' Set ACKs bit in HDB2 (xxxxxx10)
Hdb2 = Hdb2 And &B11111110
Goto Send

Nak:
' Send NAK (i.e tell master that packet was bad)
Hdb2 = Hdb2 Or &B00000011 ' Set ACK bits in HDB2 (xxxxxx11)
Goto Send

Send:
Waitms 50
' Swap SAB1 <-> DAB1 address bytes
Temp2 = Sab1
Sab1 = Dab1
Dab1 = Temp2

Check_crc , Senden

Crc2 = High(crc) ' Move calculated Hi_CRC value to outgoing packet
Crc1 = Low(crc) ' Move calculated Lo_CRC value to outgoing packet

' Send packet to master, including the preamble and SYNC byte
Preamble = Preamble_x
Printbin Preamble ; Sbyte ; Hdb2 ; Hdb1 ; Dab1 ; Sab1
Printbin Db8 ; Db7 ; Db6 ; Db5 ; Db4 ; Db3 ; Db2 ; Db1
Printbin Crc2 ; Crc1

' Goto _start ' Done, go back to Start and wait for a new packet
Return

' -----[ Subroutines ]------------------------------------------------
'
'Soubroutine for checking all received bytes in packet
Sub Check_crc(modus As Byte)
'Const Empfangen = 1
'Const Senden = 0
Crc = 0
Temp1 = Hdb2
Gosub Calc_crc
Temp1 = Hdb1
Gosub Calc_crc
Temp1 = Dab1
Gosub Calc_crc
Temp1 = Sab1
Gosub Calc_crc
Temp1 = Db8
Gosub Calc_crc
Temp1 = Db7
Gosub Calc_crc
Temp1 = Db6
Gosub Calc_crc
Temp1 = Db5
Gosub Calc_crc
Temp1 = Db4
Gosub Calc_crc
Temp1 = Db3
Gosub Calc_crc
Temp1 = Db2
Gosub Calc_crc
Temp1 = Db1
Gosub Calc_crc
If Modus = Empfangen Then
Temp1 = Crc2
Gosub Calc_crc
Temp1 = Crc1
Gosub Calc_crc
End If
End Sub

' Subroutine for calculating CRC value in variable Tmp_Byte1
Calc_crc:
Tmpw1 = Temp1 * 256
Crc = Tmpw1 Xor Crc
For Temp2 = 0 To 7
If Crc.15 = 0 Then Goto Shift_only
Tmpw2 = Crc * 2
Crc = Tmpw2 Xor Crcpoly
Goto Nxt
Shift_only:
Crc = Crc * 2
Nxt:
Next
Return

Ramer
27.02.2010, 15:30
@reinhars
Wo definierst du genau ob es sich um den Master oder Slave handelt?
Beim Slave sehe ich richtig das du die Adressierung per Hardware gelöst hast?

If Adresse = 0 Then
Adresse = 100
If Pinc.0 = 0 Then Adresse = Adresse + 2
If Pinc.1 = 0 Then Adresse = Adresse + 4
If Pinc.2 = 0 Then Adresse = Adresse + 8
End If

So haste entweder Adresse 102,104,106,108,110,112 ist das Richtig so?

Ja werde das Projekt wenn ich was zum vorzeigen habe komplett uploaden, auch einzeln das Protokoll etc. Hardwarepläne,Bilder etc.

reinhars
01.03.2010, 06:06
Der kleine unterschied bei diesem Master/Slave-Code ist, dass der Slave die ganze zeit lauscht und auf entsprechende kommandos reagiert. Ich verwende hier db1 (databyte 1) als kommandobyte um dem Slave zu sagen welche aufgabe er erfüllen soll. in den restlichen databytes kann ich noch parameter übergeben.
der slave überträgt dann db1-db8 als ergebniss.
Ich werte nicht alle ack´s und nack´s aus weil ja das projekt noch nicht fertig ist.
Das mit der Adressierung ist so richtig - ich verwende momentan jumper und später bcd-codierschalter.
Die Adressierung kann natürlich auch in software gelöst werden und z.b. über eine gencall-adresse programmiert werden.
Bei meinem projekt ist jedoch die einstellung per hardware sinvoller, weil dann eine optische kontrollmöglichkeit der einstellung möglich ist.

Vitis
01.03.2010, 11:09
hab mir mal gestern Abend die Routinen vorgenommen und angefangen für
"universellere" Verwendung umzuschreiben. Die erste Aktion ist der Slave,
den Empfang hab ich schon auf Interruptbasierend umgebaut inklusive
Timeout per Timerinterrupt wenn Zeichen verloren gehen. Die zweite
Baustelle war die Auswertung von hdb1 und hdb2, das errechnen der
Framelänge aus den dort eingehenden Angaben zur Bytezahl Adresse
Sender u. Slave, sowie die Datenbyteanzahl, crc8 crc16 crc32 Ack und
Nack ...
heut abend werd ich wenn mir mein Kleiner n paar Minütchen Zeit lässt
wieder dran gehen.

Vitis
02.03.2010, 09:59
Gestern hab ich die verschiedenen Prüfungen CRC8, CRC16,CRC32 etc. nochmal überarbeitet sowie die Ack-verarbeitung, die Flagbytes sind auch
schon drinnen und die Response angefangen ... heut nacht gehts weiter

Ramer
02.03.2010, 10:42
Vitis du bist einfach der beste!^^

Bin momentan auch drann am "herum spielen" mit SNAP, habe es allerdings noch nicht gescheit zum laufen gebracht. Aber wird schon kommen.^^

Vitis
02.03.2010, 14:08
erst loben wenn "habe fertig" ... sonst lass ich noch den hammer fallen :)

Achim S.
02.03.2010, 18:21
Hallo
kann mich erinnern, das ich bei ELV einen Bus gesehen habe der mit diesem System läuft. Vielleicht kann es weiter bringen.
Achim

Vitis
02.03.2010, 20:56
mal ein zwischenstand:







$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 70 ' default use 32 for the hardware stack
$swstack = 250 ' default use 10 for the SW stack
$framesize = 80


$baud = 19200

' Konfiguration zum Kompilieren
Const Max_framelen = 32
Dim Slaveaddress As Byte
' dim slaveaddress as word
Slaveaddress = &B00000011

Dim Tx_data(max_framelen) As Byte
Dim Tx_string As String * Max_framelen At Tx_data Overlay
#if Max_framelen > 255
Dim Tx_pointer As Word
#else
Dim Tx_pointer As Byte
#endif

Dim Rx_data(max_framelen) As Byte
Dim Rx_string As String * Max_framelen At Rx_data Overlay
#if Max_framelen > 255
Dim Rx_pointer As Word
#else
Dim Rx_pointer As Byte
#endif

Dim Data_array(max_framelen) As Byte
Dim Flag_array(3) As Byte

Dim Rx_flag As Byte
Dim Timerflag As Byte
Dim Frame_receive_flag As Byte

Declare Sub Rx_verarbeitung()

' Interrupts initialisieren
On Urxc Zeichenempfang
Enable Urxc


Config Timer0 = Timer , Prescale = 1024
On Timer0 Timer_irq
Const Timervorgabe = 178

Disable Timer0
Enable Interrupts


' Mainloop
Do
'Hier könnte Ihr Hauptprogramm stehen


If Timerflag = 1 Then
Timerflag = 0
' verarbeitung
Print Rx_string
Call Rx_verarbeitung()
Rx_pointer = 0
Rx_flag = 0
End If
If Rx_flag = 1 And Rx_data(1) = &B01010100 And Rx_pointer > 3 Then
Call Rx_verarbeitung()
End If
Loop



Timer_irq:
Timer0 = 0
Timerflag = 1
Disable Timer0
Incr Rx_pointer
Rx_data(rx_pointer) = 0
Return

Zeichenempfang:
Timer0 = Timervorgabe
Enable Timer0
Rx_flag = 1
If Rx_pointer < 19 Then
Incr Rx_pointer
Rx_data(rx_pointer) = Udr
End If
Return


Sub Rx_verarbeitung()
Local Hdb2_rx As Byte
Local Hdb1_rx As Byte

Local Dd_num As Byte
Local Ss_num As Byte
Local Pp_num As Byte
Local Aa_num As Byte
Local Eee_num As Byte

Local Checksum_var As Word
Local Checksum_byte_1 As Byte
Local Checksum_byte_2 As Byte
Local Checksum_check_flag As Byte
Local Checksum_long As Long

Local Temp_variable_1 As Word
Local Temp_variable_2 As Word
Local Temp_variable_3 As Word
Local Temp_variable_4 As Word
Local Nnnn_num As Word

Local Rx_bytes_to_load As Word
Local Slaveaddress_check_flag As Byte

' für test:
Rx_pointer = 8
Rx_data(1) = &B01010100
Rx_data(2) = &B01010001
Rx_data(3) = &B01000001
Rx_data(4) = &B00000011
Rx_data(5) = &B00000001
Rx_data(6) = &B11110000
Rx_data(7) = &B00100010
Rx_data(8) = &B00110101


' hdb2
Dd_num = Rx_data(2)
Shift Dd_num , Right , 6

Ss_num = Rx_data(2)
Ss_num = Ss_num And &B00110000
Shift Ss_num , Right , 4

Pp_num = Rx_data(2)
Pp_num = Pp_num And &B00001100
Shift Pp_num , Right , 2

Aa_num = Rx_data(2)
Aa_num = Aa_num And &B00000011

' hdb1
Eee_num = Rx_data(3)
Eee_num = Eee_num And &B01110000
Shift Eee_num , Right , 4

Nnnn_num = Rx_data(3)
Nnnn_num = Nnnn_num And &B00001111

' add framelength
Select Case Nnnn_num
Case &B00000000
Rx_bytes_to_load = 0
Case &B00000001
Rx_bytes_to_load = 1
Case &B00000010
Rx_bytes_to_load = 2
Case &B00000011
Rx_bytes_to_load = 3
Case &B00000100
Rx_bytes_to_load = 4
Case &B00000101
Rx_bytes_to_load = 5
Case &B00000110
Rx_bytes_to_load = 6
Case &B00000111
Rx_bytes_to_load = 7
Case &B00001000
Rx_bytes_to_load = 8
Case &B00001001
Rx_bytes_to_load = 16
#if Max_framelen > 16
Case &B00001010
Rx_bytes_to_load = 32
#endif
#if Max_framelen > 32
Case &B00001011
Rx_bytes_to_load = 64
#endif
#if Max_framelen > 64
Case &B00001100
Rx_bytes_to_load = 128
#endif
#if Max_framelen > 128
Case &B00001101
Rx_bytes_to_load = 256
#endif
#if Max_framelen > 256
Case &B00001110
Rx_bytes_to_load = 512
#endif
Case Else
Rx_bytes_to_load = 0
End Select

' add checksumlength
Select Case Eee_num
Case &B00000010
Rx_bytes_to_load = Rx_bytes_to_load + 1
Case &B00000011
Rx_bytes_to_load = Rx_bytes_to_load + 1
Case &B00000100
Rx_bytes_to_load = Rx_bytes_to_load + 2
Case &B00000101
Rx_bytes_to_load = Rx_bytes_to_load + 4
Case Else
' nix machen
nop
End Select

Rx_bytes_to_load = Rx_bytes_to_load + Ss_num ' source adress bytes
Rx_bytes_to_load = Rx_bytes_to_load + Dd_num ' destination adress bytes
Rx_bytes_to_load = Rx_bytes_to_load + Pp_num ' protokoll spec. flag bytes
Rx_bytes_to_load = Rx_bytes_to_load + 3 ' Sync, HDB2, HDB1

' Auf Adresse prüfen, geht im Moment nur auf 1 und 2 Byte Adresse
Temp_variable_1 = 3 + Dd_num
Temp_variable_2 = 3
Temp_variable_3 = 0
While Temp_variable_2 < Temp_variable_1
Incr Temp_variable_2
Shift Temp_variable_3 , Left , 1
Temp_variable_3 = Temp_variable_3 + Rx_data(temp_variable_2)
Wend
If Temp_variable_3 = Slaveaddress Then
Slaveaddress_check_flag = 1
Else
Slaveaddress_check_flag = 0
End If


' Checksumme prüfen
Checksum_check_flag = 0
If Rx_bytes_to_load = Rx_pointer And Slaveaddress_check_flag = 1 Then ' Frame ist ganz empfangen, Adresse stimmt
Checksum_var = 0
Checksum_byte_1 = 0
Checksum_byte_2 = 0
Select Case Eee_num
Case &B00000010 ' 8-bit checksum
Temp_variable_1 = Rx_bytes_to_load - 2
For Temp_variable_2 = 2 To Temp_variable_1
Checksum_var = Checksum_var + Rx_data(temp_variable_2)
Next
Checksum_byte_1 = Low(checksum_var)
If Rx_data(rx_bytes_to_load) = Checksum_byte_1 Then
Checksum_check_flag = 1
Else
Checksum_check_flag = 0
End If
Case &B00000011 ' 8-bit crc
Temp_variable_1 = Rx_bytes_to_load - 2
Checksum_byte_1 = Crc8(rx_data(2) , Temp_variable_1)
If Rx_data(rx_bytes_to_load) = Checksum_byte_1 Then
Checksum_check_flag = 1
Else
Checksum_check_flag = 0
End If
Case &B00000100 ' 16-bit crc
Temp_variable_1 = Rx_bytes_to_load - 3
Checksum_var = Crc16(rx_data(2) , Temp_variable_1)
Checksum_byte_1 = Low(checksum_var)
Checksum_byte_2 = High(checksum_var)
Temp_variable_1 = Rx_bytes_to_load - 1
If Rx_data(rx_bytes_to_load) = Checksum_byte_1 And Rx_data(temp_variable_1) = Checksum_byte_2 Then
Checksum_check_flag = 1
Else
Checksum_check_flag = 0
End If
Case &B00000101 ' 32-bit crc
Temp_variable_1 = Rx_bytes_to_load - 5
Checksum_long = Crc32(rx_data(2) , Temp_variable_1)
End Select
End If

' Frame war komplett, Adresse und Checksumme stimmt
' Daten in Datenarray kopieren und Flag setzen
If Checksum_check_flag = 1 Then ' And Aa_num > 0
Frame_receive_flag = 1 ' Frame ist komplett und kann in der Mainloop verarbeitet werden


Temp_variable_1 = 3
Temp_variable_1 = Temp_variable_1 + Dd_num
Temp_variable_1 = Temp_variable_1 + Ss_num
If Pp_num > 0 Then
Incr Temp_variable_1
Flag_array(1) = Rx_data(temp_variable_1)
If Pp_num > 1 Then
Incr Temp_variable_1
Flag_array(1) = Rx_data(temp_variable_1)
If Pp_num > 2 Then
Incr Temp_variable_1
Flag_array(1) = Rx_data(temp_variable_1)
End If
End If
End If

Temp_variable_2 = Temp_variable_1 + Nnnn_num
Temp_variable_3 = 0
While Temp_variable_1 < Temp_variable_2
Incr Temp_variable_1
Incr Temp_variable_3
Data_array(temp_variable_3) = Rx_data(temp_variable_1)
Wend
End If

' Frame gesetzt, acknowledge erzeugen wenn gebraucht
If Frame_receive_flag = 1 And Aa_num > 0 Then

Tx_data(1) = &B01010100 ' Preamble
Shift Dd_num , Left , 6
Shift Ss_num , Left , 4
Shift Pp_num , Left , 2

If Checksum_check_flag = 1 Then
Aa_num = &B00000010 ' Ackn
Else
Aa_num = &B00000011 ' Nack
End If

Tx_data(2) = Dd_num
Tx_data(2) = Tx_data(2) Or Ss_num
Tx_data(2) = Tx_data(2) Or Pp_num

Shift Eee_num , Left , 4
Tx_data(3) = Eee_num
Tx_data(3) = Tx_data(3) Or Nnnn_num

End If
End Sub

Vitis
02.03.2010, 23:22
so in etwa könnts laufen:




$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 70 ' default use 32 for the hardware stack
$swstack = 250 ' default use 10 for the SW stack
$framesize = 80


$baud = 19200

' Konfiguration zum Kompilieren
Const Max_framelen = 32


Dim Slaveaddress As Byte
' dim slaveaddress as word
Slaveaddress = &B00000011


Rs485_set_io Alias Portd.2
Config Rs485_set_io = Output


Dim Tx_data(max_framelen) As Byte
Dim Tx_string As String * Max_framelen At Tx_data Overlay
#if Max_framelen > 255
Dim Tx_pointer As Word
dim tx_length as word
#else
Dim Tx_pointer As Byte
Dim Tx_length As Byte
#endif

Dim Rx_data(max_framelen) As Byte
Dim Rx_string As String * Max_framelen At Rx_data Overlay
#if Max_framelen > 255
Dim Rx_pointer As Word
#else
Dim Rx_pointer As Byte
#endif

Dim Data_array(max_framelen) As Byte
Dim Flag_array(3) As Byte

Dim Rx_flag As Byte
Dim Timerflag As Byte
Dim Frame_receive_flag As Byte

Declare Sub Rx_verarbeitung()

' Interrupts initialisieren
On Urxc Zeichenempfang
Enable Urxc

On Utxc Zeichen_gesendet
Enable Utxc

Config Timer0 = Timer , Prescale = 1024
On Timer0 Timer_irq
Const Timervorgabe = 178

Disable Timer0
Enable Interrupts


' Mainloop
Do
'Hier könnte Ihr Hauptprogramm stehen


If Timerflag = 1 Then
Timerflag = 0
' verarbeitung
Call Rx_verarbeitung()
Rx_pointer = 0
Rx_flag = 0
End If
If Rx_flag = 1 And Rx_data(1) = &B01010100 And Rx_pointer > 3 Then
Call Rx_verarbeitung()
End If
Loop



Timer_irq:
Timer0 = 0
Timerflag = 1
Disable Timer0
Incr Rx_pointer
Rx_data(rx_pointer) = 0
Return

Zeichenempfang:
Timer0 = Timervorgabe
Enable Timer0
Rx_flag = 1
If Rx_pointer < 19 Then
Incr Rx_pointer
Rx_data(rx_pointer) = Udr
End If
Return

Zeichen_gesendet:
If Tx_length > Tx_pointer Then
Incr Tx_pointer
Udr = Tx_data(tx_pointer)
Else
' für rs485
Reset Rs485_set_io
End If
Return



' ################################################## #########
' Protokollverarbeitung
' ################################################## #########

Sub Rx_verarbeitung()
Local Hdb2_rx As Byte
Local Hdb1_rx As Byte

Local Dd_num As Byte
Local Ss_num As Byte
Local Pp_num As Byte
Local Aa_num As Byte
Local Eee_num As Byte

Local Checksum_var As Word
Local Checksum_byte_1 As Byte
Local Checksum_byte_2 As Byte
Local Checksum_check_flag As Byte
Local Checksum_long As Long

Local Temp_variable_1 As Word
Local Temp_variable_2 As Word
Local Temp_variable_3 As Word
Local Temp_variable_4 As Word
Local Nnnn_num As Word

Local Rx_bytes_to_load As Word
Local Slaveaddress_check_flag As Byte

' für test:
'(
Rx_pointer = 8
Rx_data(1) = &B01010100
Rx_data(2) = &B01010001
Rx_data(3) = &B01000001
Rx_data(4) = &B00000011
Rx_data(5) = &B00000001
Rx_data(6) = &B11110000
Rx_data(7) = &B00100010
Rx_data(8) = &B00110101
')

' hdb2
Dd_num = Rx_data(2)
Shift Dd_num , Right , 6

Ss_num = Rx_data(2)
Ss_num = Ss_num And &B00110000
Shift Ss_num , Right , 4

Pp_num = Rx_data(2)
Pp_num = Pp_num And &B00001100
Shift Pp_num , Right , 2

Aa_num = Rx_data(2)
Aa_num = Aa_num And &B00000011

' hdb1
Eee_num = Rx_data(3)
Eee_num = Eee_num And &B01110000
Shift Eee_num , Right , 4

Nnnn_num = Rx_data(3)
Nnnn_num = Nnnn_num And &B00001111

' add framelength
Select Case Nnnn_num
Case &B00000000
Rx_bytes_to_load = 0
Case &B00000001
Rx_bytes_to_load = 1
Case &B00000010
Rx_bytes_to_load = 2
Case &B00000011
Rx_bytes_to_load = 3
Case &B00000100
Rx_bytes_to_load = 4
Case &B00000101
Rx_bytes_to_load = 5
Case &B00000110
Rx_bytes_to_load = 6
Case &B00000111
Rx_bytes_to_load = 7
Case &B00001000
Rx_bytes_to_load = 8
Case &B00001001
Rx_bytes_to_load = 16
#if Max_framelen > 16
Case &B00001010
Rx_bytes_to_load = 32
#endif
#if Max_framelen > 32
Case &B00001011
Rx_bytes_to_load = 64
#endif
#if Max_framelen > 64
Case &B00001100
Rx_bytes_to_load = 128
#endif
#if Max_framelen > 128
Case &B00001101
Rx_bytes_to_load = 256
#endif
#if Max_framelen > 256
Case &B00001110
Rx_bytes_to_load = 512
#endif
Case Else
Rx_bytes_to_load = 0
End Select

' add checksumlength
Select Case Eee_num
Case &B00000010
Rx_bytes_to_load = Rx_bytes_to_load + 1
Case &B00000011
Rx_bytes_to_load = Rx_bytes_to_load + 1
Case &B00000100
Rx_bytes_to_load = Rx_bytes_to_load + 2
Case &B00000101
Rx_bytes_to_load = Rx_bytes_to_load + 4
Case Else
' nix machen
nop
End Select

Rx_bytes_to_load = Rx_bytes_to_load + Ss_num ' source adress bytes
Rx_bytes_to_load = Rx_bytes_to_load + Dd_num ' destination adress bytes
Rx_bytes_to_load = Rx_bytes_to_load + Pp_num ' protokoll spec. flag bytes
Rx_bytes_to_load = Rx_bytes_to_load + 3 ' Sync, HDB2, HDB1

' Auf Adresse prüfen, geht im Moment nur auf 1 und 2 Byte Adresse
Temp_variable_1 = 3 + Dd_num
Temp_variable_2 = 3
Temp_variable_3 = 0
While Temp_variable_2 < Temp_variable_1
Incr Temp_variable_2
Shift Temp_variable_3 , Left , 1
Temp_variable_3 = Temp_variable_3 + Rx_data(temp_variable_2)
Wend
If Temp_variable_3 = Slaveaddress Then
Slaveaddress_check_flag = 1
Else
Slaveaddress_check_flag = 0
End If


' Checksumme prüfen
Checksum_check_flag = 0
If Rx_bytes_to_load = Rx_pointer And Slaveaddress_check_flag = 1 Then ' Frame ist ganz empfangen, Adresse stimmt
Checksum_var = 0
Checksum_byte_1 = 0
Checksum_byte_2 = 0
Select Case Eee_num
Case &B00000010 ' 8-bit checksum
Temp_variable_1 = Rx_bytes_to_load - 2
For Temp_variable_2 = 2 To Temp_variable_1
Checksum_var = Checksum_var + Rx_data(temp_variable_2)
Next
Checksum_byte_1 = Low(checksum_var)
If Rx_data(rx_bytes_to_load) = Checksum_byte_1 Then
Checksum_check_flag = 1
Else
Checksum_check_flag = 0
End If
Case &B00000011 ' 8-bit crc
Temp_variable_1 = Rx_bytes_to_load - 2
Checksum_byte_1 = Crc8(rx_data(2) , Temp_variable_1)
If Rx_data(rx_bytes_to_load) = Checksum_byte_1 Then
Checksum_check_flag = 1
Else
Checksum_check_flag = 0
End If
Case &B00000100 ' 16-bit crc
Temp_variable_1 = Rx_bytes_to_load - 3
Checksum_var = Crc16(rx_data(2) , Temp_variable_1)
Checksum_byte_1 = Low(checksum_var)
Checksum_byte_2 = High(checksum_var)
Temp_variable_1 = Rx_bytes_to_load - 1
If Rx_data(rx_bytes_to_load) = Checksum_byte_1 And Rx_data(temp_variable_1) = Checksum_byte_2 Then
Checksum_check_flag = 1
Else
Checksum_check_flag = 0
End If
Case &B00000101 ' 32-bit crc
Temp_variable_1 = Rx_bytes_to_load - 5
Checksum_long = Crc32(rx_data(2) , Temp_variable_1)
End Select
End If

' Frame war komplett, Adresse und Checksumme stimmt
' Daten in Datenarray kopieren und Flag setzen
If Checksum_check_flag = 1 Then ' And Aa_num > 0
Frame_receive_flag = 1 ' Frame ist komplett und kann in der Mainloop verarbeitet werden


Temp_variable_1 = 3
Temp_variable_1 = Temp_variable_1 + Dd_num
Temp_variable_1 = Temp_variable_1 + Ss_num
If Pp_num > 0 Then
Incr Temp_variable_1
Flag_array(1) = Rx_data(temp_variable_1)
If Pp_num > 1 Then
Incr Temp_variable_1
Flag_array(1) = Rx_data(temp_variable_1)
If Pp_num > 2 Then
Incr Temp_variable_1
Flag_array(1) = Rx_data(temp_variable_1)
End If
End If
End If

Temp_variable_2 = Temp_variable_1 + Nnnn_num
Temp_variable_3 = 0
While Temp_variable_1 < Temp_variable_2
Incr Temp_variable_1
Incr Temp_variable_3
Data_array(temp_variable_3) = Rx_data(temp_variable_1)
Wend
End If

' Frame gesetzt, acknowledge erzeugen wenn gebraucht
If Frame_receive_flag = 1 And Aa_num > 0 Then

Tx_data(1) = &B01010100 ' Preamble
Shift Dd_num , Left , 4
Shift Ss_num , Left , 6
Shift Pp_num , Left , 2

If Checksum_check_flag = 1 Then
Aa_num = &B00000010 ' Ackn
Else
Aa_num = &B00000011 ' Nack
End If

Tx_data(2) = Dd_num
Tx_data(2) = Tx_data(2) Or Ss_num
Tx_data(2) = Tx_data(2) Or Pp_num
Tx_data(2) = Tx_data(2) Or Aa_num

Shift Eee_num , Left , 4
Tx_data(3) = Eee_num
Tx_data(3) = Tx_data(3) Or 1 ' 1 für Dummybyte

' Sender / Empfänger in umgekehrter Reihenfolge einkopieren
Temp_variable_1 = 3
Shift Dd_num , Right , 4
Shift Ss_num , Right , 6
Shift Pp_num , Right , 2
Temp_variable_1 = Temp_variable_1 + Dd_num
Temp_variable_2 = Temp_variable_1 + Ss_num
Temp_variable_3 = 3
While Temp_variable_1 < Temp_variable_2
Incr Temp_variable_1
Incr Temp_variable_3
Tx_data(temp_variable_3) = Rx_data(temp_variable_1)
Wend

Temp_variable_1 = 3
Temp_variable_2 = Temp_variable_1 + Dd_num
While Temp_variable_1 < Temp_variable_2
Incr Temp_variable_1
Incr Temp_variable_3
Tx_data(temp_variable_3) = Rx_data(temp_variable_1)
Wend

' Die Flagbytes ebenfalls zurück kopieren
If Pp_num > 0 Then
Incr Temp_variable_3
Tx_data(temp_variable_3) = Flag_array(1)
If Pp_num > 1 Then
Incr Temp_variable_3
Tx_data(temp_variable_3) = Flag_array(1)
If Pp_num > 2 Then
Incr Temp_variable_3
Tx_data(temp_variable_3) = Flag_array(1)
End If
End If
End If



' Dummy Datenbyte
Incr Temp_variable_3
Tx_data(temp_variable_3) = 0

' Checksummen
Select Case Eee_num
Case &B0010_0000 ' 8-bit checksum

For Temp_variable_2 = 2 To Temp_variable_3
Checksum_var = Checksum_var + Tx_data(temp_variable_2)
Next
Incr Temp_variable_3
Tx_data(temp_variable_3) = Low(checksum_var)
Case &B0011_0000 ' 8-bit crc
Temp_variable_1 = Temp_variable_3 - 1
Checksum_byte_1 = Crc8(tx_data(2) , Temp_variable_1)
Incr Temp_variable_3
Tx_data(temp_variable_3) = Checksum_byte_1
Case &B0100_0000 ' 16-bit crc
Temp_variable_1 = Temp_variable_3 - 1
Checksum_var = Crc16(tx_data(2) , Temp_variable_1)
Incr Temp_variable_3
Tx_data(temp_variable_3) = High(checksum_var)
Incr Temp_variable_3
Tx_data(temp_variable_3) = Low(checksum_var)
Case &B0101_0000 ' 32-bit crc
Temp_variable_1 = Temp_variable_3 - 1
Checksum_long = Crc32(tx_data(2) , Temp_variable_1)
End Select

' Übertrag für Daten senden per UTXC
Tx_pointer = 1
Tx_length = Temp_variable_3

' Erstes Byte senden zum Start der Übertragung
' für RS-485
Set Rs485_set_io
nop
nop
nop
Udr = Tx_data(1)
End If

' Frame ist komplett, pointer zurücksetzen, Frame löschen
If Rx_bytes_to_load >= Rx_pointer Then
Rx_pointer = 0
Rx_flag = 0
For Temp_variable_1 = 1 To Rx_pointer
Rx_data(temp_variable_1) = 0
Next
End If
End Sub

screwdriver
28.03.2010, 07:58
Hallo Vitis!

Vielen Dank für deinen Quellcode. Aber hast du da S.N.A.P. (=Scaleable Node Address Protocol) nicht etwas zu wörtlich genommen.
Während der Laufzeit sollte an einem Busprotokoll m.E. nichts mehr verändert werden. Auch sollten alle Busteilnehmer das gleiche Protokoll sprechen.
Warum hast du dich für diese Lösung entschieden?

MfG
screwdriver

Vitis
28.03.2010, 20:47
ganz einfach, um den Code möglichst portabel zu machen O:)

Bin da auch noch nicht ganz fertig, die Statemachine für die Rückgabewerte fehlt noch, war aber die letzten Wochen etwas im Stress.
Auch der Master ist in Arbeit, dauert aber ebenfalls noch.

Wenn Du Codeteile nicht brauchst kannst Du die ja rauslöschen, der COde ansich ist ja recht übersichtlich in der Struktur, einfach nichbenötigte Teile auskommentieren.