Hallo profis,
ich habe eine Frage ,
ich möchte für meine kommunikatin zwischen einem Master(AVR-µC) d
mehreren Sensoren(AVR-µC) aufbauen. Ich möchte der Schnittstelle RS485
benutzen.
Ich habe gelesen, dass dieser Bus keine definierte Bus-protokoll hat.
Kann ich dafür zum Beispiel, dann der Protokoll für I2C(TWI) benutzen,
oder CAN oder ... ????
oder gibt es was spezifisches für RS485 ??
Denn mir ist esnicht ganz klar wie ich den Transmit und Receives
funktion implementieren kann. Ich weiß nicht genau wie ich die
unterchiedlichen Frame innerhalb eines Formats senden Kann.
Ich würde mich freuen für konstruktive beiträge.
Sebastian
@ Sebstian (Gast)
>Ich habe gelesen, dass dieser Bus keine definierte Bus-protokoll hat.
Ist auch so.
>Kann ich dafür zum Beispiel, dann der Protokoll für I2C(TWI) benutzen,
Nein.
>oder CAN oder ... ????
Nein.
>oder gibt es was spezifisches für RS485 ??
Meist nutzt man ein logisches RS232, also den UART im uC.
>Denn mir ist esnicht ganz klar wie ich den Transmit und Receives>funktion implementieren kann.
Wie bei RS232. Wahlweise voll- oder halbduplex. Meist halbduplex. MAX485
ist dein Freund.
> Ich weiß nicht genau wie ich die> unterchiedlichen Frame innerhalb eines Formats senden Kann.
Soweit bist du noch lange nicht. Beschäftige dich erstmal mit EINFACHEN
Grundlagen. DMX512 ist ein guter Anfang.
MFG
Falk
ok
anders formulliert ,
wie kann die Kommunikation zwischen ein Master und Slave über den
RS485- Schnittstell in einem Busanordnung erfolgen.
was ich schon weißbei der RS485 ist, dass der Aufbau eines Frames
folgendr massen aussieht: Als erstes das Adressbyte mit gesetztem 9.
Bit, anschließend die Paketlänge, in diesem Fall
8 Byte, danach die 8 Datenbytes und zum Schluß die Schecksumme. Bei
allen Bytes werden 9 Bit übertragen aber nur bei der Adresse ist dieses
Bit
gesetzt. Dies führt dazu dass, bei gesetztem 9.Bit jeden Slave erkennt
der Start einer neuen Übertragung. Erst der Slave dessen Adresse
enpricht sendet ein ACK zurück (seine Adresse) und die anderen bleiben
auf empfang bis eine neuen Datensatz mit gesetzten 9.bit übertragen
wird.
Format
1 Adressebyte Paketlänge($8)| datenbyte | Cheksumme
hier ist ein Auszug der initialisierung. ATmega32
void RS485_Init (void)
{
// Baudrate Einstellung
//UBRR0L = (TAKT/(16UL*BAUD))-1; //Baudrate
UBRR0H = (unsigned char) (TEILER>>8);
UBRR0L = (unsigned char) TEILER;
//Sender und Empfänger ein
UCSR0B |= (1<<TXEN0)|(1<<RXEN0)|(1<<UCSZ02);
// Datenformats: 9 Datenbits, 1 Stoppbit
UCSR0C |= (1<<UCSZ01)|(1<<UCSZ00);
}
wie kann die Übertragung (sende TX und Empfang RX)- Funktionen aussehen,
damit den gesamten Format übertragen wird .
ich hoffe ich war etwas ausführlicher in der beschreibung
danke
@ Sebastian (Gast)
>wie kann die Kommunikation zwischen ein Master und Slave über den>RS485- Schnittstell in einem Busanordnung erfolgen.
Tausend und eine Möglichkeit.
>was ich schon weißbei der RS485 ist, dass der Aufbau eines Frames>folgendr massen aussieht:
Falsch. RS485 definiert nur elektrische Sachen, keine Logik.
> Als erstes das Adressbyte mit gesetztem 9.>Bit, anschließend die Paketlänge, in diesem Fall>8 Byte, danach die 8 Datenbytes und zum Schluß die Schecksumme.
Ohne S. Du willst nichts bezahlen ;-)
> Bei allen Bytes werden 9 Bit übertragen aber nur bei der Adresse> ist dieses Bit gesetzt.
Kann man machen, muss aber nicht.
>wie kann die Übertragung (sende TX und Empfang RX)- Funktionen aussehen,>damit den gesamten Format übertragen wird .
Beschäftige dich erstmal mit RS232 zwischen PC und uC. Wenn du das drauf
hast, mach dich an RS485.
MFG
Falk
Hallo,
ich habe in einer Anwendung auch RS485 eingesetzt.
Ein Protokoll ist ganz einfach implementiert. Meine Anwendung sendet
einen String über den RS485-Bus der als erstes die Geräteadresse und
dann den eigentlichen Befehl enthält.
zB: "B003S100"
- "B003" kennzeichnet jetzt Befehl an Gerät 003
- ist dann Schrittweite 100
Das Gerät antwortet dann mit "OK003 100" das bedeutet Befehl verstanden.
Nach dem OK können entsprechend dem Befehl weitere Daten vom Gerät
gesendet werden.
Falls keine oder eine falsche Antwort kommt wird nocheinmal gesendet.
Auf der Platine kann ich den 485 Treiber-IC einfach gegen einen 232
Treiber-IC austauschen und habe somit auch einen RS232-Bus.
Da ich die Geräte über das Hyperterminal-Programm steuere habe ich auch
in den Datenübertragungsparametern nur ganz einfache Einstellungen:
9600 Baud, 8 Datenbits, keine Parität und 1 Stopbit.
Je nach Gerätetyp (485/232) brauche ich nur einen Konverter an meine
COM-Schnittstelle zu hängen.
Gruß Micha
der TE sieht wohl bei 485 was ganz besonders ...
es ist quasi bei 2drahtbetrieb aber nur RS232 im halbduplexbetrieb
die max485 werden zum senden und empfangen umgeschaltet
ruhezustand sind ALLE auf empfang
der master kann somit immer senden
ALLE slaves empfangen das selbe protokoll und entscheiden anhand der
adresse ob sie gemeint sind .. wenn nicht verwerfen
der slave mit dieser adresse antwotet darauf und alles ist ok
man kann dazu jede belibige uart routine verwenden und erweitet diese
mit dem enable pin
So schwierig is so ein Protokoll nun auch wieder nicht. Ein Packet hat
ein Startzeichen resp eine Startsequenz, Header genannt. Dieser Header
muss verschiedene Anforderungen erfuellen. Falls man verschieden lange
Packete verwenden will, so muss die Laenge teil des headers sein. Falls
gewuenscht kann man vor dem effektive Stratzeichen noch
Synchronistationszeichen haben, die helfen dem Empfaenger, falls der mal
ein Zeichen verloren hat und ausm Tritt ist. Falls man eine sender und
viele Empfaenger hat, so muss eine Start- und eine Zieladresse, zB als
Byte, Teil des Headers sein. Falls man die Daten sicher uebertragen
will, meint, kaputte Daten erkennen will, so macht man einen CRC ueber
alles und haengt den CRC hinten an die Meldung an. Falls eine Meldunf
laenger als ein Packet sein kann, so muss man noch ein Sequenznummer
mitsenden, dass der empfaenger so einzelne bloecke, die kaputt gingen,
neu anfordern kann. Man kann sich ueberlegen, ob jedes Packet
beantwortet werden muss. Falls eine Antwort ausbleibt : neu senden -
aber wie oft ? Standardmaessig verfaehrt man bei einer kaputten
Nachricht wie bei einer nicht verstandenen Nachricht, gleich wie bei
einer Nachricht an eine fremde Adresse : keine Antwort geben.
Ein Master -Slave Netzwerk hat einen Master und viele slaves. Der Master
macht alles, darf senden wann er will. Ein slave darf nur Antwort geben.
Das muss innerhalb einer gewissen Zeit geschehen. Sonst gibt es einen
Timeout beim Master, der dann entscheidet was weiter zu geschehen hat.
danke schön für die Beiträge,
es wid langsam und langsam klarer.
Aber damit der 9.bit übertragung funktioniert , muss ich sowohl bei der
salve als auch bei Master ein AVR benutzen oder ?. weil nur bei den
kann mann das 9.bit Modus einstellen , die der Slave auch mit
konfiguriert werden kann.
Weil momentan ich ein Atmega als Master und ein Cypress als slave .
thks.
Seb
Hi
Der Multi-Prozessor-Mode (mit 9.Bit) hat natürlich gewisse Vorteile. Vor
allem werden nicht adressierte Slave weniger belästigt. Aber das ganze
funktioniert auch im 8-Bit-Mode. Nur mit etwas mehr Programmierarbeit.
MfG Spess
@ Micha(Gast)
>ich habe in einer Anwendung auch RS485 eingesetzt.>Ein Protokoll ist ganz einfach implementiert. Meine Anwendung sendet>einen String über den RS485-Bus der als erstes die Geräteadresse und>dann den eigentlichen Befehl enthält.>zB: "B003S100">- "B003" kennzeichnet jetzt Befehl an Gerät 003>- ist dann Schrittweite 100
=> Pollin bei den Slave nach jeder Sendung einem patakt auf dem Bus.
so ein einfaches Protokol , will ich realisieren.
Wie erfolgt dann die Modulation und demodulation von daten.
ich vermute bei Master hast du ein Strcat() zum Zusammenfügen von
Adresse und Befehl zu einem String.
Wie schafst du dann noch diese zu extrahieren bei den Slave.
(wenn ich zu viel wusste , hätte ch auch nicht gefragt. ich bin neu in
der Materie)
danke
Sebastian
@ Sebastian (Gast)
>=> Pollin bei den Slave nach jeder Sendung einem patakt auf dem Bus.
Der Ramschladen hat damit wenig zu tun ;-)
>so ein einfaches Protokol , will ich realisieren.
Dann fang mal EINFACH an. PC und uC. ASCII basierend. Ist langsamer,
kann man aber einfacher debuggen, nämlich per Trminalprogramm.
>Wie erfolgt dann die Modulation und demodulation von daten.
Da wird nix demoduliert, bestenfalls dekodiert.
>ich vermute bei Master hast du ein Strcat() zum Zusammenfügen von>Adresse und Befehl zu einem String.
Kann man auch mit printf machen.
>(wenn ich zu viel wusste , hätte ch auch nicht gefragt. ich bin neu in>der Materie)
Fang klein an.
MFG
Falk
danke falk
ichdachte mir es wäre da das kleinste Niveau. Ich würde gern der
Hyperterminal benutzen, aber leider ich bin ein Vista benutzer. Meine
ansicht und Kenntnisse nach , gibt es sowas nicht bei Vista.
hat jemandd eine alternative .
danke
Hallo leute
ich habe mir eine Transmit funktion geschrieben. aber es funktioniert
nicht wie erwünscht.
der UDREO bit bleibt für das Senden von Adresse und Data high .
danach geht es wieder auf O und die summe kann dann nicht übertragen
werden / geht verloren. das programm bleibt an der stelle hängen , da
UDRE0 nicht gesetzt ist.
warum ist es so ? ich habe schon alles mögliche probiert.
ich kapiere dass nicht.
Hier der Transmitfunkt.
void MS_Transmit(unsigned char addresse, unsigned char data,unsigned
char Summe)
{
PORTB |= (1 << DDB0); //Max485 auf Senden
Summe=0;
while ( !(UCSR0A & (1<<UDRE0))); //Warten, bis UDR leer
ist für Senden
UDR0 = addresse; //Adresse senden
while ( !(UCSR0A & (1<<UDRE0))); //Warten bis UDR leer
ist für Senden
UDR0 =data; // daten senden
//berechnung der Cheksumme= data xor addresse
//Summe=data ^ addresse;
UCSR0A |= (1<<UDRE0);
while ( !(UCSR0A & (1<<UDRE0))); //Warten bis UDR leer
ist für Senden
UDR0 =Summe; // checksumme senden
_delay_ms(20); //MAX485-Buffer leeren
lassen
PORTB &= ~(1 <<DDB0); //Max485 auf Emfang
}
Danke
Übrigens es bleibt icht hängen. ich habe es noch debuggen können. Es
braucht nur ziemlich eine Weile um weiter zu machen. Bestimmt dammit der
UDRO-puffer leer wird.
danach geht UDRE0 wieder auf 1 und TXCO auf 1. => Transmit
completet.
danach geht er weiter mit der Summe(schecksumme) und TXC= wird nicht
mehr auf 1 gesetzt.
nach senden von adresse und data ist TXCO weiterhin null. Erst wenn
UDRE0 wieder auf 1 ist (Puffer empty) wird dann TXC0 auch auf 1
gesetzt.
Ich dachte nach jeder Übergabe von Daten an UDR0 wird TXC0 auf 1
gesetzt.
Scheint aber nicht der fall zu sein.
Was mache ich dann hier fall. Ich sehe es nicht.
start 8bit 1 stop bit
Danke um Rat
>Ich dachte nach jeder Übergabe von Daten an UDR0 wird TXC0 auf 1>gesetzt.
Um es in den Worten meiner Latein-Lehrerin zu sagen: Denken ist manchmal
Glücksache!
Das TXC-Flag wird gesetzt, wenn der UDR-Puffer (i.d.R. zweistufig)
komplett leer ist, nicht wenn noch ein weiteres Byte drin steht.
und delays sind manchmal tötlich
gerade 20ms .. is ma verdammt lange wo man andere sahen manchen kann ...
gewöhn dir eine derartige programmierung erst garnicht an
Hi
>Das TXC-Flag wird gesetzt, wenn der UDR-Puffer (i.d.R. zweistufig)>komplett leer ist, nicht wenn noch ein weiteres Byte drin steht.
Es gibt UDR und das Transmitregister.
TXC ist das Flag für das Transmit-Register. Es wird gesetzt wenn die
Übertragung eines Bytes abgeschlossen ist und kein weiteres in UDR
bereitliegt. UDRE wird gesetzt, wenn ein Byte von UDR an das
Transmit-Register übergeben wurde.
MfG Spess
Ich weiß es gilt immer der Moto „wenn nichts raus geht, dann kommt
nichts zurück“
Nun setze ich mich dran und Programmiere wie ich es sein kann und
bitte bei denen, die mehr Erfahrung in der Sache haben auf
Plausibilität zu prüfen.
Ich kann momentan nicht echtzeit an dem Bus testen. Da ich noch keine
Hardware dafür habe.
Hier ist der receiver routine
unsigned char USART_Receive( void ) // Unterfuntion
{
/* Wait for data to be received */
while ( !(UCSR0A & (1<<RXC0)) );
/* Get and return received data from buffer */
return UDR0;
}
unsigned char MS_Receive( void ) // Receivefuntion des Masters.
{
for (unsigned int i=0; i<3;i++) // Buffer initialisieren
{
Buffer[i]=0;
}
/* Get received data from buffer */
Buffer[0]=USART_Receive();
Buffer[1]=USART_Receive();
Buffer[2]=USART_Receive();
if( (Buffer[0]!=addresse)| (Buffer[1]= =NACKNWOLEGE)) // zurücksenden
falls nicht erfolgreich
{
MS_Transmit(addresse, data, Summe);
}
else
{
return 1;
}
}
Was ich mache:
Ich initialisiere zuerst den gesamten Buffer mit Nullen
Nach jedem empfang speichere ich dann mit einem Buffer wie die Paketen
angeordnet sind.
0= adresse
1= data
2= summe
Dann vergleiche ich ob die gesendete Adresse mit der Receiveradresse
nicht übereinstimmen oder ob ich ein NACK bekommen habe. Wenn ja dann
sende ich erneut.
Wenn aber erfolgreich liefert die Funktion eine TRUE.
Die Transmitroutine dafür ist oben von mir schon gepostet worden.
Danke für anregungen.
hätte ich nach code gefragt; würde ich hier alle mögliche Sprüche
bekommen.
nun schreibe ich den Programm und bitte um rat da bekomme ich nichts.
Die Hoffnung stirb als letzte.
ich warte noch.
Hallo Sebastian,
ich finde gut dass Du das tatsächlich selber programmieren willst.
Ich habe leider keine Zeit das Programm für Dich zu debuggen.
Geh mal so vor: leihe Dir von einem Bekannten der Schule der Arbeit
/ wo auch immer, ein Speicheroszilloskop oder einen Logicanalyser.
Auf dieser Webseite findest Du auch Artikel und Links zu günstigen
Logicanalysern. Untersuche Senden und Empfangen erstmal getrennt.
Das senden mit Deiner Schaltung und auf dem Bus mit dem LA messen.
Erst wenn da die gewünschten Bits rauspurzeln mit der Empfangsseite
weitermachen.
Gruß
Olaf