PDA

View Full Version : 16F946 Instant Interrupts problem



jderson
- 14th April 2009, 19:09
This program is supposed to count pulses on RB0 (INT), display count on LCD, and blink the LED. On power up, the LED blinks as it should, and the LCD displays zero, as it should. As pulses (~100hz) are applied, LED turns off and LCD displays the count. The count is updating at about a 1hz rate, for some reason. When the incoming pulses stop, the display shows the proper count, but the LED does nothing. I can't figure out why the TMR0 interrupt quits.

Pause 100 ;for ICSP
@ __config _WDT_OFF & _CP_OFF & _PWRTE_ON & _MCLRE_ON & _INTRC_OSC_NOCLKOUT

OPTION_REG = %11000000 ;pullups disabled, rising edge, no prescale
ANSEL = 0 ;all pins digital
CMCON0 = 7 ;comparators off
ADCON0 = 0 ;ADC's off
WDTCON = 0 ;WDT off

TRISA = %00000000
TRISB = %11000001 ;switches on RB6,RB7, INT on RB0
TRISC = %00000000 ;LED on RC5, LCD bias on RC3
TRISD = %00000000
TRISE = %00001000 ;MCLR on RE3
TRISF = %00000000
TRISG = %000000

OSCCON = %01100001 ;4 mhz. internal

T1CON = 0
TMR1L = 0
TMR1H = 0

T1 var word
T2 var word

SMCOUNT var byte
LED2 var PORTC.5

LCD_DB4 VAR PORTB.1
LCD_DB5 VAR PORTB.2
LCD_DB6 VAR PORTA.7
LCD_DB7 VAR PORTA.6
LCD_RS VAR PORTB.3
LCD_E VAR PORTD.2
LCD_Lines CON 1 ' # of Lines on LCD, 1 or 2 (Note: use 2 for 4 lines)
LCD_DATAUS CON 20 ' Data delay time in us
LCD_COMMANDUS CON 2000 ' Command delay time in us

INCLUDE "LCD_AnyPin.pbp" ; *** Include MUST be AFTER LCD Pin assignments ****


;----[ Your Main program starts here ]----------------------------------------

PAUSE 50 : LCDOUT $FE,1 : PAUSE 20 ; Initialize LCD (You may not need this,
; but some displays are picky)

smcount = 0

INCLUDE "DT_INTS-14.bas" ; Base Interrupt System
INCLUDE "ReEnterPBP.bas" ; Include if using PBP interrupts


ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler INT_INT, _CountRevs, PBP, yes
INT_Handler TMR0_INT, _ToggleLED2, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

OPTION_REG = OPTION_REG & $80 | 1 ; Set TMR0 Prescaler to 256, leave RBPU alone

@ INT_ENABLE INT_INT ; enable external (INT) interrupts
@ INT_ENABLE TMR0_INT ; enable Timer 0 interrupts

low PORTC.5
low PORTC.4
low PORTD.3


Main:

lcdout $fe,1, dec SMCOUNT
pause 10

goto Main


'---[INT - interrupt handler]---------------------------------------------------

CountRevs:

while PORTB.0 = 1
wend
while PORTB.0 = 0
wend
T1CON = 1
while PORTB.0 = 1
wend
while PORTB.0 = 0
wend
T1CON = 0
T1.HighByte = TMR1H
T1.LowByte = TMR1L
if T1 > 0 then
SMCOUNT = SMCOUNT + 1
TMR1L = 0
TMR1H = 0
endif

@ INT_RETURN


'---[TMR0 - interrupt handler]-------------------------------(Blinky Light)------
T0Count VAR WORD
ToggleLED2:
T0Count = T0Count + 1
IF T0Count = 256 THEN T0Count = 0 : TOGGLE LED2
@ INT_RETURN


Any help will be appreciated!

Bruce
- 14th April 2009, 19:48
If pulses stop while it's in the CountRevs interrupt service routine, interrupts are disabled,
and you'll be waiting forever in this routine until pulses start up again.

jderson
- 14th April 2009, 20:42
Thank you, Bruce. How do I fix it so it exits from the routine?

Bruce
- 14th April 2009, 22:20
How do I fix it so it exits from the routine?
You'll need to get rid of the WHILE WEND loops waiting for state changes on RB0.