Forum: Mikrocontroller und Digitale Elektronik Wie stark beeinfluss der UART den Zähler?


von Weihnachtsmann (Gast)


Angehängte Dateien:

Lesenswert?

Hallo

Ich habe ein Programm gemacht das in jeder Sekunde 25 mal den
Zählerwert vom 16Bit zähler und noch andere Werte über den UART an den
PC schickt. Wenn ich eine höhere Baudrate einstelle macht er mehr als
25 Messungen pro sekunde.
Warum das?
Beeinflusst der UART den Timer?
Ist  der Timer überhaupt genau?


Gruss

Gestern kam der Nikolaus

von crazy horse (Gast)


Lesenswert?

wie so oft - der Fehler liegt beim Programmierer.
In deiner Timer0-ISR sendest du allerhand (rcall serout), das dauert
nunmal. Bei höherer Baudrate geht das Senden schneller, dementsprechend
ist die Timer0-ISR fertig, bevor der nächste Int kommt. Dauert das
Senden länger als bis zum nächsten Timer-Int, wird der nicht mehr zur
richtigen Zeit ausgeführt, sondern erst später. Diese Fehler summieren
sich, irgendwann gehen Ints komplett verloren.
Die alte Regel: ISR laufzeitmässig kurz halten.

von Weihnachtsmann (Gast)


Lesenswert?

Hallo crazy horse

Du scheinst ein Profi zu sein ich eher ein Einsteiger.
Ich habe deine Aussage verstanden nur weiss ich nicht wie ich das Lösen
soll.

Wie würdest du dass Konkret machen?
Das ist ISR?

von Zotteljedi (Gast)


Lesenswert?

ISR = Interrupt Service Routine

Normalerweise teilt man Interrupt-Handler die zeitintensive Arbeit
verrichten in Top Half und Bottom Half. Ersterer ist fix wie Sau und
erledigt den zeitkritischen Teil, letzterer werkelt dann irgendwann vor
sich hin, wenn Zeit ist.

Insbesondere sollte der Top Half nicht weiter gestört werden (wie für
ISRs üblich), während der Bottom Half entsprechend reentrant sein
sollte, sodaß während seiner Abarbeitung neue Interrupts bearbeitet
werden können.

Soviel zu meinem Wissen aus der Welt der PCs, ich nehme mal an das ist
auf uCs im Wesentlichen übertragbar.

von Weihnachtsmann (Gast)


Lesenswert?

Soviel ich weiss sind irgendwie die Prioritäten von den Interrupts bei
AVR schon gegen oder täusche ich mich da?

Gruss

Der Weihnachtsmann

von Thomas Burkhardt (Gast)


Lesenswert?

Hä?

Keine Ahnung, was das bedeuten soll, aber am AVR gibts jedenfalls keine
wirklichen Interruptprioritäten.

von Thomas K (Gast)


Lesenswert?

Auszug aus dem ATMega8 Datenblatt

"The complete list of Vectors is shown in ?Interrupts? on page 44. The
list also determines the priority levels of the different interrupts.
The lower the address the higher is the priority level. RESET has the
highest priority, and next is INT0 ? the External Interrupt Request 0"

von Eumel (Gast)


Lesenswert?

Hallo du Weihnachtsmann (keine Beleidigung),

irgendetwas passt nicht:

Du überträgst anscheinend 7 Bytes mit 9600 Bd. das sollte < 10 ms
daueren. Wenn der Timer wirklich nur alle 40 ms käme, könnten keine
Interrupts verloren gehen.

Ansonsten keine Warteschleifen auf das Ausgangsregister in deiner
Interruptroutine sonder den UART interrupt zum Senden des nächsten
Zeichens nutzen.

von Weihnachtsmann (Gast)


Lesenswert?

Hallo Eumel

Genau ich sende 7 Byte 25 mal in der Sekunde das wären also 175Byte pro
Sekunde ist eigentlich nicht viel.
Die Baudrate kann ich nur auf 19200 erhöhen höher macht er nicht mit.
Ein Nachteil ist sicher dass ich im Moment nur ein 6MHz Quartz habe
einen 16Mhz Quarz muss ich noch bestellen.


Du meinst ich sollte dies so ändern?

serout:                          ;Wert senden
  sbis UCSRA,UDRE
  out UDR, Sende
ret

Gruss

Weihnachtsmann

von Peter D. (peda)


Lesenswert?

Wenn Du die UART nutzen willst, dann solltest du am besten gleich einen
Standardquarz nehmen, z.B. 7,3728MHz, 9,11,0592MHz, 14,7456MHz usw.
Damit stimmen dann alle Baudraten bis 115200 Baud.


Peter

von Weihnachtsmann (Gast)


Lesenswert?

Wenn ich das Senden auf ändere:

serout:                          ;Wert senden
  sbis UCSRA,UDRE
  out UDR, Sende
ret


empfange ich nichts mehr.

Ich weiss dass es Quarze gibt die auf die Bautraten passen.
Woher weiss ich welcher für welche Baudrate passt?


Gruss

Weihnachtsmann

von Zotteljedi (Gast)


Lesenswert?

Datenblatt, beim Mega8 z.B. ab Seite 156, "Table 60. Examples of UBRR
Settings for Commonly Used Oscillator Frequencies" und folgende.

von Eumel (Gast)


Lesenswert?

Hallo Weihnachtsmann,

1. Das Senden im Interruptbetrieb würde folgendermaßen ablaufen:
du gibst ein Zeichen in das UART_Ausgangsregister, gibts den
UART-Sendeinterrupt (Ausgangsregister leer) frei. In der
Interruptroutine des Sendeinterrupts gibst du dann das jeweils folgende
Zeichen aus.
Die Warteschleife auf das Leerlaufen des Registers entfällt. Mit dem
letzten Zeichen (carriage return) sperrst du dann den Interrupt
wieder.

2. wenn ich deinen (für mich etwas unkonventionellen) Code für Timer 0
richtig interpretiere, dann unterbrichst du alle 9,8ms. Das sind
mitnichten 25 mal in der Sekunde. 256*(256-24)/6000000

Gruß
Einhart

von dave (Gast)


Lesenswert?

Ein Byte übertragen braucht knapp über 1ms (>1/920) Zeit. Du überträgst
7 Stück davon, d.h. mindestens 7.6ms. Eumel hat's schon vorgerechnet:
IRQ alle 9,8ms ==> 2,2ms über, bestenfalls.

Wenn jetzt aber was dazwischen kommt, dann entfällt der Interrupt
natürlich.

Das könnte ja grad noch gehen, aber was nich so schön ist, bzw. NIX (so
wie Du es dir gedacht hast) bringt, ist das hier:
  ldi temp, 0b00000000          ;Timer0 Aus
  OUT TIMSK,temp

  ldi temp, 0b00000010          ;Timer0 Ein
  OUT TIMSK,temp

Du schaltest nur den IRQ aus, nicht den Zähler ;) und da durch ein IRQ
die Interrupts generell (I-Flag) ausgeschaltet sind ==> nutzlos.
Nimm lieber in TCCR0 den Takt raus, d.h. die niedrigsten 3 Bits auf 0.

Warum und wie Du auf 25Hz kommst, ist mir noch schleierhaft.

Wie oft trifft denn der RXC-IRQ auf? Lösch den doch mal raus und schau
nochmal, ob er dann mit 100Hz sendet.

dave

von Philipp Sªsse (Gast)


Lesenswert?

Nachtrag zum Thema: "wie macht man es richtig": Mangels
Interrupt-Prios behilft man sich üblicherweise so:


ISR schreibt Zählerwert in Ringbuffer

main-loop leert Ringbuffer über UART.


Und wenn dann noch die ISR ein Flag setzt, wenn der Puffer überläuft,
weißt Du auch, was los ist, wenn etwas schief geht.

von Weihnachtsmann (Gast)


Angehängte Dateien:

Lesenswert?

Hallo

Also irgendwie funktioniert diese Sache immer weniger und bin immer
verzeifelter. Habe gedacht ich bringe die Sache auf die Reihe.

Ist mein Vorhaben überhaupt machbar?
Oder muss ich die Sache mit Logic-ICs aufbauen?

So wie ich es jetzt gemacht habe bringe ich es auf ca 142 Datensätze in
20 Sekunden.
Obwohl ich jetzt:  1024*(256-22)/6000000 = 0.039936
Ich bringe wenn ich will auch auf 500 Datensätzen aber mit kleinerem
Teiler.

Wenn ich dies:

  ldi temp,Teiler
  out TCCR0,temp                 ;Timer deaktivieren

Statt:
  ldi temp, 0b00000000          ;Timer0 Aus
  OUT TIMSK,temp

Diese eingebe läuft natürlich der Timer weiter.
Ich muss beides nehmen.


Gruss

Der Weihnachtsmann.

von dave (Gast)


Lesenswert?

ldi temp1, 0    ; clr temp1
out tccr0, temp1

da glaub ich dir nicht, dasser nicht stehen bleibt...

wie oft sendest du jetzt daten auf den mc? lass doch mal den
rxc-interrupt wech


dave

von Weihnachtsmann (Gast)


Lesenswert?

Hallo

Stimmt er bleibt stehen vermutlich habe ich beim Kopieren den Falschen
Wert oder Befehl genommen.

Ohne rxc-interrupt ist er gleichschnell.

Gruss

Weihnachtsmann

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.