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
Lesezeichen