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
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.
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?
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.
Soviel ich weiss sind irgendwie die Prioritäten von den Interrupts bei AVR schon gegen oder täusche ich mich da? Gruss Der Weihnachtsmann
Hä? Keine Ahnung, was das bedeuten soll, aber am AVR gibts jedenfalls keine wirklichen Interruptprioritäten.
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"
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.
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
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
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
Datenblatt, beim Mega8 z.B. ab Seite 156, "Table 60. Examples of UBRR Settings for Commonly Used Oscillator Frequencies" und folgende.
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
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
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.
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.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.