Hallo,
ich habe ein Probelm: ich hab mir ein kleines Progrämmchen auf für den
atmega8 geschrieben, er soll einfach die Zeichenkette 123x auf dem Uart
ausgeben.
Manchmal kommt korrekt:
>>>>>1>>>>>2>>>>>3>>>>>x
dann aber wieder (z.B.: wenn ich das ausleseprogramm neu starte,
Neustart des Atmega hilft dann auch nichts?
>>>>>x>>>>>à>>>>>?>>>>>à>>>>>x
....
1
//---------------------------------
2
voidsend_char(unsignedchardata)
3
//---------------------------------
4
{
5
while(!(UCSRA&(1<<UDRE)));
6
UDR=data;
7
}
8
9
//---------------------------------
10
voidsend_string(char*data)
11
//---------------------------------
12
{
13
while(*data){
14
send_char(*data);
15
data++;
16
}
17
}
18
19
20
//-----------------
21
ISR(USART_RXC_vect)//Die Interrupt-Routine
22
//-----------------
23
{
24
unsignedcharnextChar;
25
26
// Daten aus dem Puffer lesen
27
nextChar=UDR;
28
29
30
uint16_tadcval1;
31
adcval1=ADC_Read(0);
32
chartext1[32];
33
sprintf(text1,"%u",adcval1);
34
35
UDR=ADC_Read(0);
36
37
}
38
39
//************
40
intmain(void)
41
//************
42
{
43
44
charbuffer[3]={0};
45
uint16_tadcval;
46
uint16_tkanal;
47
kanal=0;
48
init_uart(UBRR_VAL);
49
init_adc();
50
sei();
51
uint8_tzahl=123;
52
53
//Hauptschleife
54
while(1){
55
adcval=ADC_Read(kanal);
56
57
58
59
itoa(zahl,buffer,10);
60
while(!(UCSRA&(1<<UDRE)));
61
62
send_string(buffer);
63
send_string("x");
64
65
66
67
}
68
return1;
69
}
Auslesezeile in Java:^
1
StringBuffer readBuffer = new StringBuffer();
2
int c;
3
// while ((c = inputStream.read()) != 88) { // lies bis X (88)
4
while ((c = inputStream.read()) != 88) { // lies bis X (88)
5
if (c != 13) {
6
System.out.println(">>>>>" + (char)c );
7
readBuffer.append((char) c);
8
}
9
}
kann mir jemand helfen - ok, ich hab noch den internen oszillator und
empfange mit 4800Baud, aber daran liegts doch nicht oder?
Gruß
Pfeiffy
Hi
>ok, ich hab noch den internen oszillator und>empfange mit 4800Baud, aber daran liegts doch nicht oder?
Wahrscheinlich ja. Vergrößere oder verkleinere doch mal den Wert für
UBRR.
MfG Spess
Das kann passieren.
Mögliche Ursachen:
Baudrate stimmt nicht ganz, Anzahl Start- und Stopbits und oder
Paritybits passen nicht. Stimmt die Einstellung der Timer für die
gewünxhte Bautrate ?
Wahrscheinlich liegt dein RC Oszilator zu sehr daneben.
Für seriele Schnittsellen sollte die Bautrate auf besser als 2% stimmen
sonst kommt es zu Fehlern. Der interne Oszillator ist meist nicht so
genau, läßt sich aber abgleichen (siehe Datenblatt, OSCAL).
Ich hatte das mal probiert und der interne Oszillator lag ca. 5%
daneben.
Nach Abgleich ging es dann ganz gut.
Für sorgenfreie Funktion mit allen Betriebsspannungen und Temperaturen
hilft nur ein Quarz, der interne Oszillator ist dafür zu schlecht.
Frohes Fest
Hans
Man sollte bedenken, dass der Abgleich des RC Oszillators von der
Temperatur, sowie von der Versorgungsspannung abhaengt. Eine sinnvolle
Loesung beruht auf einem Keramikschwinger, oder einem Quarz.
Da ein Quarz nur um die 20 cents kostet, lohnt sich eine Sparuebung hier
nicht.
Es mag nicht relevant sein, aber
Dirk P. schrieb:> char buffer[3] = { 0 };> uint8_t zahl = 123;> itoa(zahl, buffer, 10);
Wenn itoa die drei Ziffern + \0 in den Buffer schreibt, dann wird's da
drin eng. Er schreibt also munter weiter, und die \0 landet in adcval.
Die \0 wird dann von ADC_Read(kanal) überschrieben.
Die Größe des Puffers muss gewisse Kriterien erfüllen, siehe stdlib.h
Hallo,
ich habe nun einen 4MHZ ceramic quarz als externen oszilator drangehängt
und auch die Fuses richtig eingestellt. Aber es ist immer so, wenn ich
das (Abfrageprogramm) Programm starte kommen die richtigen werte, wenn
ich es aus und wieder einschalte kommen andere Zeichen - kann es sein,
dass das normal ist ,wenn ich den AVR aus und wieder einschalte kommen
wieder die richtigen Zeichen.
Gruß
Pfeiffy
Dirk P. schrieb:> und ich schreibe nur 4 chars (ohne Buffer)
Sollen wir nun raten?
Hast Du das Programm verändert? Offensichtlich ja, dann stelle es bitte
ein.
Dirk P. schrieb:> das (Abfrageprogramm) Programm starte kommen die richtigen werte, wenn> ich es aus und wieder einschalte kommen andere Zeichen - kann es sein,> dass das normal ist ,wenn ich den AVR aus und wieder einschalte kommen> wieder die richtigen Zeichen.
Sendest du in einem durch?
Dann kann das schon sein.
Eine UART muss sich erst mal mit der Gegenstelle synchronisieren, ehe
sie synchron laufen. Das geht aber nur, wenn der Sender ab und zu mal
einen kleine Pause einlegt, damit beide (Sender und Empfänger) dieselbe
Flanke einem Zeichenanfang zuordnen. Durch das Ein/Ausschalten des AVR
verschaffst du dem PC diese kleine Pause, während wenn du das
Abfrageprogramm startest es zufällig an irgendeiner Stelle die nächste
eintreffende Flanke als Zeichenanfang nimmt, was gar nicht stimmen muss.
Mach mal in deine Hauptschleife einen kleinen delay rein. Das könnte das
Problem beheben.
Karl Heinz Buchegger schrieb:> Eine UART muss sich erst mal mit der Gegenstelle synchronisieren, ehe> sie synchron laufen.
Das ist doch ziemlicher Unsinn: das Ding heisst nicht umsonst
Universal Asynchronous (!) Receiver Transmitter.
Durch Störungen kann bei anhaltendem Datenstrom die Sache zwar aus dem
Takt kommen, aber das ist hier wohl nicht das Problem: nur 4 Zeichen.
Wie etliche Vorposter auch tippe ich auf ein ungenaues Setup, entweder
wegen Oszillatorablage oder ungenauen Vorteiler. Da sind UARTs
empfindlich.
Das es mal geht und mal nicht passt ins Bild. Mitunter ist das sogar
zeichenabhängig.
Weiter Fehlermöglichkeit: die UART wird während des Betriebs durch
Registerzugriffe gestört.
Holler schrieb:> Karl Heinz Buchegger schrieb:>>> Eine UART muss sich erst mal mit der Gegenstelle synchronisieren, ehe>> sie synchron laufen.>> Das ist doch ziemlicher Unsinn:
Das ist kein Unsinn.
> das Ding heisst nicht umsonst> Universal Asynchronous (!) Receiver Transmitter.
In wie fern ist das jetzt ein widerspruch? Klar, die Übertragung ist
Asynchron, deshalb muss ja eben erst synchronisiert werden, damit es
funktioniert.
Das Synchronisieren geschieht dann über eine entsprechende Taktflanke
und einer State-Machine in dem UART Empfänger und der Baudrate, die man
vorgeben muss.
Holler schrieb:> Karl Heinz Buchegger schrieb:>>> Eine UART muss sich erst mal mit der Gegenstelle synchronisieren, ehe>> sie synchron laufen.>> Das ist doch ziemlicher Unsinn: das Ding heisst nicht umsonst> Universal Asynchronous (!) Receiver Transmitter.
Und, schon mal angesehen wie das funktioniert?
Und warum es da Probleme geben kann, wenn man sich in eine gerade
laufende Übertragung als Empfänger aufschaltet?
Nur weil das Ding Asynchron heißt, bedeutet das noch lanbge nicht, dass
Sender und Empfänger während der Dauer eines Zeichens nicht
synchronisiert werden müssen. Der Empfänger sieht haufenweise Flanken an
seinem Eingang. Welche davon ist denn der Beginn des ersten gültigen
Startbits?
> Durch Störungen kann bei anhaltendem Datenstrom die Sache zwar aus> dem Takt kommen, aber das ist hier wohl nicht das Problem: nur 4 Zeichen.
Programmtext besser lesen: die in einer Schleife laufend wiederholt
werden.
Fehlerbeshreibung besser lesen: Zitat: Wenn ich das Empfangsprogramm
abstelle und neu starte, .... Starte ich dann den AVR neu, dann klappt
wieder alles ....
Eine UART arbeitet in der Regel nicht als Statemachine die sich die
erstbeste Flanke schnappt und losrennt. Bekannte UARTS (16450, 16550D)
tasten das Signal ab. Wenn das Timing nicht passt (Stopp Bit nicht
erkannt), setzen die UARTs ein Framing Error und versuchen das nächste
Startbit zu finden, ebenfalls mit Überabtastung. Manche
Terminalprogramme können Framingfehler anzeigen. Oder bei
Selbstgeschiebenem die Register aauslesen.
Details z.B. http://www.ti.com/lit/ds/symlink/pc16550d.pdf
Auch wenn man 123 x 4 Zeichen ausgibt: das ist fast nichts (von wegen
laufend wiederholt ... eben besser lesen).
Bitte sicherstellen, dass der Teiler passt: 4 MHz / 9600 ergibt einen
krummen Teiler. Eine UART kann bei mehr als 1-3 % Ablage bereits in
Schwierigkeiten kommen.
Holler schrieb:> Bekannte UARTS (16450, 16550D)> tasten das Signal ab. Wenn das Timing nicht passt (Stopp Bit nicht> erkannt), setzen die UARTs ein Framing Error und versuchen das nächste> Startbit zu finden, ebenfalls mit Überabtastung.
Was sie aber nciht finden werden, weil sie zum falschen Zeitpunkt
beginnen, danach zu suchen.
> Auch wenn man 123 x 4 Zeichen ausgibt: das ist fast nichts (von wegen> laufend wiederholt ... eben besser lesen).
Und die while Schleife drummherum ignorierst du einfach, oder wie? Und
dass der UART am AVR 2 Zeichen buffern kann, d.h. der ADC und itoa die
Zeit bekommen ihr Ding zu machen, ehe auf der UART lange genug Ruhe
herrscht, dass PC_seitig der UART die nächste Flanke garantiert als
Startbit auffasst, auffassen muss, weil eben lange genug die Leitung
nichts getan hat.
Gerade bei 16Mhz hat der AVR viele Zyklen frei, ehe die UART komplett
leer ist.
Mach doch ein Experiment.
Sende in einer Schleife laufend ein bestimmtes Zeichen.
Während dessen ziehst du das Kabel ab und steckst es wieder an. Der
Empfänger wird dir ganz was anderes anzeigen. Und schlimmer noch: er
wird nie wieder sich korrekt in den Datenstrom einklinken.
Dann machst du einen kleinen Delay in die Schleife zusätzlich mit rein.
10ms.
Und probierst dasselbe. Das erste Zeichen nach dem Wiedereinstecken wird
falsch sein. Aber die restlichen stimmen wieder. Warum? Weil die Pause
dem Empfänger ermöglicht hat, sich auf die richtige Flanke als Startbit
zu synchronisieren.
Alles schon vor Jahren durchprobiert und durchdacht, warum das so ist.
> Eine UART arbeitet in der Regel nicht als Statemachine> die sich die erstbeste Flanke schnappt und losrennt.
Natürlich tut sie das! Sie hat ja nichts anderes als eine Leitung auf
der der Pegel ständig wechselt. Die UART weiß nicht per se, welche
Flanke jetzt ein Startbit ist und welche nicht.
Und klar: man kriegt einen Framing Error, wenn die Leitung eigentlich
auf Ruhepegel für das Stoppbit sein sollte, es aber nicht ist. Man kann
aber auch die Daten so hindrehen, dass diese Bedingung erfüllt ist, es
also keinen Framing Error gibt, und die Übertragung trotzdem falsch ist.
Karl Heinz Buchegger schrieb:> Und die while Schleife drummherum ignorierst du einfach, oder wie?
Stimmt, da habe ich Mist geschrieben. Stellt aber den restlichen Text
nicht in Frage.
Was definitiv nicht geht, ist auf eine laufende Sendung des AVRs das
Terminalprogramm bzw die Java-Abfrageschleife zu starten. Das geht
schief.
Um den Fehler einzugrenzen, würde ich z.B. ein Freeware Terminalprogramm
starten (z.B. Terraterm unter Windows).
- Standardeinstellung 9600N81 (9600 Bit/s, keine Parität, 8 Daten, ein
Stoppbit.)
- AVR starten
- Alles sauber? Mehrfach den AVR stoppen und starten.
- Wenn wieder Schrott erscheint, ggf den AVR mit 2 Stoppbits betreiben.
Damit kann man unsauberes Timing kaschieren.
Oder wie oben beschrieben ein kleines Delay einbauen. Das reduziert die
Datenrate und ist eine Krücke.
Eine grundlegende andere Sache fällt mir in dem Programm aber auch noch
auf. Sowohl in der Hauptschleife als auch im RXC Interrupt wird
ADC_Read() aufgerufen.
Um Konflikte zu vermeiden, würde ich mich da auf eine Methode
beschränken, also entweder im Interrupt oder in der Hauptschleife.
Wenns nämlich in der Hauptschleife ein RXC Interrupt gibt, während
ADC_Read() gerade läuft, wirds lustig.
Holler schrieb:> Oder wie oben beschrieben ein kleines Delay einbauen. Das reduziert die> Datenrate und ist eine Krücke.
Da geh ich absolut mit dir konform. Eine Krücke ist es. Zur Not würde
ich es so machen, dass ich diesen delay nur ab und zu (zb 10.
Schleifendurchlauf) mache. Um eine Möglichkeit zur empfängerseitigen
Fehlererkennung kommt man sowieso nicht herum. Ist zwar nicht ideal,
aber sein hinten nach gesendetes 'x' kann das in Ansätzen schon leisten.
Der PC verwirft dann eben alle Übertragungen, bei denen das 'x' fehlt
und die Zeichen dazwischen keine Zahl ergeben.
Karl Heinz Buchegger schrieb:> Natürlich tut sie das! Sie hat ja nichts anderes als eine Leitung auf> der der Pegel ständig wechselt. Die UART weiß nicht per se, welche> Flanke jetzt ein Startbit ist und welche nicht.>
Es trägt wenig zur Problemlösung bei, trotzdem: Eine UART tastet den
Eingangspegel ständig ab, meist mit 16facher Baudrate. Wenn aus dem
Idle-Zustand eine bestimme Anzahl von Abtastwerten low sind, wird das
als Startbit gewertet. Mittig der low-erkannten Startsamples wird allen
16. folgenden Samples die Folgebits abgetastet. Beim Stoppbit findet
wieder eine Gewichtung statt.
So funktioniert der Empfang bei einer UART. Wenn du mir nicht glaubst
lese ausführliche Datenblätter. Oder schaue dich in Asic/VHDL Foren um.
Holler schrieb:> Karl Heinz Buchegger schrieb:>> Natürlich tut sie das! Sie hat ja nichts anderes als eine Leitung auf>> der der Pegel ständig wechselt. Die UART weiß nicht per se, welche>> Flanke jetzt ein Startbit ist und welche nicht.>>> Es trägt wenig zur Problemlösung bei, trotzdem: Eine UART tastet den> Eingangspegel ständig ab, meist mit 16facher Baudrate. Wenn aus dem> Idle-Zustand eine bestimme Anzahl von Abtastwerten low sind, wird das> als Startbit gewertet.
Du redest von anderen Dingen.
Du redest davon, wann ein Bit als gültig erkannt wird und wann nicht.
Das stelle ich überhaupt nicht in Frage. Es geht mir um das was danach
kommt! Was bedeutet dieses Bit? Ist es ein Startbit oder ist es eines
der 8 Datenbits aus einem Byte dessen Beginn zu einem Zeitpunkt
erfolgte, als die UART noch gar nicht auf der Leitung gehorcht hat.
Und bei einer UART ist es nun mal so, dass man einem Bit nicht ansehen
kann, welches Bit (Startbit, Datenbit oder Stoppbit) es ist. D.h. man
muss relativ willkürlich annehmen, dass das der erste eintrudelnde
Low-Pegel ein Startbit ist. Diese Annahme muss aber nicht stimmen! Erst
dann, wenn die Leitung zuvor mindestens über die Zeitspanne eines
kompletten "UART-Bytes" (Start, Daten und Stoppbits zusammengenommen)
auf Ruhepegel war, kann ich mit Sicherheit davon ausgehen, dass das
nächste Low-Bit ein Startbit sein muss: Sender und Empfänger haben sich
für dieses Zeichen synchronisiert. Und wenn diese Synchronisierung erst
einmal erfolgt ist, dann benötigt man auch die Pause nicht mehr, damit
sie sich für das nächste Zeichen erneut synchronisieren können. Sie
werden wieder übereinstimmend dasselbe Bit als das Startbit anerkennen.
Das hat nichts damit zu tun, wie ein Empfänger jetzt seine Bits durch
Oversampling von der Leitung holt(*), sondern ist sozusagen logisch
gesehen schon eine Schicht höher angesiedelt.
(*) Und das ist auch das Asynchron in UART: Der Sender kann zu jedem
Zeitpunkt mit einem Zeichen anfangen. Also asynchron zu jeglichem
irgendwie geartetem sonstigen Takt. Das bedeutet aber nicht, dass die
beiden sich überhaupt nie Synchronisieren. Während eines Zeichens sind
die beiden synchron: Der Empfänger interpretiert den Leitungsstatus
zeitlich synchron mit dem, was der Sender mit der Leitung macht. Während
einer Zeichenübertragung sind die beiden synchron. Nach einem Zeichen
ist diese Synchronisierung wieder aufgehoben und wird mit dem nächsten
Startbit wieder hergestellt.
da core, Aufstart in eine laufende, lückenlose Sendung ist kaum möglich.
Geht nur durch trail- und error mit framing-error Beobachtung.
Üblich war in den 80-90igern zur Modem-Zeit die Hardware-Flußkontrolle
RTS/CTS bzw S2/M2. Damit gehts immer.
Hallo,
danke für die Antworten und Erklärungen. Ich dachte mir schon, dass es
mit dem starten des Abfrageprogramms während des Sendens was zu tun hat,
sonst hatte ich immer das senden durch einen interrupt angestoßen, da
gab es keine Probleme, nun möchte ich durch den Interrupt nur die Kanäle
auswählen aber immerfort senden.
Ich habe nun einen delay von 10ms eingebaut, dann kann ich das
Abfrageprogramm immer beenden und wieder starten, ohne Probleme.
Gruß
Pfeiffy
Hallo,
Ich beschäftige mich auch seit kurzem mit dem UART PC16550D, hab da auch
ein Problem mit den Interrupts, wäre super wenn du mal in meinem
BBeitrag reinschauen könnstest. Hab weiter oben gelesen:
Holler schrieb:> Eine UART arbeitet in der Regel nicht als Statemachine die sich die> erstbeste Flanke schnappt und losrennt. Bekannte UARTS (16450, 16550D)> tasten das Signal ab. Wenn das Timing nicht passt (Stopp Bit nicht> erkannt), setzen die UARTs ein Framing Error und versuchen das nächste> Startbit zu finden, ebenfalls mit Überabtastung.Karl Heinz Buchegger schrieb:>> Bekannte UARTS (16450, 16550D)>> tasten das Signal ab. Wenn das Timing nicht passt (Stopp Bit nicht>> erkannt), setzen die UARTs ein Framing Error und versuchen das nächste>> Startbit zu finden, ebenfalls mit Überabtastung.>> Was sie aber nciht finden werden, weil sie zum falschen Zeitpunkt> beginnen, danach zu suchen.
Kannst dir ja mein Fehlerbild anschauen, ich denke dass es irgendwie
dasselbe Problem sein kann.
Danke.
Beitrag "UART PC16550D Interrupt Fehler"