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.
Er ist definitiv im sleep mode der Controller verbraucht nur noch 176uA @3V (gemessen). Im normal Zustand verbraucht er 275uA @3V
1 | do
|
2 | {
|
3 | SLEEP(); |
4 | NOP(); |
5 | NOP(); |
6 | }while(1); |
Wenn ich beim ersten NOP() einen breakpoint setze, kommt er nicht an. Sprich er geht auf direktem wege in den sleep mode.
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 ;)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.