Menu

PIC16F18857 and Interrupt-On-Change

jackjames
2019-09-06
2020-12-21
1 2 3 4 > >> (Page 1 of 4)
  • jackjames

    jackjames - 2019-09-06

    I have another problem always on the PIC16F18857.
    I have to use interrupt-on-change on PORTC.6.
    I execute all the settings of the case and I can not get this interrupt.
    Where am I wrong?

     
  • Anobium

    Anobium - 2019-09-06

    You need to setup the interrupt. Section 15.2 and 15.3 of the datasheet.

    I have made the code simply. Great Cow BASIC should set up everything else. And, you should not do much in an interrupt - keep an interrupt small (as the general case).

    Untested but should be ok code.

    :-)

    '       $formattagcb
    '       -
    '       Configuration
            #Chip 16F18857, 32
    '       -
            On Interrupt PORTChange Call Interrompo
    '       -
    '       -
            #Option Explicit
            dim eventhappened as bit
    
            'Call setup...
            Registri
    '       -
    '       -
            Do
                if eventhappened = true then
                    'CLS
                    'Print "It happened"
                    eventhappened = False
                end if
            Loop
    '       -
    '       -
    '       -
    Sub Registri
            Dir PORTC.6 In
            IOCCP6 = 1   ' Imposta l'Interrupt su rising Edge
    End Sub
    
    
    Sub Interrompo
          'has the event happended and we need to check we have completed handlign the previous event
          IF IOCCF6 = 1 AND eventhappened = false THEN
              eventhappened = true
          END IF
    End Sub
    

     

    Last edit: Anobium 2019-09-07
  • Anobium

    Anobium - 2019-09-07

    Code that works.

    Your approach in using a sub may fail you. Why? You enable all the interrupt handlers in the command On Interrupt PORTChange Call Interrompo, then, you in the sub you setup the interrupt bit - the event could then fire and your main code is never reached... the interrupt is firing all the time (I can that here on the scope).

    So, an approach that should work for you is shown below. Note. If you do not clear the event bit in the interrupt handler you will also get stuck in the interrupt handler... as the switch causing the event may bounce.

    Interrupts like this look simple. They are not.

    :-)

    '       $formattagcb
    '       -
    '       Configuration
            #Chip 16F18857, 32
    '       -
    
    '       -
    '       -
            #Option Explicit
            dim eventhappened as byte
    
            'led out
            dir porta.2 out
    
    
            'You need to consider very carefully about using a sub....
            Dir PORTC.6 In
            IOCCN6 = 1   ' Imposta l'Interrupt su rising Edge
            eventhappened = false
            On Interrupt PORTChange Call Interrompo
    
            Do
                'There is debounce here. You may get multiple events event with this approach
                if eventhappened = true then
                    porta.2 = !porta.2
                    wait 10 ms
                    eventhappened = False
                end if
    
            Loop
    
    
    Sub Interrompo
    
          'has the event happended and we need to check we have completed handling the previous event
          IF eventhappened = false THEN
              eventhappened = true
          END IF
          'clear the event here!
          If IOCCF6 = 1 then IOCCF6 = 0
    
    End Sub
    
     
  • jackjames

    jackjames - 2019-09-07

    Thank you for your help.
    Now the program runs perfectly.
    Studying the assembler listing I noticed that the compiler zeroed the IOCIF bit of PIR0
    ( banksel PIR0
    bcf PIR0,IOCIF
    ).
    The datasheet indicates it as a read-only bit
    (The IOCIF bits are the logical OR of all the IOCAF-IOCEF flags.
    Therefore, to clear the IOCIF flag, application firmware should clear all of the lower level IOCAF-IOCEF register bits.)
    This obviously has no effect on the operation of the program.

     
  • Anobium

    Anobium - 2019-09-07

    Yes, I spotted the read-only bit. This is deep in the compiler so I would not worry about this.

    Enjoy.

     
  • Megha Bhirade

    Megha Bhirade - 2020-11-08

    Hi guys,

    i am also facing problem to make work IOC (interrupt on change) for PIC16F18857..

    i am using MPLAB X IDE and XC8 compiler and code configurator (MCC)..

    i configured 1 pin as input (IOC negative edge detection) and one pin as output ( LED)....

    generated code...

    interrupt manager file has code :

    #include "interrupt_manager.h"
    #include "mcc.h"
    
    void __interrupt() INTERRUPT_InterruptManager (void)
    {
        // interrupt handler
        if(PIE0bits.IOCIE == 1 && PIR0bits.IOCIF == 1)
        {
            PIN_MANAGER_IOC();
        }
        else
        {
            //Unhandled Interrupt
        }
    }
    /**
    

    pin manager file , where i added the LED toggle macro:

    #include "pin_manager.h"
    
    
    
    
    void (*IOCAF0_InterruptHandler)(void);
    
    
    void PIN_MANAGER_Initialize(void)
    {
        /**
        LATx registers
        */
        LATA = 0x00;
        LATB = 0x00;
        LATC = 0x00;
    
        /**
        TRISx registers
        */
        TRISA = 0xFD;
        TRISB = 0xFF;
        TRISC = 0xFF;
    
        /**
        ANSELx registers
        */
        ANSELC = 0xFF;
        ANSELB = 0xFF;
        ANSELA = 0xFC;
    
        /**
        WPUx registers
        */
        WPUE = 0x00;
        WPUB = 0x00;
        WPUA = 0x00;
        WPUC = 0x00;
    
        /**
        ODx registers
        */
        ODCONA = 0x00;
        ODCONB = 0x00;
        ODCONC = 0x00;
    
        /**
        SLRCONx registers
        */
        SLRCONA = 0xFF;
        SLRCONB = 0xFF;
        SLRCONC = 0xFF;
    
        /**
        INLVLx registers
        */
        INLVLA = 0xFF;
        INLVLB = 0xFF;
        INLVLC = 0xFF;
        INLVLE = 0x00;
    
    
        /**
        IOCx registers 
        */
        //interrupt on change for group IOCAF - flag
        IOCAFbits.IOCAF0 = 0;
        //interrupt on change for group IOCAN - negative
        IOCANbits.IOCAN0 = 1;
        //interrupt on change for group IOCAP - positive
        IOCAPbits.IOCAP0 = 0;
    
    
    
        // register default IOC callback functions at runtime; use these methods to register a custom function
        IOCAF0_SetInterruptHandler(IOCAF0_DefaultInterruptHandler);
    
        // Enable IOCI interrupt 
        PIE0bits.IOCIE = 1; 
    
    }
    
    void PIN_MANAGER_IOC(void)
    {   
        // interrupt on change for pin IOCAF0
        if(IOCAFbits.IOCAF0 == 1)
        {
            IOCAF0_ISR();  
        }   
    }
    
    /**
       IOCAF0 Interrupt Service Routine
    */
    void IOCAF0_ISR(void) {
    
        // Add custom IOCAF0 code
    
        // Call the interrupt handler for the callback registered at runtime
        if(IOCAF0_InterruptHandler)
        {
            IOCAF0_InterruptHandler();
        }
        IOCAFbits.IOCAF0 = 0;
    }
    
    /**
      Allows selecting an interrupt handler for IOCAF0 at application runtime
    */
    void IOCAF0_SetInterruptHandler(void (* InterruptHandler)(void)){
        IOCAF0_InterruptHandler = InterruptHandler;
    }
    
    /**
      Default interrupt handler for IOCAF0
    */
    void IOCAF0_DefaultInterruptHandler(void){
        // add your IOCAF0 interrupt custom code
        // or set custom function using IOCAF0_SetInterruptHandler()
        LED_Toggle();
    }
    
    /**
     End of File
    

    */

    main code :

    #include "mcc_generated_files/mcc.h"
    
    /*
                             Main application
     */
    void main(void)
    {
        // initialize the device
        SYSTEM_Initialize();
    
        // When using interrupts, you need to set the Global and Peripheral Interrupt Enable bits
        // Use the following macros to:
    
        // Enable the Global Interrupts
        **INTERRUPT_GlobalInterruptEnable();
    **
        // Enable the Peripheral Interrupts
        INTERRUPT_PeripheralInterruptEnable();
    
        // Disable the Global Interrupts
        //INTERRUPT_GlobalInterruptDisable();
    
        // Disable the Peripheral Interrupts
        //INTERRUPT_PeripheralInterruptDisable();
    
        while (1)
        {
            // Add your application code
        }
    }
    

    these are the coding files....

    when i press the switch LED is not toggling ...

    not getting where is the problem in IOC(interrupt on change)..

    please help me to sort out... this is much needed to me..

     

    Last edit: Anobium 2020-11-10
    • Anobium

      Anobium - 2020-11-08

      Megha - we are the forum for Great Cow BASIC not MPLAB-IDE.

      But, you just need to use MMC (part of MPLAB-IDE) and this should work.

       
  • Megha Bhirade

    Megha Bhirade - 2020-11-09

    Hi thanks for reply..

    what is MMC in MPLAB...

    I used MCC - MPLAB CODE configurator ....

    i not hard about MMC can u please explain it

     
    • Anobium

      Anobium - 2020-11-09

      My apologies. I meant MCC not MMC. :-)

       
  • Megha Bhirade

    Megha Bhirade - 2020-11-09

    Thanks for your reply...

    I used MCC only for configuration but IOC not working...

    struggling to fix it but not getting where is the problem..

    tried to post in microchip but not able to post...

    please help me if you have any idea

     
  • Anobium

    Anobium - 2020-11-09

    The issue is we do Great Cow BASIC here and Great Cow BASIC generates ASM that you could use within your MPLAB-X project. Is this any use?

     
  • Megha Bhirade

    Megha Bhirade - 2020-11-09

    just tell me the steps to configure the IOC ...

    i took one pin RA0/pin2 as input and RA1/pin3 as switch...

    for input i selected IOC negative edge..

    wpu week pullup...

    output LED , digital..

    after generating the MCC project...

    ISR routine it generated ...

    void __interrupt() INTERRUPT_InterruptManager (void)
    {
    // interrupt handler
    if(PIE0bits.IOCIE == 1 && PIR0bits.IOCIF == 1)
    {
    PIN_MANAGER_IOC();
    }
    else
    {
    //Unhandled Interrupt
    }
    }
    /**

    i am trying to clear PTR0bits.IOCF = 0 in this interrupt handler but they given

    (The IOCIF bits are the logical OR of all the IOCAF-IOCEF flags.
    Therefore, to clear the IOCIF flag, application firmware should clear all of the lower level IOCAF-IOCEF register bits.)

    inside pin manager ioc i saw:

    IOCAFbits.IOCAF0 = 0;

    so where i am missing.... consider the steps and suggest me

     
  • Anobium

    Anobium - 2020-11-09

    I can look later, I need to install MPLAB etc.

     
  • Anobium

    Anobium - 2020-11-10

    Here is a Great Cow BASIC project. This is tested and works on a real chip.
    PB7 - switch
    PB6- LED

    This is truly simple and took about 5 minutes.

    Evan

    'Chip Settings.
    #CHIP 16f18875
    #OPTION Explicit
    
    
    #DEFINE SWITCH_DOWN         1
    #DEFINE SWITCH_UP           0
    
    #DEFINE SWITCH      PORTB.7
    Dir     SWITCH In
    
    #DEFINE LED         PORTB.6
    Dir     LED    Out
    
        On Interrupt PortChange call MyISR
        //IOCx registers
        //interrupt on change for group IOCBF - flag
        IOCBF7 = 0
        //interrupt on change for group IOCBN - negative
        IOCBN7 = 1
        //interrupt on change for group IOCBP - positive
        IOCBP7 = 1
    
        Do Forever
        Loop
    
        End
    
    
    Sub MyIsr
    
      PORTB.6 = !PORTB.6
    
      IOCBF7 = 0
    
    End Sub
    
     

    Last edit: Anobium 2020-11-10
  • Megha Bhirade

    Megha Bhirade - 2020-11-10

    can you try with Port A pins ..and try once....
    if possible try for MCC....
    needed for me

     
  • Anobium

    Anobium - 2020-11-10

    Great Cow BASIO with Porta.0 rather than Portb.6 as the swtich.

    'Chip Settings.
    #CHIP 16f18875
    #OPTION Explicit
    
    
    #DEFINE SWITCH_DOWN         1
    #DEFINE SWITCH_UP           0
    
    #DEFINE SWITCH      PORTA.0
    Dir     SWITCH In
    
    #DEFINE LED         PORTB.6
    Dir     LED    Out
    
        On Interrupt PortChange call MyISR
    
        //IOCx registers
        //interrupt on change for group IOCAF - flag
        IOCAF0 = 0
        //interrupt on change for group IOCAN - negative
        IOCAN0 = 1
        //interrupt on change for group IOCAP - positive
        IOCAP0 = 1
    
        Do Forever
        Loop
    
        End
    
    
    Sub MyIsr
    
      PORTB.6 = !PORTB.6
    
      IOCAF0 = 0
    
    End Sub
    

    This is very easy to do in Great Cow BASIC and you should be able to use the approach in MPLABX -IDE as ALL the registers are the same.

     
  • Megha Bhirade

    Megha Bhirade - 2020-11-10

    hi..
    i am checking by debugging mode after pressing the switch
    IOCAF0 bit is not setting....PIRbits.IOCF is not setting....
    what is the reason

     
  • Anobium

    Anobium - 2020-11-10

    I would be guessing. Not set as an input? not enabled the interrupts?

     
  • Megha Bhirade

    Megha Bhirade - 2020-11-10

    but IOCAN0 = 0x01 i can check while debugging..
    which is negative edge detection i setted...

     
    • Anobium

      Anobium - 2020-11-10

      Have you checked?

      //IOCx registers
      //interrupt on change for group IOCAF - flag
      IOCAF0 = 0
      //interrupt on change for group IOCAN - negative
      IOCAN0 = 1
      //interrupt on change for group IOCAP - positive
      IOCAP0 = 1
      
      And, porta.0 is an input? and not analog?
      
       
  • Megha Bhirade

    Megha Bhirade - 2020-11-10

    i setted
    IOCAF0 = 1 at initialization...

    IOCAN0 = 1
    IOCAP0 = 0...
    that first bit setting what will happen

     
  • Megha Bhirade

    Megha Bhirade - 2020-11-10

    i checked with
    IOCF0 = 0

    IOCANO = 1
    IOCAP0 = 0

    pin is input only and it is not analog

     
  • Megha Bhirade

    Megha Bhirade - 2020-11-10

    still also IOCAF0 bit is not setting
    means negative edge is not detecting..
    how to fix...

     
  • Anobium

    Anobium - 2020-11-10

    Sounds like you have no enabled the interrupts.

    Attach main.c please.

     
  • Megha Bhirade

    Megha Bhirade - 2020-11-10

    hi...
    i attached enabled global interrupt enable.
    peripheral interrupt enable..

    i shared main code previous post can you check once.
    please

     
1 2 3 4 > >> (Page 1 of 4)

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.