Forum: Mikrocontroller und Digitale Elektronik externer 32,768kHz Crystal für Timer1 funktioniert nicht PIC16F1823


von Oliver K. (ollik)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe ein Problem mit dem Timer1 des PIC16F1823 (QFN Gehäuse), und 
zwar funktioniert der Timer mit dem Oszillator Circuit zwischen PIN 
T1OSI und T1OSO nicht.

Ich habe den Timer mal mit dem internen Oszillator getaktet und damit 
hat es funktioniert. Kaum stell ich um auf den externen 32,768kHz 
Oszillator funktioniert es nicht.

Mit dem internen Oszillator kann ich ihn nicht takten, da der Timer auch 
im Sleep-Modus weiter laufen soll und das funktioniert nur mit dem 
externen 32,768kHz Oszillator.

Ich habe auch schon einen neuen Quartz ausprobiert, da ich dachte das 
der Quartz vielleicht defekt ist. Aber es funktionierte mit dem neuen 
Quartz auch nicht.

Kann mir bitte wer weiter helfen wo das Problem liegen könnte?

Im Anhang noch die Beschaltung des Quartzes zwischen T1OSI und T1OSO.

Und hier noch die Initialisierung des Timers:
1
void init_Timer1()
2
{
3
     //Osc.Circuit On T1OSI/T1OSO Pins
4
     T1CON.TMR1CS1 = 1;
5
     T1CON.TMR1CS0 = 0;
6
     T1CON.T1OSCEN = 1;
7
     wait_ms(100); //start-up and stabilization time
8
9
     //select Prescaler 1:8
10
     T1CON.T1CKPS1=1;
11
     T1CON.T1CKPS0=1;
12
13
     //Asynchronous Counter
14
     T1CON.NOT_T1SYNC = 1;
15
16
     //TNR1H, TMR1L and TMR1IF should be cleared before enabling the interrupt
17
     PIR1.TMR1IF = 0;
18
     
19
     // 1s
20
     TMR1H = 0xEF; //high byte
21
     TMR1L = 0xFF; //low byte
22
     
23
     //enable overflow interrupt (0xFFFF -> 0x0000)
24
     PIE1.TMR1IE = 1;
25
     INTCON.PEIE = 1;
26
     INTCON.GIE = 1;
27
28
     //Timer1 always on
29
     T1CON.TMR1ON = 1;
30
     T1GCON.TMR1GE = 0;
31
}

Oliver K.

von Oliver K. (ollik)


Lesenswert?

Bitte hilft mir, ich komme einfach nicht hinter den Fehler. Ich wäre für 
jeden kleinen Denkanstoß der zur Lösung führen könnte dankbar!

von Chris B. (dekatz)


Lesenswert?

Habe jetzt kein DB von 16F1823 zur Hand sondern nur von F1826/1827.
Aber falls es beim F1823 auch das OSCSTAT Register mit dem T1OSCR-Bit 
gibt, dann könntest du dieses Abfragen und dir den Status an eine LED 
ausgeben lassen.
Wenn OSCSTAT.T1OSCR = 1 dann ist der Timer1-Oszillator bereit. Das 
kannst du dann auch an Stelle der "wait_ms(100)" verwenden
Natürlich erst nach TMR1ON.

von usuru (Gast)


Lesenswert?

Kannst Du an T1OSO einen Takt vom Quarz messen?

von usuru (Gast)


Lesenswert?

> wait_ms(100); //start-up and stabilization time

Davor müsste übrigens TMR1ON stehen, in Deiner Situation läuft der Timer 
da noch gar nicht. Spielt hier aber keine Rolle.

Läuft Dein Timer frei durch oder soll der eine ISR auslösen? Im ersten 
Fall darfst Du GIE nicht setzen, nur TMR1IE und PEIE, im 2. Fall musst 
Du am Ende der ISR das TMR1IF wieder löschen.

von Oliver K. (ollik)


Lesenswert?

Danke erstmal für die Rückmeldungen.

@Chris B.: Habe gerade im DB nachgeschaut und es gibt dieses OSCSTAT 
Register.
Hier das controle-Bit:
>bit 7 T1OSCR: Timer1 Oscillator Ready bit
>If T1OSCEN = 1:
>1 = Timer1 oscillator is ready
>0 = Timer1 oscillator is not ready
>If T1OSCEN = 0:
>1 = Timer1 clock source is always ready

Ich habe jetzt das wait_ms(100) weggelassen und nachdem ich den Timer 
einschalte also am Ende der Init das Bit abgefragt: 
while(!OSCSTAT.T1OSCR);
Und er kommt aus der while-Schleife nicht mehr raus! Frage ich das Bit 
falsch ab?

@usuru: Habe leider erst am Montag die Möglichkeit es zu messen, da ich 
zu Hause kein Oszilloskop habe.
Er soll auch einen Interrupt auslösen und dann in die ISR gehen, was 
auch wie gesagt funktioniert wenn ich es mit dem internen Oszillator 
takte.

von Manfred G. (magroma)


Lesenswert?

Hallo, für einen 32 kHz Quarz sind die Kondensatoren zu klein. Mal auf 
82 bis 150 pF vergrößern.

von platzs (Gast)


Lesenswert?

> Hallo, für einen 32 kHz Quarz sind die Kondensatoren zu klein. Mal auf
> 82 bis 150 pF vergrößern.

Nö, 18-27 pF sind an einem PIC für einen Uhrenquarz ok. Mit 82 pF 
schwingt der nicht mehr an.

von PICfan (Gast)


Lesenswert?

Alle andere Peripherie an diese Pins deaktiviert?  Wenn die pins noch 
als Analog eingänge sind dann geht's nicht.

Zeig uns die restliche Init teile deines Programmes.

HTH
PICfan

von Oliver K. (ollik)


Lesenswert?

Sorry wegen der späten Antwort.

@PICfan: wie kann ich die anderen Peripherien an diesem PIN 
deaktivieren?

Hier nochmal mein ganzer Code, da er sich inzwischen ein bisschen 
geändert hat:
1
void interrupt(void)
2
{
3
     if(PIR1.TMR1IF == 1) //interrupt from Timer1?
4
     {
5
          PORTC.B2 = 1;   //nur zum testen! ob er überhaupt in die ISR geht
6
          PIR1.TMR1IF = 0; //re-enabling the interrupt
7
          TMR1H = 0x80; //high byte
8
          TMR1L = 0x00; //low byte
9
     }
10
}
11
12
void TIMER1_Init()
13
{
14
     //oszillator circuit : f=32,768 kHz
15
     //instruction periode = 1/f = 30,52 us = T
16
     //prescaller value = 1:8
17
     //timer0 rate = 8 * T = 8 * 30,52 us =  244,16 us (1 pulse)
18
     //16-bit-timer
19
     //interrupt intervall = 10 s
20
     //pulses to interrupt = 10 s / 244,16 us = 40956,7 = 40957
21
     //decimal: counter start = 65535-40957 = 24578 -> 0x6002
22
     //Interrupt after 10s
23
24
     /*TMR1H = 0x60; //high byte
25
     TMR1L = 0x02; //low byte*/
26
27
     //Osc.Circuit On T1OSI/T1OSO Pins
28
     T1CON.TMR1CS1 = 1;
29
     T1CON.TMR1CS0 = 0;
30
     T1CON.T1OSCEN = 1;
31
32
     //select Prescaler 1:8
33
     /*T1CON.T1CKPS1=1;
34
     T1CON.T1CKPS0=1;*/
35
36
     //Asynchronous Counter
37
     T1CON.NOT_T1SYNC = 1;
38
39
     //TNR1H, TMR1L and TMR1IF should be cleared before enabling the interrupt
40
     PIR1.TMR1IF = 0;
41
42
     // 1s
43
     TMR1H = 0x80; //high byte
44
     TMR1L = 0x00; //low byte
45
46
     //enable overflow interrupt (0xFFFF -> 0x0000)
47
     PIE1.TMR1IE = 1;
48
     INTCON.PEIE = 1;
49
     INTCON.GIE = 1;
50
51
     //Timer1 always on
52
     T1CON.TMR1ON = 1;
53
     T1GCON.TMR1GE = 0;
54
55
     while(!OSCSTAT.T1OSCR); //Wait while Timer1 Oscillator is not rdy
56
}
57
58
void main()
59
{
60
     ANSELA = 0xFF; // define PORTA digital
61
     TRISA = 0xFF;  // define PORTA as input
62
     TRISC = 0x00; // define PORTC as output
63
     PORTC = 0x00;
64
     PORTC.B2 = 0;
65
     
66
     TIMER1_Init();
67
     
68
     while(1)
69
     {
70
     }
71
}

und ich bin drauf gekommen das er am Ende der INIT bei der 
while-Schleife
hängen bleibt, das so viel heißt das der Oscillator Cicruit nicht bereit 
ist. An was kann das liegen?

von Oliver K. (ollik)


Lesenswert?

Aber wieso sollte es nicht funktionieren wenn die Pins analog sind? Der 
Quarz liefert ja kein digitales Signal.

von John B. (johnbauer)


Lesenswert?

Oliver K. schrieb:
> Aber wieso sollte es nicht funktionieren wenn die Pins analog sind? Der
> Quarz liefert ja kein digitales Signal.

Weil die Pins dann intern mit dem A/D-Wander verbunden sind und nicht 
mit der Oszillatorschaltung.

Hast Du in der Config 'Interner Oszillator' eingestellt?

von Chris B. (dekatz)


Lesenswert?

Der Timer1-Oscillator ist unabhängig von Oscillatormodul des 
Controllers.
Ich sehe auch keinen Fehler in der Timer1-Initalisierung.

Da unterschiedliche Konfiguration der betroffenen Pins(analog vs. 
digital)und Quarztausch nichts gebracht hat und der Timer1 selbst mit 
internen Takt ja laufen würde, tippe ich langsam auf eien defekten PIC.

Eventuelle könnte man noch mit anderen C-Werten bei der Quarzbeschaltung 
sein Glück probieren.

von John B. (johnbauer)


Lesenswert?

In der Config muss auch CLKOUT abgeschaltet sein.

von John B. (johnbauer)


Lesenswert?

Chris B. schrieb:
> Der Timer1-Oscillator ist unabhängig von Oscillatormodul des
> Controllers.

Bei diesem (kleinem) PIC teilen sich Oszillatormodul und 
Timer1-Oszillator die Anschlusspins. Da das Oszillatormodul eine höhere 
Priorität als der Timer1-Oszillator besitzt, muss es abgeschaltet werden 
-> Interner Oszillator.

von Chris B. (dekatz)


Lesenswert?

Stimmt, war im falschen Datenblatt unterwegs O-) (sollte wieder mal ein 
paar Fenster schliessen ;-) )

von Oliver K. (ollik)


Lesenswert?

OK, mit dem NOT_CLKOUTEN Bit des Configurations Word 1 kann man CLKOUT 
deaktivieren und jetzt meine blöde Frage: Wie kann ich das Bit setzten? 
Er kennt das Bit nicht wenn ich es setzten möchte..
1
NOT_CLKOUTEN = 1;

Weis jemand wie man das Bit richtig setzten kann?

von Chris B. (dekatz)


Lesenswert?

Das wird in den ConfigWords eingestellt.
Keine Ahnung welchen Compiler du verwendest aber beim Hi-Tech C-Compiler 
sieht es in etwa so aus:

(nur ein Beispiel!!!)

#include <htc.h>
__CONFIG(CLKOUTEN_OFF); // Program config. word 1
__CONFIG(LVP_OFF); // Program config. word 2

In der MPLAB-IDE kannst du die Konfiguration auch über ein Menü 
einstellen und diese wird dann mit in das Hex-File übernommen.
Configur ->> Configuration Bits.....und das Häckchen bei "Configuration 
bits set in code" rausnehmen wenn du die Einstellung dort vornimmst!

In MPLABX kann man sich einen Sourcecode mit den Config-Einstellungen 
erzeugen lassen und diesen in den eigenen Sourcecode reinkopieren (oder 
so ähnlich habe ich da in Erinnerung)

Wie du deinen Chip genau Konfiguriert haben willst, weisst du selbst.

von Oliver K. (ollik)


Lesenswert?

Ok danke!

So jetzt funktioniert es! DANKE an alle für die Hilfe!

Oliver K.

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.