external interrupts too slow
hallo,
I have a problem with external interrupt of port_B. I'm using a SX28 with 50MHz clock.
In my project I must check 3 external signal (square wave) by RB.0, RB.1 and RB.2. The frequency of RB.0 is about 100Hz, RB.1 about 120Hz and RB.2 = 15Hz.
RB0 and RB1 signal come from a proximity sensors (installed in front and rear wheel of motorbike). RB2 come from engine RPM signal. All signals are very clear (0 to 5V).
In main program I increase 2 counters (16bit counter_fr and counter_rr) every 15uSec (by PAUSEUS 15). In the interrupt subroutine, I save the value of counter.
If the difference between counter_fr and counter_rr is too big (depend on value of RA port) on a extra control start on RB3. RB3 drive a power Pmos. Basically the RB3 go to 0 for 1 period of RB2 signal and come back to 1 for the next "some" periods (depend on value of RA port).
The program is the following:
[code]
'
' Program Description
'
'
'
' Device Settings
'
DEVICE SX28, OSCHS2, TURBO, STACKX, OPTIONX
FREQ 50_000_000, 45_000_000
'IRC_CAL IRC_4MHZ
'
' IO Pins
'
'fr_sensor VAR RB.0 'impulsi da sensore ruota anteriore
'rr_sensor VAR RB.1 'impulsi da sensore ruota posteriore
'rpm_sensor VAR RB.2 'impulsi da giri motore
t_control VAR RB.3 'uscita controllo MOS di potenza
'RB.3 pilota il MOS
'RA
I have a problem with external interrupt of port_B. I'm using a SX28 with 50MHz clock.
In my project I must check 3 external signal (square wave) by RB.0, RB.1 and RB.2. The frequency of RB.0 is about 100Hz, RB.1 about 120Hz and RB.2 = 15Hz.
RB0 and RB1 signal come from a proximity sensors (installed in front and rear wheel of motorbike). RB2 come from engine RPM signal. All signals are very clear (0 to 5V).
In main program I increase 2 counters (16bit counter_fr and counter_rr) every 15uSec (by PAUSEUS 15). In the interrupt subroutine, I save the value of counter.
If the difference between counter_fr and counter_rr is too big (depend on value of RA port) on a extra control start on RB3. RB3 drive a power Pmos. Basically the RB3 go to 0 for 1 period of RB2 signal and come back to 1 for the next "some" periods (depend on value of RA port).
The program is the following:
[code]
'
' Program Description
'
'
'
' Device Settings
'
DEVICE SX28, OSCHS2, TURBO, STACKX, OPTIONX
FREQ 50_000_000, 45_000_000
'IRC_CAL IRC_4MHZ
'
' IO Pins
'
'fr_sensor VAR RB.0 'impulsi da sensore ruota anteriore
'rr_sensor VAR RB.1 'impulsi da sensore ruota posteriore
'rpm_sensor VAR RB.2 'impulsi da giri motore
t_control VAR RB.3 'uscita controllo MOS di potenza
'RB.3 pilota il MOS
'RA
Comments
Post Edited (JonnyMac) : 8/8/2008 6:54:03 PM GMT
Your propouse is interesting. I'll try tomorrow (now in Italy is already night).
In a my old project I already use 3 external interrupt with the same signal: 2 SX28, the first one to drive a LCD display and a eeprom and the second one to control the external interrupts. Basically that system worked well until 400Hz frequency for RB0 and RB1 and 200Hz for RB2. The old project did the same job as the new one. For this reason actually I don't understand why the new one don't work well.
I want a post the code of old project (of SX28 who control external interrupts):
[code]
DEVICE SX28, OSC4MHZ, TURBO, STACKX, OPTIONX
FREQ 4_000_000
IRC_CAL IRC_4MHZ
'ID "GRIPOne_004"
'
' IO Pins
'
fr_sensor VAR RB.0 'impulsi da sensore ruota anteriore
rr_sensor VAR RB.1 'impulsi da sensore ruota posteriore
rpm_sensor VAR RB.2 'impulsi da giri motore
t_control VAR RC.0 'uscita controllo MOS di potenza
'RC.0 pilota il MOS
'RA.0 - RA.1 sono utilizzati per lo scambio dei dati con il master
'
' Constants
'
spin_base CON 102
rpm_limit CON 25
limite_taglio CON 20
controllo_ON CON 0
controllo_OFF CON 1
'
' Variables
'
vettore1 VAR byte(16) 'array di variabili byte del bank1
byte1 VAR vettore1(0)
byte2 VAR vettore1(1)
byte4 VAR vettore1(3)
spinning VAR vettore1(4) 'valore massimo di pinning accettato per non attivare il controllo
taglio VAR vettore1(5) 'numero di cicli tra un taglio e l'altro
controllo VAR vettore1(6) 'stato del controllo di trazione: 0=off, 1=on
decimali VAR vettore1(7)
sr VAR vettore1(8) 'sviluppo ruota posteriore (185..220 cm)
sf VAR vettore1(9) 'sviluppo ruota anteriore (185..220 cm)
pr VAR vettore1(10) 'impulsi ruota posteriore (3..6 impulsi/giro)
pf VAR vettore1(11) 'impulsi ruota anteriore (3..6 impulsi/giro)
ratio_l VAR vettore1(12)
ratio_h VAR vettore1(13)
spin_l VAR vettore1(14)
spin_h VAR vettore1(15)
vettore2 VAR byte(16) 'array di variabili byte del bank1
cicli VAR vettore2(0)
rpm VAR vettore2(1)
spin_counter VAR vettore2(2)
taglio_limit VAR vettore2(3)
n_bit VAR vettore2(4)
filtro_rpm VAR vettore2(5)
word1 VAR Word
word2 VAR Word
word3 VAR Word
word4 VAR Word
counter_fr VAR Word
counter_rr VAR Word
last_fr VAR Word
last_rr VAR Word
byte_interrupt VAR byte '0=fr, 1=rr, 2=rpm
byte3 VAR byte
bit_rx VAR byte3.0
'
INTERRUPT
'
ISR_Start:
WKPND_B = byte_interrupt ' get byte_interrupt
Ch1: ' check channel
IF byte_interrupt <> %00000001 THEN GOTO Ch2 ' if not, try next
last_fr = counter_fr 'quando l'ingresso cambia di stato salvo il valore del contatore e azzero il contatore
counter_fr = 0
GOTO ISR_Exit
Ch2:
IF byte_interrupt <> %00000010 THEN GOTO Ch2b ' if not, try next
last_rr = counter_rr 'quando l'ingresso cambia di stato salvo il valore del contatore e azzero il contatore
counter_rr = 0
GOTO ISR_Exit
Ch2b:
Ch3:
IF byte_interrupt <> %00000100 THEN GOTO ISR_Exit
IF filtro_rpm < rpm_limit THEN GOTO ISR_Exit
filtro_rpm = 0
IF controllo = 1 THEN
IF taglio < taglio_limit THEN
IF cicli < taglio THEN 'se cicli = 0 e taglio = 0 non ci deve essere controllo in ogni caso, altrimenti dipende da "controllo"
IF cicli <= rpm THEN 'se cicli < taglio e cicli = 0 apro il MOS
t_control = controllo_ON
ELSE
t_control = controllo_OFF
ENDIF
INC cicli
ELSE
cicli = 0
ENDIF
ELSE
t_control = controllo_OFF
ENDIF
ELSE
t_control = controllo_OFF
ENDIF
GOTO ISR_Exit
ISR_Exit:
WKEN_B = %11111000 ' prepare for new ISR
WKPND_B = %00000000 ' clear pending
RETURNINT
'
' Subroutine Declarations
'
CHECK_SPINNING SUB 0 'calcola il valore spinning
CALCOLA_RATIO SUB 0 'calcola il valore ratio dato dallo svilluppo ruote e dal numero di impulsi per giro
LEGGI_BYTE SUB 0
LEGGI_DATI SUB 0
' =========================================================================
PROGRAM Start
' =========================================================================
'
' Program Code
'
Start:
TRIS_B = %00000111 ' imposto gli ingressi e le uscite della porta B
TRIS_C = %00001000 ' imposto gli ingressi e le uscite della porta C
TRIS_A = %1111 ' imposto gli ingressi e le uscite della porta A
WKPND_B = %00000000 ' clear pending
WKED_B = %11111111 ' falling edge detect
WKEN_B = %11111000 ' use bits 0..2 for inputs
WKPND_B = %00000000 ' clear pending
'ASM 'disattivo la resistenza di pull up su tute le porte
'mov M,#$0E 'MODE=0Eh to access port pullup registers
'
'mov W,#$0F 'W = 0000 1111
'mov !RA,W 'disable pullups for RA0 and RA3
'
'mov W,#$FF 'W = 1111 1111
'mov !RB,W 'disable all pullups for RB0-RB7
'
'mov W,#$FF 'W = 1111 1111
'mov !RC,W 'disable all pullups for RC0-RC7
'ENDASM
'inizializzazione variabili
t_control = controllo_OFF
last_fr = 6553
last_rr = 6553
counter_fr = 0
counter_rr = 0
filtro_rpm = 0
spin_counter = 1
controllo = 0
byte_interrupt = 0
byte1 = 0
cicli = 0
'lettura dei parametri dal master
PAUSE 550
LEGGI_DATI
Main:
PAUSEUS 15
IF counter_fr < 65535 THEN
INC counter_fr
ENDIF
IF counter_rr < 65535 THEN
INC counter_rr
ENDIF
IF filtro_rpm < 255 THEN
INC filtro_rpm
ENDIF
IF RA.1 = 1 THEN
LEGGI_DATI 'verifico in polling se il master sta inviando i dati di configrazione
PAUSE 400
ENDIF
INC byte1
IF byte1 < 200 THEN GOTO Main
CHECK_SPINNING
byte1 = 0
GOTO Main
'
' Subroutines Code
'
LEGGI_DATI:
spinning = LEGGI_BYTE
taglio = LEGGI_BYTE
sf = LEGGI_BYTE
pf = LEGGI_BYTE
sr = LEGGI_BYTE
pr = LEGGI_BYTE
rpm = LEGGI_BYTE
IF taglio = 0 THEN
WKEN_B = %11111100 ' use bits 0..2 for inputs
t_control = controllo_OFF
ENDIF
taglio = limite_taglio - taglio 'se rpm = 1 il segnale dei giri
Which is the meaning of "isrFlag = 1" in the 2line of interrupt subroutine ????
Thanks in advance
Basically I moved the "INC counter" in interrupt subroutine so in the main program remain only the call to CHECK_SPINNING and LEGGI_DATI subroutines.... I think that it is easier fix like this:
Thanks a lot for your help
Your code work very well!!! I also used the IsrFlag to trigger the foreground loop and everything is perfect.
Thank a lot