Hallo,
Empfänger:
Mµ:Atmega8-16 mit 16MHz Quarz
Mein Sendestring sieht so aus uart_puts("0xA4\r" );
Ich versuche nun meine RS485 Test-Routiene zum laufen zu bringen
aber ich kann nur einmal etwas empfangen.
Das Senden geht überhauptnich.
Wenn ich anstelle von den RS485 Baustein ein Max232 anschliese
funktioniert alles.
Vielleicht könnte mir einer Weiterhelfen
mfg
denken die Funktionen:
setTransmitMode();
setReceiveMode();
auch an eine Zeitliche Verzögerung?
Ich würde folgendes Testen:
setTransmitMode(); //Sende-Pin auf HIGH schalten
delay_ms(5); // eine Verzögerung
uart_puts("TEST OK" );
Hi
>UCSRA |= (1<<TXC); // clear txc flag> while (*s)> { /* so lange *s != '\0' also ungleich dem "String->> UDR = *s;> s++;> }
Damit überfährst du die UART gnadenlos.
MfG Spess
Spess53 schrieb:> Hi>>>UCSRA |= (1<<TXC); // clear txc flag>>> while (*s)>> { /* so lange *s != '\0' also ungleich dem "String->>> UDR = *s;>> s++;>> }>> Damit überfährst du die UART gnadenlos.>> MfG Spess
Das ist eindeutig
void uart_puts (char *s)
{
UCSRA |= (1<<TXC); // clear txc flag
while (*s)
{
while (!(UCSRA & (1<<UDRE))) /* warten bis Senden moeglich */
{
}
/* so lange *s != '\0' also ungleich dem
"String-Endezeichen(Terminator)" */
UDR = *s;
s++;
}
}
Trotzdem bekomme ich nur ab und zu den String empfangen
@Tim (Gast)
>Welche Optimierungsstufe nutzt du vom gcc?>ggf schmeisst das der ggc nämlich raus:
Nö, Zugiffe auf IO-Register sind volatile und damit nicht entfernbar.
while (!(UCSRA & (1<<UDRE))); /* warten bis Senden moeglich */
mit Semikolon am Ende reicht.
@Falk Brunner:
Ok, Danke für den Hinweis.
@Sven (Gast):
Ich habe mir nochmal den Code angesehen und der passt soweit.
>Wenn ich anstelle von den RS485 Baustein ein Max232 anschliese>funktioniert alles.
Also doch eher Richtung Hardware.
Mal Dauerhaftes senden versucht?
Was hast du auf der anderen Seite? Einen PC?
Kann es sein das der nicht schnell genug von senden
auf empfangen umschaltet? Also im µC mal ein delay
vor dem umschalten zum Senden einbauen.
Kannst du mit einem 3 Teilnehmer der Bus belauschen?
Hast du eine Aktive Terminierung am bus damit
der sich nicht jeden Müll einfängt?
(+5V 620R A 120R B 620R GND)
Tim schrieb:> @Falk Brunner:> Ok, Danke für den Hinweis.>> @Sven (Gast):> Ich habe mir nochmal den Code angesehen und der passt soweit.>>>Wenn ich anstelle von den RS485 Baustein ein Max232 anschliese>>funktioniert alles.>> Also doch eher Richtung Hardware.> Mal Dauerhaftes senden versucht?>> Was hast du auf der anderen Seite? Einen PC?> Kann es sein das der nicht schnell genug von senden> auf empfangen umschaltet? Also im µC mal ein delay> vor dem umschalten zum Senden einbauen.>> Kannst du mit einem 3 Teilnehmer der Bus belauschen?>
also ich verwende ein Stm32F103 Board(3.3V) als Master der sendet dan
uart_puts("0xA4\r" ) das wird auch vom Slave(atmega8 5V) auch jedesmal
erkannt.
wenn ich nun vom slave etwas zurück senden will wird nur manchmal etwas
empfangen.
> Hast du eine Aktive Terminierung am bus damit> der sich nicht jeden Müll einfängt?> (+5V 620R A 120R B 620R GND)
Ich hab nur zwischen A 120R B
aber es sind ja nur 2Teilnehmer soll sich da die Terminierung so sehr
auswirken??
Probiert mal folgendes:
Nachdem das letzte byte ins UDR geschickt wird das "send complete" Flag
pollen. Und erst wenn das Byte komplett auf dem Bus liegt den receive
mode einschalten.
Im Moment wird das letzte Byte einfach abgeschnitten.
Wenn du nur 120Ohm dran hast dann mal schauen ob der RS485 Baustein
failsafe ist. 0V sind bei RS485 nicht definiert, also weder logisch 1
noch 0. Damit haben dann die nicht failsafe Transceiver ein Problem das
Startbit zu erkennen.
>wenn ich nun vom slave etwas zurück senden will wird nur manchmal etwas>empfangen.
Wie gesagt lass den slave mal eine kurze Pause machen bevor er
antwortet.
>aber es sind ja nur 2Teilnehmer soll sich da die Terminierung so sehr>auswirken??
Der Trick sind 2x 620R.
Dadurch wird der Bus auf einem Definierten Pegel gehalten
und hängt nicht frei in der Luft wenn beide im Empfangsmodus sind.
Andere Sache: Dein Master schaltet den Empfänger aus wenn er sendet?
Nicht das er sich selbst hört und dadurch die Software aus dem Tritt
kommt.
Hab gerade den max1487 erfolgreich am laufen. Daher kurz folgendes
beachten:
- Wenn du den max485 auf transmit setzt, dann schicke gleich mal zwei
0x00 Bytes vorweg, damit die nachfolgenden Start/Stop-Bits korrekt
erkannt werden können. Das produziert schlimmstenfalls einen oder zwei
Frame-Error beim Empfänger, aber dafür kommt der Rest dann auch an.
z.B. bei DMX wird auch erstmal für eine bestimmte Zeit (88µS?) die
Leitung auf einen festen Pegel gesetzt, zum einen für die Startkennung,
zum anderen eben um die StartBits sauber erkennen zu können.
- Wenn du Daten in UDR raufschiebst ist die Verwendung von UDRIE
optimal, damit die nächsten Daten bereitgestellt werden noch bevor das
vorangegangene Byte abgesetzt wurde. Aber eben nicht um nach dem letzten
Byte den transciever wieder umzuschalten...
- ,denn du musst auch TXCIE nutzen um beim letzten zu sendenden Byte den
transciever auf "recieve" umzuschalten, NACHDEM das letzte Byte komplett
inkl. Stop-Bit abgesetzt wurde.
- Verdrahtung mit ordentlichem Massebezug und Terminierung (2x120Ohm)
vorrausgesetzt...
Hinweis zu TXCIE und UDRIE. TXCIE ist flankengesteuert und kommt nur
einmal nachdem ein Byte erfolgreich gesendet wurde, aber UDRIE blockiert
so lange, bis man entweder ein neues Byte in UDR schiebt oder eben UDRIE
deaktiviert.
Meine Lösung ist momentan nicht dolle und für 9Bit, aber tut. Ggf. kann
ich sie dir schicken.
Hi
>Hinweis zu TXCIE und UDRIE. TXCIE ist flankengesteuert und kommt nur>einmal nachdem ein Byte erfolgreich gesendet wurde, aber UDRIE blockiert>so lange, bis man entweder ein neues Byte in UDR schiebt oder eben UDRIE>deaktiviert.
xxxIE heißt, Interrupt Enable. Was soll da flankengesteuert sein?
MfG Spess
Natürlich sind die ISRs dahinter gemeint, braucht aber nicht viel um das
zu erkennen...
- Die ISR (USART_TXC_vect), welche mit TXCIE eingeschaltet wird, (usw.
s.o.)
- Die ISR (USART_UDRE_vect), welche mit UDRIE eingeschaltet wird, (usw.
s.o.)
1.ich hab mal in einer endlosschleife 2 strings mit jeweils 1secunde
pause dazwischen gesenden
das kommt auch grössten teils an.
2.habe auch mal die uart lib von P.Fleury benutzt wo auch für das senden
der Interrupt benuzt wird,das gleiche Ergebniss.
3.wie muss die Terminierung bei 5V und bei 3.3V sein
Vielleicht kann mir denn jemand von ihnen einen Link zeigen
oder sagen wie mann das senden korrekt macht.
Mfg
Nehmen wir mal den mega8:
TXC_vect mit steigender Flanke auf das Bit TXC in UCSRA. Dann wird die
ISR einmal betreten und fertig. Danach erst wieder, wenn 0 und dann 1
kam.
UDRE_vect auf Pegel von UDRE in UCSRA. Wenn die ISR kommt und verlassen
wird, geht es direkt dort wieder rein, wenn UDRE nicht verschwindet oder
der Interrupt deaktiviert wird.
Jetzt aber genug der SpAesse, das war schließlich kein Einsteiger-Threat
und da setz ich ein bissl Mitdenken mal vorraus und nicht dass ich
wieder beim µC-Alphabet anfangen muss.
>3.wie muss die Terminierung bei 5V und bei 3.3V sein
Die 620R passen für 5V.
Du Brauchst das auch nur an einer stelle, soll ja nur
verhindern dass der bus einen undefinierten Pegel hat.
Ob du da jetz 620R ider 1K nimmst ist bei kurzen
Strecken egal.
Wenn du was längeres vorhast guck dir mal den LT1785 an.
Welche Baudrate fährst du eigentlich?
Die schon mal reduziert?
Zum lesen:
RS-485
Und zum Rechnen:
http://www.ti.com/lit/an/slla036d/slla036d.pdf
Bild vom Aufbau?
(Speicher-) Oszie Vorhanden?
Tim schrieb:>> Die 620R passen für 5V.
Die muss ich dann noch einbauen bis jetz hab ich nur zwischen A 120R B
drin
> Welche Baudrate fährst du eigentlich?
76800
> Die schon mal reduziert?
Ja von 9600 bis 250000
> (Speicher-) Oszie Vorhanden?
Nicht Vorhanden
So die Terminierung hab ich jezt so wies Vorgeschlagen wurde.
Verwende die Uart-Lib von P.Fleury , der Empfang klapt wunderbar aber
wenn ich mein "TEST OK" sende kommt ohne die Delays nie komplett an mit
den Delays klapt dies.
Es wird doch in setReceiveMode while ( !( UCSRA & (1<<TXC)) );
abgefragt ob senden möglich ist.
komisch?
1
voidsetTransmitMode(void)
2
{
3
PORT_UART_OUT|=(1<<PIN_UART_OUT);
4
}
5
6
voidsetReceiveMode(void)
7
{
8
while(!(UCSRA&(1<<TXC)));// Wait for empty transmit buffer
@ Sven (Gast)
>Es wird doch in setReceiveMode while ( !( UCSRA & (1<<TXC)) );>abgefragt ob senden möglich ist.
Nö, ob das letzte Zeichen im Buffer gesendet wurde.
>void setReceiveMode( void )>{> while ( !( UCSRA & (1<<TXC)) ); // Wait for empty transmit buffer> PORT_UART_OUT &= ~( 1 << PIN_UART_OUT );
Hier muss TXC gelöscht werden, damit es beim nächsten Mal nich vorzeitig
als gesetzt erkannt wird.
UCSRA = (1<<TXC); // clear TXC
Funktioniert es auch noch, wenn du das letzte Delay raus nimmst?
Ich nehme mal an dass das erste Delay notwendig ist um das StartBit
ordentlich zu erkennen. So weit so gut...
Aber das letzte Delay in deinem Code ist wohl notwendig, weil deine
bisherige Version von setReceiveMode nicht erkennt, wann das LETZTE Byte
aus dem Puffer aus ist.
Die müsstest du so abändern, dass du auch auf einen leeren Puffer (der
lib-eigene Ringpuffer, nicht der HW-Buffer) der UART-lib prüfst. Sonst
bricht er nach dem erfolgreichen senden irgendeines Bytes ab. Evtl.
klappt es sogar manchmal, denn in der PFleury lib werden die Daten auf
UDRE_vect schon nachgeschoben.