I'm trying to build a power controller for a battery operated device. I choose PIC12F675. The idea is putting pic in sleep mode. Wake it up with Watchdod timer approx each second. Check pin states, decide whether to switch on or off. The decision code is working as expected. But PIC does not sleep. It looks like PIC skips SLEEP() macro. Before asking this question i've made a deep research and tested everything I found. So here are the configuration:
---------- Vdd |1 8| GND/VSS Dock test pin(out) GP5 |2 7| GP0 (in) Batt Measure Power Fet Drive(out)GP4 |3 6| GP1 (in) Batt Measure reference voltage Charge Status (in) GP3 |4 5| GP2 (in) Dock sense ---------- All pins are io. No external crystal, no reset. No floating pin.
I do not observe any sleep condition, also no reset condition.
The question is what am i doing wrong that the PIC12F675 is not sleeping?
Programing platform: MPLABX + XC8 (Latest version-Free) + pickit3 Config.h
#pragma config FOSC = INTRCIO // Oscillator Selection bits (INTOSC oscillator: I/O function on GP4/OSC2/CLKOUT pin, I/O function on GP5/OSC1/CLKIN) #pragma config WDTE = ON // Watchdog Timer Enable bit (WDT enabled) #pragma config PWRTE = ON // Power-Up Timer Enable bit (PWRT enabled) #pragma config MCLRE = OFF // GP3/MCLR pin function select (GP3/MCLR pin function is digital I/O, MCLR internally tied to VDD) #pragma config BOREN = ON // Brown-out Detect Enable bit (BOD enabled) #pragma config CP = OFF // Code Protection bit (Program Memory code protection is disabled) #pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled) #define _XTAL_FREQ 4000000 // this is used by the __delay_ms(xx) and __delay_us(xx) functions main.c
unsigned int Read_ADC_Value(void) { unsigned int ADCValue; ADCON0bits.GO = 1; // start conversion while (ADCON0bits.GO); // wait for conversion to finish ADCValue = ADRESH << 8; // get the 2 msbs of the result and rotate 8 bits to the left ADCValue = ADCValue + ADRESL; // now add the low 8 bits of the resut into our return variable return (ADCValue); // return the 10bit result in a single variable } unsigned int Check_Dock() { GPIO5 = HIGH; __delay_ms(5); unsigned int result = GPIO2; GPIO5 = LOW; return result; } unsigned int Read_Batt(){ unsigned int adc=Read_ADC_Value(); float voltage = ADCSTEP * adc * 200.0; return (unsigned int)(voltage); } void main(void) { //Configure Watchdog to approx 1 sec CLRWDT(); OPTION_REGbits.PSA = 1; //postscaler is for wdt OPTION_REGbits.PS = 0x110; //postscaler 1:64 OPTION_REGbits.nGPPU = 0; //pullups enabled WPU = 0xff; //enable pullups TRISIObits.TRISIO0 = INPUT; //AN0-GPIO0 - input - analog okuma için pil değeri. TRISIObits.TRISIO1 = INPUT; //AN1 -Vref ANS2=0; TRISIObits.TRISIO2 = INPUT; //GP2 <- Dock sense low=docked high=undocked ANS3=0; TRISIObits.TRISIO3 = INPUT; //Charge Status -> GP3 TRISIObits.TRISIO4 = INPUT; TRISIObits.TRISIO5 = OUTPUT; //Dock test pin <- GP5 GPIO5 = LOW; //do not output anything //Setup analog ANSELbits.ANS0 = INPUT; //analog input 0 is used ADCON0bits.ADON = 1; //adc is on ADCON0bits.CHS = 0x00; //an0 is tied to the sampler ADCON0bits.VCFG = 1; //1=>use vRref pin as voltage reference, 0=> use vdd ADCON0bits.ADFM = 0x01; //ADC results are right-justifed ANSELbits.ADCS = 0x011; //Conversion clock = FRC internal: measurement can take till 6usec INTCON = 0; //disable every interrupt PIE1=0; PIR1=0; INTCONbits.GIE = 0; //Program Loop while (1) { SLEEP(); NOP(); INTCONbits.GPIF=0; unsigned char sta = 0; if(Read_Batt() <= BATTLOWTHRESHOLD){ //Batt low turn everything off sta++; } unsigned int isCharging = GPIO3; //0:not charging; 1: charging; sta+=isCharging; unsigned int isnotDocked = Check_Dock(); if(isnotDocked) { //0:docked; 1:flying NOP(); }else{ sta++; } if(sta) { //disable fet TRISIObits.TRISIO4 = INPUT; WPU4=1; //enable port pullup } else { TRISIObits.TRISIO4 = OUTPUT; GPIO4 = LOW; //enable fet } }//End of: Main loop }