16F1823 - Can't get RA3 (MCLR) to be a switch input (attached switch resets PIC).


Closed Thread
Results 1 to 7 of 7
  1. #1
    Join Date
    Mar 2009
    Posts
    653

    Default 16F1823 - Can't get RA3 (MCLR) to be a switch input (attached switch resets PIC).

    Now I'm sure this is simple - but I've stared at it to the point where I now need to go for a shave, but I need to use PortA.3 (which can be a MCLR pin), as an 'input' for a tactile switch...I want to use an internal weak pullup on that pin too.

    What I'm getting Is the PIC resetting everytime I press the switch attached to pin 4 (PortA.3)....so it looks like MCLR is not being disabled. I've checked the associated .inc file in my PC's MPASM directory for the necessary syntax - i think i've got it right.

    I've slimmed my program down to the basics...just to get to the bottom of this. A simple loop, when either one of two switches are pressed, A DT interrupt happens & I get some syntax on screen - but it aint right, Sw1 doesn't interrupt at all, Sw2 does, but I just see "Interrupt Sw1" on my screen
    ...and it doesn't exit until I press Sw1 (which threw me, but then I put a litte trap at the top of my program & established that Sw1 was simply resetting the PIC)

    Top tips warmly received.....

    Code:
    @ __CONFIG _CONFIG1, _FCMEN_OFF & _FOSC_INTOSC & _WDTE_OFF & _MCLRE_OFF & _CP_OFF & _IESO_OFF & _BOREN_OFF & _PWRTE_OFF
    
    DEFINE  OSC 4
    INCLUDE "DT_INTS-14.bas"     ' Base Interrupt System  PO90OOO9
    INCLUDE "ReEnterPBP.bas"     ' Include if using PBP interrupts
    
    RCSTA = $90   ' Enable serial port & continuous receive
    TXSTA = $24   ' Enable transmit, BRGH = 1
    SPBRG = 8     ' 115200 Baud @ 4MHz, -3.55%
    SPBRGH = 0
    BAUDCON.3 = 1 ' Enable 16 bit baudrate generator
    
    '-------------------------------------------------------------------------
    
    Osccon = %01101010     'sets the internal oscillator 
    
    APFCON.2 = 0            ;Hserout onto RC.4 Pin 6
    ADCON0 = 0
    ADCON1 = 0
    
    CM1CON0 = 0   ' COMPARATORS OFF
    CM2CON0 = 0   ' COMPARATORS OFF
    
    ANSELA     = %00010000  
    ANSELC     = %00000100  
    TRISA      = %11111111
    TRISC      = %00000100  
    OPTION_REG.7 = 0
    
    WPUA  = %00101000
    IOCAN = %00101000 
    
    SW1    VAR PORTA.3
    SW2    VAR PORTA.5
    hserout ["reset", 13, 10]
    
    ASM
    INT_LIST  macro ; IntSource,    Label,         Type, ResetFlag?
        INT_Handler  IOC_INT,  _Switch_Interrupt,  PBP,  YES 
        endm
        INT_CREATE       ; Creates the interrupt processor
    ENDASM
           
    IOCAF = 0
    
    @ INT_ENABLE IOC_INT   ; Enable 'Int On Change' interrupts
    
    
    Loop1:
        hserout ["Waiting", 13, 10]
        pause 500
        GOTO Loop1
        'ENDIF
    
    
    '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    Switch_Interrupt:
    @ INT_DISABLE IOC_INT  ; Disable further IOC interrupts
    
            pause 10
            IF sw1 = 0 THEN
            HSEROUT ["INTERRUPT Sw1", 13, 10]
            goto interrupt_end
            endif
            
            IF sw2 = 0 THEN
            HSEROUT ["INTERRUPT Sw2", 13, 10]
            goto interrupt_end
            endif
    
    interrupt_end:     
    @ INT_ENABLE IOC_INT
    @ INT_RETURN 
    
    
    end
    Last edited by HankMcSpank; - 9th January 2011 at 01:33.

  2. #2
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    Make sure you include _LVP_OFF in CONFIG2 and test/clear IOCAF.3 and IOCAF.5 in your interrupt handler. The IOCAF bits will indicate which switch was pressed so you don't need to have a switch being held down or test for it.

    The /MCLR bit in CONFIG1 is ignored when LVP is enabled so it remains the reset input. LVP is enabled by default when you don't specifically clear it in CONFIG2.

    It never exits your interrupt because you're not clearing the IOCAF int flags in your int handler, so it's a continuous loop until reset by SW1 on /MCLR.
    Last edited by Bruce; - 9th January 2011 at 14:15.
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  3. #3
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by Bruce View Post
    Make sure you include _LVP_OFF in CONFIG2 and test/clear IOCAF.3 and IOCAF.5 in your interrupt handler. The IOCAF bits will indicate which switch was pressed so you don't need to have a switch being held down or test for it.
    Excellent stuff Bruce, the following line - containing the changes you siuggested - sorted my problem....
    Code:
    @ __CONFIG _CONFIG2, _LVP_OFF
    My RA3 pin now works as a digital input! (I've spent hours on this puppy - what a relief ...a hearty thanks for chiming in!)

    Now I'm sure you're going to say this snippet of (IMHO obscure!) info is in the datasheet?

  4. #4
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    See REGISTER 4-1:CONFIGURATION WORD 1 in the datasheet.

    If LVP = 1 the /MCLR bit is ignored and the pin remains the reset input. Since you didn't include CONFIG2 settings in your code, LVP defaulted to 1 ON and that caused the problem.

    I would get rid of the 10mS pause in the int handler, then test & clear whatever IOCAF flag bits are set to determine which switch was pressed. This is a really nice feature on the 16F1s since IOC pins have individual flag bits now. I.E. you don't need to read the port when the IOC happens any more.
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  5. #5
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by Bruce View Post
    See REGISTER 4-1:CONFIGURATION WORD 1 in the datasheet.

    If LVP = 1 the /MCLR bit is ignored and the pin remains the reset input. Since you didn't include CONFIG2 settings in your code, LVP defaulted to 1 ON and that caused the problem.

    I would get rid of the 10mS pause in the int handler, then test & clear whatever IOCAF flag bits are set to determine which switch was pressed. This is a really nice feature on the 16F1s since IOC pins have individual flag bits now. I.E. you don't need to read the port when the IOC happens any more.
    Thanks Bruce ....that 10ms pause has now gone (I can't recall why it was in there...obviously been dabbling at one point & it's remained!)

    Re testing for an IOCAF flag (to establish which switch has been pressed)...is there a win over vs checking for a 'Low'/0V as I'm doing presently? (if so, then I'll work out what needs to be done....but all the new registers on this IC are scrambling my head!)
    Last edited by HankMcSpank; - 9th January 2011 at 14:49.

  6. #6
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    You can test the input for 0, but any interrupt flag bits that get set should always be cleared before re-enabling the interrupt.
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  7. #7
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by Bruce View Post
    You can test the input for 0, but any interrupt flag bits that get set should always be cleared before re-enabling the interrupt.
    Thanks once again Bruce, here's my interrupt handler now (complete with a clear flag at the end!)...

    Code:
    Switch_Interrupt:
    @ INT_DISABLE IOC_INT  ; Disable further IOC while handling an IOC interrupt
    
            IF Sw1 = 0 AND Sw2 = 1 THEN           
            HSEROUT ["INTERRUPT Sw1", 13, 10]
            goto interrupt_end
            endif
            
            IF Sw1 = 1 AND Sw2 = 0 THEN
            HSEROUT ["INTERRUPT Sw2", 13, 10]
            goto interrupt_end
            endif
            
            IF Sw1 = 0 AND Sw2 = 0 THEN
            HSEROUT ["INTERRUPT Sw3", 13, 10]
            goto interrupt_end
            endif
     
            interrupt_end:
            IOCAF = 0
    @ INT_ENABLE IOC_INT
    
    @ INT_RETURN

Members who have read this thread : 2

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts