Timer1 Interrupt : nix mit ruptus

Begonnen von picass, 27.07.2025, 15:21:40 CEST

Vorheriges Thema - Nächstes Thema

picass

#20
KLATSCH und KREISCH !

Es ist vollbracht: die angesprochene LED blinkt im Sekundentakt!
Neben den ersten, zweiten und dritten Fehlern war es letztlich das Konfigurations-Register für die Timer1-Einstellung, welche alles verhinderte. Da hatte ich das "Timer1 Block Diagramm" - also die stark vereinfachte Skizze der Funktionsblöcke für die Timer1-Funktion - studiert und messerscharf geschlossen, dass das Taktsignal an den Port A,5 zu legen wäre, welcher in dieser Skizze als "OSC1/T13CLK" benannt ist. Und von da aus ginge das Signal über die dargestellte durchgehende interne Leitung zu einem Schmitt-Trigger und von dort weiter zum Übergabepunkt ""Timer1 Clock Input". Anders gesagt: das Signal würde am Timer1-Oszillator vorbei gelenkt, der würde ergo nicht gebraucht.

Weswegen ich ihn im Config-Word abgeschaltet hatte. Das war das Bit 3 oder anders: T1CON,T1OSCEN. Dieser Oszillator war also still gelegt in dem Glauben, dass es ja wegen der durchgängigen Verbindung den nicht braucht. Zudem wird der PIC selbst ja über seinen LFINTOSC angetrieben, was braucht es da noch einen weiteren Oszillator. Aber wie das so ist mit dem Glauben. Tatsächlich läuft das Prog, sobald dieser Oszi doch wieder enabled ist, er läuft nicht, wenn disabled, er läuft, wenn......Er läuft und auch dieser Floh wurde ertappt und zerquetscht ! Schwitz, wieder so'n Kampf und die Stunden gingen dahin. Nun gehe ich dahin, kaufe erst noch schnell 'ne Runde ein und freue mich heute Abend dann mal 'ne etwas größere Runde.
Sehr herzlichen Dank für eure zahlreichen Bemühungen, das war ganz toll von euch. Danke.
Grüße, picass

pic18

Ich habe mir mal das Datenblatt angeschaut und schon einen Fehler aus Seite 10 gefunden :o
Timer0 and Timer3 external clock input

Nun zu deinem Prog.
Du hast T1CON geschrieben:
movlw  b'10000111'  ;timer1 controll reg:16bit/timer1-oszi aus/keine
muss aber
movlw  b'10000011'  ;timer1 controll reg:16bit/timer1-oszi aus/keine
heißen

/T1SYNC: Timer1 External Clock Input Synchronization Select bit
When TMR1CS = 1:
1 = Do not synchronize external clock input
0 = Synchronize external clock input

außerdem würde ich noch Priorität vom Timer 1 auf Hi setzen.
IPR1 TMR1IP

was mir auch aufgefallen ist, du tust deinen Timer nur beim start in Main "Befüllen" sollte dies nicht in jeden Interrupt sein?
in blink die Test LED einschalten würde ich anders lösen, die LED leuchtet sonst ständig. Das siehst Du nicht, wenn im Interrupt der Ausgang mal kurz toggle wird.

pic18


Ottmar

Hallo picass,
habe mal Dein ASM-File "stundenzaehler05.txt" mit einer funktionierenden ISR versehen. Jetzt blinkt die LED im 1s-Takt. Das ASM-file müßte auch bei Dir funktionieren, habe es im relocatable Code geschrieben.
Das mit dem Input einer Halbwelle habe ich noch nicht richtig verstanden.. naja.

mfG Ottmar

P.S.: was um alles in der Welt veranlasst Dich immer fosc=31kHz zu nehmen?
Bis die LED anfängt zu blinken, erschrickt man regelrecht, man glaubt der Code stimmt nicht.

pic18

Zitat von: pic18 in 29.07.2025, 21:44:42 CESTin blink die Test LED einschalten würde ich anders lösen, die LED leuchtet sonst ständig. Das siehst Du nicht, wenn im Interrupt der Ausgang mal kurz toggle wird.
vergiss die Zeile, das ist ja ein anderer Port.

pic18

@Ottmar ich habe mal dein Prog. angeschaut, dies arbeitet mit den 31Khz (internal clock (FOSC/4)), nicht mit dem RA5 Takteingang. Da müsste das eine Bit noch gedreht werden. 

Ottmar

picass,
PIC18
ich habe es verstanden. Wenn der unten stehende Code über den bestehenden in dem von mitgeteilten ASM-File kopiert wird, klappt das so wie von picass beabsichtigt.Was er beabsichtigt hat, habe ich erst nach dem Upload meiner Datei bemerkt.
Bei mir wird RA5 mit 130 kHz Sinus 2,2Vss direkt beaufschlagt, bei dem der Sinus gerade noch über die interne Triggerschwelle rutscht damit die LED blinkt. 
fosc in   . 130kHz -> LEDfosc ca. 0,9Hz

Bei wechselnder Frequenz, folgt die Blinkfrequenz dieser Änderung. und die LED bei wechselnder frequenz, entsprechend langsamer/schneller analog blinken läßt.

;---T1CON: TIMER1 CONTROL REGISTER                             DS.94
; external TMR1 oscillator is enabled when T1OSCEN = 1 
; and TMR1CS is set to 1 external clock enabled
; the signal goes straight from pin RA5 throug a schmitt-trigger
; to the clock input of TMR1.  
;;   movlw    b'00000000'
   movlw    b'00001010'
   ;          ....1..   b3/T1OSCEN 0/1 external Tmr1-clock disabled/enabled
   ;          ......1.  b1/TMR1CS 0/1 = Internal(external clock (FOSC/4)
   ;          .......0  b0/TMR1ON 0/1 disable/enable TMR1
   movwf    T1CON
   clrf     TMR1H       ;clear Hi-Byt  ;TMR1 is set o 0x0000
   clrf     TMR1L       ;clear Lo-Byte

picass

#27
Auf diese Darstellung in der angehängten Skizze - ein Auszug aus dem Microchip-Datenblatt - bin ich rein gefallen, was meiner Art entspricht, zunächst alles wörtlich zu nehmen. Da gibt es die scheinbar direkte Verbindung vom Eingangsport PA5 zum internen Übergabepunkt für das Timer1-Signal. Auch jetzt nach Entdeckung des wahren Sachverhaltes ist mir nicht eingängig, warum das nicht direkt durch geht. U.a. geht es ja direkt durch, denn dieser Port kann ja sowohl für digitale wie auch analoge Signale als Eingangspin genutzt werden, ohne dass dieser vermaledeite Oszi in Betrieb gesetzt wird.
Die Synchronisations-Möglichkeit hat keinen Einfluss auf die Funktion meiner Schaltung, egal, ob on oder off, da ändert sich nichts Erkennbares.

Der Input über die Halbwelle ist schlicht erklärbar. Es sollte halt als einfache Taktquelle die 230-V-Netzfrequenz gewählt werden. Bei Vollgleichrichtung müsste dann durch 100 geteilt werden, um auf eine Sekunde zu kommen. Bei Halbwellen reicht ein 50-Teiler, der auch noch den Vorteil hat, dass die Null-Stelle weitaus ausgeprägter ist.

Nicht alles aus der Welt, aber eine nüchterne Betrachtung veranlasst mich, bei dem überwiegenden Teil meiner Schaltungen die niedrige interne Taktfrequenz von 31 kHz zu wählen. Ist an diesem Beispiel wunderbar zu erklären. Die Erzeugung eines Sekunden-Taktes gelingt über diese Halbwellen und einem "speed" mit 20 mS-Taktzyklus. Das ist selbst für den gemütlichen 31-er-PIC noch ein Schnarchmodus, weil...... weil selbst diese Schnarch-Frequenz im Programm noch durch 50 geteilt werden muss. Selbstredend könnte man den PIC auch mit 4 MHz rasen lassen und dann...? Dann müsste man einen irren Teilungsfaktor erstellen, um wieder auf das Ein-Herz-Signal zu kommen. Aus meiner Sicht: was soll der Quatsch?!
Ein passender Vergleich: um mit einem Kfz auf eine Geschwindigkeit von 20 km/h zu kommen, könnte man einen leistungsschwachen und mit nur 1.800 U/min ruhig dahin nagelnden Diesel greifen und den sogar noch im dritten Gang fahren. Genauso könnte man einen Ferrari mit 700 Newtonmeter bei 5.000 U/min betreiben, bei dem dann allerdings vorher noch ein Spezialgetriebe eingeflanscht werden müsste, um die irre Drehzahl runter zu bekommen für den Antrieb.
Bei meiner PIC-Testplatine dauert nach dem Starten auch nichts. Die erste Dunkelpause nach dem Einschalten dauert exakt genau so lang, wie die späteren Dunkelpausen beim Blinken im 1-Herz-Rhytmus. Zudem: wie oft wird eine Schaltung, welche sich im Jahres-Dauer-Einsatz befindet überhaupt eingeschaltet?! Ne, lass ma, für mich und meine PICs passt das.
Grüße, picass
counter1.jpg

Ottmar

Hi picass,
langer Rede kurzer Sinn: Es geht einfacher, ohne Netzanbindung/Optokoppler und Halbwellenbildung, eine exakte 50Hz-Frequenz zu generieren.

Nimm das von mir anfänglich übermittelte ASM-File mit diesen Änderungen:
Internen Oszillator, Fosc = 4Mhz, das ergibt Fosc/4=1.000.000 wc (working cycles). 

Diese nimmst Du als clock für den TMR1, dazu den TMR1 overflow-Interrupt. In der ISR machst Du einen Preset 2^16us - 20.000us = 45536 = 0xB1EO.

Die "Denkpause" wird  vermieden, wenn man direkt vor Freigabe des Interrupts, (bsf INTCON,GIE) den TMR1 auf den Preset wie nachstehend setzt.

ZitatISR_H:
bcf        PIR1,TMR1IF
movlw   0xB1
movwf   TMR1H
movlw   0xE0
movwf   TMR1L
movlw   b'10000000' ;LED ist an bit 7
xorwf    PORTA,f        ;RA7 toggelt alle 200ms und LED blinkt mt 50Hz
RETFIE  FAST
Voila - das geht ganz ohne Vorteiler... fertig! Solls genauer sein, nimm einen 4MHz Quarz.

Ottmar

A
Zitateinen Preset 2^16us - 20.000us = 45536 = 0xB1EO
richtig ist: 
2^16us - 10.000us = 55536us = 0xDBF0
denn die Periodendauer von 50Hz ist 20ms und dafür bedarf es 2 ISR-Intervalle zu je 10ms.

picass

#30
Hallo Ottmar !
Deine Rechenübung kann ich nicht nachvollziehen.
Zunächst stimmt deine Zuordnung nicht: h'dbf0' sind d'56.304'

Dann ist völlig unklar, was genau du denn nun den PIC zählen lassen willst, um von seiner hohen Frequenz runter zu kommen auf 1 Hz. Takt soll 4 Mhz sein, ein Cyclus dann 1 Mhz, also jeder Cyclus belegt 1 µS. Dann soll nach deiner Rechnung der Counter1 gesamt 55.536 µS abzählen. Und wie kommt man nun auf eine Sekunde ?
Grüße, picass
 

Ottmar

Hi picass,
Du hast recht. das war von mir ein Ablesefehler auf dem Windowsrechner "Programmierer", habe "B" anstatt korrekt "8" abgelesen. Die dezimale Berechnung stimmt jedoch, hättest Du das beim Nachvollziehen der Berechnung bemerken können?
Die Blinkfrequenz 1Hz mit dem LF-Osillator habe ich in dem ASM-File vom 25.7 bereits dargestellt.

Ok, ich gebe Dir 2 Beispiele für 50 Hz bzw. 1 Hz Blinkfrequenz mittels TIMER1-overflow-Interrupt, wie man dafür den Vorteiler und den Preset berechnet. Beachte bitte, daß der Arbeitstakt stets 1/4 der Oszillatorfrequenz beträgt. TMR1 zählt nur den Arbeitstakt.
;
a) 50Hz, Periodendauer 0,02s, zusammengesetzt aus
   0,01s High, 0,01s Low

b) 1Hz, Periodendauer 1s, zusammengesetzt aus 0,5s High, 0,5s Low
 
Gesucht a) Interrupt-intervall 0,01s (50Hz
        b) "                "              0,5s  (1Hz)
        dazu TMR1.Prescaler

Gegeben:fosc=4MHz (eingestellt z.B. mit OSCCON)
        TMR1-Modul (Zählbereich 0-2^16) + TMR1 overflow interrupt
        und Prescaler 1:1-1:8 vgl. Register TMR1CON

a) TMR1-Zähltakt = fosc/4 also 1.000.000 wc (Arbeitszyklen/sek.)
   ISR-Aufruf muss  für 10ms  (Peridodendauer 2x10ms) alle 10ms
   erfolgen. 
   Prescaler 1:1 wird verwendet, da TMR1 den Zählbereich offensichtlich
   ohne Vorteiler überstreicht, was Rechenarbeit erspart.

   Preset: = 2^16 - 10.000 = 55536 = 0xD8F0

b) TMR1-Zähltakt = fosc/4 also 1.000.000 wc (Arbeitszyklen/sek.)
   ISR-Aufruf muss  für 1Hz (Peridodendauer 2x0,5s) alle 0,s erfolgen

   Prescaler: 500.000 wc / 65536 = 7,6 nicht verfügbar!
   daher: nächsthöherer, verfügbarer Prescale: 1:8
   Preset TMR1: 2^16 - (500.000/8) = 3036 = 0x0BDC
   TMR1CON,T1CKPS<1:0>  = 11

   Der Vorteil einer zweckentsprechend gewählten Oszillatorfrequenz
   liegt damit wohl auf der Hand.

   mdG Ottmar

  

pic18

#32
das mit dem Timer stellen mache ich schon lange nicht mehr, das ist mir zu ungenau.
Ich würde es so machen:
den Vorteiler auf 32 setzen Timer auf 8 Bit (256 Überlauf)
bei 4Mhz würde ich dann 100ms zählen.
| bedeutet hoch, kann ich hier nicht darstellen.

256 und 32 Teiler 4 TOS/4
4*10|-6 s|-1 = 4MHz
100|10-3s =100ms

(256*32*4)/(4*10|-6s|-1 *100|10-3s) = 8,192E-2 = (256/3125)
 
jedes mal wenn der Interrupt aufgerufen wird, Variable Z  256 addieren
wenn Z >=3125 ist dann Z=Z-3125 und hier sind 100ms vorbei.

PICkel

Noch ein Tipp zum Thema Timerauslegung:

Von mikroe gibt es ein Programm, das auch "standalone" läuft: den Timer- Calculator:  https://www.mikroe.com/timer-calculator
Hier kann man PIC-Typ, Timer, Taktfrequenz und Verzögerung eingeben und erhält einen Code wahlweise in mikro-C/-Basic oder -Pascal.
Eine Portierung in ASM ist bei den paar Zuweisungen auch kein Problem.
Aber seht selbst im Anhang. Bei Bedarf kann ich Euch ein zip-File mit den Daten bereitstellen.


Gruß
PICkel
Timer_Calculator.jpg

Ottmar

@pic18 
Hm... meine Interrupt-Intervalle stimmen auf den Arbeitstakt genau. In der ISR, deren Intervall fast immer einige Arbeitstakte zu kurz ist, gleiche ich das dann mit einigen sinnvollen der auch wirkungslosen Instruktionen aus.

pic18

Da muss genau die Taktzyklen abgezählt werden, damit der Timer richtig gestellt wird. Bei mir gleicht sich dies automatisch aus. Gut es ist manchmal ein Takt etwas kürzer. Eine Uhr läuft aber über Monate Ganggenau.

Ottmar

Hi pic18,
das Abzählen fällt leicht, den in MPLAB 8 gibt es einen praktischen Timer zum Zählen der Arbeitstakte zwischen zwei Haltepunkten.
Intervall stoppen, Sollzeit - Istzeit = Extratakte (wc) hinzuzufügen. So kann auch die Ausführungszeit z.B. von Schleifen mit ein paar Clicks, taktgenau festgestellt werden. Nachstehend ein Beispiel.

ISR:
bcf  INTCON,TMR0IF
NOP        ->1wc
GOTO $ +1  ->2wc 
; und so weiter.....und wenn es ganz extrem werden sollte:

isr_taktehinzufügen:
movlw  (n)                  ->1wc   n * (8wc) = 8...-x wc zum Abgleich verfügbar
movwf  dummy                ->1wc 
decfsz dummy,f              ->2-3wc 
GOTO   isr_taktehinzufügen  ->2wc 
;
movlw  tmr0preset
movwf  TMR0     --- hier endet das alte, beginnt das neue Intervall



pic18

Ist schon richtig, nur die Zählerei ist mir zu kompliziert. Zumal ich in C programmiere. Je nachdem welchen C-Compiler genommen wird, ändert sich dann der Code. Dann stimmt alles nicht. 

Schnellantwort

Name:
Verifizierung:
Bitte lassen Sie dieses Feld leer:
Geben Sie die Buchstaben aus dem Bild ein
Buchstaben anhören / Neues Bild laden

Geben Sie die Buchstaben aus dem Bild ein:

Tastenkürzel: Alt+S Beitrag schreiben oder Alt+P für Vorschau

🡱 🡳