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
voidinterrupt()
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
voidwait_ms(inttime)
14
{
15
for(i=0;i<time;i++)
16
Delay_ms(1);
17
}
18
19
voidinit_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
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 :)
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.....
@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..
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
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...
@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?
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.
@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
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.
> 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 ;_)
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?
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.
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:
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....
;-)
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.
@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.