Hallo zusammen
Ich habe gerade ein Projekt am laufen. Folgendes: An meinem PIC 16F946
ist ein RTC Quarz mit 32.768kHz über T1OSO/RA6 und T1OSI/RA7
angeschlossen.
Über den Timer1 lasse ich jede Sekunde einen Interrupt aufrufen, wo er
jeweils eine Sekunde hinaufzählt. Die ganze Sache wird danach auf ein
7Segment LCD ausgegeben. Da das Gerät Batteriebetrieben ist würde ich
den PIC gerne in den sleep mode setzen wenn nichts zu verarbeiten ist.
(Stromsparen).
Mein Problem ist nun das der PIC über den Interrupt nicht mehr aufweckt.
Alle nötigen Interrupt Bits sind gesetz.
Anbei, die ganze Firmware funktioniert einwandfrei mit dem Timer1
Interrupt, nur eben nicht mit dem sleep mode.
Hat jemand schon ein ähnliches Problem gehabt?
Ich weiß jetzt nicht genau, woran es liegen könnte. Was mir in den Sinn
kam:
Vielleicht ist ja die Interrupt-Routine noch nicht vorbei, wenn der
nächste kommt. Also dass da irgendwo zu lange gewartet wird. Ansich soll
ja ein Interrupt-Routine so schnell wie möglich beendet werden.
Was mir noch aufgefallen ist:
1
if(min_high>5)
2
{
3
min_low=0;
4
hour_low++;
5
}
6
if(min_low>9)
7
{
8
min_low=0;
9
min_high++;
10
}
das min_low wurde doch kurz vorher schon geprüft. Muss das dann hier
nicht hour_low sein? Das wird nämlich noch nirgends auf > 9 geprüft.
Danke für den Hinweis. Du hast recht ich hatte zweimal das gleiche
abgefragt.
1
if(min_high>5)
2
{
3
min_high=0;
4
hour_low++;
5
}
6
if(hour_low>9)
7
{
8
hour_low=0;
9
hour_high++;
10
}
Ich schreibe jetzt ein kurzes Programm mit wenig Code und schaue ob dies
evtl. einen Einfluss auf den Interrupt hat. Vlt. ist es schon von der
Grösse des Codes abhängig.
mach mal hinter //SLEEP(); noch 2x NOP: wenn ein PIC in den SLEEP geht,
dann ist der nächste Befehl nach dem SLEEP schon im Kern und es kommt
(allerdings sehr selten) vor, dass dieser Befehl dann nicht ausgeführt
wird.
BTW: Das Programm ist für den 16F887 statt für den 16F946 geschrieben.
Und lass den 32768-Quarz am Oszillator des Timer1 laufen statt am
Hauptsoszillator. Schalte den interene Oszillator ein (z.B. mit 4 MHz),
sonst kommst Du mit dem abarbeiten Deiner ISR nicht rum.
Du hast da eine Fliesskommaarithmetik in der ISR (!) drin
1
temp=((adc_value*0.0024414)/0.023);
Die wird bei 32.768 nie fertig, kaum setzt Du im Interrupt TMR1IE = 1
(danach kommt ja noch einiges wie time_calculation und put_display) ist
schon der nächste Interrupt da (und Du bist aus dem vorherigen noch gar
nicht draussen).
Deine ISR ist viel zu lang und der µC viel zu langsam getaktet.
tt2t schrieb:> BTW: Das Programm ist für den 16F887 statt für den 16F946 geschrieben.
Stimmt, hatte ich vergessen umzuschreiben ist eh auskommentiert ;)
tt2t schrieb:> Schalte den interene Oszillator ein (z.B. mit 4 MHz),> sonst kommst Du mit dem abarbeiten Deiner ISR nicht rum.
Es ist mir klar dass das ganze System langsam läuft. Ohne den sleep hat
er ja genügend Zeit alles abzuarbeiten, zeigt einwandfrei aufs LCD an.
Die Zeit ist acuh genau. Braucht die sleep Funktion zusätzliche
Geschwindigkeit?
Danke
Datenblatt 16F946 Page 259 (für den 16F887 sind es wenige µA mehr):
Bei 3 Volt sind 176 µA für SLEEP viel zu viel, das dürften höchstens 6-8
µA sein, typisch wären nur 2-3 µA! Also kein SLEEP! Auch wenn der µC
nicht im SLEEP ist, düfte er bei 3 Volt nur etwa 20-25 µA verbrauchen.
Ich habe mal etwas genauer in Dein Programm geguckt.
Im SLEEP geht der Haupt-Oszillator aus, Dein Timer1 läuft also nicht
weiter, weil Du den Takt für Timer1 aus dem Haupt-Oszillator holst und
der PIC wacht nie mehr auf. Häng den Quarz an Timer1 (der hat einen
eigenen Oszillator) und betreibe den µC sonst aus dem internen
Oszillator.
tt2t schrieb:> Ich habe mal etwas genauer in Dein Programm geguckt.>> Im SLEEP geht der Haupt-Oszillator aus, Dein Timer1 läuft also nicht> weiter, weil Du den Takt für Timer1 aus dem Haupt-Oszillator holst und> der PIC wacht nie mehr auf. Häng den Quarz an Timer1 (der hat einen> eigenen Oszillator) und betreibe den µC sonst aus dem internen> Oszillator.
Oke, vielen Dank für deine wertvollen Tipps. Sind alles Sachen an die
ich nicht gedacht habe(Geschwindigkeit). Bei der Stommessung war das LCD
und der Debugger ICD3 auch noch dabei, daher der höhere Verbrauch.
Also kann ich den Quartz einfach auf den PIN RC5/T1CKI/CCP1/SEG10 und
RA6/OSC2/CLKO/T1OSO verbinden? Intern natürrlich als Systemtakt nehmen
(4MHz)
Quarz und 2 Last-C an T1OSI und T1OSO (=RA6 und RA7), T1OSCEN setzen,
TMR1ON setzen, TMR1CS setzen, ggf. TMR1GE (meist nicht), ggf. T1SYNC
(meist nicht), ggf. Prescaler, internen Oscillator einstellen, bei den
CONFIG-Bits INTOSC bzw. INTOSCIO setzen, den Rest hast Du schon gemacht
(schau Dir die Bits/Register im Datenblatt Page 102 ff an).
tt2t schrieb:> Quarz und 2 Last-C an T1OSI und T1OSO (=RA6 und RA7), T1OSCEN setzen,> TMR1ON setzen, TMR1CS setzen, ggf. TMR1GE (meist nicht), ggf. T1SYNC> (meist nicht), ggf. Prescaler, internen Oscillator einstellen, bei den> CONFIG-Bits INTOSC bzw. INTOSCIO setzen, den Rest hast Du schon gemacht> (schau Dir die Bits/Register im Datenblatt Page 102 ff an).
Hallo
Ist zwar schon eine Weile her, doch der Code funktioniert nun mit SLEEP
mode einwandfrei..
Evtl. kann jemand den Code gebrauchen ;)