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..
Bild hier  
Spannungsversorgung Kondensatoren und so hab ich weggelassen..
Bild hier  
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
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)
{
	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
Code:
#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:
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_ */