• AVR Freaks

Hot!HLVD continues to interrupt after direction change

Author
spinnaker
Super Member
  • Total Posts : 212
  • Reward points : 0
  • Joined: 2009/12/04 22:04:40
  • Location: 0
  • Status: offline
2018/12/14 14:25:37 (permalink)
0

HLVD continues to interrupt after direction change

 
I am experimenting with the HLVD feature of a PIC18F27J13.
 
Initially the code works as expected.   The interrupt is generated after the voltage drops on VDD.  But I change the direction, don't touch the voltage on VDD and the interrupt continues to be generated.
 
I am setting RA0 and I can see it pulsing so I know the interrupt continues to be generated.   How would I fix this?  I only want one interrupt to be generated when VDD falls below my set point.
 

// PIC18F27J13 Configuration Bit Settings

// 'C' source line config statements

// CONFIG1L
#pragma config WDTEN = OFF      // Watchdog Timer (Disabled - Controlled by SWDTEN bit)
#pragma config PLLDIV = 1       // 96MHz PLL Prescaler Selection (PLLSEL=0) (No prescale (4 MHz oscillator input drives PLL directly))
#pragma config CFGPLLEN = OFF   // PLL Enable Configuration Bit (PLL Disabled)
#pragma config STVREN = ON      // Stack Overflow/Underflow Reset (Enabled)
#pragma config XINST = OFF      // Extended Instruction Set (Disabled)

// CONFIG1H
#pragma config CP0 = OFF        // Code Protect (Program memory is not code-protected)

// CONFIG2L
#pragma config OSC = INTOSC     // Oscillator (INTOSC)
#pragma config SOSCSEL = HIGH   // T1OSC/SOSC Power Selection Bits (High Power T1OSC/SOSC circuit selected)
#pragma config CLKOEC = OFF     // EC Clock Out Enable Bit  (CLKO output disabled on the RA6 pin)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor (Disabled)
#pragma config IESO = OFF       // Internal External Oscillator Switch Over Mode (Disabled)

// CONFIG2H
#pragma config WDTPS = 32768    // Watchdog Postscaler (1:32768)

// CONFIG3L
#pragma config DSWDTOSC = INTOSCREF// DSWDT Clock Select (DSWDT uses INTRC)
#pragma config RTCOSC = T1OSCREF// RTCC Clock Select (RTCC uses T1OSC/T1CKI)
#pragma config DSBOREN = OFF    // Deep Sleep BOR (Disabled)
#pragma config DSWDTEN = OFF    // Deep Sleep Watchdog Timer (Disabled)
#pragma config DSWDTPS = G2     // Deep Sleep Watchdog Postscaler (1:2,147,483,648 (25.7 days))

// CONFIG3H
#pragma config IOL1WAY = OFF    // IOLOCK One-Way Set Enable bit (The IOLOCK bit (PPSCON<0>) can be set and cleared as needed)
#pragma config ADCSEL = BIT10   // ADC 10 or 12 Bit Select (10 - Bit ADC Enabled)
#pragma config PLLSEL = PLL4X   // PLL Selection Bit (Selects 4x PLL)
#pragma config MSSP7B_EN = MSK7 // MSSP address masking (7 Bit address masking mode)

// CONFIG4L
#pragma config WPFP = PAGE_127  // Write/Erase Protect Page Start/End Location (Write Protect Program Flash Page 127)
#pragma config WPCFG = OFF      // Write/Erase Protect Configuration Region  (Configuration Words page not erase/write-protected)

// CONFIG4H
#pragma config WPDIS = OFF      // Write Protect Disable bit (WPFP<6:0>/WPEND region ignored)
#pragma config WPEND = PAGE_WPFP// Write/Erase Protect Region Select bit (valid when WPDIS = 0) (Pages WPFP<6:0> through Configuration Words erase/write protected)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>


void main(void)
{
   OSCCONbits.IRCF0 = 1;
   OSCCONbits.IRCF1 = 1;    
   OSCCONbits.IRCF2 = 1;   
    
    HLVDCONbits.HLVDEN = 0;                 // Disable HLDV
    HLVDCONbits.HLVDL = 0b1100;                 // Set point to low value    
    HLVDCONbits.VDIRMAG = 0;                // Interrupt when voltage drops    
    PIR2bits.HLVDIF = 0;                    // Clear the HLVD interrupt flag    
    HLVDCONbits.HLVDEN = 1;                 // Enable HLDV                  
    RCONbits.IPEN = 1;
    INTCONbits.GIEH = 1;                    // Enable general interrupts high
    PIE2bits.HLVDIE = 1;                    // Enable low voltage detect interrupt    
   
    TRISAbits.TRISA0 = 0;
    LATAbits.LATA0 = 1;
   
   
   while(1);
    return;
}


__interrupt(high_priority) void interrupts_highPriority(void)
{
    if (PIR2bits.HLVDIF == 1)
    {
        PIR2bits.HLVDIF = 0;
        
        
        
         LATAbits.LATA0 = HLVDCONbits.VDIRMAG;
        
        HLVDCONbits.HLVDEN = 0;         
        HLVDCONbits.HLVDL = 0b1110;
        HLVDCONbits.VDIRMAG = ~HLVDCONbits.VDIRMAG;
        HLVDCONbits.HLVDEN = 1;
        
    }
    
   
    
}




#1

5 Replies Related Threads

    spinnaker
    Super Member
    • Total Posts : 212
    • Reward points : 0
    • Joined: 2009/12/04 22:04:40
    • Location: 0
    • Status: offline
    Re: HLVD continues to interrupt after direction change 2018/12/14 21:35:49 (permalink)
    0
    I simplified my interrupt code and added a counter.   I am setting the trip point to the max and change the direction within the interrupt. 
     
    When I pause the debugger I can see the count go to as high as 4 before it stops interrupting.  Why would I be getting 4 interrupts?
     
     
    Aside from using an analog input, is there anyway to know I am below my setpoint or above it?
     

    __interrupt(high_priority) void interrupts_highPriority(void)
    {
        interruptCount++;
        
        if (PIR2bits.HLVDIF == 1)
        {
            PIR2bits.HLVDIF = 0;
            interruptCount++;   
            HLVDCONbits.HLVDEN = 0;                 
            HLVDCONbits.HLVDL = 0b1110;
            HLVDCONbits.VDIRMAG = 1;
            HLVDCONbits.HLVDEN = 1;
             
        }  
        
    }

     
    #2
    spinnaker
    Super Member
    • Total Posts : 212
    • Reward points : 0
    • Joined: 2009/12/04 22:04:40
    • Location: 0
    • Status: offline
    Re: HLVD continues to interrupt after direction change 2018/12/14 22:01:16 (permalink)
    0
    Below is my updated code that works.  Not sure why I need to detect 4 interrupts.  For the  low set point the difference between max and my setpoint is 4.  Could one interrupt be generated for each of the possible setpoints in between max amd the selected setpont? 
     
    But that does not explain why 4 interrupts are being triggered for my normal trip voltage.   And I see nothing in the datasheet that mentions multiples will be generated.
     
    Update: Code slightly corrected.   Ws not checking for interrupt flag.  Hey it was a late night last night. ;)
    Also just noticed, the 4 interrupts occur only when the voltage crosses below the setpoint.   One interrupt is generated when the voltage rises above the setpoint.
     
     

    /*
     * File:   main.c
     * Author: Bruce
     *
     * Created on December 14, 2018, 2:16 PM
     */


    // PIC18F27J13 Configuration Bit Settings

    // 'C' source line config statements

    // CONFIG1L
    #pragma config WDTEN = OFF      // Watchdog Timer (Disabled - Controlled by SWDTEN bit)
    #pragma config PLLDIV = 1       // 96MHz PLL Prescaler Selection (PLLSEL=0) (No prescale (4 MHz oscillator input drives PLL directly))
    #pragma config CFGPLLEN = OFF   // PLL Enable Configuration Bit (PLL Disabled)
    #pragma config STVREN = ON      // Stack Overflow/Underflow Reset (Enabled)
    #pragma config XINST = OFF      // Extended Instruction Set (Disabled)

    // CONFIG1H
    #pragma config CP0 = OFF        // Code Protect (Program memory is not code-protected)

    // CONFIG2L
    #pragma config OSC = INTOSC     // Oscillator (INTOSC)
    #pragma config SOSCSEL = HIGH   // T1OSC/SOSC Power Selection Bits (High Power T1OSC/SOSC circuit selected)
    #pragma config CLKOEC = OFF     // EC Clock Out Enable Bit  (CLKO output disabled on the RA6 pin)
    #pragma config FCMEN = OFF      // Fail-Safe Clock Monitor (Disabled)
    #pragma config IESO = OFF       // Internal External Oscillator Switch Over Mode (Disabled)

    // CONFIG2H
    #pragma config WDTPS = 32768    // Watchdog Postscaler (1:32768)

    // CONFIG3L
    #pragma config DSWDTOSC = INTOSCREF// DSWDT Clock Select (DSWDT uses INTRC)
    #pragma config RTCOSC = T1OSCREF// RTCC Clock Select (RTCC uses T1OSC/T1CKI)
    #pragma config DSBOREN = OFF    // Deep Sleep BOR (Disabled)
    #pragma config DSWDTEN = OFF    // Deep Sleep Watchdog Timer (Disabled)
    #pragma config DSWDTPS = G2     // Deep Sleep Watchdog Postscaler (1:2,147,483,648 (25.7 days))

    // CONFIG3H
    #pragma config IOL1WAY = OFF    // IOLOCK One-Way Set Enable bit (The IOLOCK bit (PPSCON<0>) can be set and cleared as needed)
    #pragma config ADCSEL = BIT10   // ADC 10 or 12 Bit Select (10 - Bit ADC Enabled)
    #pragma config PLLSEL = PLL4X   // PLL Selection Bit (Selects 4x PLL)
    #pragma config MSSP7B_EN = MSK7 // MSSP address masking (7 Bit address masking mode)

    // CONFIG4L
    #pragma config WPFP = PAGE_127  // Write/Erase Protect Page Start/End Location (Write Protect Program Flash Page 127)
    #pragma config WPCFG = OFF      // Write/Erase Protect Configuration Region  (Configuration Words page not erase/write-protected)

    // CONFIG4H
    #pragma config WPDIS = OFF      // Write Protect Disable bit (WPFP<6:0>/WPEND region ignored)
    #pragma config WPEND = PAGE_WPFP// Write/Erase Protect Region Select bit (valid when WPDIS = 0) (Pages WPFP<6:0> through Configuration Words erase/write protected)

    // #pragma config statements should precede project file includes.
    // Use project enums instead of #define for ON and OFF.

    #include <xc.h>
    #define LOW_POWER_SETPOINT 0b1010
    #define NORMAL_POWER_SETPOINT 0b1101
    #define _XTAL_FREQ 8000000

    unsigned interruptCount = 0;

    #define DETECT_LOW_POWER 0
    #define DETECT_NORMAL_POWER 1

    unsigned char  detectPowerMode = 0;



    void main(void)
    {
       OSCCONbits.IRCF0 = 1;
       OSCCONbits.IRCF1 = 1;    
       OSCCONbits.IRCF2 = 1;   
        
        HLVDCONbits.HLVDEN = 0;                 // Disable HLDV
        HLVDCONbits.HLVDL = LOW_POWER_SETPOINT;             // Set point to low value    
        HLVDCONbits.VDIRMAG = detectPowerMode;     // Interrupt when voltage drops    
        PIR2bits.HLVDIF = 0;                    // Clear the HLVD interrupt flag    
        HLVDCONbits.HLVDEN = 1;                 // Enable HLDV                  
        RCONbits.IPEN = 1;
        INTCONbits.GIEH = 1;                    // Enable general interrupts high
        PIE2bits.HLVDIE = 1;                    // Enable low voltage detect interrupt    
       
        TRISAbits.TRISA0 = 0;
        TRISAbits.TRISA1 = 0;
         
        LATAbits.LATA0 = 1;
        
        
        while(1);
     
        return;
    }


    __interrupt(high_priority) void interrupts_highPriority(void)
    {
        if (PIR2bits.HLVDIF == 1)        
        {
            PIR2bits.HLVDIF = 0;
            if (PIR2bits.HLVDIF == DETECT_NORMAL_POWER)
            {
                
                interruptCount++;

                if (interruptCount<4)
                    return;

               interruptCount=0;

                if (detectPowerMode == 1)
                {

                    LATAbits.LATA0 = 1;    
                    detectPowerMode = DETECT_LOW_POWER;
                    HLVDCONbits.HLVDEN = 0;                 
                    HLVDCONbits.HLVDL = LOW_POWER_SETPOINT;            
                    HLVDCONbits.VDIRMAG = detectPowerMode;                                   
                    HLVDCONbits.HLVDEN = 1;                       


                }
                else
                {

                    LATAbits.LATA0 = 0;     
                    detectPowerMode = DETECT_NORMAL_POWER;            
                    HLVDCONbits.HLVDEN = 0;       
                    HLVDCONbits.HLVDL = NORMAL_POWER_SETPOINT;
                    HLVDCONbits.VDIRMAG = detectPowerMode;
                    HLVDCONbits.HLVDEN = 1;
                }         

            }
        
        }
        
    }




     
    post edited by spinnaker - 2018/12/15 09:04:12
    #3
    spinnaker
    Super Member
    • Total Posts : 212
    • Reward points : 0
    • Joined: 2009/12/04 22:04:40
    • Location: 0
    • Status: offline
    Re: HLVD continues to interrupt after direction change 2019/03/22 15:33:27 (permalink)
    0
    Any help on this?
     
    #4
    1and0
    Access is Denied
    • Total Posts : 9289
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: HLVD continues to interrupt after direction change 2019/03/24 09:52:15 (permalink)
    0
    spinnaker
    Below is my updated code that works.  
    ...

    __interrupt(high_priority) void interrupts_highPriority(void) 
    {
        if (PIR2bits.HLVDIF == 1)        
        {
            PIR2bits.HLVDIF = 0;
            if (PIR2bits.HLVDIF == DETECT_NORMAL_POWER)
            {
                  // snipped
            } 
        }
    }


    spinnaker
    Any help on this?

    It has been over 3 months.  Is your current code still the same as quoted from Post #3?  If so, what do you expect that to do?


    #5
    spinnaker
    Super Member
    • Total Posts : 212
    • Reward points : 0
    • Joined: 2009/12/04 22:04:40
    • Location: 0
    • Status: offline
    Re: HLVD continues to interrupt after direction change 2019/03/24 14:39:16 (permalink)
    0
    I have a fix.   The code below works.   It is based on code found on the MicroChip site but I believe I have made improvements.
     

     
    #include <xc.h>
    #define LOW_POWER_SETPOINT 0b1001
    #define NORMAL_POWER_SETPOINT 0b1010
    #define _XTAL_FREQ 8000000

    unsigned interruptCount = 0;

    #define DETECT_LOW_POWER 0
    #define DETECT_NORMAL_POWER 1

    unsigned char  detectPowerMode = 0;

    unsigned char enterSleep = 0;
    unsigned char hlvdISRoccured = 0;

    void WaitForStableVdd(void);

    void main(void)
    {
       OSCCONbits.IRCF0 = 1;
       OSCCONbits.IRCF1 = 1;    
       OSCCONbits.IRCF2 = 1;   
       
       TRISAbits.TRISA0 = 0;
       TRISAbits.TRISA1 = 0;
         
       LATAbits.LATA0 = 1;
       
     
       
       OSCCONbits.IDLEN = 0;
        
        HLVDCONbits.HLVDEN = 0;                 // Disable HLDV
        HLVDCONbits.HLVDL = LOW_POWER_SETPOINT; // Set point to low value    
        HLVDCONbits.VDIRMAG = detectPowerMode;  // Interrupt when voltage drops    
        PIR2bits.HLVDIF = 0;                    // Clear the HLVD interrupt flag    
        HLVDCONbits.HLVDEN = 1;                 // Enable HLDV         
        while(HLVDCONbits.BGVST == 0);          // wait for stable bandgap reference voltage
        while(HLVDCONbits.IRVST == 0);          // wait for stable HLVD internal reference voltage
        RCONbits.IPEN = 1;
        INTCONbits.GIEH = 1;                    // Enable general interrupts high
        PIE2bits.HLVDIE = 1;                    // Enable low voltage detect interrupt    
          

        
        
        
        while(1)
       {
           
           LATAbits.LATA1 = 0;
           __delay_ms(100);
           LATAbits.LATA1 = 1;
           __delay_ms(100);

           
           if (hlvdISRoccured)
           {
               
            hlvdISRoccured = 0;        
            WaitForStableVdd();
            PIE2bits.LVDIE = 1;  // Renable HLVD ISR       
            
            if (enterSleep)
               Sleep();
            
            
           }

           
       }
        return;
    }


    __interrupt(high_priority) void interrupts_highPriority(void)
    {
        if (PIR2bits.HLVDIF == 1)        
        {
            PIE2bits.LVDIE = 0;  
            hlvdISRoccured = 1;

            if (detectPowerMode == 1)
            {

                LATAbits.LATA0 = 1;    
                detectPowerMode = DETECT_LOW_POWER;
                HLVDCONbits.HLVDEN = 0;                 
                HLVDCONbits.HLVDL = LOW_POWER_SETPOINT;            
                HLVDCONbits.VDIRMAG = detectPowerMode;                                   
                HLVDCONbits.HLVDEN = 1;
                enterSleep=0;


            }
            else
            {

                LATAbits.LATA0 = 0;     
                detectPowerMode = DETECT_NORMAL_POWER;            
                HLVDCONbits.HLVDEN = 0;       
                HLVDCONbits.HLVDL = NORMAL_POWER_SETPOINT;
                HLVDCONbits.VDIRMAG = detectPowerMode;
                HLVDCONbits.HLVDEN = 1;
                enterSleep =1;
            }         


          
        }
        
    }

    void WaitForStableVdd(void)
    {  
        
     while(HLVDCONbits.BGVST == 0);    // wait for stable bandgap reference voltage
     while(HLVDCONbits.IRVST == 0);     // wait for stable HLVD internal reference voltage   
     PIR2bits.LVDIF = 0;                 // clear HLVD interrupt flag      
     
    }
     




     
     
     

     
     
    #6
    Jump to:
    © 2019 APG vNext Commercial Version 4.5