PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : RS485-Protokoll



ngblume
16.03.2007, 09:44
Guten Morgen !

ich habe für meinen ROV namens ROUVus (www.hardegser-sv.de/rov) versucht, ein Protokoll für den RS485-Bus zu schaffen. Ich will zum Verständnis der Frage kurz beschreiben wie es funktioniert:
| ! | Adresse | Data1 | Data2 | Data3 | Data4 | Data5 | ist der Aufbau eines Packets. Nun habe ich den Empfangsinterrupt soweit, dass er in ein Array of Char (char buffer[6]) dann Adresse + Datenbytes speichert wenn die adresse seine ist. das scheint auch einwandfrei zu funktionieren..
nun muss ich das angekommene Kommando noch weiter verarbeiten..
also setzt der interrupt bei vollständigem empfang eine variable auf eins..
im hauptprogramm läuft eine schleife, die diese variable prüft..
bei wert == 1 tritt sie in aktion.. und zwar einfach den ganzen buffer zurückzusenden...
fürs senden habe ich mir zwei funktionen geschrieben, die einzelne chars und ganze "strings" senden kann..
wenn ich der stringfunktionen den buffer übergebe, kommt der auch im terminalprogramm (HTerm) an...
problem: da kommt noch viel mehr danach an.. statt der 6 bytes die er empfangen hat kommen ungefähr 20 bytes an und nur am anfang stehen die richtigen... danach kommt kauderwelsch..
übergebe ich der stringsende funktion einen string direkt, kommt dieser vollständig und ausschließlich an..
um das problem weiter einzugrenzen habe ich versucht den buffer in einer schleife als char zu senden:
UDR = buffer[i]; in etwa.. das hat dazu geführt, dass er nichts gesendet hat (nur die standards die drumherum gelegt werden von der sende funktion (| ! | Adresse |). kann man mit buffer[i] auf einzelne zeichen zugreifen oder nicht ? und die nächste frage wo kommen diese ominösen zeichen her..
wenn ich nur ein zeichen sende und das direkt im interrupt verarbeite, gibt es keine probleme, was für mich bedeutet, das die schnittstelle nicht noch nachfolgende signale sendet, da im testprogramm in allen fällen außer "a" die led ausgeschaltet wird. wenn ich ein "a" senden, die LED auch angeht und an bleibt.

Ich hoffe , ihr versteht was ich meine und könnt mir ein wenig unter die arme greifen..

MfG
ngb

P.S.: quellcode poste ich heute nachmittag... vielleicht gibt es ja eine nicht software-bedingte lösung

Johannes G.
16.03.2007, 14:30
Hallo,

ich arbeite gerade auch ein einem RS485 Bus...
Ich hänge aber noch an der Hardware..
Kannst du mir da eventuell mal einen Schaltplan schicken?

Viele Grüße,
Johannes

ngblume
16.03.2007, 17:07
Hallo..
ich habe mir einen RS485-RS232-Konverter gebaut und an den µC kann man MAX485 direkt dranhängen (beim ATMega8 einfach Pin2 an Pin1 vom MAX485 und Pin3 vom ATMega8 an Pin4 vom MAX485, Pin2 und Pin3 vom MAX485 mit Pin4 vom ATMega8 verbinden [kann jeder Output-Pin sein, da hier zwischen Senden und Empfangen umgeschaltet wird], Pin 6 und 7 einfach identisch parallel an alle anderen MAX485er anschließen..)
Für den Konverter hab eich den von aquaticus.info genommen...
http://aquaticus.info/rs485_to_rs232 WICHTIG: in dem Layout fehlt die Spannungsversorgung den Pins des Max232.. das scheint normal zu sein hat mich aber ziemlich irritiert ;-)...
Was auch gut geht, ist den RS232-TTL-Wandler von Pollin zu nehmen und dann einfach daran noch ne kleine Platine mit dem rest (MAX485 und ne Diode samt widerstand anzusetzen..) (wenn man keine platinen ätzt/ätzen kann..)
Wenn du nen oszi hast, kannst du nach dem Bau einfach ne Differentialmessung machen und dann sehen, wenn du ein signal dauerhaft sendest (dann hast du ne chance was zu sehen), dass die schaltung funktioniert..
hab leider kein programm für nen schaltplan, sonst hätte ich dir meine schaltung aufgezeichnet (mache einfach ne paint skizze)
am besten mit HTerm machen da gibts den "ASend" button. dann wird ein zeichen folge du eingibst dauerhaft gesendet..
Wichtig: zum umschalten zwischen senden und empfangen am PC gilt es leider wegen der umsetzung mit RTS umgekehrt..
wenn du RTS angeklickt hast (in HTerm) dann empfängst du daten und wenn du den button nicht geklickt hast empfängst du..
(hoffe, dass ist noch verständlich - man siehts auch auf dem hterm bild, da ist der button geklickt für empfang.. - bei dem aquaticus konverter geht dann die LED aus.. ) bei längeren strecken sei auf die terminierung hingewiesen... ich denke auf der RS485 seite sollte was zu dem thema stehen mit den widerstandswerten..
http://www.hardegser-sv.de/rov/bilder/max485.jpg
Spannungsversorgung Kondensatoren und so hab ich weggelassen.. ;-)
http://www.hardegser-sv.de/rov/bilder/hterm.jpg
hier sieht man den kauderwelsch der noch so übertragen wird ohne, dass ich weiß wo der her kommt.. und hier der Code (Kommunikationsfunktionen ausgelagert..)
Motor-treiber.c


//-----------------------------------------------------------------------------------------//
//-----------------------------------------------------------------------------------------//
// RS485- Implementierung mit MAX 485 //
// Autor: Niels Göran Blume 2007 für ROUVus //
// www.hardegser-sv.de/rov //
//-----------------------------------------------------------------------------------------//
//-----------------------------------------------------------------------------------------//
/*
Hardware- Konzessionen:
Atmega8 mit UART an PORTD0 und PORTD1 und Switch Receive/Send für MAX 485 an PORTD2
Halb-Duplex
*/

/* Protokoll- Definition:
Das Protokoll ist auf den One-Master-Multi-Slave-Betrieb ausgelegt.
Bei entsprechender Programmierung ist auch ein eingeschränkter
Multi-Master-Betrieb möglich.

Standard: Jede Nachricht startet mit "!".
Es folgt die Adresse des Ziels in einem Byte.
Nun folgen 5 Datenbytes, die beliebig gefüllt werden können (Erweiterung einfach möglich).
Am Ende steht in der Zielmaschine ein char- Array bereit, dass alle Bytes seit dem "!"
(sprich Adresse und 5 Datenbytes) enthält.

| ! | a | L | E | D | 1 | 1 | als Beispiel...

An Adresse "a" ergeht die Nachricht "LED11", was vielleicht als "LED1 auf Status 1 setzen"
interpretiert werden könnte.
*/

#define F_CPU 16000000UL

#include <avr/io.h>
#include <inttypes.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <string.h>
#include "rs485.c"

int main(void)
{
int i = 0;
// USART initialisieren (8n1 - 19200)
rs485_init();

//Output DDD2 setzen für Send/Receive- Wechsel / DDD3 für ne LED
DDRD = (1<<DDD2)|(1<<DDD3);

warte(5000);

rs485_puts('a',"Melde mich zum Dienst ! Meine Adresse: b");

sei();

PORTD |= (1 << 3);

while(1) //Reaktion in Schleife
{
if (befehl_fertig == 1)
{
warte(5000);
rs485_puts('a',buffer);
befehl_fertig = 0;
}
}
;
}

rs485.c


#include "rs485.h"
#define BAUD 19200UL
#define UBRR_BAUD ((F_CPU/(16UL*BAUD))-1)

char buffer[6];
char kommando[6];
int buffer_pos = 0;
int befehl = 0;
int address = 0;
int befehl_fertig = 0;

void warte (uint16_t loop) //loop: wartezeit in ms
{
uint16_t i;
for(i=0;i<loop;i++) _delay_ms(1);
}

// Empfangene Zeichen werden im Buffer gespeichert und warten dort
SIGNAL (SIG_UART_RECV)
{
char data;
int i;

data = UDR;
if (data == '!')
{
befehl = 1;
address = 0;
return;
}
else
{
if(befehl == 1 && address == 0)
{
if (data == 'b') //Unsere Adresse ?
{
buffer[buffer_pos] = data;
buffer_pos++;
address = 1;
return;
}
else
{
befehl = 0;
address = 0;
return;
};
};

if(befehl == 1 && address == 1)
{
buffer[buffer_pos] = data;
if (buffer_pos < 5) //Noch ein Platz frei im Buffer ?
{
buffer_pos++; //Dann Zeiger erhöhen
return;
}
else
{
buffer_pos = 0; //Wenn Buffer voll, reset an Anfang
befehl = 0; //Befehl fertig...
address = 0;
//Interrupt starten -> Befehl fertig !!
//for (i=0; i<6; i++)
//{
// kommando[i] = buffer[i];
//};
befehl_fertig = 1;
return;
};
};
};
}

void rs485_init()
{
// Baudrate einstellen (Normaler Modus)
UBRRH = (unsigned char) (UBRR_BAUD>>8);
UBRRL = (unsigned char) (UBRR_BAUD & 0x0ff);

// Aktivieren des Empfängers, des Senders und des "Daten empfangen"-Interrupts
UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);

// Einstellen des Datenformats: 8 Datenbits, 1 Stoppbit
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
}

// Um das Problem bei RS485 zu umgehen, dass nicht gleichzeitig gesendet und empfangen werden kann (2 Adern),
// nur "direktes" Senden möglich

// Einzelnes Zeichen senden
void rs485_putc (unsigned char address, unsigned char buffer)
{
while ( !(UCSRA & (1<<UDRE))); //Warten bis UDR leer ist für Senden
PORTD |= (1 << 2); //Max485 auf Senden
UDR = '!'; //Sendungsanfang

while ( !(UCSRA & (1<<TXC))); //Warten bis Senden abgeschlossen
UCSRA &= ~(1<<TXC); //Gesendet-Bit löschen
UDR = address; //Adresse senden

while ( !(UCSRA & (1<<TXC))); //Warten bis Senden abgeschlossen
UCSRA &= ~(1<<TXC); //Gesendet-Bit löschen
UDR = buffer; //Daten senden

warte(100); //MAX485-Buffer leeren lassen
PORTD &= ~(1 << 2); //Max485 auf Empfang
}

// String senden
void rs485_puts (unsigned char address, const char *s)
{
while ( !(UCSRA & (1<<UDRE))); //Warten bis UDR leer ist für Senden
PORTD |= (1 << 2); //Max485 auf Senden
UDR ='!';

while ( !(UCSRA & (1<<TXC))); //Warten, bis Senden abgeschlossen wurde
UCSRA &= ~(1<<TXC); //Gesendet-Bit löschen
UDR = address; //Adresse senden

while ( !(UCSRA & (1<<TXC))); //Warten bis Senden abgeschlossen
UCSRA &= ~(1<<TXC); //Gesendet-Bit löschen

while (*s != 0)
{
loop_until_bit_is_set(UCSRA,UDRE); //warte bis Datenregister frei
UDR = *s; //Zeichen nach Sendedatenregister
s++; //Adresse erhöhen
}

while (*s++);
warte(100); //MAX485-Buffer leeren lassen
PORTD &= ~(1 << 2); //Max485 auf Emfang
}

rs485.h:


#ifndef _RS485_H_
#define _RS485_H_

extern void rs485_init();
extern void rs485_putc(unsigned char address, unsigned char buffer);
extern void rs485_puts(unsigned char address, const char *s);
extern void warte(uint16_t loop);

static inline void rs485_flush()
{
while (UCSRB & (1 << UDRIE));
}

#endif /* _RS485_H_ */

robocat
16.03.2007, 17:31
brauchst du nicht einen null-terminierten string (und damit 7 bytes), damit deine sende-routine funktioniert? ohne \0 wird er fröhlich weitersenden, was den zeichenmüll erklären würde.

gruesse

ngblume
16.03.2007, 17:40
Hallo..

probier ich gleich mal aus.
ich glaube es aber eher nicht denn ich hab noch ein paar test durchgeführt undfolgendes festgestellt:


//-----------------------------------------------------------------------------------------//
//-----------------------------------------------------------------------------------------//
// RS485- Implementierung mit MAX 485 //
// Autor: Niels Göran Blume 2007 für ROUVus //
// www.hardegser-sv.de/rov //
//-----------------------------------------------------------------------------------------//
//-----------------------------------------------------------------------------------------//
/*
Hardware- Konzessionen:
Atmega8 mit UART an PORTD0 und PORTD1 und Switch Receive/Send für MAX 485 an PORTD2
Halb-Duplex
*/

/* Protokoll- Definition:
Das Protokoll ist auf den One-Master-Multi-Slave-Betrieb ausgelegt.
Bei entsprechender Programmierung ist auch ein eingeschränkter
Multi-Master-Betrieb möglich.

Standard: Jede Nachricht startet mit "!".
Es folgt die Adresse des Ziels in einem Byte.
Nun folgen 5 Datenbytes, die beliebig gefüllt werden können (Erweiterung einfach möglich).
Am Ende steht in der Zielmaschine ein char- Array bereit, dass alle Bytes seit dem "!"
(sprich Adresse und 5 Datenbytes) enthält.

| ! | a | L | E | D | 1 | 1 | als Beispiel...

An Adresse "a" ergeht die Nachricht "LED11", was vielleicht als "LED1 auf Status 1 setzen"
interpretiert werden könnte.
*/

#define F_CPU 16000000UL

#include <avr/io.h>
#include <inttypes.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <string.h>
#include "rs485.c"

int main(void)
{
int i = 0;
char *test = "Test!";
// USART initialisieren (8n1 - 19200)
rs485_init();

//Output DDD2 setzen für Send/Receive- Wechsel / DDD3 für ne LED
DDRD = (1<<DDD2)|(1<<DDD3);

warte(5000);

rs485_puts('a',"Melde mich zum Dienst ! Meine Adresse: b");

rs485_puts('a', test);

sei();

PORTD |= (1 << 3);

while(1) //Reaktion in Schleife
{
if (befehl_fertig == 1)
{
warte(5000);
rs485_puts('a',buffer);
befehl_fertig = 0;
}
}
;
}

Da wird ja eine art string initialisiert (was ist das eigentlich wirklich ??) un ihm der inhalt "Test!" zugewiesen und dann wird das ganze gesendet.. Funktioniert perfekt kein datenmüll hinterher...
ich habe den verdacht, dass das an dem array liegt in dem ich die datenbytes speichere.. ich habs mal mit:

char *data;
char *buffer;
und dann buffer = buffer + data;

versucht..
aber da wollte er dann nicht so wirklich, weil er "+" nicht auf binary anwenden wollte..
ich denke irgendwo liegt der sprichtwörtliche hund begraben..

MfG
ngb

ngblume
16.03.2007, 17:53
hey..
außerdem ist mir noch eingefallen, dass das ja bedeuten würde, dass mein test automatisch null-terminierd wird, oder ?
und rs485_puts an dieser stelle auf die terminierung wartet:


while (*s != '\0')
{
loop_until_bit_is_set(UCSRA,UDRE); //warte bis Datenregister frei
UDR = *s; //Zeichen nach Sendedatenregister
s++; //Adresse erhöhen
}

daraus resultiert eine andere frage:
kann man das nicht irgerndwie abändern, dass er am ende einfach aufhört..?
ich würde gerne ohne null-terminierte string-chars arbeiten..

MfG
ngb

robocat
16.03.2007, 18:07
strings sind char arrays, deren letztes byte 0 ist.
wenn du mit char test[]="test"; einen string erzeugst, hat dieser nicht 4 sondern 5 bytes. strings ohne \0 kannst du notfalls verwenden, wenn du ihre exakte länge (bei dir 6 zeichen) kennst, und nicht überschreitest.
for(i=0;i<6;i++)send(test[i]);
sobald du aber "while(...!=0){}" verwendest, musst du mit 0 terminieren, sonst weiss der µC/prozessor nicht, wie lang der string ist.

ngblume
16.03.2007, 18:19
Danke..
das klärt einiges..
ich hab den code angepasst an die idee mit terminierung und jetzt sieht das result wie gewünscht aus..
ein problem stellt sich noch und das ist der vergleich mit terminierten strings..


while(1) //Reaktion in Schleife
{
if (befehl_fertig == 1)
{
warte(5000);
rs485_puts('a',buffer);
if(buffer == "bled11")
{
PORTD |= (1 << 3);
rs485_puts('a', "Kommando erhalten...");
warte(2000);
PORTD &= ~(1 << 3);
};
befehl_fertig = 0;
}
};

das problem ist das die LED nie leuchtet und er sich auch nicht zu wort meldet wie gewünscht, wenn ich ihm das kommando sende..
wie kann ich am einfachsten den vergleich für das kommando durchführen und kann ich später wenn ich kommandos mit parameter habe (motorgeschwindigkeiten) noch per string[i] auf einzelne zeichen zugreifen ?
wenn du mir das noch auch beantworten könntest, wäre mir sehr geholfen !
Vielen dank !

MfG
ngb

izaseba
16.03.2007, 18:40
Hallo,
schau mal, was Du da vergleichst


if(buffer == "bled11")

buffer könnte man auch so ausschreiben
&buffer[0]
Du vergleichst dann wohl eine Adresse mit string.
Schau dir mal Funktionen von string.h und vor allem strcmp
http://www.nongnu.org/avr-libc/user-manual/group__avr__string.html

Ich hoffe, daß ich helfen konnte.

Gruß Sebastian

ngblume
16.03.2007, 21:00
vielen dank ! =D>
ich dachte nicht, dass man das so ohne weiteres mit strcmp machen kann..
und das mit dem &-Zeichen kommt mir auch wieder dunkel in den sinn aus den C++ zeiten...
jetzt funktioniert das einwandfrei..
fertig..
werden den code mal posten falls jemand etwas ähnliches braucht vielleicht als inspiration oder relativ fertige funktionen zum senden und empfangen.. (wobei die qualität noch etwas zu wünschen übrig lässt, auch was das protokoll angeht..)
motor-treiber.c


//-----------------------------------------------------------------------------------------//
//-----------------------------------------------------------------------------------------//
// RS485- Implementierung mit MAX 485 //
// Autor: Niels Göran Blume 2007 für ROUVus //
// www.hardegser-sv.de/rov //
//-----------------------------------------------------------------------------------------//
//-----------------------------------------------------------------------------------------//
/*
Hardware- Konzessionen:
Atmega8 mit UART an PORTD0 und PORTD1 und Switch Receive/Send für MAX 485 an PORTD2
Halb-Duplex
*/

/* Protokoll- Definition:
Das Protokoll ist auf den One-Master-Multi-Slave-Betrieb ausgelegt.
Bei entsprechender Programmierung ist auch ein eingeschränkter
Multi-Master-Betrieb möglich.

Standard: Jede Nachricht startet mit "!".
Es folgt die Adresse des Ziels in einem Byte.
Nun folgen 5 Datenbytes, die beliebig gefüllt werden können (Erweiterung einfach möglich).
Am Ende steht in der Zielmaschine ein char- Array bereit, dass alle Bytes seit dem "!"
(sprich Adresse und 5 Datenbytes) enthält.

| ! | a | L | E | D | 1 | 1 | als Beispiel...

An Adresse "a" ergeht die Nachricht "LED11", was vielleicht als "LED1 auf Status 1 setzen"
interpretiert werden könnte.
*/

#define F_CPU 16000000UL

#include <avr/io.h>
#include <inttypes.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <string.h>
#include "rs485.c"

int main(void)
{
rs485_init(); //USART initialisieren (8 Datenbits, no Parity, 1 Stopbit)
//Baud: 19200
DDRD = (1<<DDD2)|(1<<DDD3); //Output DDD2 setzen für Send/Receive- Wechsel
//DDD3 für ne LED
warte(5000);

rs485_puts('a',"Melde mich zum Dienst ! Meine Adresse: b");

sei(); //Interrupts enablen

PORTD &= ~(1 << 3); //LED ausschalten

while(1) //Reaktion in Schleife
{
if (befehl_fertig == 1) //Befehl vorhanden
{
warte(5000); //Zeit damit ich den Sende-Mode am PC mit der Maus beenden kann
rs485_puts('a',buffer); //Einfach empfangenes Kommando zurücksenden
if(strcmp(buffer, "bled11") == 0) //Beispielkommando als Vergleichsgrundlage
{ //später weitere zum Beispiel als Switch
PORTD |= (1 << 3); //mit einzelnem Byte (&buffer[i]) | LED an
rs485_puts('a', "Kommando erhalten..."); //If-Routine erreicht-Bestätigung
warte(2000); //Damit man die LED überhaupt leuchten sieht
PORTD &= ~(1 << 3); //LED aus
};
befehl_fertig = 0; //Befehl abgearbeitet - Status zurücksetzen
}
};
}

rs485.c:


#include "rs485.h"
#define BAUD 19200UL
#define UBRR_BAUD ((F_CPU/(16UL*BAUD))-1)

char buffer[7];
int buffer_pos = 0;
int befehl = 0;
int address = 0;
int befehl_fertig = 0;

void warte (uint16_t loop) //loop: wartezeit in ms
{
uint16_t i;
for(i=0;i<loop;i++) _delay_ms(1);
}

// Empfangene Zeichen werden im Buffer gespeichert und warten dort
SIGNAL (SIG_UART_RECV)
{
char data;
int i;

data = UDR;
if (data == '!')
{
befehl = 1;
address = 0;
return;
}
else
{
if(befehl == 1 && address == 0)
{
if (data == 'b') //Unsere Adresse ?
{
buffer[buffer_pos] = data;
buffer_pos++;
address = 1;
return;
}
else
{
befehl = 0;
address = 0;
return;
};
};

if(befehl == 1 && address == 1)
{
buffer[buffer_pos] = data;
if (buffer_pos < 5) //Noch ein Platz frei im Buffer ?
{
buffer_pos++; //Dann Zeiger erhöhen
return;
}
else
{
buffer_pos = 0; //Wenn Buffer voll, reset an Anfang
befehl = 0; //Befehl fertig...
address = 0;
buffer[6] = '\0';

befehl_fertig = 1;
return;
};
};
};
}

void rs485_init()
{
// Baudrate einstellen (Normaler Modus)
UBRRH = (unsigned char) (UBRR_BAUD>>8);
UBRRL = (unsigned char) (UBRR_BAUD & 0x0ff);

// Aktivieren des Empfängers, des Senders und des "Daten empfangen"-Interrupts
UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);

// Einstellen des Datenformats: 8 Datenbits, 1 Stoppbit
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
}

// Um das Problem bei RS485 zu umgehen, dass nicht gleichzeitig gesendet und empfangen werden kann (2 Adern),
// nur "direktes" Senden möglich

// Einzelnes Zeichen senden
void rs485_putc (unsigned char address, unsigned char buffer)
{
while ( !(UCSRA & (1<<UDRE))); //Warten bis UDR leer ist für Senden
PORTD |= (1 << 2); //Max485 auf Senden
UDR = '!'; //Sendungsanfang

while ( !(UCSRA & (1<<TXC))); //Warten bis Senden abgeschlossen
UCSRA &= ~(1<<TXC); //Gesendet-Bit löschen
UDR = address; //Adresse senden

while ( !(UCSRA & (1<<TXC))); //Warten bis Senden abgeschlossen
UCSRA &= ~(1<<TXC); //Gesendet-Bit löschen
UDR = buffer; //Daten senden

warte(100); //MAX485-Buffer leeren lassen
PORTD &= ~(1 << 2); //Max485 auf Empfang
}

// String senden
void rs485_puts (unsigned char address, const char *s)
{
while ( !(UCSRA & (1<<UDRE))); //Warten bis UDR leer ist für Senden
PORTD |= (1 << 2); //Max485 auf Senden
UDR ='!';

while ( !(UCSRA & (1<<TXC))); //Warten, bis Senden abgeschlossen wurde
UCSRA &= ~(1<<TXC); //Gesendet-Bit löschen
UDR = address; //Adresse senden

while ( !(UCSRA & (1<<TXC))); //Warten bis Senden abgeschlossen
UCSRA &= ~(1<<TXC); //Gesendet-Bit löschen

while (*s != '\0')
{
loop_until_bit_is_set(UCSRA,UDRE); //warte bis Datenregister frei
UDR = *s; //Zeichen nach Sendedatenregister
s++; //Adresse erhöhen
}

warte(100); //MAX485-Buffer leeren lassen
PORTD &= ~(1 << 2); //Max485 auf Emfang
}

rs485.h:


#ifndef _RS485_H_
#define _RS485_H_

extern void rs485_init();
extern void rs485_putc(unsigned char address, unsigned char buffer);
extern void rs485_puts(unsigned char address, const char *s);
extern void warte(uint16_t loop);

static inline void rs485_flush()
{
while (UCSRB & (1 << UDRIE));
}

#endif /* _RS485_H_ */


Schönes Wochenende !
MfG
ngb

RettungsTim
31.01.2012, 14:38
Hallo zusammen,

der Beitrag ist etwas älter, aber für mich aktuell.

Ich wollte dieses gerne Ausprobieren aber ich bekomme keine Kommunikation zu stande.

Wie ist der der Hardware aufbau?

Brauche ich bei 10cm Testleitung auch die Abschlusswiderstände? Brauche ich den Pull-up und Pull-up?

Fragen über Fragen.

Danke schon mal und Grüße
Tim

masasibe
31.01.2012, 17:55
Hallo RettungsTim,

Hast du dir diesen Artikel schon einmal durchgelesen:
http://www.rn-wissen.de/index.php/RS485 ?
Hier ist die Verkabelung genau beschrieben.

Und in Wikipedia: http://de.wikipedia.org/wiki/EIA-485

Vielleicht klärt das einen Teil deiner Fragen!


Ich wollte dieses gerne Ausprobieren aber ich bekomme keine Kommunikation zu stande.

Wie sieht denn dein Aufbau genau aus?

mfg masasibe

RettungsTim
19.02.2012, 18:37
Danke, nun habe es endliche hinbekommen.

Jetzt habe ich nur das Problem das die Schleife:


...

if (befehl_fertig == 1) //Befehl vorhanden
{
...

nicht abgearbeitet wird.

In der rs485.c wir die Variable zwar auf 1 gesetzt aber in der main.c nicht.

Habt ihr noch Tipps für mich?

Danke und Grüße
Tim

sternst
19.02.2012, 22:43
In der rs485.c wir die Variable zwar auf 1 gesetzt aber in der main.c nicht.

Habt ihr noch Tipps für mich?Schlage die Bedeutung von "volatile" nach.

RettungsTim
20.02.2012, 04:34
Oh, danke. Das habe ich total vergessen. :(
Lange nicht mehr Programmiert.
Werde ich morgen gleich ausprobieren.

Werde mich melden und ein Update posten wenn funktioniert.

Grüße
Tim