Hallo, ich versuche über Bsacom ein Programm zu schreiben mit dem ich 5 AVR (Mega8) über eine RS485 Schnittstelle vernetzen kann. Geplant ist, dass der Master eine Abfrage auf den Bus gibt und ein angesprochender Slave antwortet. Mein Problem dabei ist, wie können die Slave's in den Bus hinein hören um denn die ankommenden Abfragen aus zu werten? Gibt es da unter Bascom Basic einen speziellen Befehl? Vielen Dank für eure Unterstützung Klaus
Wenn du RS485 in der 2-Draht-Variante verwendest: Die Richtung des RS485-Treibers wird über einen Portpin umgeschaltet. Alle Slaves lauschen gleichzeitig. Wird ein Slave angesprochen, stellt er die Daten bereit und schaltet die Richtung um, genauso wie der Master. Also kein "spezieller" Befehl, sondern blos Port toggeln.
Hallo Ralf, so weit habe ich es auch schon geschafft. Sowohl vom Master als auch Slave kann ich Daten auf den Bus geben. Nur: Wie sieht der Code aus mit dem der Slave (oder Master) den Bus abliest? Kann man über deb Porpin vielleicht einen Interrupt auslösen? Wenn ja wie?
Ah, jetzt wird mir dein Problem klarer... Verwendest du die serielle Schnittstelle der AVRs für irgendwelche speziellen Sachen? Wenn nicht, dann kannst du die serielle an die MAX485-Treiber anschliessen... brauchst aber evtl. noch zusätzliche Bauteile. Wenn du es über normale Portpins machst, dann solltest du es wohl am besten wissen, ob der Portpin einen Interrupt unterstützt... :-) Und WIE die Daten übertragen werden, das definiert der Entwickler, also DU!!! Du kannst das serielle Protokoll oder auch das I2C-Protokoll verwenden, alles was du möchtest, aber du musst es dann in Software implementieren, was bei Verwendung der seriellen Schnittstelle entfallen würde. Ich habe noch keine RS485-Schnittstelle gesehen, die ein anderes Protokoll als das normale serielle verwendet. Der Unterschied zwischen RS232 und RS485 liegt soweit ich weiss nur in den unterschiedlichen elektrischen Eigenschaften... Ralf Ralf
Ja, ich hab emir eine (zwei) kleine Schaltungen zusammen gesteckt und über RS485 verbunden. Über eine RS485/RS232 Schnittstelle kann ich den Datenverkehr auf dem PC Terminal beobachten. Sowohl der Master als auch der Slave senden Daten. Was mir fehlt ist jetzt der Code, und zwar in Bascom basic den ich einspielen müsste um dem Slave das lesen bei zu bringen. Da ich Einsteiger bin fehlt mir hier einfach das Wissen. Für einen Programmierer sicher gar kein Problem
Hi, da auch ich ein RS485 Netzwerk mit AVR plane, folgende Frage: Mit welchem Adapter und welcher Software beobachtest Du den Datenverkehr ? Einem einfachen Terminalprogramm (Hyperterm)? Greets Karlheinz
die slaves haben alle eine andere adresse die slaves sind standard auf lauschen eingestellt also senden nie bis sie aufgefordert werden ( so der sinn eines slaves ) in deinem datanpaket must du nun sagen welcher slave dir was liefern soll also sendest du in deinem protokoll z.B. [ die adresse des slaves ; daten ; chksumme ] dieses empfangen erstmal alle slaves nur der slave der antworten soll . also die entsprechnde adresse besitzt... der master lauscht also auch .. wenn nix zu tun ist wenn er sendet , schaltet der den TX_EN am MAX485 sendet das paket , und schaltet wieder auf empfang der slave der sich angesprochen fühlt , schaltet auf senden und übermittelt die daten sobald die weg sind wieder auf empfang
da diese Frage immer wieder auftaucht hier ein kleines Codebespiel :
1 | $regfile = "m16def.DAT" |
2 | $crystal = 8000000 |
3 | $baud = 9600 |
4 | $loadersize = 512 |
5 | $hwstack = 64 |
6 | $swstack = 48 |
7 | $framesize = 60 |
8 | |
9 | '--------[Serial Output]---------- |
10 | Sub Send_data(byval Byte1_w As Byte , Byval Byte2_w As Byte , Byval Byte3_w As Byte , Byval Byte4_w As Byte , Byval Byte5_w As Byte , Byval Byte6_w As Byte , Byval Byte7_w As Byte) |
11 | Linebusy = 1 |
12 | Txcomplete = 0 |
13 | Crcbyte_w = Crc(byte1_w , Byte2_w , Byte3_w , Byte4_w , Byte5_w , Byte6_w , Byte7_w) ' make send Checksum |
14 | Waitms 2 |
15 | Portc.7 = 1 'set RS485 to Send Mode |
16 | Waitus 7 'wait for tranceiver switched to send mode |
17 | Ucsrb.0 = 1 ' mark next Byte in UDR as Adress |
18 | Udr = Byte1_w ' Set Byte in UDR (Recipient) |
19 | Ucsrb.0 = 0 ' mark next Byte in UDR as Data |
20 | Printbin Byte2_w ; Byte3_w ; Byte4_w ; Byte5_w ; Byte6_w ; Byte6_w ; Crcbyte_w ; 'Sending without line feed |
21 | While Txcomplete = 0 |
22 | nop |
23 | Wend |
24 | 'Print #2 , "Sended--->" ; "To:" ; Byte1_w ; " From:" ; Byte2_w ; " Command:" ; Byte3_w ; " D1:" ; Byte4_w ; " D2:" ; Byte5_w ; " D3:" ; Byte6_w ; " D4:" ; Byte7_w ; " CRC:" ; Crcbyte_w 'set RS485 to receive mode |
25 | 'Linebusy = 0 |
26 | Return |
27 | End Sub |
28 | '^^^^^^^^[END of Serial Output]^^^^^^^^^^ |
29 | |
30 | '--------<<Serial input IRQ>>------------ |
31 | Receive: |
32 | Linebusy = 1 |
33 | Adressflag = Ucsrb.1 'Read UCSRB Register Bit 1 (RXB8) for determing the 9th Bit |
34 | Inbyte = Udr 'Read UDR into Byte VAR |
35 | If Inbyte = Unitid And Rxactive = 0 Then 'compare received Unitid |
36 | Ucsra.0 = 0 'Reset UCSRA.0 (MPCM) to get Data Frames |
37 | Ucsrb.1 = 0 'Reset UCSRB.1 (RXB8) to be ready for a other 9th Bit |
38 | Rxactive = 1 'Set RXactive Flag |
39 | Broadcast_flag = 0 'Set Broadcast Flag |
40 | End If |
41 | 'Determ If Broadcast Is Send |
42 | If Inbyte = 0 And Rxactive = 0 Then 'compare received Unitid |
43 | Ucsra.0 = 0 'Reset UCSRA.0 (MPCM) to get Data Frames |
44 | Ucsrb.1 = 0 'Reset UCSRB.1 (RXB8) to be ready for a other 9th Bit |
45 | Rxactive = 1 'Set RXactive Flag |
46 | Broadcast_flag = 1 'Set Broadcast Flag |
47 | End If |
48 | |
49 | |
50 | If Rxactive = 1 Then |
51 | Incr Arraycounter 'count up Array |
52 | Datastring_r(arraycounter) = Inbyte ' Fill Array with received Data |
53 | End If |
54 | |
55 | If Arraycounter = 8 Then |
56 | Ucsra.0 = 1 ' set Ucsra MPCM Mode on if last Byte is Transmitted |
57 | Stringcomplete = 1 ' Set Flag for complete transmission |
58 | Arraycounter = 0 ' Reset Arraycounter |
59 | Rxactive = 0 ' Reset RXactive |
60 | Linebusy = 0 |
61 | Adressflag = 0 'Reset Adressflag |
62 | Crc_check = Crc(datastring_r(1) , Datastring_r(2) , Datastring_r(3) , Datastring_r(4) , Datastring_r(5) , Datastring_r(6) , Datastring_r(7)) ' Make Checksum of Received Data |
63 | Print #2 , "received-> " ; "From:" ; Datastring_r(2) ; " To:" ; Datastring_r(1) ; " Command:" ; Datastring_r(3) ; " D1:" ; Datastring_r(4) ; " D2:" ; Datastring_r(5) ; " D3:" ; Datastring_r(6) ; " D4:" ; Datastring_r(7) ; " CRC:" ; Datastring_r(8) |
64 | |
65 | End If |
66 | Return |
67 | '^^^^^^^^[END of serial input]^^^^^^^^^^^^ |
68 | |
69 | '-------<<IRQ for sending complete>>------ |
70 | Send_complete: |
71 | Waitus 14 |
72 | Portc.7 = 0 |
73 | Txcomplete = 1 |
74 | Return |
75 | '^^^^^<<END IRQ sending complete>>^^^^^^^^ |
so in etwa funktioniert das Senden / Empfangen mit 9Bit. Bitte nicht irritieren lassen. Die Auszüge sind aus einem laufendem Projekt für einen MultiMaster Bus mit Token-Passing. Daher kann ich leider nicht alles Posten. Aber mit etwas Googeln und nachdenken lässt sich bestimmt das wichtigste extrahieren. Der Rest steht im Datasheet. Wichtig ist das das ganze nur mit einem Hardware USART des At-Mega läuft da die Register und Interrupts zwingen gebraucht werden. Bei der Übertragung der Daten mit 9-Bit wird der Überwachungsaufwand der Slaves deutlich verringert da nur die der richtigen Adresse folgenden Daten beachtet werden. Alle anderen Daten werden direkt verworfen. Nachteilig ist, das man den Bus nicht ganz so einfach mithören kann. Ich löse das über einen RS485->Rs232 Wandler um mit einem Terminal Programm die Daten mit zu lesen. Bei der Master Slave Variante wird (kleiner Tip) ein Empfangstimeout irgandwann wichtig. Da unter umständen der Master sonst endlos auf die Antwort von einem inzwischen "verstorbenen" Slave wartet. Ein gleichzeitiges Senden beider (Master und SLave) muss natürlich wirksam unterbunden werden um Kollisionen zu vermeiden. Dies ist aber bei Master Slave Betrieb recht leicht durch ein simples Protokoll (ACK ö.Ä) zu lösen. Gruß Verri
hier eine interessante Protokol für so ein Netzwerk: www.hth.com/snap/
Zum Empfang einfach die URXC Interruptroutine setzen und dort das UDR-Register auslesen, Senden durch schreiben des UDR-Registers
Das ist genau das was im Programauszug passiert. Gut ohne das direkte schreiben in UDR . Aber Print macht auch nix anderes, ganz im Gegenteil. Print wartet noch so lange bis alle Daten raus sind. Als denn Verri
Ihr könnt auch in meinem OpenHC-Projekt abgucken. Das ist RS485 Multimaster, mit CRC und einem Toggle-Bit in den Paketen. Läuft auf AVR Mega8, funktioniert zuverlässig.
Ich hab mir ein Kabel von FTDI gekauft, das hat einen USB-zu-seriell-Konverter .Daran habe ich einen LTC485 angeschlossen. Die 5V kannst Du direkt aus dem Kabel verwenden. So brauchst Du nur GND, VCC, TX und RX vom LTC 485 zum Adapterkabel verbinden. Das Kabel kostest zwar etwas mehr (so etwa 20€) aber das hat schon eine Stiftleiste, mit der es sehr flexibel einsetzbar bleibt. Der LTC485 kostet etwa 5 Euro.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.