Hallo, hab ein großes Problem mit Timer und Interrupt. Ich hab ein Programm zur Temperaturmessung mit Speicherung in EEPROM. Alle 10 min. wird gespeichert. Jetzt will ich die Temp. auch auf LCD ausgeben.Jedes für sich läuft. Wenn ich jetzt beides in mainloop nehme, wird logischerweise auch d.Anzeige nur aller 10 min. erneuert. Nun hat jemand gesagt ich soll das mit 2 Timern machen. Leuchtet mir auch ein, aber wie das geht ................... Hab mal probiert nur die LCD mit 1 Timer laufen zu lassen, da blinkt die Anzeige u. nach einer gewissen Zeit kommt nichts mehr. Da ist bestimmt in meine Code alles verkehrt. Könnte vielleicht jemand das Code mal anschauen? Danke!!!!! begin: rjmp main ; 1 POWER ON RESET reti ; 2 Int0-Interrupt reti ; 3 Int1-Interrupt reti ; 4 TC2 Compare Match reti ; 5 TC2 Overflow reti ; 6 TC1 Capture reti ; 7 TC1 Compare Match A reti ; 8 TC1 Compare Match B rjmp onTimer1Ov ; 9 Timer1 Interrupt bei Überlauf reti ;10 TC0 Overflow reti ;11 SPI, STC Serial Transfer Complete reti ;12 UART Rx Complete reti ;13 UART Data Register Empty reti ;14 UART Tx Complete reti ;15 ADC Conversion Complete reti ;16 EEPROM Ready reti ;17 Analog Comparator reti ;18 TWI (I²C) Serial Interface reti ;19 Store Program Memory Ready ;----------------------------------------------------------------------- - ; Initialisierungen ;----------------------------------------------------------------------- - main: ;--- Stack Initialisierung --- ldi r16,hi8(RAMEND) out SPH,r16 ldi r16,lo8(RAMEND) out SPL,r16 .equ TWI_ADR,(0b10010000|0b00000000) ; Feste und Variable (per Jumper) Adresse rcall lcdInit rcall twiInitMaster ;Config = NoShutdown,ComperatorMode,ActiveLow,FaultQueue=0 ldi r16,0 ldi r17,0 ldi r18,REG_CONFIG rcall lm75SetRegister ;--- Timer 1 initialisieren --- ldi r16,0b00000101 ; Teiler 1/1 out TCCR1B,r16 ; Teiler+Modus schreiben in r16,TIMSK ; Interrupt bei Überlauf ori r16,0b00000100 out TIMSK,r16 ;--- Interrupts erlauben --- sei ;----------------------------------------------------------------------- - ; Hauptprogramm-Schleife ;----------------------------------------------------------------------- - mainloop: wdr rcall onTimer1Ov rjmp mainloop ; Sprung zum Beginn der Hauptprogrammschleife ;----------------------------------------------------------------------- - onTimer1Ov: ; Hier beginnt die Interrupt-Service-Routine PUSH R16 ; Benutztes Register auf den Stapel IN R16,SREG ; Statusregister Zustand einlesen PUSH R16 ; ebenfalls auf den Stapel ablegen rjmp Ausgabe POP R16 ; alten Inhalt von SREG vom Stapel holen OUT SREG,R16 ; und Statusregister wiederherstellen POP R16 ; alten Inhalt von R16 wiederherstellen reti ;Rücksprung ;----------------------------------------------------------------------- - Ausgabe: wdr ;---Temperatur -> r22:r21 rcall lm75GetTemp ;--- Ausgabe mov r16,r22 rcall lcdZahl ldi r16,0xDF rcall lcdData ldi r16,'C' rcall lcdData rcall lcdLine1 ldi R16,'I' rcall lcdData ldi R16,'T' rcall lcdData ldi r16,'' rcall lcdData
>wird logischerweise auch d.Anzeige nur aller 10 min. erneuert Wenn du es so programmiert hast, dann ja. "Logisch" ist das aber nicht. >Nun hat jemand gesagt ich soll das mit 2 Timern machen. Das ist Käse. Ein Timer(interrupt) reicht aus, um die meißten zeitlich gesteuerten Dinge auszulösen. Laß den Timerinterrupt mit der höchsten von deiner Applikation benötigten Frequenz laufen. Alle anderen leitest du durch Zählen/Teilen davon ab.
Danke f. Antwort. "Laß den Timerinterrupt mit der höchsten von deiner Applikation benötigten Frequenz laufen. Alle anderen leitest du durch Zählen/Teilen davon ab." Und das is das was ich nicht bringe. Geht in meine alte Birne nicht mehr rein. Wenn ich einmal ein Codebeispiel hätte, käme ich dann mit ausprobieren, umstellen und so, auch weiter.
Du springst in der Interruptschleife mit rjmp Ausgabe raus, das geht nicht weil der IRQ dann nicht beendet wird. Du kannst anstatt rjmp RCALL verwenden.
Hab ich jetzt mit rcall probiert. Sieht in der Ausgabe dann so aus. IT 20 °C dann IT 20 °C C C dann IT 20 °C CC° dann IT 20° C CC21° usw. Komisch, muss was nicht stimmen
Hi >mainloop: wdr > rcall onTimer1Ov -> Was soll der Aufruf??? > rjmp mainloop ; Sprung Du musst dich schon entscheiden, ob du mit Interrupt oder Unterprogramm arbeiten willst. 1.Dein Timerinterrupt ist viel zu schnell. Für deine Anwendung würde 1s reichen. Und das lässt sich im CTC-Modus besser erreichen. 2. In der Interruproutine werden deine Funktionen nur vorbereitet. Einmal wird ein Flag(Register oder im RAM) für die LCDAusgabe gesetzt (0->1). 3. Für die EEPROM-Speicherung zählst du eine Variable herunter. Wenn die 0 wird setzt du ein weiteres Flag und setzt die Variable wieder auf den Startwert. 4. Im Hauptprogramm testest du die Flags auf <>0. Wenn das zutrifft führst du die entsprechnde Routine (Anzeige oder EEPROM) aus und setzt das Flag wieder auf 0. MfG Spess
> Wenn ich einmal ein Codebeispiel hätte, käme ich dann mit ausprobieren, > umstellen und so, auch weiter. Beitrag "Kleiner Funktionsgenerator mit Tiny2313" Sieh Dir die Abfrage von Drehgeber und Drehgebertaste an, die werden vom selben Timer-Interrupt synchronisiert. Das Prinzip müsste daran erkennbar sein. ~
Danke erstmal an alle!!!!!! Werd versuchen das Beste draus zumachen. Allen einen Guten Rutsch
Hi, ich wieder erstmal allen alles Gute im Neuen Jahr. Das mit CTC Modus klingt gut. Hab nun auch alles versucht, es zu begreifen, komm aber nicht klar damit. Nun ganz einfach meine Frage: Kann mir jemand konkret aufschreiben wie das aussieht. Ich hab "Workpadplus" als Programm und die ganzen Beispielcodes sind ja anders. Das einzige was ich weiß ist,daß in main: rjmp TIM1_COMPA ; Timer1 CompareA Handler eingestellt werden müsste. Kann aber auch schon wieder falsch sein. Mit Timer 1 siehts ja so aus: ;--- Timer 1 initialisieren --- ldi r16,0b00000101 ; Teiler entspricht ca.15 sek. out TCCR1B,r16 ; Teiler+Modus schreiben in r16,TIMSK ; Interrupt bei Überlauf ori r16,0b00000100 ; out TIMSK,r16 aber wie sieht sowas mit CTC aus? Mit den Tipps weiß ich nichts anzufangen. >2. In der Interruproutine werden deine Funktionen nur vorbereitet. >Einmal wird ein Flag(Register oder im RAM) für die LCDAusgabe gesetzt >(0->1). >3. Für die EEPROM-Speicherung zählst du eine Variable herunter. Wenn die >0 wird setzt du ein weiteres Flag und setzt die Variable wieder auf den >Startwert. >4. Im Hauptprogramm testest du die Flags auf <>0. Wenn das zutrifft >führst du die entsprechnde Routine (Anzeige oder EEPROM) aus und setzt >das Flag wieder auf 0. Das ist keine Bequemlichkeit von mir, aber ich grieg das einfach nicht hin. Ich möchte eigentlich nur das dieses eine Projekt läuft um meine Heizugsanlage auszuwerten. Weitere Projekte hab ich gar nicht vor. Bin einfach zu alt, um mich da noch reinzufinden. Für einen kompletten CTC Code wäre ich sehr dankbar!!! Gruss kurtel
Ich finde die Stelle nicht, in der Du den verwendeten AVR-Typ nennst. Daher kann ich Dir auch nichts zum CTC-Modus sagen. Denn die Timer der unterschiedlichen AVRs sind unterschiedlich mit Features ausgestattet. Bei einigen AVRs gibt es tatsächlich ein CTC-Bit im Steuerregister der Timer, bei anderen AVRs geht das in den WGM-Bits unter, da eben neben CTC noch etliche andere Modi möglich sind. Zu alt bist Du vermutlich nicht, ich bin auch schon lange keine Fuffzich mehr und Programmieren ist nicht mein Beruf. ~
Je älter der Programmierer, desto schwerer fällt ihm das Pushen und erst recht das Poppen!
Hi Tippe auf ATMega8. Habe dir mal auf die Schnelle die Initialisierung gemacht (ohne Gewähr). Im Datenblatt ist ist eine Tabelle mit den verschiedenen Timermodes. MfG Spess
Hallo Sinusgeek, danke f. d.Antwort. Ich hatte mir das "TWI-Projekt" bei MyAVR gekauft. Da war alles dazu. LCD, EEpromm, Tempsensor und Programmer. Als Controller ist d. Atmega 8 dazu.Das Grundgerüst sieht so aus. ;Reset and Interruptvectoren ;VNr. Beschreibung begin: rjmp main ; 1 POWER ON RESET reti ; 2 Int0-Interrupt reti ; 3 Int1-Interrupt reti ; 4 TC2 Compare Match reti ; 5 TC2 Overflow reti ; 6 TC1 Capture reti ; 7 TC1 Compare Match A reti ; 8 TC1 Compare Match B reti ; 9 TC1 Overflow reti ;10 TC0 Overflow reti ;11 SPI, STC Serial Transfer Complete reti ;12 UART Rx Complete reti ;13 UART Data Register Empty reti ;14 UART Tx Complete reti ;15 ADC Conversion Complete reti ;16 EEPROM Ready reti ;17 Analog Comperator reti ;18 TWI (I²C) Serial Interface reti ;19 Strore Program Memory Ready Übrigens, Hut ab, wenn du alles noch kappierst in d. Alter. Ganz blöd bin ich ja auch nicht, aber irgendwie macht´s noch nicht Klick. Wenn ich etwas fertiges habe, kann ich mich dann einfach besser hinein versetzen. kurtel
> Wenn ich etwas fertiges habe, kann ich mich dann einfach besser hinein > versetzen. Das ist bei mir umgekehrt, wenn ich was Eigenes mache, dann kann ich es an meine Wünsche anpassen... ;-) Mega8... Das Datenblatt des Mega8 zeigt in Tabelle 39 die verschiedenen Betriebsarten des 16-Bit-Timer1. Mode 4 wird CTC genannt, der Zählumfang gehört dabei in OCR1A (Spalte TOP). In den Spalten weiter links sind die WGM-Bits und ihre Bitwerte aufgelistet, die in die zuständigen Steuerregister eingetragen werden müssen. In dieser Betriebsart klappert der Timer von 0 bis zu dem Wert in OCR1A, löst dann den Compare1A-Interrupt aus und beginnt wieder bei 0 mit der Zählerei. Das ist also die "Sorglos-Betriebsart", man gibt dem Timer einmalig seinen Zählumfang, schaltet ihn ein (Vorteiler), gibt seinen Interrupt frei (TIMSK und SEI), und schon wird in regelmäßigen Zeitabständen ohne weiteres Zutun die ISR aufgerufen. In dieser können dann kleinere (schnelle) Aufgaben erledigt werden oder Merker für größere Aufgaben gesetzt werden, die das Hauptprogramm dann prüft und deren Jobs abarbeitet (die dann den Merker auch wieder löschen, da die Arbeit ja getan ist). @Katpaulski: Dein Katapult ist ja wieder mal mit scharfer Munition geladen... ;-) ~
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.