Bonjour,
Je travaille sur un projet à base de PIC24EP512GU810 pour lequel j'ai besoin de gérer la consommation (grossomodo 95% du temps en veille), et réveil sur interruption (2 boutons poussoir + 1 UART).
En fonctionnement, j'utilise l'oscillateur interne sans PLL (FRC : COSC=0) ajusté à 8,00 MHz (OSCTUN à 23) soit une fréquence Fcy de 4 MHz pour les périphériques (3 SPI, 4 UART et 2 timers). J'aurai un autre mode pour l'USB si on décide d'utiliser le bus interne plutôt qu'un FTDI. J'ai donc prévu la possibilité de mettre un quartz externe au cas où mais pour le moment pas monté.
J'ai des LEDs (3 RVB + 3 Oranges) montées en groupe avec multiplexage et commande PWM, pas besoin d'entrer dans les détails c'est juste une question de consommation et d'optimisation des E/S du micro.
Pour le moment, j'utilise le Timer1 avec une période de 1ms pour faire clignoter les LEDs, avec une période de 1s (500ms ON, 500ms OFF).
Mon problème :
Le micro entre bien en mode Low-Power : passage sur l'oscillateur LPRC puis instruction Sleep(). Mais lorsque je génère une interruption (bouton poussoir) il met environ 4 secondes pour repasser sur l'oscillateur principal (FRC à 8 MHz).
Lorsque j'entre en veille, les LEDs sont éteintes, OK.
Lorsque je génère une interruption, les LEDs clignotent très lentement pendant 4 secondes (LPRC à 32 kHz), puis se mettent à clignoter à la bonne fréquence (passage sur FRC à 8 MHz).
Je ne comprends pas pourquoi il met 4 secondes à repasser sur le FRC...
Voici la configuration des fusibles :
voici mon main.c :Code:// FGS #pragma config GWRP = OFF // General Segment Write-Protect bit (General Segment may be written) #pragma config GSS = OFF // General Segment Code-Protect bit (General Segment Code protect is disabled) #pragma config GSSK = OFF // General Segment Key bits (General Segment Write Protection and Code Protection is Disabled) // FOSCSEL #pragma config FNOSC = FRC // Initial Oscillator Source Selection bits (Internal Fast RC (FRC)) #pragma config IESO = ON // Two-speed Oscillator Start-up Enable bit (Start up device with FRC, then switch to user-selected oscillator source) // FOSC #pragma config POSCMD = NONE // Primary Oscillator Mode Select bits (Primary Oscillator disabled) #pragma config OSCIOFNC = ON // OSC2 Pin Function bit (OSC2 is general purpose digital I/O pin) #pragma config IOL1WAY = OFF // Peripheral pin select configuration (Allow multiple reconfigurations) #pragma config FCKSM = CSECMD // Clock Switching Mode bits (Clock switching is enabled,Fail-safe Clock Monitor is disabled) // FWDT #pragma config WDTPOST = PS32768 // Watchdog Timer Postscaler bits (1:32,768) #pragma config WDTPRE = PR128 // Watchdog Timer Prescaler bit (1:128) #pragma config PLLKEN = OFF // PLL Lock Wait Enable bit (Clock switch will not wait for the PLL lock signal.) #pragma config WINDIS = OFF // Watchdog Timer Window Enable bit (Watchdog Timer in Non-Window mode) #pragma config FWDTEN = OFF // Watchdog Timer Enable bit (Watchdog timer enabled/disabled by user software) // FPOR #pragma config FPWRT = PWR128 // Power-on Reset Timer Value Select bits (128ms) #pragma config BOREN = ON // Brown-out Reset (BOR) Detection Enable bit (BOR is enabled) #pragma config ALTI2C1 = OFF // Alternate I2C pins for I2C1 (SDA1/SCK1 pins are selected as the I/O pins for I2C1) #pragma config ALTI2C2 = OFF // Alternate I2C pins for I2C2 (SDA2/SCK2 pins are selected as the I/O pins for I2C2) // FICD #pragma config ICS = PGD1 // ICD Communication Channel Select bits (Communicate on PGEC1 and PGED1) #pragma config RSTPRI = PF // Reset Target Vector Select bit (Device will obtain reset instruction from Primary flash) #pragma config JTAGEN = OFF // JTAG Enable bit (JTAG is disabled) // FAS #pragma config AWRP = OFF // Auxiliary Segment Write-protect bit (Aux Flash may be written) #pragma config APL = OFF // Auxiliary Segment Code-protect bit (Aux Flash Code protect is disabled) #pragma config APLK = OFF // Auxiliary Segment Key bits (Aux Flash Write Protection and Code Protection is Disabled) #include <xc.h>
voici les fonctions de l'oscillateur :Code:#include <xc.h> #include <stdio.h> #include <stdlib.h> #include "state_machine.h" int main(int argc, char** argv) { while(1) { switch (currentSystemState) { case HARDWARE_INIT_STATE: hardware_init(); currentSystemState = SYSTEM_INIT_STATE; break; case SYSTEM_INIT_STATE: system_init(); currentSystemState = SYSTEM_RUNNING_STATE; break; case SYSTEM_RUNNING_STATE: Blink_LEDs(); // Timer1 : 500ms blink period if(SW3_pressed == TRUE) activityTicks = 0; if(SW4_pressed == TRUE) activityTicks = 0; if(activityTicks > 5000) // Timer1 : activityTicks updated each 1ms, enter sleep after 5 second inactivity currentSystemState = ENTER_SYSTEM_SLEEP_STATE; break; case ENTER_SYSTEM_SLEEP_STATE: enterLowPowerClockMode(); // switch to LPRC currentSystemState = SYSTEM_SLEEP_STATE; break; case SYSTEM_SLEEP_STATE: Sleep(); // ASM Sleep instruction currentSystemState = SYSTEM_WAKE_STATE; // will be executed after a wake interrupt break; case SYSTEM_WAKE_STATE: activityTicks = 0; exitLowPowerClockMode(); // switch to FRC SW3_pressed = FALSE; SW4_pressed = FALSE; currentSystemState = SYSTEM_RUNNING_STATE; break; default: break; } } }
MerciCode:void oscillator_init (void) { RCONbits.SWDTEN = 0; // Disable Watch Dog Timer OSCTUN = 23; // FRC Tunning : Adjust FRC to 8.00 MHz } void enterLowPowerClockMode(void) { __builtin_write_OSCCONH(0x05); __builtin_write_OSCCONL(OSCCON | 0x01); while (OSCCONbits.OSWEN != 0); //while (OSCCONbits.COSC != 0x05); } void exitLowPowerClockMode(void) { __builtin_write_OSCCONH(0x00); __builtin_write_OSCCONL(OSCCON | 0x01); while (OSCCONbits.OSWEN != 0); //while (OSCCONbits.COSC != 0x00); }
-----