-
so in etwa könnts laufen:
Code:
$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
-
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
-
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.