Forum: Mikrocontroller und Digitale Elektronik Timer1 weckt nicht den PIC2LF1840 vom SLEEP()


von skorpionx (Gast)


Angehängte Dateien:

Lesenswert?

Hat jemand eine Idee...?

von skorpionx (Gast)


Lesenswert?

PIC12LF1840...

von Norbert S. (pianoforte)


Lesenswert?

Also ich nutze den das MPLAB X IDE V3.45 und dazu den XC8 Compiler
Und schreibe dann die Interrupts so :
1
void interrupt high_priority ISRH(void){
2
 
3
   // Overflow von Timer_0 ?
4
   if (INTCONbits.TMR0IF){
5
6
      //.... mache was ..... wenn Timer 0 Overflow ausgelöst hat 
7
      
8
   INTCONbits.TMR0IF=0;
9
   }
10
   
11
}

und die define sind auch sehr unleserlich
entweder man definiert es hexdezimal oder mit 1<<x
Bsp.
1
#define T1_ON 0x04
2
3
oder ...
4
5
#define T2_ON 1<<4

3.
Und kommt der SLEEP() Befehl nicht in die "main" ?
Der PIC muss die ISR sauber verlassen und dann darf er schlafen geht, 
bin ich der Meinung.

Ich benutze den PIC18F25K22, aber es sollte so ähnlich sein.
das sollten Sie an ihrem Programm mal überprüfen.
ggf. mal ins Datenblatt schauen !

Mfg

: Bearbeitet durch User
von Klaus (Gast)


Lesenswert?

Ich verstehe die ganzen #defines überhaupt nicht. Wenn der richtige 
Prozessor im Projekt gesetzt ist, erledigt xc.h das alles automatisch. 
Da kommt im eigenen Code so etwas gar nicht vor. Und da ist dann auch 
sichergestellt, daß man ohne Compilerfehler nur SFRs bzw Bits benutzen 
kann, die auf diesem Prozessor auch existieren.

Aber auch diese leuchtet mir nicht ein:

> TMR1H = 0x10000000;

TMR1H wird ja wohl kein 32 Bit Register sein.

MfG Klaus

von skorpionx (Gast)


Lesenswert?

Klaus schrieb:
>> TMR1H = 0x10000000;

Ja. Es sollte sein: TMR1H = 0b10000000;

von skorpionx (Gast)


Lesenswert?

Norbert S. schrieb:
> Und kommt der SLEEP() Befehl nicht in die "main" ?

Ich habe alles ausprobiert. Darum diese Variable InterruptDa.

von skorpionx (Gast)


Lesenswert?

Timer1 läuft mit dem externer  32768Hz Quarzoszillator. Diese
TMR1H = 0b10000000; ist dazu um Interruptintervall auf 1 Sekunde zu 
Stellen (ohne das sind das 2 Sekunden). System Clock ist auf  interne 
Oszillator mit  4Mhz gesetzt. Timer1 läuft und externer Signal von 
32768Hz ist ständig da (Oszilloskop...) auch nach dem SLEEP();
Was muss ich machen um den PIC aufwecken? Muss ich vielleicht den
Watchdog aktivieren?

von Hurra (Gast)


Lesenswert?

skorpionx schrieb:
> Timer1 läuft mit dem externer  32768Hz Quarzoszillator. Diese
> TMR1H = 0b10000000; ist dazu um Interruptintervall auf 1 Sekunde zu
> Stellen (ohne das sind das 2 Sekunden). System Clock ist auf  interne
> Oszillator mit  4Mhz gesetzt. Timer1 läuft und externer Signal von
> 32768Hz ist ständig da (Oszilloskop...) auch nach dem SLEEP();
> Was muss ich machen um den PIC aufwecken? Muss ich vielleicht den
> Watchdog aktivieren?

Die Defines sind derartig schwierig zu lesen, sorry, das tu ich mir 
nicht an.

Norbert S. hat eh schon hingeschrieben, wies geht.

Also:
Jedes Register kannst du einfach beschreiben mit z.B.
T1CONbits.TON = 1; und so weiter.

Da gibts einen Header von Microchip, der automatisch inkludiert ist, 
sobald du xc.h einbindest. Da hat Mircohip für jedes einzelne Register 
Bitfelder deklariert, die <Registername>bits heißen. Und das passt genau 
zu deinem PIC, für jedes gibts einen eigenen Header, es wird automatisch 
der für deinen verwendet.
Dabei gilt: Registername im Datenblatt = Registername im Header. Wodurch 
du die entsprechende Sektion im Datenblatt nur aptippen musst.

Das ist viel weniger fehleranfällig, weil die nötigen defines 
üblicherweise stimmen.

Was beim Timer der Fehler sein kann:
- IE-Flag nicht gesetzt
- Interrupt Priorität auf 7
- TON-Bit des Timers nicht gesetzt
- Timer-Register falsch beschrieben
usw usf.

Wirf doch auch mal den Debugger an, tu einen Breakpoint in main und 
schau dir die ganzen Bits an.

von skorpionx (Gast)


Lesenswert?

Hurra schrieb:
> Das ist viel weniger fehleranfällig, weil die nötigen defines
> üblicherweise stimmen.

Hurra schrieb:
> Interrupt Priorität auf 7

Ich arbeite mit PdfDoku. Suche ich entsprechende Register und kopiere 
ich einzelne Kommentare (die sind für mich wichtig). Das mit Bits und 
Schieberei wird alles durch Präprozessor erledigt. Im Programm wird das 
alles mit einer Zuweisung erledigt, anders als bei einzelnen Zuweisungen 
(z.B.  T1CONbits.TON = 1;) .Dadurch wird auch kleinere Code generiert.
Aber das ist Nebensache.
Leider habe ich noch keine Lösung gefunden. Alle deine Vorschläge
sind schon im Programm. Nur diese Sache mit dem „Interrupt Priorität“ 
verstehe ich nicht. Im Doku habe ich nichts davon gefunden.

von Hurra (Gast)


Lesenswert?

skorpionx schrieb:
> Hurra schrieb:
>> Das ist viel weniger fehleranfällig, weil die nötigen defines
>> üblicherweise stimmen.
>
> Hurra schrieb:
>> Interrupt Priorität auf 7
>
> Ich arbeite mit PdfDoku. Suche ich entsprechende Register und kopiere
> ich einzelne Kommentare (die sind für mich wichtig). Das mit Bits und
> Schieberei wird alles durch Präprozessor erledigt. Im Programm wird das
> alles mit einer Zuweisung erledigt, anders als bei einzelnen Zuweisungen
> (z.B.  T1CONbits.TON = 1;) .Dadurch wird auch kleinere Code generiert.
> Aber das ist Nebensache.
> Leider habe ich noch keine Lösung gefunden. Alle deine Vorschläge
> sind schon im Programm. Nur diese Sache mit dem „Interrupt Priorität“
> verstehe ich nicht. Im Doku habe ich nichts davon gefunden.

Wenn nur die Sache mit dem schnelleren Code wichtig ist, dann kopier dir 
doch die Bitfelder aus dem Header und mache eine Konstante draus.
Der Compiler müsste dass dann die Register in einer einzelnen Zuweisung 
schreiben. Möglich ist auch, dass der Compiler ohnehin alle 
zusammenfasst.

Bei einer Initroutine wäre mir die Laufzeit allerdings egal. Das läuft 
sowieso nur ein einziges mal ab.

Ich würde mal einen Breakpoint vor das sleep setzen und prüfen:
- Ist der Interrupt ein?
- Passt die Priorität?
- ist der Timer an?
- Inkrementiert der Timer wirklich?
- Ist das Resetregister WIRKLICH das was du reingeschrieben hast?
- Passt die clocksource für den Timer?
- Ist Timer 1 auch wirklich eine wakeup-source?

Du hast schon sleep und nicht deep-sleep? Das ist ein wichtiger 
Unterschied, was die wakeup-Sources angeht.

Ja, Debuggen mit 32kHz ist unlustig. Aber es geht. Ich habe bei einem 
ähnlichen Projekt (Temperaturanzeige) nebenbei Witcher 3 gespielt. Bis 
der Brakepoint triggert und die Variablen im Watch geladen sind, kann 
man bequem ein paar Quests machen...

Eine gute Methode ist auch, den ganzen Code zunächst mal mit dem FRC zu 
testen. Das geht deutlich flotter.

von Johannes R. (oa625)


Lesenswert?

Wo wird GIE gesetzt?
Ich sehe nur ein #define (bin aber auch kein C-Nutzer).

Gruß
J.R.

von chris (Gast)


Lesenswert?

Defined sind falsch, teilweise mehr als 8 Bit.
Diese Defines sind horrend, sollte ein anderer Prozessor verwendet 
werden, oder auch zwei von derselben Source.

von skorpionx (Gast)


Lesenswert?

Hurra schrieb:
> Ist Timer 1 auch wirklich eine wakeup-source?

Und das ist die Frage...Timer1 läuft zwar im SLEEP() aber  ob der 
Überlauf weckt auf den PIC, das bin ich nicht sicher...

von BeastyK (Gast)


Lesenswert?

Moin Leute,
einen schönen zweiten Weihnachtstage!

Ich schiesse nur ins Blaue rein, ohne Datenblatt, und erinner mich bei 
anderen PICs ganz dunkel daran das man einen externen Oszi braucht.
Check das doch mal ab.

Best wishes
dat
Beast

von Stefan (Gast)


Angehängte Dateien:

Lesenswert?

Ob dein Programm läuft oder nicht, sollte
man zuerst einmal die Hardware überprüfen.
Hier mal ein kleines Programm, welches eine LED an
PORT A0 blinken läßt. Der Controller läuft mit 4MHz
internen Takt und an RA4 und RA5 ist ein 32768 KHz
Quarz dran. Das Programm ist nach dem Start im Sleep Modus,
LED leuchtet. Nach einer Zeit wird durch den Timer1, der
Sleep Modus beendet und die LED geht aus. Und dann wieder
von vorne.
Probiere es mal aus und wenn es nicht
läuft dann stimmt was nicht mit deiner Hardware.

von pic (Gast)


Lesenswert?

Hw wird
 schon gehen.
Es gibt mehrere Fehler. Wahrscheinlich Arduino Generation. Datenblatt, 
das sieht man sich nicht an, Programmierung ad absurdum mit fehlerhaftem 
Programmcode.

Fehler Nr 1
Timer1 läuft mit internem clock.
Fehler Nr 2
Timer1 clock wird mit internem clock synchronisiert.

Beide Fehler bewirken auch einzeln dass Timer1 im Sleep nicht 
weiterzählt.

Fehler Nr 3,
Sleep im Interrupt.
Dabei ist GIE off, sprich der Prozessor kann nur durch ein WDT oder 
Reset/BOR aufgeweckt werden.
Eventuell geht es doch durch ein Bug im Sleep modus, sollte ein retfie 
direkt nach dem Sleep Befehl stehen, man muss aber das Programm 
disassrmblieren oder sich den ASM Code ansehen und auch da ist es nicht 
sicher ob es funktioniert, habe mir diesen Bug nie besonders genau 
angesehen, immer nur den workaround verwendet wenn nötig.

von Hurra (Gast)


Lesenswert?

pic schrieb:
> Hw wird
>  schon gehen.
> Es gibt mehrere Fehler. Wahrscheinlich Arduino Generation. Datenblatt,
> das sieht man sich nicht an, Programmierung ad absurdum mit fehlerhaftem
> Programmcode.

Also ich kann jetzt nur von mir spechen, aber ein längeres fehlerfreies 
Programm habe ICH noch nie eingetippt. Nicht auf Anhieb.

Tippst du ausschließlich fehlerfreien Code ein?
Wie schaffst du das?

von pic (Gast)


Lesenswert?

Arduino Generation:
Kopieren soviel code wie möglich.
Lies niemals das Datenblatt.
Wenn es nicht funktioniert, lass andere möglichst in diversen Foren dein 
Problem suchen und beheben.

Wenn der TO die Kopiererei nicht so verteidigt hätte, hatte ich es nicht 
so geschrieben. Auch ist er nicht auf deine konstruktiven Ansätze 
eingegangen. Wenn im Datenblatt nicht extra ein Kapitel wäre, was zu 
beachten ist dass der Timer1 im Sleep mit externem Quarz die CPU bei 
Uberlauf aufweckt, könnte man es ohne weiteres der Unerfahrenheit mit 
der Pic Architektur zuschreiben, aber ....

von skorpionx (Gast)


Angehängte Dateien:

Lesenswert?

Stefan schrieb:
> Probiere es mal aus und wenn es nicht

Es läuft! Wenn das kein Scherz (könntest du auch Source zeigen...)ist, 
dann habe ich mindestens Hoffnung.

von pic (Gast)


Lesenswert?

Wenn du TMR1CS (0b10<<7) aufTMR1CS (0b10<<6) anders sowie T1SYNC auf 1 
setzt und sleep vom Interrupt in die while schleife nach dem 
SleepZahler++; anderst, flag brauchst du keines, dann funktioniert dein 
code warscheinlich auch.

von Stefan (Gast)


Lesenswert?

Hört sich doch gut an. Dann liegt es nicht
an der Hardware. Hier das Programm dazu:
1
program test4
2
3
sub procedure Interrupt()
4
  if (TMR1IF_bit) then
5
    TMR1IF_bit = 0
6
    TMR1H         = 0x0f
7
    TMR1L         = 0x2C
8
  end if
9
end sub
10
11
12
sub procedure InitTimer1()
13
  T1CON         = %10001101
14
  TMR1IF_bit         = 0
15
  TMR1H         = 0x0f
16
  TMR1L         = 0x2C
17
  TMR1IE_bit         = 1
18
  INTCON         = 0xC0
19
20
end sub
21
22
main:
23
24
ANSELA = 0
25
PORTA = 0
26
LATA = 0
27
TRISA = 0
28
TRISA.4 = 1
29
TRISA.5 = 1
30
31
OSCCON = 104
32
InitTimer1
33
34
while True
35
   LATA.0 = 1
36
37
   sleep
38
   
39
   nop
40
   nop
41
   nop
42
 
43
   LATA.0 = 0
44
   delay_ms(3000)
45
46
wend
47
48
end.

von skorpionx (Gast)


Lesenswert?

Stefan schrieb:
> OSCCON = 104

Leider in deinem Programm hast du einen Fehler.

104 das ist 0b‭01101000‬. Du hast zwar mit Bit 6-3  1101 4MHz HF 
Internal Oscillator
gewählt aber durch Bit 1-0 hast du die Entscheidung an Configuration 
Word 1 übertragen:

bit 1-0 SCS<1:0>: System Clock Select bits
1x = Internal oscillator block
01 = Timer1 oscillator
00 = Clock determined by FOSC<2:0> in Configuration Word 1.

und dort muss du noch das beschreiben:
#pragma config FOSC =     // Oscillator Selection

oder statt  104 andere Zahl mit anderen zwei untersten Bit schreiben.
Ich kämpfe weiter.. Melde dich wenn du etwas neues hast...

von Stefan (Gast)


Lesenswert?

Nein da muß nichts geändert werden.
Im Compiler Menu wird der Controller auf den
internen Takt umgestellt. Damit ist das
FOSC<2:0> durch den Compiler gesetzt.

von skorpionx (Gast)


Lesenswert?

Stefan schrieb:
> FOSC<2:0> durch den Compiler gesetzt.

Was wird dann gesetzt?:

FOSC<2:0>: Oscillator Selection bits
111 = ECH: External Clock, High-Power mode (4-32 MHz):
      device clock supplied to CLKIN pin
110 = ECM: External Clock, Medium-Power mode (0.5-4 MHz):
      device clock supplied to CLKIN pin
101 = ECL: External Clock, Low-Power mode (0-0.5 MHz):
     device clock supplied to CLKIN pin
100 = INTOSC oscillator: I/O function on CLKIN pin
011 = EXTRC oscillator: External RC circuit connected
      to CLKIN pin
010 = HS oscillator: High-speed crystal/resonator
      connected between OSC1 and OSC2 pins
001 = XT oscillator: Crystal/resonator connected
      between OSC1 and OSC2 pins
000 = LP oscillator: Low-power crystal connected
      between OSC1 and OSC2 pins

Ich möchte weiter die sache untersuchen...

von Stefan (Gast)


Lesenswert?

Es wird das gesetzt was du im Compiler
ausgewählt hast. Bei meinem Programm was ich als
HEX Datei geschickt habe, wird das INTOSC gesetzt.

von Stefan (Gast)


Lesenswert?

Das mußt du natürlich in deinem Compiler auch setzen,
sonst läuft er nicht auf den internen Takt.
Standartmäßig ist es auf externen Takt gestellt.
Also in den Projekt Settings umstellen.

von skorpionx (Gast)


Angehängte Dateien:

Lesenswert?

Ichhabe zwischenzeitig eine Lösung gefunden.
Hauptänderungen:
#pragma config FOSC = XT   // Oscillator Selection (INTOSC
                              oscillator:     I/O function on CLKIN pin)
#define TMR1CS  (0b01<<7)  //Timer1 clock source is system clock (FOSC)

Systemclock hat jetzt dieser 32768 Hz. Wenig, aber für meine Zwecke(Uhr)
wird das  reichen. Vielleicht findet jemand noch eine besser Lösung.
Im SLEEP sieht man auf dem Oszi auch sehr kleine Amplitude vom
Oszillator.Es wird Strom gespart. Ich möchte dieser Uhr für meine 
Heizungsteuerung verwenden. Uhr setzen und auslesen über
Kommunikation durch I/O.

von Stefan (Gast)


Lesenswert?

Warum läßt du den Controller nicht mit
4 MHz intern laufen ? Und nimmst den
Quarz nur für den Timer 1, so wie ich
es gemacht habe ?

von skorpionx (Gast)


Lesenswert?

Stefan schrieb:
> Warum läßt du den Controller nicht mit
> 4 MHz intern laufen ?

Weill für diese Konstellation wurde meinen PIC nicht vom SLEEP 
aufgeweckt.
Prüfe noch dein Programm. Z.B. kann auch watchdog den SLEEP beenden. 
Diese
delay_ms(3000) ist für mich ein Rätsel. Und Frequenz vom Blinken stimmt 
auch nicht.

von Stefan (Gast)


Lesenswert?

Da mein Programm läuft, liegt der Fehler in deinem
Programm. Der  Timer 1 läuft mit 32768 KHz und der
Controller mit 4 MHz Takt. Da du weder das Compiler
Programm beherschst noch die Programmiersprache kannst, würde
ich dir empfehlen mit einem kleinen Programm an zu fangen,
damit du in die Materie rein kommst.
delay_ms(3000) bedeutet 3 Sekunden warten.

von skorpionx (Gast)


Lesenswert?

Stefan schrieb:
> Da mein Programm läuft

Kein Kommentar...

von skorpionx (Gast)


Lesenswert?

Haupt Problem war:
TMR1CS<1:0>: Timer1 Clock Source Select bits:
#define TMR1CS  (0b10<<7)  //Crystal oscillator on T1OSI/T1OSO pins

Nach dem ist das geändert habe auf:
#define TMR1CS  (0b01<<7)  //Timer1 clock source is system clock (FOSC)

läuft das alles. Wie sollte man die Beschreibung verstehen?. Aber
nur diese Option funktioniert mit SLEEP. Auch interne Frequenz kann man 
z.B. auf 4 Mhz setzen.

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.