Forum: Mikrocontroller und Digitale Elektronik Timer1 PIC16F1823 funktioniert nicht


von Oliver K. (ollik)


Lesenswert?

Hallo,
ich bin gerade dabei den Timer1 des PIC16F1823 auszuprogrammieren.
Ich möchte das er auch im Sleepmode arbeitet und verwende daher einen 
externen Crystal zum takten.
Doch leider funktioniert er nicht. Zum testen will ich einfach mal eine 
LED im 1s-Takt blinken lassen.
1
void interrupt()
2
{
3
     if(INTCON.TMR1IF == 1) //interrupt from Timer1?
4
     {
5
          TMR1H = 0x60; //high byte
6
          TMR1L = 0x02; //low byte
7
          INTCON.TMR1IF = 0; //re-enabling the interrupt
8
9
          PORTC.B2 != PORTC.B2;
10
     }
11
}
12
13
void wait_ms(int time)
14
{
15
     for(i = 0; i<time; i++)
16
             Delay_ms(1);
17
}
18
19
void init_Timer1()
20
{
21
     //Timer1 always on
22
     T1CON.TMR1ON = 1;
23
     T1GCON.TMR1GE = 0;
24
     
25
     //Osc.Circuit On T1OSI/T1OSO Pins
26
     T1CON.TMR1CS1 = 1;
27
     T1CON.TMR1CS0 = 0;
28
     T1CON.T1OSCEN = 1;
29
     wait_ms(50); //start-up and stabilization time
30
31
     //select Prescaler 1:8
32
     T1CON.T1CKPS1=1;
33
     T1CON.T1CKPS0=1;
34
35
     //Asynchronous Counter
36
     T1CON.NOT_T1SYNC = 1;
37
38
     //TNR1H, TMR1L and TMR1IF should be cleared before enabling the interrupt
39
     TMR1H = 0x00;
40
     TMR1L = 0x00;
41
     PIR1.TMR1IF = 0;
42
     
43
     //enable overflow interrupt (0xFFFF -> 0x0000)
44
     PIE1.TMR1IE = 1;
45
     INTCON.PEIE = 1;
46
     INTCON.GIE = 1;
47
48
     //oszillator circuit : f=32,768 kHz
49
     //instruction periode = 1/f = 30,52 us = T
50
     //prescaller value = 1:8
51
     //timer0 rate = 8 * T = 8 * 30,52 us =  244,16 us (1 pulse)
52
     //16-bit-timer
53
     //interrupt intervall = 10 s
54
     //pulses to interrupt = 10 s / 244,16 us = 40956,7 = 40957
55
     //decimal: counter start = 65535-40957 = 24578 -> 0x6002
56
     //Interrupt after 10s
57
     
58
     /*TMR1H = 0x60; //high byte
59
     TMR1L = 0x02; //low byte*/
60
     
61
     // 1s
62
     TMR1H = 0xEF; //high byte
63
     TMR1L = 0xFF; //low byte
64
}
65
66
void main() 
67
{
68
     init_Timer1();
69
     TRISC = 0x00; //Define PORTC as output
70
     PORTC = 0x00;
71
     PORTC.B2 = 1;
72
     
73
     while(1)
74
     {
75
     }
76
}

von Oliver K. (ollik)


Lesenswert?

Könnt ihr mit bitte weiterhelfen, ich komme einfach nicht auf den Fehler

von Michael H. (morph1)


Lesenswert?

ich bin zu 99% sicher, dass die interrupt routine anders definiert wird. 
leider hast du den compiler nicht genannt, sonst könnte man dir leichter 
helfen :)

von Oliver K. (ollik)


Lesenswert?

ich compiliere mit mikroC PRO for PIC

von Chris B. (dekatz)


Lesenswert?

Beim Initialiseiren von Timer1 würde ich den Timer erst an Ende der 
Init-Routine einschalten.

Zu Beschreiber der beiden Timerregister im "async. counter mode" sollte 
der Timer dabei angehalten werden (Datenblatt 21.5.1).:
.....
For writes, it is recommended that the user simply stop
the timer and write the desired values. A write
contention may occur by writing to the timer registers,
while the register is incrementing. This may produce an
unpredictable value in the TMR1H:TMR1L register pair.
.....
Also in der INT-Routine:

T1CON.TMR1ON = 0;
TMR1H = 0x60; //high byte
TMR1L = 0x02; //low byte
T1CON.TMR1ON = 1;

Ob sonst noch wo was faul ist, kann ich auf die schnelle auch nicht 
sagen.....

von Michael .. (bigneal)


Lesenswert?

und wo bleibt das Prgramm hängen?
Kommt es bis in die while schlaufe?
wo ist "i definiert?

von Oliver K. (ollik)


Lesenswert?

@Chris B.: habe jetzt den Timer erst am Ende der Init_Timer1 gestartet 
aber es funktioniert leider noch immer nicht.. und das Problem bei mir 
ist das er nicht einmal in die ISR reinkommt.

@michael ..: das Programm kommt in die while-Schleife, ich habe es 
gerade getestet und i wird definiert nur hab ich es vergessen mit rein 
zu kopieren.

bin schon am verzweifeln..

von Chris B. (dekatz)


Lesenswert?

Wie ist der externe Quarz für Timer1 beschaltet?
Läuft Timer1 überhaupt bzw. kannst du das testen??

von Maik W. (werner01)


Lesenswert?

warum wait-ms unnd dann noch Delay_ms? Aber egal.
so fängt meine Interruptding aus...


static void interrupt
isr(void)      // Here be interrupt function - the ..

und schau mal im disassembler nach was der Programmzeiger beim Überlauf 
macht...


maik

von Oliver K. (ollik)


Lesenswert?

Der externe Quarz ist so beschalten wie in dem Bild im Anhang.

Im Datenblatt steht folgendes:

A dedicated low-power 32.768 kHz oscillator circuit is
built-in between pins T1OSI (input) and T1OSO
(amplifier output). This internal circuit is to be used in
conjunction with an external 32.768 kHz crystal.

T1OSO ist am Pin 3
T1OSI am Pin 2


Ich habe leider keine Idee wie ich testen kann ob der Timer läuft...

von Oliver K. (ollik)


Angehängte Dateien:

Lesenswert?

Habe das Bild im Anhang vergessen

von Oliver K. (ollik)


Lesenswert?

@maik: wait_ms ist meine eine von mir definierte Funktion, da so das 
delay_ms nur einmal implementiert wird und somit weniger Speicher 
benötigt.

Was ist genau der disassembler?

von Chris B. (dekatz)


Lesenswert?

Oliver K. schrieb:
> Ich habe leider keine Idee wie ich testen kann ob der Timer läuft...

In der <while(1)> TMR1H auslesen und auf PORTB ausgeben. Mit einer LED 
und Vorwiderstand prüfen ob sich die PORTB-Leitungen ändern. PORTB.7 
dürfte sich langsam genüg ändern, damit man die LED blinken sieht.

von Maik W. (werner01)


Lesenswert?

@OLiver: Der Disassembler zeigt dir die Software wie sie im Speicher 
steht. Da könntest du schauen was genau beim Timerüberlauf geschieht...
Wenn der nirgendwo hinspringt so weist du wenigstens erst mal ,das der 
Interrupt nicht aktiv ist.

maik

von Michael S. (rbs_phoenix)


Lesenswert?

Das Bild ist aber von einem anderen Schaltplan oder? Der PIC16F1823 hat 
ja keine 16 Pins.

edit: Oh ok. Als QFN schon.


Der PORTC.2 ist als Ausgang gemultiplext mit SDO und P1D. Ich würde 
diese beiden Module nochmal explizit ausschalten. Dann ins Interrupt 
(vor das "if") einen Ausgang setzen. Wenn der an is, is er jedenfalls 
schonmal darein gegangen. Und wie schon gesagt wurde, in der 
while-schleife ein paar bits vom Timerregister an ein paar Pins 
ausgeben.

Dann kannst du zumindest schonmal prüfen, ob der Timer läuft und wenn, 
ob er in die Interrupt-Funktion reinspringt.

von Chris B. (dekatz)


Lesenswert?

> In der <while(1)> TMR1H auslesen und auf PORTB ausgeben. Mit einer LED
>
> und Vorwiderstand prüfen ob sich die PORTB-Leitungen ändern. PORTB.7
>
> dürfte sich langsam genüg ändern, damit man die LED blinken sieht.

Sollte natürlich PORTC sein....habe mich von dem "B2" im obigen Listing 
verwirren lassen ;_)

von Oliver K. (ollik)


Lesenswert?

Habe gerade TMR1H auf LEDs ausgegeben und festegestellt das der Timer 
nicht einmal läuft. TMR1H hält einfach den Wert den ich ihm am Anfang 
zuteile und zwar: 0xEF...

An was kann das liegen?

Im Datenblatt steht das der Crystal ein Start-up and Stabilization Time 
benötigt aber nicht wie lange.
..........
The oscillator requires a start-up and
stabilization time before use. Thus,
T1OSCEN should be set and a suitable
delay observed prior to enabling Timer1.
..........

Nun habe ich einfach mal ihn nach der Auswahl des Osc.Circuit 50 ms 
warten lassen. Kann das an dem liegen?

von Oliver K. (ollik)


Lesenswert?

Michael Skropski schrieb:
> Der PORTC.2 ist als Ausgang gemultiplext mit SDO und P1D. Ich würde
> diese beiden Module nochmal explizit ausschalten.

Was hat das mit dem Timer zu tun? Der externe Quarz hängt ja an PORTA.4 
und PORTA.5.

von Stefan (Gast)


Angehängte Dateien:

Lesenswert?

Versuch mal das File was im
Anhang ist auf deine sprache um zu
setzen. Und schau dann mal wo dein
Fehler ist.

von Oliver K. (ollik)


Lesenswert?

Danke für die Hilfe, jetzt geht er wenigstens mal, wenn auch nur mit dem 
internen Oszillator.

Ich wollte jetzt Stück für Stück dein Programm auf meines Abstimmen um 
auf meinen Fehler zu kommen und dabei ist mir was sehr seltsames 
aufgefallen.

Wenn ich bei dem T1CON register alle einzelenen Bits setze funktioniert 
es nicht:
1
     //Timer1 always on
2
     T1CON.TMR1ON = 1;
3
     
4
      //Osc.Circuit On T1OSI/T1OSO Pins
5
     T1CON.TMR1CS1 = 1;
6
     T1CON.TMR1CS0 = 1;
7
     T1CON.T1OSCEN = 1;
8
9
     //select Prescaler 1:8
10
     T1CON.T1CKPS1=1;
11
     T1CON.T1CKPS0=1;
12
13
     //Asynchronous Counter
14
     T1CON.NOT_T1SYNC = 1;

Aber wenn ich wie du T1CON so setzte funktioniert es:
1
     T1CON = 1;

Hat jemand eine Idee wieso das so ist?

von Chris B. (dekatz)


Lesenswert?

Oliver K. schrieb:
> Aber wenn ich wie du T1CON so setzte funktioniert es:     T1CON = 1;
>
>
> Hat jemand eine Idee wieso das so ist?

Na klar funkteoniert das!
T1CON = 1  also T1CON = b'00000001'
Was heisst das?
TMR1CS<1:0> = b'00' = Takt kommt vom internen Takt Fosc/4
T1CKPS<1:0> = b'00' = Prescealer 1:1
T1OSCEN = b'0' = Timer1-Oscillator abgeschaltet
und letztendlich
TMR1ON = 1 = Timer gestartet.

Da ist es natürlich egal falls der Quarz für den Timer1-Oscillator 
kaputt ist oder falsch angeschlossen oder kalte Lötstelle oder oder.... 
;-)

von Michael S. (rbs_phoenix)


Lesenswert?

Oliver K. schrieb:
> Michael Skropski schrieb:
>> Der PORTC.2 ist als Ausgang gemultiplext mit SDO und P1D. Ich würde
>> diese beiden Module nochmal explizit ausschalten.
>
> Was hat das mit dem Timer zu tun? Der externe Quarz hängt ja an PORTA.4
> und PORTA.5.

Ich habe gedacht, wenn du dieses Bit toggelst und er tut es nicht, 
vielleicht liegt es daran, das er garnicht als normaler Digital-Ausgang 
gesetzt ist.


Wenn es mit internen Oszillator geht, liegt es bestimmt an der Hardware. 
Ist vielleicht unterm QFN Pin1&2 verbunden? Sonst mal messen ob der 
Oszillator schwingt.

edit:

Oliver K. schrieb:
> Der externe Quarz ist so beschalten wie in dem Bild im Anhang.

Dazu nochmal die Frage. Welches Gehäuse hast du? Laut Bild ist es ein 
QFN. Hat 16 pins, 16 is Vdd, 1&2 ist T1OSO/T1OSI. Im text schreibst du 
aber:
> T1OSO ist am Pin 3
> T1OSI am Pin 2

Was auf SOIC/DIP deutet. Ist nun die Zeichnung "falsch" oder der Text.

von Oliver K. (ollik)


Lesenswert?

@Chris B.: natürlich :) war ein Denkfehler von mir. Ich habe gedacht 
T1CON = 1 ist das  gleiche wie T1CON = 0b11111111.

Michael Skropski schrieb:
> Dazu nochmal die Frage. Welches Gehäuse hast du? Laut Bild ist es ein
> QFN. Hat 16 pins, 16 is Vdd, 1&2 ist T1OSO/T1OSI. Im text schreibst du
> aber:

Habe mich in der Spalte verschaut. Ich verwende ein QFN Gehäuse mit 16 
Pins und habe den Quarz auch Pin 1&2 angeschlossen.

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.