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.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.h: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 }
Schönes Wochenende !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_ */
MfG
ngb







Zitieren

Lesezeichen