-
Probleme mit RS 485 Bus
Hallo,
habe mir eine Schaltung aufgebaut mit 2 x Atmega 16, 2 x Max 485 und einem LCD Display, somit will einen RS 485 Bus realisieren.
Der erste Atmega soll als Master dienen und der zweite Atmega als Slave. Diese habe ich auf einem Steckbrett aufgebaut mit folgendem Code:
Master Code:
$regfile = "m16def.dat"
$crystal = 10000000
$baud = 1200
Config Portd.2 = Output
Portd.2 = 1
Dim i As Byte
Dim wTest As Word
I = 1
'wTest = 35000
Do
Portd.2 = 1
Printbin I
Print "1" ; I
'waitms 10
Portd.2 = 0
Loop
End
Slave Code:
$regfile = "m16def.dat"
$crystal = 10000000
$baud = 1200
Config Portd.2 = Input
Portd.2 = 0
Dim I As Byte
' - - - Lcd - - -
Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Porta.0 , Db5 = Porta.1 , Db6 = Porta.2 , Db7 = Porta.3 , E = Porta.5 , Rs = Porta.4 'Ausgänge zum LCD
Config Lcdbus = 4
Config Lcdmode = Port
Config Serialin = Buffered , Size = 20
' - - - - - - - - -
Do
If Usr.rxc = 1 Then ' Wenn Byte empfangen...
I = Udr 'Byte aus UART auslesen
Select Case I
Case "1"
Cls
Lcd "Hallo AVR Nr.1"
Case "2"
Cls
Lcd "Hallo AVR Nr.2"
Case Else
Cls
Lcd "Nichts"
End Select
End If
Loop
Leider bekomme ich auf dem LCD am Slave die Meldung Nichts angezeigt. Die Schaltung habe ich auch schon etliche male kontrolliert.
Würde mich über eine Hilfe freuen.
Mfg
Tobias
-
Ich habe das hier mit zwei ATMega128 aufgebaut:
Sender:
Code:
$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
Empfaenger:
Code:
$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
Ich uebertrage in diesem Falle ersteinmal sechs Bytes. Das soll dann spaeter eine Art Protokoll werden. Das ganze laeuft wunderbar stabil. Allerdings habe ich da auch einige Zeit experimentiert bis es einwandfrei lief.
Der Empfaenger sucht zunaechst nach den zwei ID-Bytes. Wenn diese korrekt angekommen sind, dann werden die 4 nachfolgenden Bytes verarbeitet. Sobald die Uebertragung vollstaendig ist, werden die Daten auf dem LC-Display angezeigt.
Gerade heute habe ich noch ein paar MAX485 bekommen. Sobald ich den naechsten Bastelflash bekomme, werde ich einen dritten AVR mit Display in den Bus haengen und die Software so umschreiben, dass jeder Senden und Empfangen kann.
Dafuer hatte ich auch das Empfaenger- und Senderbyte vorgesehen.
Ein Foto von dem Drahtigel:
http://www.elektronik-web.de/fotos/rs485.jpg
Mit freundlichen Gruessen
Digitali
-
Hallo Digitali,
werde mich mal in deinen Code einlesen bin zwar noch nicht so fit mit der Programmierung versuche es aber mal ;-)
Mfg
Tobias
-
Ich habe das mal auf das Notwendigste abgespeckt:
Sender:
Code:
$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 As Byte
Bl Alias Portc.6
Rs485 Alias Porte.2
Bl = 1
Rs485 = 1 'Senden
Cursor Off
Cls
Locate 1 , 1
Lcd "RS485 Sender"
A = 128
Do
Printbin A
Waitms 500
Loop
End
Empfaenger:
Code:
$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 , Db As Byte
Bl Alias Portc.6 ' Hintergrundbeleuchtung LC-Display
Bl = 1
A = 0
Rs485 = 0 'Empfangen
Cursor Off
Cls
Locate 1 , 1
Lcd "RS485 Empfaenger"
Do
If A = 1 Then
Locate 4 , 1
Lcd Db
A = 0
End If
Loop
End
Isrlabel:
Db = Udr
A = 1
Return
Es wird nur ein einziges Byte (128) uebertragen. Sobald der UART ein Zeichen empfaengt wird ein Interrupt ausgeloest. In der Urxc-Isr wird dann das Byte ausgelesen (Db=UDR). Und das war's dann auch schon. Eigentlich total simpel.
Mit freundlichen Gruessen
Digitali
-
Hallo Digitali,
also habe mal den Code etwas angepasst für den Atmega 16 kann sein das ich da noch einen fehler habe.
Master
$regfile = "m16def.dat"
$crystal = 1000000
$hwstack = 32
$swstack = 20
$framesize = 40
$baud = 9600
Dim A(8) As Byte
Dim B As Byte
Bl Alias Portd.1 'txd vom atmel verbunden mit max485 pin 4 (DI)
Rs485 Alias Portd.2 'INT0 vom atmel verbunden mit max485 pin 2,3 (RE,DE)
Bl = 1
Rs485 = 1
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
Gosub Send_data
Waitms 250
Next B
Loop
End
Send_data:
Printbin A(1) ; 6
Return
Slave:
$regfile = "m16def.dat"
$crystal = 1000000
$hwstack = 32
$swstack = 20
$framesize = 40
$baud = 9600
' - - - Lcd - - -
Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Porta.0 , Db5 = Porta.1 , Db6 = Porta.2 , Db7 = Porta.3 , E = Porta.5 , Rs = Porta.4 'Ausgänge zum LCD
Config Lcdbus = 4
Config Lcdmode = Port
' - - - - - - - - -
Rs485 Alias Portd.2 'INT0 vom atmel verbunden mit max485 pin 2,3 (RE,DE)
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 Portd.0 'RXD vom Atmel zu Max 486 Pin 1 RO
Bl = 1
A = 0
Zeiger = 1
Rs485 = 0
Cursor Off
Cls
Locate 1 , 1
Lcd "RS485 Empfaenger"
Do
If A = 1 Then
Locate 2 , 1
Lcd "Absender : " ; Db2(3) ; " "
Locate 2 , 1
Lcd "Empfaenger: " ; Db2(4) ; " "
Locate 2 , 1
Lcd "Datensatz : " ; Db2(5) ; " "
Locate 2 , 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
Bekomme keine Daten vom Master.
-
Bl Alias Portd.1 'txd vom atmel verbunden mit max485 pin 4 (DI)
Bl Alias Portd.0 'RXD vom Atmel zu Max 486 Pin 1 RO
Ich hatte mein Listing schlecht dokumentiert. Bl steht bei mir fuer Backlight. Damit schalte ich lediglich die Hintergrundbeleuchtung des Displays ein. Das musst Du bei Dir wieder loeschen.
Mit freundlichen Gruessen
Digitali
-
Also brauche ich nur beim Master den Portd.2 ?
Mfg
Tobias
-
Pin 2 und 3 vom MAX 485 sind ja zusammengeschaltet. Dort wird zwischen Senden und Empfangen umgeschaltet. Das mache ich beim Sender und Empfaenger jeweils mit dem PortPin E.2.
RxD vom AVR an Pin1 (RO) vom MAX und TxD vom AVR an Pin4 (DI) vom MAX.
Mit freundlichen Gruessen
Digitali
-
jaja, die 485 ... ich hatte mal probleme damit, weil die
A-undB-Leitung floatete. hab sie dann damit gelöst, dass ich
Pullup-Pulldown und Abschlusswiderstände einlötete.
Dann gings auf Anhieb.
ach so, eins noch, warum verwendest Du nicht einfach den
PCA82C250? Ist zwar n CAN-Bus Baustein, die Funktion
ist aber vergleichbar, bis auf den Punkt, dass man sich
die Umschaltung der Datenflussrichtung schenken kann.
-
Hallo Vitis,
habe die Abschlusswiderstände an den Bus gemacht und siehe da es funzt :-)
Danke
Mfg
Tobias