Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Power down data save to EEprom - PIC

Status
Not open for further replies.
I've used a trimpot instead of a fixed resistor for the lower part of the divider so that I can manually trip it without turning the power off, that way, when it trips I can see the LED stay on - worked fine this way in the previous two iterations before trying the FVR.

Probably should have mentioned that :banghead:

I can then move this on to doing actual power down tests by writing some miscellaneous stuff to EEprom.
 
A couple of things -

You should enable the FVR prior to setting up the comparator. Also, there is an FVR Stabilization Period (sec 14.2)
after enabling the FVR. I didn't see where that's called out in the 16F1827, but it's typically 30us (40us max) for most other devices.
Add a 40us delay loop before setting up the comparator.

I prefer to setup all the register settings before turning on the comparator (ie set CM2CON0.CxON=1 last).
You may get a stray INT when you first turn on the CM or change its settings.

If you enable C2OUT on RA4 you can monitor the CM output (clear RA4 TRIS, set CM2CON0.CxOE=1)

If you have an analog voltage on RA2 you may want to leave ANSELA set to analog for that pin.
 
I have seen the FVR start up mentioned but no actual time frame that I could find (the electrical specs only give % error for FVR) and also that there is a flag that is set when it's ready, but the 16F1827 datasheet has so many errors it's not funny and of course it says in the datasheet said flag is permanently set which doesn't help.

I'll rearrange the software and see what happens.

I did the CM out (RA4) monitoring in the previous incarnation of that software (dividers on both CM inputs) and purposely moved the LED to another pin so I know that it is the interrupt turning it on.

No analog voltage on RA2 at this stage.
 
Thank you Tumbleweed, that got it all working.

Just in case anybody is following or comes across this particular bit about Comparators, I have tidied up the test code a little bit and added some notes at the top :-

C-like:
; *******************************************************************************
;            comparator-16F1827.asm
;
;                NOTES
;    RA3 input = Junction of resistive divider 10k in series with 5k trimpot.
;            free end of 10k to +V, connect wiper to one end of 5k trimpot
;            and connect to GND, other end to of trimpot to 10k.
;            Set trimpot
;            with wiper to GND end.
;
;    Reference voltage for Comparator is Fixed Voltage Reference set to 4.096V.
;  
;    LED with 470 ohm series resistor conected between RA1 and GND.
;
;    Turning trimpot up will trigger interrrupt routine and turn on LED.
;    Power off to reset.
;********************************************************************************
;                                                                            
; Target Controller        PIC16F1827
;                __________                                        
;        SPARE------RA2 |1       18| RA1---LED
;        COMP-NEG---RA3 |2       17| RA0---SPARE
;        SPARE------RA4 |3       16| RA7---SPARE
;        SPARE------RA5 |4       15| RA6---SPARE
;        Ground-----Vss |5       14| VDD---+5 V
;        SPARE------RB0 |6       13| RB7---SPARE
;        SPARE------RB1 |7       12| RB6---SPARE
;        SPARE------RB2 |8       11| RB5---SPARE
;        SPARE------RB3 |9       10| RB4---SPARE
;                ----------                                        
;                                                                            
; *******************************************************************************
; * Device type and options                            *
; *******************************************************************************
;
        processor 16F1827
        radix     dec
    errorlevel -207    ; Skip found label after column 1
    errorlevel -302    ; Skip out of bank nuisance messages
    errorlevel -303    ; Skip program word too large. Truncated to core size
;
; *******************************************************************************
; * Configuration fuse information for 16F1827:                    *
; *******************************************************************************
;
        include   <P16F1827.INC>

 __CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_ON & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
 __CONFIG _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_LO & _LVP_OFF
;
; *******************************************************************************
;
;    16F1827 Oscillator setup
    ; OSCCON - Oscillator control reg.
    ; ---------------------------------
    ; SPLLEN b7 enable PLL x4
    ; 1 = enabled 0 = disabled
    ; IRCF | b6-3 frequency selection
    ; 1111 = 16MHz HF
    ; 1110 = 8 or 32MHz HF
    ; 1101 = 4MHz HF
    ; 1100 = 2MHz HF
    ; 1011 = 1MHz HF
    ; 1010 = 500kHz HF
    ; 1001 = 250kHz HF
    ; 1000 = 125kHz HF
    ; 0111 = 500kHz MF (default)
    ; 0110 = 250kHz MF
    ; 0101 = 125kHz MF
    ; 0100 = 62.5kHz MF
    ; 0011 = 31.25kHz HF
    ; 0010 = 31.25kHz MF
    ; 000x = 31.25kHz LF
    ; Reserved B2 reserved, 0
    ; SCS      B1 0-: 1x = int. OSC.
    ; 01 = Timer1 oscillator
    ; 00 = determined by FOSC <2:0> in Configuration
    ; POR default 00111-00 500 kHz (POR = Power On Reset)

OSCCONVAL    EQU    b'01101000'    ; 4MhZ CLOCK
;
; *******************************************************************************
; *           Allocate variables in general purpose register space        *
; *******************************************************************************
;
    CBLOCK    0x20        ; Start Data Block
    temp

    ENDC            ; End of Data Block
;
; *******************************************************************************
; *    Macro's                                    *
; *******************************************************************************
;
LED_on    macro
    bsf    PORTA,1
    endm

LED_off macro
    bcf    PORTA,1
    endm
;
; *******************************************************************************
; * Purpose:  This is the start of the program.                    *
; *******************************************************************************
;
;
    ORG     0x0000              
    goto    start        ; Jump to main program

    ORG     0x0004        ; interrupt routine data save

    bcf    INTCON,GIE    ; Clear Global Interrupt Enable bit

    BANKSEL    PIR2
    bcf    PIR2,C2IF    ; Clear comparator flag
    movlb    0

    clrf    PORTA
    clrf    PORTB

    LED_on

    goto    $

    retfie             ; Enable general interrupts and return
;
;--------------------------------------------------------------------------------
;
start
    clrf    INTCON        ; clear INTCON
    clrf    PORTA
    clrf    PORTB

; Set PIC oscillator frequency
    banksel    OSCCON        ; Select OSCCON
    movlw    OSCCONVAL    ; Oscillator frequency
    movwf    OSCCON        ; Loads the wanted value

; Configures I/O analog/digital function
    Banksel    ANSELA
    movlw    b'00001000'    ; RA3 analog all others digital
    movwf    ANSELA
    clrf    ANSELB        ; PORTB all digital

; Disable all wakeup pull-ups
    Banksel    WPUA
    clrf    WPUA
    clrf    WPUB

    banksel    OPTION_REG
    movlw    b'10000000'    ; Pull-ups disabled
                ;
    movwf    OPTION_REG    ;
;
    movlw    b'00111100'    ; PORTA (RA2:5 inputs RA0:1 & 6:7 outputs)    
    movwf    TRISA        ;
    movlw    b'10001111'    ; PORTB 0:3 & 7 inputs 4:6 outputs
    movwf    TRISB        ; NOTE: Pull-up via 10k resistor all unused pins
;
    BANKSEL    FVRCON
    movlw    b'10001100'    ; FVR on, Comparator ref 4.096V
    movwf    FVRCON
;
    movlb    0
    movlw    40        ; Delay for FVR to stabilise
    movwf    temp
    decfsz    temp
    goto    $-1

    BANKSEL CM1CON0
    clrf    CM1CON0
    clrf    CM1CON1

    movlw    b'10100011'
    movwf    CM2CON1        ; Positive interrupt on
                ; Negative interrupt off
                ; C2VP connects to FVR
                ; C2VP connects to FVR
                ; Unimplemented
                ; Unimplemented
                ; C2VN connects to C12IN3- pin - RA3
                ; C2VN connects to C12IN3- pin - RA3

    movlw    b'10000110'
    movwf    CM2CON0        ; Comparator enabled
                ; Comparator Output bit polarity
                ; Comparator Output internal
                ; Comparator output is not inverted
                ; Unimplemented
                ; Comparator operates in normal power, higher speed mode
                ; Comparator hysteresis enabled
                ; Comparator output to Timer1 and I/O pin is asynchronous


    BANKSEL    PIE2
    bsf    PIE2,C2IE    ; Turn on Comparator 2 interrupt
    bsf    INTCON,PEIE    ; Turn on Periperal interrupts
    movlb    0

main
    bsf    INTCON,GIE    ; Turn on Global interrupts
    nop
    goto    $-1        ; Endless loop as comparator is independent of
                ; anything happening here.
;
        END
;--------------------------------------------------------------------------------
 
I happened to be looking at the electrical characteristics of another pic and noticed the EEPROM erase/write cycle time - typically 4mS - maximum 5mS per byte. The flash write cycle time for a row of 32 locations (14 bits each) is maximum 2.5mS. It might be worth further investigation.

Mike.
 
This thread got me thinking about calculating Vdd from the ADC reading. On the newer chip (your included) you can use Vdd as the ADC reference and feed the ADC the fixed voltage reference. This gives a reading that increases as Vdd decreases as the 2.048V stays the same.

I played around with some code. It generates a 100uS interrupt and starts the ADC on each interrupt, on completion of the ADC reading it places the value in a variable (called value). It's in C but the general idea will work in any language. It's written for a 16F18854 as I happen to have some boards laying around with those on. Some of the registers are different to the 1827.
Code:
#include <xc.h>
#include <stdint.h>

// CONFIG1
#pragma config FEXTOSC = OFF    // External Oscillator mode selection bits->Oscillator not enabled
#pragma config RSTOSC = HFINTPLL    // Power-up default value for COSC bits->HFINTOSC with 2x PLL, with OSCFRQ = 16 MHz and CDIV = 1:1 (FOSC = 32 MHz)
#pragma config CLKOUTEN = OFF    // Clock Out Enable bit->CLKOUT function is disabled; i/o or oscillator function on OSC2
#pragma config CSWEN = ON    // Clock Switch Enable bit->Writing to NOSC and NDIV is allowed
#pragma config FCMEN = ON    // Fail-Safe Clock Monitor Enable bit->FSCM timer enabled

// CONFIG2
#pragma config MCLRE = ON    // Master Clear Enable bit->MCLR pin is Master Clear function
#pragma config PWRTE = OFF    // Power-up Timer Enable bit->PWRT disabled
#pragma config LPBOREN = OFF    // Low-Power BOR enable bit->ULPBOR disabled
#pragma config BOREN = ON    // Brown-out reset enable bits->Brown-out Reset Enabled, SBOREN bit is ignored
#pragma config BORV = LO    // Brown-out Reset Voltage Selection->Brown-out Reset Voltage (VBOR) set to 1.9V on LF, and 2.45V on F Devices
#pragma config ZCD = OFF    // Zero-cross detect disable->Zero-cross detect circuit is disabled at POR.
#pragma config PPS1WAY = ON    // Peripheral Pin Select one-way control->The PPSLOCK bit can be cleared and set only once in software
#pragma config STVREN = ON    // Stack Overflow/Underflow Reset Enable bit->Stack Overflow or Underflow will cause a reset
#pragma config DEBUG = OFF    // Background Debugger->Background Debugger disabled

// CONFIG3
#pragma config WDTCPS = WDTCPS_31    // WDT Period Select bits->Divider ratio 1:65536; software control of WDTPS
#pragma config WDTE = SWDTEN    // WDT operating mode->WDT enabled/disabled by SWDTEN bit in WDTCON0
#pragma config WDTCWS = WDTCWS_7    // WDT Window Select bits->window always open (100%); software control; keyed access not required
#pragma config WDTCCS = SC    // WDT input clock selector->Software Control

// CONFIG4
#pragma config WRT = OFF    // UserNVM self-write protection bits->Write protection off
#pragma config SCANE = available    // Scanner Enable bit->Scanner module is available for use
#pragma config LVP = ON    // Low Voltage Programming Enable bit->Low Voltage programming enabled. MCLR/Vpp pin function is MCLR.

// CONFIG5
#pragma config CP = OFF    // UserNVM Program memory code protection bit->Program Memory code protection disabled
#pragma config CPD = OFF    // DataNVM code protection bit->Data EEPROM code protection disabled

uint16_t value;

void main(void){
    T2CLKCON=0b0011;            //HFIOSC(16MHz))
    T2CON=0b11000000;           //pre=16=1MHz,PR4=100=10KHz, post=1 = 10kHz, timer on
    PR2=99;                     //counts 0-99 = 100 counts
    TMR2IE=1;                   //enable timer 2 interrupts
    FVRCON=0b10001010;          //enable FVR at 2.048V
    ADCON0=0b10000100;          //ADC on, Fosc and right justify
    ADCLK=0x0f;                 //Fosc/32 = 1uS
    ADACQ=0x05;                 //5uS acquisition time
    ADPCH=0b00111111;           //select FVR as ADC input
    PIE1bits.ADIE=1;            //enable ADC complete interrupt
    while(!FVRRDY);             //wait for FVR to be ready
    PEIE=1;                     //enable peripheral interrupts
    GIE=1;                      //enable global interrupts
    while(1){
    }
}

void __interrupt() inter(void){
    if(TMR2IE && TMR2IF){
        TMR2IF=0;
        ADGO=1;
    }
    if(ADIF && ADIE){
        ADIF=0;
        value=ADRES;
    }
}
Note, the config data is over half the code. The interrupt that does all the work is just 7 instruction lines.

Mike.
 
I just so happen to have been reading something yesterday about calculating the VDD supply using the onboard reference - not sure if it was in an app note or datasheet.

Re writing to flash, with the 100uF cap on the supply input, it is giving way more than enough time to save to EEprom.

There's also the fact that EEprom read/writes are more durable than flash writes in how many times it can be done - 100,000 as opposed to 10,000 times for the 16F1827.
 
Of course you could check the data in EEPROM against new data, and if unchanged
no writes to EEPROM saving lifetime.

And code the routine to do your own wear leveling, further enhancement of lifetime.




Regards, Dana.
 
This thread got me thinking about calculating Vdd from the ADC reading. On the newer chip (your included) you can use Vdd as the ADC reference and feed the ADC the fixed voltage reference. This gives a reading that increases as Vdd decreases as the 2.048V stays the same.

I played around with some code. It generates a 100uS interrupt and starts the ADC on each interrupt, on completion of the ADC reading it places the value in a variable (called value). It's in C but the general idea will work in any language. It's written for a 16F18854 as I happen to have some boards laying around with those on. Some of the registers are different to the 1827.
Code:
#include <xc.h>
#include <stdint.h>

// CONFIG1
#pragma config FEXTOSC = OFF    // External Oscillator mode selection bits->Oscillator not enabled
#pragma config RSTOSC = HFINTPLL    // Power-up default value for COSC bits->HFINTOSC with 2x PLL, with OSCFRQ = 16 MHz and CDIV = 1:1 (FOSC = 32 MHz)
#pragma config CLKOUTEN = OFF    // Clock Out Enable bit->CLKOUT function is disabled; i/o or oscillator function on OSC2
#pragma config CSWEN = ON    // Clock Switch Enable bit->Writing to NOSC and NDIV is allowed
#pragma config FCMEN = ON    // Fail-Safe Clock Monitor Enable bit->FSCM timer enabled

// CONFIG2
#pragma config MCLRE = ON    // Master Clear Enable bit->MCLR pin is Master Clear function
#pragma config PWRTE = OFF    // Power-up Timer Enable bit->PWRT disabled
#pragma config LPBOREN = OFF    // Low-Power BOR enable bit->ULPBOR disabled
#pragma config BOREN = ON    // Brown-out reset enable bits->Brown-out Reset Enabled, SBOREN bit is ignored
#pragma config BORV = LO    // Brown-out Reset Voltage Selection->Brown-out Reset Voltage (VBOR) set to 1.9V on LF, and 2.45V on F Devices
#pragma config ZCD = OFF    // Zero-cross detect disable->Zero-cross detect circuit is disabled at POR.
#pragma config PPS1WAY = ON    // Peripheral Pin Select one-way control->The PPSLOCK bit can be cleared and set only once in software
#pragma config STVREN = ON    // Stack Overflow/Underflow Reset Enable bit->Stack Overflow or Underflow will cause a reset
#pragma config DEBUG = OFF    // Background Debugger->Background Debugger disabled

// CONFIG3
#pragma config WDTCPS = WDTCPS_31    // WDT Period Select bits->Divider ratio 1:65536; software control of WDTPS
#pragma config WDTE = SWDTEN    // WDT operating mode->WDT enabled/disabled by SWDTEN bit in WDTCON0
#pragma config WDTCWS = WDTCWS_7    // WDT Window Select bits->window always open (100%); software control; keyed access not required
#pragma config WDTCCS = SC    // WDT input clock selector->Software Control

// CONFIG4
#pragma config WRT = OFF    // UserNVM self-write protection bits->Write protection off
#pragma config SCANE = available    // Scanner Enable bit->Scanner module is available for use
#pragma config LVP = ON    // Low Voltage Programming Enable bit->Low Voltage programming enabled. MCLR/Vpp pin function is MCLR.

// CONFIG5
#pragma config CP = OFF    // UserNVM Program memory code protection bit->Program Memory code protection disabled
#pragma config CPD = OFF    // DataNVM code protection bit->Data EEPROM code protection disabled

uint16_t value;

void main(void){
    T2CLKCON=0b0011;            //HFIOSC(16MHz))
    T2CON=0b11000000;           //pre=16=1MHz,PR4=100=10KHz, post=1 = 10kHz, timer on
    PR2=99;                     //counts 0-99 = 100 counts
    TMR2IE=1;                   //enable timer 2 interrupts
    FVRCON=0b10001010;          //enable FVR at 2.048V
    ADCON0=0b10000100;          //ADC on, Fosc and right justify
    ADCLK=0x0f;                 //Fosc/32 = 1uS
    ADACQ=0x05;                 //5uS acquisition time
    ADPCH=0b00111111;           //select FVR as ADC input
    PIE1bits.ADIE=1;            //enable ADC complete interrupt
    while(!FVRRDY);             //wait for FVR to be ready
    PEIE=1;                     //enable peripheral interrupts
    GIE=1;                      //enable global interrupts
    while(1){
    }
}

void __interrupt() inter(void){
    if(TMR2IE && TMR2IF){
        TMR2IF=0;
        ADGO=1;
    }
    if(ADIF && ADIE){
        ADIF=0;
        value=ADRES;
    }
}
Note, the config data is over half the code. The interrupt that does all the work is just 7 instruction lines.

Mike.
Nice one Mike, but presumably only useful if you're not using a voltage regulator, otherwise you want to read the incoming voltage, not that out of the regulator (Vdd).

I know what you mean about the huge number of config settings, it seems to get more and more as the chips get more and more facilities - BTW, did you mean to have LVP=ON?, or did you forget to untick it :D
 
There's also the fact that EEprom read/writes are more durable than flash writes in how many times it can be done - 100,000 as opposed to 10,000 times for the 16F1827.
A very simple form of wear leveling would be to reserve 1k of flash and write to 32 word locations sequentially therefore giving you 320,000 writes.
Out of curiosity, how many bytes can you write to EEPROM?

BTW, did you mean to have LVP=ON?, or did you forget to untick it :D
I'd just copied it from another project which shouldn't have had it ON either!!! Didn't the pickit2/3 warn you if this was the case? Obviously PK4 doesn't - another step forward - not.

Mike.
 
A very simple form of wear leveling would be to reserve 1k of flash and write to 32 word locations sequentially therefore giving you 320,000 writes.
Out of curiosity, how many bytes can you write to EEPROM?


I'd just copied it from another project which shouldn't have had it ON either!!! Didn't the pickit2/3 warn you if this was the case? Obviously PK4 doesn't - another step forward - not.

It's nothing to do with the PK2/3/4 - the default from MCC is for LVP, and you need to untick it when you run MCC. I presume you're setting the config bits via MCC, as I do - there's too many do do it manually.
 
It's nothing to do with the PK2/3/4 - the default from MCC is for LVP, and you need to untick it when you run MCC. I presume you're setting the config bits via MCC, as I do - there's too many do do it manually.
I'm sure I used to get a warning if LVP was on. Yes, using MCC as far too complicated any other way.

Mike.
 
I'm sure I used to get a warning if LVP was on. Yes, using MCC as far too complicated any other way.

Mike.
I've never seen (or at least noticed) any warning, and to be fair it's not that un-complicated even using MCC :D

I also noticed you seem to cut & paste the code from MCC into your own source code, much as I do.
 
If using a LDO many, when they go into saturation, become a fixed V drop
relationship to their input voltage. To a point.


1641214351885.png


Its more involved to do the design by measuring Vout of reg but has the advantage that
what you are concerned with is Vout of the regulator. Note some datasheets do not have
adequate parameters to do this reliably, you may have to contact manufacturer to get
at device behavior. Or use a part better characterized in its datasheet.

Keep in mind when a reg goes into sat its line rejection evaporates, so this is best considered
with designs that have decent or minimal line noise.

Trade-offs, always trade-offs. In ap note there is a deeper discussion of this.

I assume when you state "warning" you mean the typical interrupt, in most processors these
days, produced by the low voltage, brownout condition ?


Regards, Dana.
 
Last edited:
I assume when you state "warning" you mean the typical interrupt, in most processors these
days, produced by the low voltage, brownout condition ?
Assuming you're referring to the very recent posts?, then no - we're discussing possible warnings from MPLABX if you don't turn off the default LVP setting.
 
Assuming you're referring to the very recent posts?, then no - we're discussing possible warnings from MPLABX if you don't turn off the default LVP setting.

Yes, I followed that, as well as insuring OP following HW considerations, like regulator measurement point.
 
Last edited:
I also noticed you seem to cut & paste the code from MCC into your own source code, much as I do.
Yes, I dislike having code spread over a huge number of files unless the project requires it and then I split them into functional routines rather than peripherals. I like to have connected code in the same file so I can see it all at once and not have to keep switching between files to check things.

Mike.
Edit, apologies to Terry for the thread drift.
 
Not a problem Mike, as I started this thread in the vein of a general enquiry anyway, rather than a "I have a problem" one.

Thankyou to everyone, much valuable information passed on not just to me but others that may come across this in the future.

Off to the Mens Shed for a while :happy:
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top