PDA

View Full Version : DT INTs which int to use??



Heckler
- 11th March 2012, 22:37
working with a 16F690 PIC

My program is supposed to generate 1 or more pulses of specific length and quantity.

Thought I had Darrels Instant Interrupts working in my code...

But when I remarked out these lines (because I thought they were redundant with DT INT's)

'IOCB.7=1 'enable INT on change RB7
'IOCB.6=1 'enable INT on change RB6
'IOCB.5=1 'enable INT on change RB5 rotary push button

My rotary encoder stopped working.

I had this code in my program also... but I don't think I have the correct interrupt selected.


ASM
INT_LIST macro ; IntSource, Label, Type, Resetflag?
INT_Handler IOC_INT, _Encoder, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM



So my question is... How does one know which INT to use?? I am wanting to interrupt on change for B.5, B.6, B.7 and sometimes B.4 .
I am looking at the 16F690 documentation but am confused on exactly how to determine which INT to use.


I also would like to, at times, disable B.5,6&7 but keep B.4 as interruptable.

Here is my complete code...
#CONFIG
__CONFIG _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOD_OFF & _IESO_OFF & _FCMEN_OFF
#endconfig
include "ALLDIGITAL.pbp" ' makes all I/O pins digital, no analog
INCLUDE "DT_INTS-14.bas" ; Base Interrupt System
INCLUDE "ReEnterPBP.bas" ; Include if using PBP interrupts
wsave VAR BYTE $70 SYSTEM ' alternate save location for W
DEFINE OSC 4
Define LCD_DREG PORTC
Define LCD_DBIT 4
Define LCD_RSREG PORTA
define LCD_RSBIT 4
define LCD_EREG PORTA
define LCD_EBIT 5
define LCD_BITS 4
define LCD_LINES 4
define LCD_COMMANDUS 3000
define LCD_DATAUS 100
red var PortC.0
grn var PortC.1
sLCD var PortA.2 'serial LCD (if used)
TrisA = %00000000 'xx543210
TrisB = %11110000 '7654xxxx
TrisC = %00001000 '76543210
' N/U PortB.0 (output)
' N/U PortB.1 (output)
' N/U PortB.2 (output)
' N/U PortB.3 (output)
' N/U PortB.4 (input - to be grounded)
' Encoder PushButton PortB.5 (input)
' Encoder channel A PortB.6 (use pullups resistor if necessary)
' Encoder channel B PortB.7 (use pullups resistor if necessary)
'-------------------------------------------------------------------------
eeprom 0,[2,0,3,1,1,3,0,2]
PortB = 0
Flag var byte
BtnFlag var byte '0=adj P1, 1=adj P2, 2=adj Cnt
CFlag var bit
Q_New var Byte
Q_Old var byte
M_Count var byte [4]
P_Count var byte [4]
Q_Count var word
Low_Count var word
L var bit 'flag Rotate Left
R var bit 'flag Rotate Right
P1 var word ' first pulse value
P2 var word ' second pulse value
Cnt var word ' quantity of pulses to generate
Reps var word ' counter to loop for pulses
Cursor var word 'if 0 then P1, if 1 then P2, if 2 then Cnt
Busy var bit
P1=500 'default pulse width
P2=0 'default no second pulse toggle
Cnt=1 'default count of 1 pulse
cflag=0 'default to One pulse repitition
' ---------------------- Set variable value @ startup ----------------------
Start:
btnflag=0
Cursor=0
low_count = 100
Busy=0
For Q_Old = 0 to 3
Read Q_Old,M_Count[Q_Old]
Read Q_Old + 4,P_Count[Q_Old]
Next Q_Old

Q_Count = 0
Q_New = 0
Q_Old = 0
Flag = 0
'IOCB.7=1 'enable INT on change RB7
'IOCB.6=1 'enable INT on change RB6
'IOCB.5=1 'enable INT on change RB5 rotary push button

ASM
INT_LIST macro ; IntSource, Label, Type, Resetflag?
INT_Handler IOC_INT, _Encoder, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
low PortC.2 'initialize contact output
pause 1000
Lcdout $FE, 1 ' Clear LCD screen
Lcdout $FE,$80,"Pulse Generator" ' Display message
'serout2 slcd,16468,[$FE,$80,"Pulse Generator"]
'serout2 SLCD,16468,[$1b, $2a, $20]
pause 500
lcdout $FE,$C0+19,"<" 'initial pointer on P1
'serout2 slcd,16468,[$FE,$C0+19,"<"]
gosub disp1
gosub DisP2
gosub DisC
Pause 500 ' Wait .5 second
sound PortA.0,[90,5,100,5,110,5]
'===============================
'================================================= ==========
'======= Main Program Loop ==========================
'================================================= ==========
Main_Loop:
@ INT_ENABLE IOC_INT ; enable external (INT) interrupts
if PortB.4=0 then gosub pulseout ' "GO" button pushed so generate pulses
if PortC.3=0 then ' "Toggle" button pushed so invert output
Toggle PortC.2
sound PortA.0,[120,2]
do while PortC.3=0 : loop 'wait for button to be released
endif
if flag=0 then main_loop 'no activity from rotary encoder
'@ INT_DISABLE ; DISABLE external (INT) interrupts
if btnflag=1 then
if Cursor=0 then ' erase Cursor on Row 2
lcdout $FE,$C0+19," "
'serout2 slcd,16468,[$FE,$C0+19," "]
endif
if Cursor=1 then ' erase Cursor on Row 3
lcdout $FE,$94+19," "
'serout2 slcd,16468,[$FE,$94+19," "]
endif
if Cursor=2 then ' erase Cursor on Row 4
lcdout $FE,$D4+19," "
'serout2 slcd,16468,[$FE,$d4+19," "]
endif

Cursor=Cursor+1 ' now increment Cursor position
if (p2>0) and (Cursor=3) then Cursor=0
if (p2=0) and (Cursor=2) then 'skip moving cursor to 4th row
Cursor=0 'instead goto row 2
cnt=1
gosub DisC
endif
btnflag=0
if Cursor=0 then 'display cursor on row 2
lcdout $FE,$C0+19,"<"
'serout2 slcd,16468,[$FE,$C0+19,"<"]
endif

if Cursor=1 then 'display cursor on row 3
lcdout $FE,$94+19,"<"
'serout2 slcd,16468,[$FE,$94+19,"<"]
endif

if Cursor=2 then 'display cursor on row 4
lcdout $FE,$D4+19,"<"
'serout2 slcd,16468,[$fe,$d4+19,"<"]
endif
sound PortA.0,[100,2]
endif
if Cursor=1 then goto p2counter
if Cursor=2 then goto ccounter
'else fall through to P1Counter
'-------------------------------
' adjust value of P1
'-------------------------------
P1Counter:
if r =1 then
high grn 'rotation is Right so Incriment
if p1>999 then
p1=p1+100

elseif p1>99 then
P1=P1+10
else
p1=p1+1
endif
if p1>10000 then p1=0

gosub DisP1
r=0
endif
if l =1 then
High red 'rotation is Left so Decriment
if p1>1000 then
p1=p1-100
elseif p1>100 then
P1=P1-10
else
p1=p1-1
endif
if p1>65000 then p1=10000

gosub DisP1
l=0
endif
goto Main_Loop
'-------------------------------
' adjust value of P2
'-------------------------------
P2Counter:
if r=1 then
high grn 'rotation is Right so Incriment
if p2>999 then
p2=p2+100

elseif p2>99 then
P2=P2+10
else
p2=p2+1
endif
if p2>10000 then p2=0

gosub DisP2
r=0
endif
if l=1 then
High red 'rotation is Left so Decriment
if p2>1000 then
p2=p2-100
elseif p2>100 then
P2=P2-10
else
p2=p2-1
endif
if p2>65000 then p2=10000

gosub DisP2
l=0
endif

goto main_loop
'-------------------------------
' adjust value of Cnt
'-------------------------------
CCounter:
if r=1 then 'rotation is Right so Incriment
high grn
if cnt>999 then
cnt=cnt+100

elseif cnt>99 then
cnt=cnt+10
else
cnt=cnt+1
endif
if cnt>10000 then cnt=0

gosub DisC
r=0
endif
if l=1 then 'rotation is Left so Decriment
High red
if cnt>1000 then
cnt=cnt-100
elseif cnt>100 then
cnt=cnt-10
else
cnt=cnt-1
endif
if cnt>65000 then cnt=10000

gosub DisC
l=0
endif

goto main_loop
'-------------------------------
' Update LCD display
'-------------------------------
DisP1:
If P1>999 then P1Sec 'change to seconds instead of milliseconds
P1Ms:
lcdout $FE,$C0,"1st Pulse= ",dec3 P1," mS "
'serout2 slcd,16468,[$FE,$C0,"1st Pulse= ",dec3 p1," mS "]
goto donelcd
P1Sec:
if P1=10000 then
lcdout $FE,$C0,"1st Pulse= ",dec2 (P1/1000),".",dec1 (p1/100)," Sec"
'serout2 slcd,16468,[$FE,$C0,"1st Pulse= ",dec2 (P1/1000),".",dec1 (p1/100)," Sec"]
else
lcdout $FE,$C0,"1st Pulse= ",dec1 (P1/1000),".",dec1 (p1/100)," Sec "
'serout2 slcd,16468,[$FE,$C0,"1st Pulse= ",dec1 (P1/1000),".",dec1 (p1/100)," Sec "]
endif
goto DoneLCD
DisP2:
if P2>999 then P2Sec 'change to seconds instead of milliseconds
P2Ms:
lcdout $FE,$94,"2nd Pulse= ",dec3 P2," mS "
'serout2 slcd,16468,[$FE,$94,"2nd Pulse= ",dec3 P2," mS "]
goto donelcd
P2Sec:
If P2=10000 then
lcdout $FE,$94,"2nd Pulse= ",dec2 (P2/1000),".",dec1 (p2/100)," Sec"
'serout2 slcd,16468,[$FE,$94,"2nd Pulse= ",dec2 (P2/1000),".",dec1 (p2/100)," Sec"]
else
lcdout $FE,$94,"2nd Pulse= ",dec1 (P2/1000),".",dec1 (p2/100)," Sec "
'serout2 slcd,16468,[$FE,$94,"2nd Pulse= ",dec1 (P2/1000),".",dec1 (p2/100)," Sec "]
endif
goto DoneLCD

DisC:
if cnt = 10000 then
lcdout $FE,$d4,"Continuous Pulses "
goto DoneLCD
endif
if cnt <10 then
lcdout $FE,$d4,"Pulse Count= ",dec cnt," " 'need extra space char
else
lcdout $FE,$d4,"Pulse Count= ",dec cnt," "
'?? serout2 slcd,16468,[$FE,$d4,"Pulse Count= ",dec cnt," "]
endif
DoneLCD:
Flag = 0 ' reset flag after display updated
low red
low grn
return
'-------------------------------
' Generate desired Pulse
'-------------------------------
PulseOut:
'@ INT_DISABLE RABC_INT ; disable external (INT) interrupts
sound PortA.0,[75,2]
Busy=1
Continuous:
if cnt=10000 then 'do continuous pulses
Toggle PortC.2
pause P1
Toggle PortC.2
pause p2
goto Continuous 'do unitl Rotary button pushed
endif

for reps=1 to cnt
Toggle PortC.2
pause P1
Toggle PortC.2
pause p2
next reps
if (cnt=1) and(P2>0) then Toggle PortC.2 'on/off/on or off/on/off

sound PortA.0,[100,10,50,10]
pause 500
Busy=0
return 'to Main program loop
'================================================= ===============
'======================================
'-- Rotary Encoder Interrupt Handler --
'======================================
Encoder: ' ISR
If PortB.5=0 then 'INT caused by encoder push button
btnflag=1
do while PortB.5=0 : loop
goto Exitint
endif
Q_New = PortB.7 + PortB.7 + PortB.6 ' get port status
'--------------------
' decriment -
'--------------------
If M_Count[Q_Old] = Q_New then ' if M_Count code satisfied then minus
Q_count = Q_Count - 1
r=1 ' Set Left Flag
goto Q_Skip
endif
'--------------------
' incriment -
'--------------------
If P_Count[Q_Old] = Q_New then ' if M_Count code satisfied then plus
Q_Count = Q_Count + 1
l=1 ' Set Right Flag
endif
Q_Skip:
Q_Old = Q_New ' update Q_Old Byte
ExitInt:
flag=1
@ INT_RETURN



Also a little unsure of EXACT syntax when using instant interrupts with regard to how many spaces, etc. when defining the interrupts.

HankMcSpank
- 12th March 2012, 00:08
I used to use a 16f690 (but haven't for ages....the more modern version 16f1828 is much nicer with respect to IOC...unless you are specifically tied to the 16f690 I heartily recommend getting/using a 16f1828 instead...it's pin for pin compatible to the 16f690) ), but here's an old thread where I was struggling with my 16f690 , Bruce sailed to the rescue...

http://www.picbasic.co.uk/forum/showthread.php?t=13558

there's an example IOC for a 16f690 zip file attached to the post (near the bottom of that page) ...that should show you how to approach IOC on a 16f690.

Heckler
- 12th March 2012, 20:09
Thanks Spankey...

I followed that thread you referenced and could see that in that case with the 16f690 they used RABC_INT... and I used that in my latest code and it is working. Although I did have to un-comment the lines [CODE]['IOCB.7=1 'enable INT on change RB7
'IOCB.6=1 'enable INT on change RB6
'IOCB.5=1 'enable INT on change RB5 rotary push button/CODE]

So I guess they are not redundant with DT-INT's


What I am not understanding is how does one determine that RABC_INT is the correct one for 16f690 from the microchip documentation. I searched the .pdf for that PIC and it fails to even find "rabc".

I also would like clarification on the exact syntax of setting up DT-INT's. ie. where and how many spaces are required at the beginning and inside of each line of the code

Help me "mister wizard" er... Darrell

Heckler
- 12th March 2012, 22:01
So, for clarification, here is what I have that is working...



IOCB=%11110000 'enable INT on change RB 7,6,5,4

ASM
INT_LIST macro ; IntSource, Label, Type, Resetflag?
INT_Handler RABC_INT, _Binthndlr, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM



Note that I changed the individual ...

'IOCB.7=1 'enable INT on change RB7
'IOCB.6=1 'enable INT on change RB6
'IOCB.5=1 'enable INT on change RB5 rotary push button

Into one statement...

IOCB=%11110000 'enable INT on change RB 7,6,5,4
(and added the additional bit that enables IOC on B.4)

But I still wonder which part of my code is actually enabling the INT on change. As I look over at darrel's web page where he gives examples I do not see anywhere that he has to manipulate the registers to enable the INT's.

So I am back to thinking that it is really my code
IOCB=%11110000 that is making the INT's work and part of Darrel's code that tells the PIC where to jump to on INT. "Binthndler"

still confused

HankMcSpank
- 13th March 2012, 00:23
To know which Int to use, you need to be a bit of a sleuth, the same thread...

http://www.picbasic.co.uk/forum/showthread.php?t=13558&p=92315#post92315 (checkout Bruce's post #30)

I think you need to open dts_int-14.bas, do a search within for RABC, you should see these entries...



#define RAC_INT INTCON,RAIF, INTCON,RAIE ;-- RA Port Change *
#define RBC_INT INTCON,RBIF, INTCON,RBIE ;-- RB Port Change
#define RABC_INT INTCON,RABIF, INTCON,RABIE ;-- RAB Port Change


....see which one of those bolded registers a 16f690 actually has & then use the associated DTS Int. (eg search the data sheet for RAIF...nothing, RBIF...nothing, RABIE ...bingo ...so use the RABC_INT)