Hallo meine Lieben,
Ich bin total verzweifelt mit meinem Problem hier.
ich möchte eine Kommunikation zwischen einem Master und Empfänger über
UART auf RS485-Basis aufbauen. Der Master ist ein AVRATMEGA32 und der
Empfänger ein PSOC-µC.
Der Baudrate ist auf 9600 eingestellt beidseitig und geprüft. alles
I.O.
Der Master sendet ein Paket mit 8 Bit einem Start- und Stop-bit.
Die kommen beim Eingang Rx_Psoc-µC ganz gut an. In einem Programm
möchte ich die Daten zurücksenden an dem Master.
Nun funktioniert der echo nicht ganz gut. Ich weiß nicht, ob der
Psoc_Rx ordnungsgemäß die Daten aufnimmt. Denn sporadisch sendet er den
richtigen Wert und manchmal was falsches.
Kann mir jemand checken was ich in meinem Code falsch mache?
Uart-Einstellung in Psoc:
Parameters
Parameters Value
Clock Row_0_Output_1
ClockSync Sync to SysClk
CommandTerminator 13
Enable_BackSpace Disable
IgnoreCharsBelow 32
IntDispatchMode ActiveStatus
InterruptAPI Enable
InvertRX Input Normal
Param_Delimiter 32
RX Clock Out None
RX Input Row_0_Input_1
RX Output None
RxBufferSize 16
RxCmdBuffer Enable
TX Clock Out None
TX Interrupt Mode TXComplete
TX Output Row_0_Output_0
Code:
While(1)
{
DigBuf_RS_Stop(); Driver - Empfang
while(!(UART_1_bReadRxStatus()& UART_1_RX_COMPLETE));
x=UART_1_bReadRxData();
DigBuf_RS_Start(); Driver- Senden
while(!(UART_1_bReadTxStatus()&UART_1_TX_BUFFER_EMPTY));
UART_1_SendData(x);
while(!(bUART_1_ReadTxStatus()&UART_1_TX_COMPLETE ));
DigBuf_RS_Stop();
}
wäre sehr dankbar für jede Hilfe.
lg
Florian dielman
ja das problem ist das ich schon eine fertige platine uaf dem ich
keine Quarz mehr einbauen kann. Zum anderen meine Ressource(Pins)
sind schon alle besetzt.
Nun kann ich nur Machen mit was ich in den Händen habe.
Ist der Code so korrekt ?
Danke
Man kann den internen RC-Oszillator kalibrieren, das ist dann
einigermassen genau genug für UART, wenn die Temperatur nicht zuviel
schwankt (sagen wir +/-20K). Das Register OSCAL ist dein Freund.
MFG
Falk
Man kann anhand eines empfangenen Bytes den Reloadwert für das
Zählerregister errechnen. Das wäre dann so eine Art
Auto-Baud-Funktion...
Aber einfacher ist die Methode von Falk ;-)
@ Lothar Miller (lkmiller)
>Man kann anhand eines empfangenen Bytes den Reloadwert für das>Zählerregister errechnen.
Reloadwert und UART? Ahhhh, der alte 8051 Schrott.
Hey, wir leben im 21. Jahrhundert. AVR rulez!
Falk Brunner schrieb:
> Hey, wir leben im 21. Jahrhundert. AVR rulez!
Und da geht das nicht mehr? Schade, schade :-/
Aber wenn ich mir das Datenblatt ansehe
1
The USART Baud Rate Register (UBRR) and the down-counter connected to it
2
function as a programmable prescaler or baud rate generator. The
3
down-counter, running at system clock (fosc), is loaded with the UBRR value
4
each time the counter has counted down to zero or when the UBRRL Register is
5
written.
dann hört sich das für mich nach einem Reloadwert an ;-)
Andere Prozessorarchitekturen wie ST10 haben das sogar im Bootloader
drin...
@ Lothar Miller (lkmiller)
>dann hört sich das für mich nach einem Reloadwert an ;-)
Lässt sich ja prinzipiell kaum vermeiden. Aber das Reloaden macht die
Hardware allein, für so einen Schnulli die CPU zu belästigen ist ja fast
strafbar. . .
MFG
Falk
Danke schön für Anregungen
ich sehe dass es vielleicht mein Problem sein kann. Denn die Factory
Calibrated Frequency ist für ein Betrieb mit 3V und hat eine
Abweichung von +-10%.
Ich habe auch gelesen, dass die vom User kalibrierte Frequenz zwischen
7.3Mh und 8.1MH abweicht.(ATMEGA328P Seite 317)
Ist es dann damit möglichst eine genauere 8Mhz zu erzielen?
zum anderem muss man nur den OSCALL am Anfang vor dem main() schreiben
und ist dann alles erledigt oder?.
Entschuldigung für die Fragen ich habe noch nicht ein Internen RC
kalibriert.
Danke
@ Florian dielman (Gast)
>Ich habe auch gelesen, dass die vom User kalibrierte Frequenz zwischen>7.3Mh und 8.1MH abweicht.(ATMEGA328P Seite 317)
Ist auch so.
>Ist es dann damit möglichst eine genauere 8Mhz zu erzielen?
Definiere genau. Man bekommt das ganze in etwa auf 0,5% kalibriert.
>zum anderem muss man nur den OSCALL am Anfang vor dem main() schreiben>und ist dann alles erledigt oder?.
Ja.
>Entschuldigung für die Fragen ich habe noch nicht ein Internen RC>kalibriert.
Ach du Ärmster.
> Bitte Um hilfe ich bien schon verzweifelt.
Weil du innerhalb von 2 Stunden keine Antwort bekommt? Bleib mal locker.
In der Zeit hätte man es dreimal selber ausprobieren können.
MFG
Falk
@Florian:
Bei Atmel gibt es mehrere AppNotes, die sich mit der Kalibrierung des
internen Oszillators befassen (AVR351, AVR053, AVR054, AVR140).
Falls Du beim Übertragungsprotokoll nicht festgelegt bist, dürfte AVR054
für Dich am interessantesten sein. Die beschreibt, wie sich ein Slave zu
Beginn eines jeden Übertragungsblocks anhand eines vom Master gesendeten
Bitmusters auf dessen Takt kalibrieren kann.
Bei serieller Übertragung musst Du deine Baudrate auf 1,5 bis 2,5% genau
einhalten (je nach Begleitumständen). Bei zwei Geräten gilt das für die
Summe der Abweichungen beider. Kannst Du das nicht einhalten, erreichst
Du keine zuverlässige Verbindung -- keine Arme -> keine Kekse, in der
Technik ist das so einfach.
Es ist nun Deine Aufgabe, das sicherzustellen; Verzweiflungsäußerungen
bringen Dich dem Ziel nicht näher. Da Du Deine Hardware am besten
kennst, ist es nun an Dir, die Möglichkeiten abzuklopfen.
Hast Du irgendwo eine hinreichend genaue Frequenz, auf die Du
ei^H^Hkalibrieren kannst?
> Es ist nun Deine Aufgabe, das sicherzustellen; Verzweiflungsäußerungen> bringen Dich dem Ziel nicht näher. Da Du Deine Hardware am besten> kennst, ist es nun an Dir, die Möglichkeiten abzuklopfen.
Wobei der erste Schritt immer darin besteht, eine Fehleranalyse zu
machen. Wenn du 2 Geräte hast, von denen du nicht weißt, welches Schuld
ist, dann ist eine gute Strategie zb. eines der Geräte durch ein anderes
zu ersetzen, welches garantiert richtiges Verhalten aufweist.
Garantie richtig gibt es selten, aber in diesem Fall kann man wohl davon
ausgehen, dass die UART eines PC keinen allzugroßen Fehler haben wird.
Also wird man wohl jedes der unbekannten Geräte mit einem PC verbinden
und nachsehen, ob sich dort bei einem der beiden (oder bei beiden)
Fehler in der UART-Kommunikation zeigen.
Findet sich da etwas, hat man schon viel gewonnen. Immerhin ist das
Problem dadurch schon um 50% leichter geworden.
Wie Hazeh schon so richtig sagte:
Verzweifeln bringt nichts. Systematisch überlegt vorgehen!
Überlegen "Was könnte es sein" und daraus sofort eine Strategie
ableiten, wie man diesen möglichen Fehler testen oder ausschliessen
kann.
Hi Leute,
ich habe die mögliche Quelle meines Problem gefunden. aber weiß noch
nicht wieso und warum es auftritt.
Die Übetragung läuft perfekt. Der master sendet, der Slave empfängt und
sendet zurück. Das Problem liegt bei der ATmel _µC und nicht beim
PSOC.
Die TX und RX leitung von dem ATMEGA32 sind direct auf dem Treiber
MAX487 angeschlossen.
Sobald ich die RX einschalte "UCSR0B |=(1<<RXEN0);" die gesamte
Übertragungsweg geht nicht mehr. schalte ich RX ab läuft alles wierder
wunderbar. D.h. ich kann nichts empfangen am Master.
Ich habe versucht ein Verbraucher (Widerstand, Diode) zwischen RX und
Eingang Treiber zu schalten , es klappt aber nicht.
es wäre als ob er würde dauern die leitung auf low oder high oder weiß
nicht genau ziehen und die Gesamte Übertragung komplet stören.
Weißt jemand woran es liegen kann ?
Danke
Die Verdrahtung ist genau so gleich wie auf dem gelinkten Forumbeitrag.
120 Ohm habe ich auch dran. Variert +-30 habe ich auch schon. Trotzdem.
Enable-Eingänge(DE, /RE) werden zusammen angesteuert. R0 an RX und DI
an TX .
Ich habe auch versucht den Pin als Eingang zu schalten, die Übertragung
ist immer gestört. Enferne ich den Master Tx leitung bekomme ich das
gleiche Bild als wäre RX ein .
Ich vermute es wenn RX ein ist zusätzlich zu TX . collidieren die beide
intern, sodass die Wirkung von Tx nicht mehr zu sehen ist.
Andere Treiber holen. Klar habe ich schon gemacht . Bei dem auch das
gleiche Verhalten.
> Ich vermute...
Das ist m.E. nicht die richtige Vorgehensweise.
> Die Verdrahtung ist genau so gleich wie auf dem gelinkten Forumbeitrag.
Jaja. Welchem Teil des Beitrags?
Machs doch einfach so: zeichne genau deine Beschaltung ab und poste
den Plan hier. Aber bitte nicht irgendwo was herkopieren und sagen "fast
genauso ähnlich".
BTW:
> ich mache mich am Werk und lass euch berichten.
Hast du das Thema mit der Baudrate (interner Takt) inzwischen behoben?
>> Ich vermute...>Das ist m.E. nicht die richtige Vorgehensweise.
Solange ich etwas nicht aufklären kann, kann ich nur Vermutungen
äussern und keine feste Ursache , da ich selber nicht weiß.
hier habe ich meine plan gezeichnet.
> ich mache mich am Werk und lass euch berichten.>Hast du das Thema mit der Baudrate (interner Takt) inzwischen behoben?
ja ich habe es gelöst. Ich habe die interne Takt so getrimmt(mit
osscal-register )bis eine gesamte Übertragung von 1 Byte 833µs erreicht.
Dies kommt dann beim Empfänger gut an und der Echo klappt auch gut.
Nur der Master auf dem receive-Eingang macht mir nun probleme.
>also wenn es bei deinem Master RX ist solltes es beim Client schon am TX>angeschlossen sein. bei deinem Schaltplan ist das aber nicht so. ;)
Nein vielleicht ist eine Verwirrung.
Der MAX487 hat als Bedienpin von µC aus die DI für Tx und R0 für RX.
und geben auf dem Bus die invertierende Signal A und B.
Es ist auf dem Bild nicht auf die lineare Anordnung von Tx bzw. A
oder B aufzupassen. Dies zeigt nur den Prinzip
Nö, der "Plan" ist ja im Prinzip richtig.
Es fehlen halt "lediglich" die Enable-Leitungen. Von anderen Problemen,
die sich im Schaltplan oder auf der Platine befinden können nicht zu
reden.
Den Wert "1 Byte 833µs" kann man auch schlecht einschätzen - ist das für
2 Protokollbits plus 8 Datenbits gerechnet oder für ein Byte (8-Bit)?
Ist das ein gemessener Wert für den AVR Sender und ist der Wert
vergleichbar mit dem gemessenen Wert für den PSoC Sender?
Die AVR UART hat einen Fehlerdetektor, was meldet der beim Empfang?
Wieviel % der Zeichen sind fehlerhaft? Ändert sich die Fehlerrate mit
der Art oder der Geschwindigkeit der zeichen oder mit Pausen zwischen
den Zeichen oder mit der Menge der Zeichen pro Block? Wie sehen die
Bitmuster der Zeichen auf dem Bus und der empfangenen, fehlerhaften
Zeichen aus; Versatz? Fehlendes Anfangsbits?
Wie ist die Software beim Empfänger AVR geschrieben? Ist die Umschaltung
TX-Betrieb zu RX-Betrieb schnell genug?
Im Plan sind noch zwei weitere "Slaves" eingezeichnet. Sind die fiktiv
oder real da? Sehen die auch verstümmelte Daten oder sehen die korrekte
Daten?
BTW. AVR2006 Contest... Ich würde mir wahrscheinlich zum Debuggen eine
solche RS232-nach-RS485 Bridge aufbauen. Mit Quarz ;-)
>Den Wert "1 Byte 833µs" kann man auch schlecht einschätzen - ist das für>2 Protokollbits plus 8 Datenbits gerechnet oder für ein Byte (8-Bit)?>Ist das ein gemessener Wert für den AVR Sender und ist der Wert>vergleichbar mit dem gemessenen Wert für den PSoC Sender?
Der Wert steht für 8 Bit ohne start und Stop-Bit. und Mit kontrolbit
1ms.
Diese Wert sinid vergleichbar mit dem Psoc sender.
>Im Plan sind noch zwei weitere "Slaves" eingezeichnet. Sind die fiktiv>oder real da? Sehen die auch verstümmelte Daten oder sehen die korrekte>Daten?
sie sind nur fiktiv da. Nun ist nur ein in meinem Aufbau vorhanden
>Wie ist die Software beim Empfänger AVR geschrieben? Ist die Umschaltung>TX-Betrieb zu RX-Betrieb schnell genug?
Momentan es soll zuerst mal ankommen ohne gelesen zu werden. Erst
dann kann ich die entprechende While einbauen.
1
UCSR0B|=(1<<TXEN0)|(1<<RXEN0);;
2
while(1)
3
{
4
PORTB|=(1<<DDB0);//Max485 auf Senden
5
6
while(!(UCSR0A&(1<<UDRE0)));
7
UDR0=0x0F;
8
9
while(!(UCSR0A&(1<<TXC0)));//Warten bis Übertragung fertig
10
UCSR0A|=(1<<UDRE0);//Register leeren
11
12
PORTB&=~(1<<DDB0);//Max485 auf Empfang
13
14
15
_delay_ms(4);
16
}
>Wie sehen die>Bitmuster der Zeichen auf dem Bus und der empfangenen, fehlerhaften>Zeichen aus; Versatz? Fehlendes Anfangsbits?
wenn RX-enable (MAster )
Am EMpfang:fehlendes Bits, unperiodisches auftritt (nur einmal).
Am Sender : kontinuerliches unregelmäsiges Bitfolges unabhängig von
RS485 enable-Leitung.
ich suche immer wo der Hase liegt.
> wenn RX-enable (MAster )> Am EMpfang:fehlendes Bits, unperiodisches auftritt (nur einmal).
Das ist seltsam. Werden die Bits mit dem obigen Codefetzen detektiert?
da sollte man garnix sehen, denn in obigem Codefetzen ist keine
Empfangsanweisung enthalten. Hast du Messequipment zum Überwachen des
Bitstroms?
BTW. Warum hast du diese Zeile drin?
UCSR0A |= (1<<UDRE0); //Register leeren
> Am Sender : kontinuerliches unregelmäsiges Bitfolges unabhängig von> RS485 enable-Leitung.
Das ist seltsam. Der Bitstrom muss von den Enable-Leitung abhängig
sein. Die gesendeten Daten dürfen nur auf dem Bus (A/B Leitungspaar)
sein, wenn der Sender seinen MAX487 per DE enabled hat. Und der
Empfänger kann den Bitstrom nur empfangen, wenn er seinem MAX487 die
/RE-Leitung enabled hat.
Ich würde Nägel mit Köpfen machen:
0. 8-Spur Logikanalyzer beschaffen
1. Einfaches Senderprogramm für PSoC schreiben. Einfaches
Empfangsprogramm für AVR schreiben. Laufenlassen.
2. 8-Spur Logikanalyzer an die vier Digitalleitungen der beiden MAX487
hängen. Mitschnitt zeigen.
3. Einfaches Senderprogramm für AVR schreiben. Einfaches
Empfangsprogramm für PSoC schreiben. Laufenlassen.
4. Schritt 2 wiederholen.
@ Stefan B.
Danke für deine Hilfbereitschaft.
>BTW. Warum hast du diese Zeile drin?> UCSR0A |= (1<<UDRE0); //Register leeren
das problem ist, dass ich keine IMpuls am PORTB bekomme solange ich
diese Zeile nicht hinzugefügt habe. Und das signal kommt periodisch
alle 4 ms.
Kommentiere ich diese Zeile kommt das Signal nach reset einmal sauber(
ca. 1ms) und dann nur als Spitze von paar pikrosekunde.
>Das ist seltsam. Werden die Bits mit dem obigen Codefetzen detektiert?
ich denke der code ist sehr einfach gehalten nur für das Senden.
Wenn ich für den Empfang diese Zeilen hinzufügt bleibt aber das Programm
hängen
Florian dielman schrieb:
> das problem ist, dass ich keine IMpuls am PORTB bekomme solange ich> diese Zeile nicht hinzugefügt habe. Und das signal kommt periodisch> alle 4 ms.> Kommentiere ich diese Zeile kommt das Signal nach reset einmal sauber(> ca. 1ms) und dann nur als Spitze von paar pikrosekunde.
Welchen Impuls/Signal willst du an PORTB periodisch BEkommen?
TXD und RXD liegen beim Atmega32 an PORTD; die kannst du nicht meinen.
Die Enable-Leitung(en) zum MAX487 sind an einen Output-Pin (PORTB.0)
gekoppelt, d.h. du willst ein Signal ABgeben; den kannst du auch nicht
meinen.
Ist für PORTB.0 DDRB richtig auf Ausgang initialisiert? In deinem
Codefetzen sieht man das nicht.
> Wenn ich für den Empfang diese Zeilen hinzufügt bleibt aber das Programm> hängen
So lange keiner an deinem Bus was sendet, ja. Deshalb hatte ich ja auch
vorgeschlagen, dass du den PSoC nur mit der Sendeaufgabe betreust und
den AVR nur mit der Empfangsaufgabe.
Hast du noch einen MAX487 pkus einen MAX232 oder drei NPN-Transistoren
im Lager um die RS485-to-RS232 Bridge zu bauen?
>Welchen Impuls/Signal willst du an PORTB periodisch BEkommen?
das Umschaltsignal für den Treiber (DE,/RE).
>Ist für PORTB.0 DDRB richtig auf Ausgang initialisiert? In deinem>Codefetzen sieht man das nicht.
ja in dem Ini()
hier ist der code zum senden:
1
#ifndef F_CPU
2
#define F_CPU 8000000UL // Frequenz
3
#endif
4
5
#include<avr/io.h>
6
#include<util/delay.h>
7
#include<avr/interrupt.h>
8
#include<string.h>
9
#define BAUD 9600UL
10
11
12
#define TEILER (F_CPU/(16UL*BAUD))-1
13
14
15
voidRS485_Init(void)
16
{
17
unsignedintx;
18
19
DDRB|=(1<<DDB0);//ausgang Treiberumschaltung
20
21
22
// Baudrate Einstellung
23
UBRR0H=(unsignedchar)(TEILER>>8);
24
UBRR0L=(unsignedchar)TEILER;
25
26
//Sender und Empfänger ein
27
UCSR0B|=(1<<TXEN0)|(1<<RXEN0)|(1<<RXCIE0);
28
29
30
// Datenformats: 8 Datenbits, 1 Stoppbit
31
UCSR0C|=(1<<UCSZ01)|(1<<UCSZ00);
32
x=UDR0;// Empfänger leeren
33
34
}
35
36
37
intmain(void)
38
{// Kalibrierung der internen RC-Oszillator
39
OSCCAL=0x6C;
40
41
unsignedcharx,k;
42
k=0x0F;
43
44
45
46
RS485_Init();
47
48
49
while(1)
50
{
51
PORTB|=(1<<DDB0);//Max485 auf Senden
52
53
while(!(UCSR0A&(1<<UDRE0)));
54
UDR0=0x0F;
55
56
while(!(UCSR0A&(1<<TXC0)));//Warten bis Übertragung fertig
57
UCSR0A|=(1<<UDRE0);//Register leeren
58
59
PORTB&=~(1<<DDB0);//Max485 auf Empfang
60
61
62
_delay_ms(4);
63
}
64
}
in Projekt/ config wird Frenquency auf 8000000 eingestellt.
in STK500 auf "Fuses" SUT_CKSEL : Int. RC.OSc.8MHz
>Hast du noch einen MAX487 pkus einen MAX232 oder drei NPN-Transistoren>im Lager um die RS485-to-RS232 Bridge zu bauen?
Max487 ja . Max232 nein. aber eine STK500
>So lange keiner an deinem Bus was sendet, ja. Deshalb hatte ich ja auch>vorgeschlagen, dass du den PSoC nur mit der Sendeaufgabe betreust und>den AVR nur mit der Empfangsaufgabe.
mache ich nun auf diesem Weg.
Florian dielman schrieb:
>>Welchen Impuls/Signal willst du an PORTB periodisch BEkommen?> das Umschaltsignal für den Treiber (DE,/RE).
Wie vermutet ist das ein Mistverständnis. Du musst vom AVR Programm aus
sorgen, dass an PORTB.0 das DE bzw. /RE Signal ausgegeben wird. Du
bekommt dort kein Signal von außen. Im Programm ist das auch gemacht.
> UCSR0B |= (1<<TXEN0)|(1<<RXEN0)|(1<<RXCIE0);
^^^^^^^^^^^
Wo ist die dazugehörige UART Receiver ISR? Wenn die fehlt, resettet sich
der AVR beim ersten empfangenen Zeichen (also beim Echo des PSoC). Lass
das |(1<<RXCIE0) weg.
Rest nicht mehr angeschaut.
@ Stefan B.
es hat geklappt. ouf!
>Lass das |(1<<RXCIE0) weg.
was so eine kleines Bit(Schrift), jemand Studen kosten kann.
Aber nirgendwo habe ich deine Begründung/Erklärung gelesen. Kannst du
mir ein Link zuschicken wo sowas steht(wenn vorhanden).
vielen Dank an dir für deine Gedult.
werde nun den Code erweitern für ein Telegramm(mehrere Bit
nacheinander).
lg
Flo.
Schau dir den Artikel AVR-GCC-Tutorial/Der UART an und achte auf die
"händischen" Sende/Empfangsverfahren (Polling) kontra die
Interruptverfahren.
Die Bedeutung des Bits steht auch im Datenblatt. Es schaltet den
Interruptbetrieb der UART ein. Und der verlangt eine Routine zum
Behandeln des Interrupts, die sog. ISR (Interrupt Service Routine). Wenn
die fehlt und der Interrupt kommt, gibt es Chaos. ISR vergessen oder
falscher Name oder unabsichtlich anschalten oder nicht anschalten sind
Fehler, die 99% der Programmierer mal machen.
Nächstes Mal gleich Sourcecode beibringen und auch eine echte
Schaltplanskizze. Die Skizze muss nicht perfekt layoutet sein; sie darf
handgezeichnet und eingescannt oder fotografiert sein. Den Bug hätten
wir mit Sourcecode am ersten Abend gekillt ;-)