Hey..
hier der richtige code..
hoffe der hilft bei der lösung
und die 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)|(1<<DDB1); //Output DDD2 setzen für Send/Receive- Wechsel //DDD3 für ne LED und DDB1 für PowerMOSFet warte(5000); rs485_puts('a',"Melde mich zum Dienst ! Meine Adresse: b"); sei(); //Interrupts enablen PORTD &= ~(1 << 3); //LED ausschalten PORTB &= ~(1 << 1); 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 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', "led11"); }; if(strcmp(buffer,"bled10")==0) { PORTD &= ~(1 << 3); rs485_puts('a',"bled10"); }; if(strcmp(buffer,"bpwm11")==0) { PORTB |= (1 << 1); }; if(strcmp(buffer,"bpwm10")==0) { PORTB &= ~(1 << 1); }; befehl_fertig = 0; //Befehl abgearbeitet - Status zurücksetzen } }; }
und die 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 }
vielen dank für alle vorschläge im voraus !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