-

+ Antworten
Seite 2 von 2 ErsteErste 12
Ergebnis 9 bis 15 von 15

Thema: RS485-Protokoll

  1. #9
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    43
    Beiträge
    2.234
    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-...r__string.html

    Ich hoffe, daß ich helfen konnte.

    Gruß Sebastian
    Software is like s e x: its better when its free.
    Linus Torvald

  2. #10
    Neuer Benutzer Öfters hier
    Registriert seit
    17.02.2004
    Beiträge
    23

    Protokoll funzt..

    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
    Code:
    //-----------------------------------------------------------------------------------------//
    //-----------------------------------------------------------------------------------------//
    //                         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:
    Code:
    #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:
    Code:
    #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

  3. #11
    Neuer Benutzer Öfters hier
    Registriert seit
    27.09.2007
    Beiträge
    8
    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

  4. #12
    Erfahrener Benutzer Fleißiges Mitglied Avatar von masasibe
    Registriert seit
    21.01.2011
    Beiträge
    181
    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

  5. #13
    Neuer Benutzer Öfters hier
    Registriert seit
    27.09.2007
    Beiträge
    8
    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

  6. #14
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    665
    Zitat Zitat von RettungsTim Beitrag anzeigen
    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.
    MfG
    Stefan

  7. #15
    Neuer Benutzer Öfters hier
    Registriert seit
    27.09.2007
    Beiträge
    8
    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

+ Antworten
Seite 2 von 2 ErsteErste 12

Berechtigungen

  • Neue Themen erstellen: Ja
  • Themen beantworten: Ja
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •