Forum: Mikrocontroller und Digitale Elektronik PIC24F aus dem SLEEP aufwecken


von andi (Gast)


Lesenswert?

Hallo Leute,

ich versuche seit Tagen den PIC24FJ16GA004 per SLEEP-Befehl schlafen zu 
legen und dann per UART-Interrupt wieder aufzuwecken. Ohne SLEEP 
funktioniert alles wunderber, wenn ich den SLEEP-Befehl einfüge, dann 
geht der PIC schlafen und läßt sich nicht mehr aufwecken, obwohl er 
Daten von außen bekommt. Weiß da jemand einen Trick? Mit Errata kam ich 
nicht weiter. Das Einzige, was funktioniert, wenn der Watchdog aktiviert 
ist und im Sleep-Modus überläuft, dann wacht der PIC auf.

Gruß
Andy

von Zwirbeljupp (Gast)


Lesenswert?

Du solltest Dir unbedingt mal das Kapitel 21.11 im Family Reference 
Manual anschauen - da offensichtlich noch nicht getan.

Ich zitieren: "The UART does not function in Sleep mode."

Ist ja auch logisch, da im Sleep üblicherweise die Taktquelle 
abgeschaltet ist, die für die Funktion der UART nun einmal nötig ist.

Allerdings gibt es ein Auto-Wake-up Feature. Möglicherweise ist das eine 
Option für Dich.

von andi (Gast)


Lesenswert?

diesen Umstand kenne ich. Beim UART ist der Receive/Transmit-Interrupt 
aktiviert, der den PIC aufwecken sollte. Ohne den Sleep-Modus 
funktionieren alle Interrupts so wie sie sollten. Ich habe auch den 
Idle-Modus ausprobiert, mit gleichem Ergebnis. Aus irgendeinem Grund 
kann der UART-Receive-Interrupt den PIC nicht aufwecken.

von Zwirbeljupp (Gast)


Lesenswert?

Ich frage mich gerade, warum ich hier meine Zeit investiere, um Dir zu 
helfen. Es ist mal wieder typisch: es werden zwei Zeilen hingetipt und 
dann darf man hier erst einmal herumorakeln und dem TE mühsam die 
Details aus der Nase ziehen, die er einfach eingangs hätte hinschreiben 
können. Ein paar Zeilen Code zu kopieren und hier einzufügen ist doch 
auch keine unlösbare Aufgabe?

Es gibt haufenweise mögliche Gründe, warum das so mit dem Wakeup nicht 
funktioniert. Z.B. an falsch gesetzten CPU- oder Interrupt-Prioritäten. 
Einfach zu testen, indem Du den PIC durch andere Interrupts mit 
identisch eingestellten Prioritäten versuchst aufzuwecken. DAS würde ich 
als erstes Testen.

Um den PIC per USART aufzuwecken, muss das Prozedere von Section 21.11.1 
eingehalten werden. Setzt Du das WAKE-Bit vorm Schlafengehen? Schickst 
Du tatsächlich ein Sync Break als Wakeup-Signal? Wenn nein: tja dann 
klappt das halt auch nicht.

von andi (Gast)


Lesenswert?

tut mir leid, hast ja recht


1
void UART1_Init(void)
2
{
3
  IPC2bits.U1RXIP = 4;
4
  IPC3bits.U1TXIP = 4;
5
  
6
  // UART konfigurieren:
7
  // Baudrate (aufgerundet) einstellen
8
  U1BRG = (unsigned int)((((unsigned long)FCY + ((4*(unsigned long)BAUDRATE)/2)) / (4*(unsigned long)BAUDRATE)) - 1);
9
  // Modus: enable, stop in idle mode, use only U2TX and U2RX, 8-N, 1 stop bit
10
  // U1MODE = (1 << 15) | (1 << 13) | (0 << 8) | (0 << 1) | (0 << 0);
11
  U1MODE = (1 << 15);
12
  
13
  U1MODEbits.BRGH  = 1;
14
  
15
  // Status: irq when tx done, transmit enable, irq when rx done
16
  U1STA = (1 << 10);
17
18
  // TX-Interrupt-Flag löschen (wird durch Initialisierung ausgelöst)
19
  IFS0bits.U1TXIF = 0;
20
21
  // Interrupts aktivieren
22
  IEC0bits.U1TXIE = 1;  // TX
23
  IEC0bits.U1RXIE = 1;  // RX
24
}
25
26
27
void hardwareInit(void)
28
{
29
  //Oszillator initialisieren 
30
  
31
  OSCCON  = 0x0000;
32
  
33
  OSCCONbits.COSC0 = 1;  //Interner FRC mit Postscaler (FRCDIV) ist eingestellt.
34
  OSCCONbits.COSC1 = 1;
35
  OSCCONbits.COSC2 = 1;  
36
  
37
  OSCCONbits.SOSCEN = 0;  //Secondary Oscillator deaktiviert.
38
  
39
  CLKDIV   = 0x0000;     
40
  
41
  CLKDIVbits.RCDIV0 = 0;  
42
  CLKDIVbits.RCDIV1 = 1;
43
  CLKDIVbits.RCDIV2 = 0;
44
45
  //PPS initialisieren
46
47
    
48
  //*************************************************************
49
  // Unlock Registers
50
  //*************************************************************
51
  __builtin_write_OSCCONL(OSCCON & 0xbf); //clear the bit 6 of OSCCONL to
52
  //unlock Pin Re-map
53
  //******************************************************************
54
55
  //************************************************************
56
  // Configure Input Functions
57
  //************************************************************
58
  //
59
  // Zuweisen U1Rx zu Pin RP15
60
  RPINR18bits.U1RXR = 15;
61
62
  // #ifdef DEBUG
63
    // Zuweisen U2Rx zu Pin RP11
64
    RPINR19bits.U2RXR = 11;
65
  // #endif
66
  
67
  //************************************************************
68
  // Configure Output Functions
69
  //************************************************************
70
  //
71
  // Zuweisen U1Tx zu Pin RP13
72
  //***************************
73
  RPOR6bits.RP13R = 3; 
74
75
  // #ifdef DEBUG
76
    // Zuweisen U2TX zu Pin RP10
77
    RPOR5bits.RP10R = 5; 
78
  // #endif
79
80
  // Zuweisen OC1 zu Pin RP21
81
  RPOR10bits.RP21R = 18;
82
  
83
  //************************************************************
84
  // Lock Registers
85
  //************************************************************
86
  __builtin_write_OSCCONL(OSCCON | 0x40); //set the bit 6 of OSCCONL to
87
  //lock Pin Re-map
88
  //******************************************************************
89
90
  
91
  //PORTs initialisieren
92
  
93
  TRISA  = (1<<0)    //RA0,RA1,RA7 sind Eingänge, RA8-RA10 sind Ausgänge
94
      | (1<<1)
95
      | (1<<7)
96
      ;
97
  TRISB  = (1<<0)    //RB0,RB1,RB2,RB3,RB11,RB12,RB15 sind Eingänge
98
      | (1<<1)    
99
      | (1<<2)
100
      | (1<<3)
101
      | (1<<11)   
102
      | (1<<12)
103
      | (1<<15)    
104
      ;
105
  
106
  TRISC  = (1<<0)    //RC0,RC1,RC2 sind Eingänge
107
      | (1<<1)
108
      | (1<<2)
109
      ;  
110
      
111
  AD1PCFG  = 0xFFFF;    //Alle Portpins erstmal digitale I/Os
112
  
113
  LATA  = 0x0000;
114
  LATB  = 0x0000;
115
  LATC  = 0x0000;
116
}
117
118
119
120
// JTAG | Code Protect | Write Protect | Background Debugger | Clip-on Emulation mode
121
// ICD pins select | Watchdog Timer | Windowed WDT | Watchdog prescaler | Watchdog postscale)
122
_CONFIG1(JTAGEN_OFF & GCP_OFF & GWRP_OFF & BKBUG_OFF & COE_OFF & ICS_PGx2 & FWDTEN_OFF & WINDIS_OFF & FWPSA_PR32 & WDTPS_PS4096) 
123
// Two Speed Start-up | Secondary Oscillator | Voltage Regulator Standby-mode Wake-up Timer
124
// Oscillator Selection | Clock switching and clock monitor | OSCO/RC15 function
125
// RP Register Protection | I2C1 pins Select | Oscillator Selection)
126
_CONFIG2(IESO_ON & SOSCSEL_SOSC & WUTSEL_LEG & FNOSC_FRCDIV & FCKSM_CSDCMD & OSCIOFNC_ON & IOL1WAY_OFF & I2C1SEL_PRI & POSCMOD_NONE)
127
128
129
130
int main(void)
131
{
132
   EnableWDT(WDT_ENABLE);  //Watchdog-Timer per Software (SWDTEN) aktivieren. 
133
   hardwareInit();
134
   ...
135
  
136
  while(1)
137
  {
138
    ClrWdt();
139
    
140
    ...  
141
142
    //EnableWDT(WDT_DISABLE);
143
  U1MODE |= (1 << 7);    //Set WAKE-Bit für UART1
144
    Sleep();
145
    
146
  }
147
    
148
}

von andi (Gast)


Lesenswert?

Ich benutze den 2en UART, um Debug/Statusmeldungen auszugeben. Wenn ich 
disen UART initialisiere und eine kleine Zeichenkette ausgeben lasse, 
dann funktioniert das Aufwecken aus dem Sleep. Dieser Uart ist ohne 
Interrupts aufgesetzt.

von Zwirbeljupp (Gast)


Lesenswert?

andi schrieb:
> Ich benutze den 2en UART, um Debug/Statusmeldungen auszugeben. Wenn ich
> disen UART initialisiere und eine kleine Zeichenkette ausgeben lasse,
> dann funktioniert das Aufwecken aus dem Sleep. Dieser Uart ist ohne
> Interrupts aufgesetzt.

Äh, da kann ich nicht ganz folgen. Wie kannst Du denn mit der zweiten 
UART eine Zeichenkette versenden, während der PIC schläft?

Und nochmal die wichtige Frage: klappt das Aufwecken durch einen anderen 
Interrupt, z.B. einen INT_EXT?

von andi (Gast)


Lesenswert?

Die Zeichenkette verschicke ich kurz davor und wenn ich dann den PIC 
schlafen lege, dann wacht er auch wie erwartet auf, nur halt wenn ich 
diese Debug-Ausgabe abstelle, dann  geht das Aufwecken nicht mehr.

Einen anderen Interrupt habe ich noch nicht probiert, weil ich so auf 
das eigentliche UART-Interrupt fixiert war, werde ich aber machen.

andi

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.