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_ */
Lesezeichen