PDA

View Full Version : 16f886 interrupt on portB problem



antonjan
- 8th October 2008, 11:21
I don’t seem to get the portb interrupt on change working on 16f886….
Please need help.

I must Be doing something wrong with the enabling of interrupt or disabling the secondary port functions on portb.

antonjan
- 8th October 2008, 11:57
'******************************
'Portb 4-7 as inputs for interrupt
'using hserout to do debug
'using portc for output to see if there is anything happening
'I can read the port and send the values to hserout and works ok
'But interrupt don't work ??
'******************************
INCLUDE "MODEDEFS.BAS" '
@ DEVICE PIC16F886
@ DEVICE HS_OSC
define LOADER_USED 1 ' using a loader, OK to leave in if a loader is not used
define OSC 20 ' this example uses a 20MHz clock
DEFINE HSER_RCSTA 90h 'rx enable
DEFINE HSER_TXSTA 20h 'tx enable
DEFINE HSER_BAUD 9600 ' set baud rate to 19200
DEFINE HSER_CLOERR 1 ' automatic clear overrun error
TRISC = %10000000 ' PORTC.7 is the RX input, PORTC.6 is the TX output

Old_Bits VAR BYTE
New_Bits VAR BYTE
Minute var byte ' Define minute variable
Second var byte ' Define second variable
Ticks var byte ' Define pieces of seconds variable
DoUpdate var byte ' Define variable to indicate update
intPortb var BYTE 'THE PORTB REGISTER STORE
DoUpdate = 1 ' Force first display
'OPTION_REG RBPU INTEDG T0CS T0SE PSA PS2 PS1 PS0
OPTION_REG = %01010111
ADCON1 = 7 ' 00000111
CM1CON0 = 0 'DISABLE COMPARITORS
CM2CON0 = 0 'DISABLE COMPARITORS
ANSELH = %00000000 '0= DIGITAL 1= ANALOG PORTB -,-,ANS13,ANS12,ANS11,ANS10,ANS9,ANS8
ANSEL = %00000000 '0= DIGITAL 1= ANALOG PORTB -,-,ANS13,ANS12,ANS11,ANS10,ANS9,ANS8
'Addr Name Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 Value on POR, BOR Page
'0Bh INTCON GIE PEIE T0IE INTE RBIE T0IF INTF RBIF(1) 0000 000x 31,217
INTCON = %10001000 '%10001000 port b int on change and global interrupt enable
'bit 7 = GIE: Global Interrupt Enable bit
'bit 6 = PEIE: Peripheral Interrupt Enable bit
'bit 5 = T0IE: Timer0 Overflow Interrupt Enable bit
'bit 4 = INTE: INT External Interrupt Enable bit
'bit 3 = RBIE: PORTB Change Interrupt Enable bit(1)
'bit 2 = T0IF: Timer0 Overflow Interrupt Flag bit(2)
'bit 1 = INTF: INT External Interrupt Flag bit
'bit 0 = RBIF: PORTB Change Interrupt Flag bit
IOCB.0=0 'ENABLE INERRUPT ON CHANGE PIN ON PORT B (W3)
IOCB.4=0 'ENABLE INERRUPT ON CHANGE PIN ON PORT B (W1)
IOCB.5=0 'ENABLE INERRUPT ON CHANGE PIN ON PORT B (E3)
IOCB.6=0 'ENABLE INERRUPT ON CHANGE PIN ON PORT B (E2)
IOCB.7=0 'ENABLE INERRUPT ON CHANGE PIN ON PORT B (E1)
TRISB = %11111001 'PORT B INPUT OUTPUT SETTINGS 1=INPUT 0=OUTPUT
CM1CON0 = 0
CM2CON0 = 0
WPUB = %111110001 '1=PULL UP O=PULL UP DISABLE PORTB WEAK PULL-UP
LOW PORTC.4 'BATTERY CHARGE ON
'Interrupt Source Enabled by Completion Status
'RB4–RB7 state change RBIE = 1 RBIF =1
B0 VAR BYTE
B0 =PORTB
intPortb = PORTB

On Interrupt Goto TickInterrupt

' Main program loop
MainLoop:
B0=PORTB
HSEROUT ["PORTB ",#B0,13,10]
pause 500
if DoUpdate then
B0=PORTB
HSEROUT ["PORTB INTERUPT ",#PORTB ,13,10]
TOGGLE PORTC.0

DoUpdate = 0
endif
Goto MainLoop

' Interrupt routine to handle each timer tick
' Disable interrupts during interrupt handler
disable
TickInterrupt:

DoUpdate = 1 ' Set update
TOGGLE PORTC.0

ExitInterrupt:
INTCON.2 = 0 ' TOIF Reset timer interrupt flag
INTCON.0 = 0 ' RBIF Clear interrupt flag portb
Resume

sougata
- 8th October 2008, 13:46
Hi,

If I remember correct then you need to read the portb to end the mismatch condition.
This has to be done inside the ISR.




TEMP = PORTB ' temp is some variable


This should end your interrupt condition.

Bruce
- 8th October 2008, 15:15
Also - set each IOCB bit instead of clearing them. 1= int enabled. 0= int disabled.

sougata
- 8th October 2008, 20:00
INTCON = %10001000 '%10001000 port b int on change and global interrupt enable
'bit 7 = GIE: Global Interrupt Enable bit
'bit 6 = PEIE: Peripheral Interrupt Enable bit
'bit 5 = T0IE: Timer0 Overflow Interrupt Enable bit
'bit 4 = INTE: INT External Interrupt Enable bit
'bit 3 = RBIE: PORTB Change Interrupt Enable bit(1)
'bit 2 = T0IF: Timer0 Overflow Interrupt Flag bit(2)
'bit 1 = INTF: INT External Interrupt Flag bit
'bit 0 = RBIF: PORTB Change Interrupt Flag bit
IOCB.0=0 'ENABLE INERRUPT ON CHANGE PIN ON PORT B (W3)
IOCB.4=0 'ENABLE INERRUPT ON CHANGE PIN ON PORT B (W1)
IOCB.5=0 'ENABLE INERRUPT ON CHANGE PIN ON PORT B (E3)
IOCB.6=0 'ENABLE INERRUPT ON CHANGE PIN ON PORT B (E2)
IOCB.7=0 'ENABLE INERRUPT ON CHANGE PIN ON PORT B (E1)


Is it my head ????

Thanks Bruce for pointing out (Not that I am getting dumber)........ the IOCB bits

antonjan
- 8th October 2008, 20:06
It seems to have been the wrong setting on IOCB register
I cleared the bits and was not setting them.
Here is a copy off the working program.
I was compiled with PBP ASM


'************************************************* ***************
INCLUDE "MODEDEFS.BAS" '
@ DEVICE PIC16F886
@ DEVICE HS_OSC
define LOADER_USED 1 ' using a loader, OK to leave in if a loader is not used
define OSC 20 ' this example uses a 20MHz clock
DEFINE HSER_RCSTA 90h 'rx enable
DEFINE HSER_TXSTA 20h 'tx enable
'DEFINE HSER_SPBRG 25h

DEFINE HSER_BAUD 9600 ' set baud rate to 19200
DEFINE HSER_CLOERR 1 ' automatic clear overrun error
TRISC = %10000000 ' PORTC.7 is the RX input, PORTC.6 is the TX output

Old_Bits VAR BYTE
New_Bits VAR BYTE
Minute var byte ' Define minute variable
Second var byte ' Define second variable
Ticks var byte ' Define pieces of seconds variable
DoUpdate var byte ' Define variable to indicate update
intPortb var BYTE 'THE PORTB REGISTER STORE

clear ' clear all RAM (sets all VAR declarations to zero)
DoUpdate = 1 ' Force first display
'OPTION_REG RBPU INTEDG T0CS T0SE PSA PS2 PS1 PS0
OPTION_REG = %01010111
ADCON1 = 7 ' 00000111
CM1CON0 = 0 'DISABLE COMPARITORS
CM2CON0 = 0 'DISABLE COMPARITORS
ANSELH = %00000000 '0= DIGITAL 1= ANALOG PORTB -,-,ANS13,ANS12,ANS11,ANS10,ANS9,ANS8
ANSEL = %00000000 '0= DIGITAL 1= ANALOG PORTB -,-,ANS13,ANS12,ANS11,ANS10,ANS9,ANS8
'Addr Name Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
'0Bh INTCON GIE PEIE T0IE INTE RBIE T0IF INTF RBIF
INTCON = %10001000 '%10001000 port b int on change and global interrupt enable
'bit 7 = GIE: Global Interrupt Enable bit
'bit 6 = PEIE: Peripheral Interrupt Enable bit
'bit 5 = T0IE: Timer0 Overflow Interrupt Enable bit
'bit 4 = INTE: INT External Interrupt Enable bit
'bit 3 = RBIE: PORTB Change Interrupt Enable bit(1)
'bit 2 = T0IF: Timer0 Overflow Interrupt Flag bit(2)
'bit 1 = INTF: INT External Interrupt Flag bit
'bit 0 = RBIF: PORTB Change Interrupt Flag bit
IOCB.0=1 'ENABLE INERRUPT ON CHANGE PIN ON PORT B (W3) <<<<fix
IOCB.4=1 'ENABLE INERRUPT ON CHANGE PIN ON PORT B (W1) <<<<fix
IOCB.5=1 'ENABLE INERRUPT ON CHANGE PIN ON PORT B (E3) <<<<fix
IOCB.6=1 'ENABLE INERRUPT ON CHANGE PIN ON PORT B (E2) <<<<fix
IOCB.7=1 'ENABLE INERRUPT ON CHANGE PIN ON PORT B (E1) <<<<fix
TRISB = %11111001 'PORT B INPUT OUTPUT SETTINGS 1=INPUT 0=OUTPUT
CM1CON0 = 0
CM2CON0 = 0
WPUB = %111110001 '1=PULL UP O=PULL UP DISABLE PORTB WEAK PULL-UP
LOW PORTC.4 'BATTERY CHARGE ON
'Interrupt Source Enabled by Completion Status
'RB4–RB7 state change RBIE = 1 RBIF =1
B0 VAR BYTE
B0 =PORTB
intPortb = PORTB

On Interrupt Goto TickInterrupt

' Main program loop
MainLoop:
B0=PORTB
HSEROUT ["PORTB ",#B0,13,10]

pause 500
if DoUpdate then
B0=PORTB
HSEROUT ["PORTB INTERUPT ",#PORTB ,13,10]
TOGGLE PORTC.0

DoUpdate = 0
endif
Goto MainLoop

' Interrupt routine to handle each timer tick
' Disable interrupts during interrupt handler
disable
TickInterrupt:

DoUpdate = 1 ' Set update
b0 = PORTB ' temp is some variable
ExitInterrupt:
INTCON.2 = 0 ' TOIF Reset timer interrupt flag
INTCON.0 = 0 ' RBIF Clear interrupt flag portb
Resume
'*************************************************