PDA

View Full Version : Timer Interrupt to exit a closed loop



duncan303
- 11th December 2007, 14:12
Hi,
Damn I am struggling lately, I could really use some help right now.
I have a program that is capturing different data from both CCP modules, the routine is started by an interrupt on a comparator and I am attempting to limit the duration that the ccp modules are capturing by setting a timer for approx 200ms.

What Is hapening is that the interrupt timer is flagged but it is looping through the routine again, but only once.

I have identified where the problem lies and I have stripped out the irrelevant code.

As can be seen I am using Darrel's Instant Interrupts. I have tried rearanging the placement of the timer0 commands, timer on/off enable/disable I have disabled the flag and set those manually in the INTCON but all to no avail.

The following code produces a trace on portd that clearly shows the routine passing through the timer0 interrupt sequence twice. As this is a module in larger compilation I would really wish not to ignore this error, besides I dislike things not being correct it is like attempting to sweep things under the carpet,, they will always come back to haunt you!

Thanks

ps Now I have to try and find out how to insert the code inside this message.

mister_e
- 11th December 2007, 14:50
i didn't read the whole thing carefully, but usually when you load a timer, you want to stop it before to load, .

Will be great to know the PIC you're usiing so far.

To post your code in a box, just use code tags



paste your code here

Darrel Taylor
- 11th December 2007, 14:58
Hi Duncan,

The comparator will give an interrupt on any change of the comparator (rising and falling, 2 per cycle).

If you only want one edge, you'll need to test CMCON bit 6 or 7, (depending on which comparator you are using), to see which edge it was.

If using both comparators, you'll get an interrupt when either comparator changes.
<br>

duncan303
- 11th December 2007, 15:31
Hi Steve

Sorry I forgot to mention It is in an 18F4520, actually it's on a fairly well modified LABX1 board, Ill migrate to a suitable MCu after I have finished.
and I had a scout about the forum for info about the VB code to do all sorts of wonderfull things to the post




define OSC 16

INCLUDE "DT_INTS-18.bas" ; Base Interrupt System
INCLUDE "ReEnterPBP-18.bas" ; Include if using PBP interrupts
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler CMP_INT, _StartTag, PBP, yes
INT_Handler TMR0_INT, _AllDone, PBP, yes
endm
INT_CREATE
ENDASM

TRISA = %00001111
TRISB = %11011111
TRISC = %00111111
TRISD = %00000000
PORTD = 0

Z var byte

T0CON = %10000011 'set up timer 0 and turn it ON @16mhz 0011 = 262ms
CMCON = %00100011 ' set up comparator inputs


@ INT_ENABLE TMR0_INT ;all done
T0CON.7 = 0 ' turn off timer until needed


start:
portd.5 = 0
'================================================= ============
'================================================= ============
Get_Raw_Data:' GET RAW DATA
'-------------------------------------------------- Z = 0-----------------

@ INT_ENABLE CMP_INT ;wait here until an interrupt event
Z = 0 'on the comparators
Waiting:
if z = 0 then waiting
@ INT_DISABLE CMP_INT
'----------------------------------------- Z = 1--------------------
portd.5 = 1 'all done marker
TMR0H = %00111100 ' preload timer to 15400
TMR0L = %00100000
T0CON.7 = 1 ' turn back on timer 0 , used by all done

getData: ']loop here until timer1 overflows
if z = 1 then getdata ']
'--------------------------------------------Z = 4-----------------
getout:
PORTD.5 = 0 'all done marker
T0CON.7 = 0 'turn timer0 off until used again

finished:
goto start

;;;;;;;;;;;;;;;;;;;;; interrupt handlers ;;;;;;;;;;;;;;;;;;;;;;

StartTag:
z = 1 ' moves towards middle of routine
@ INT_RETURN

AllDone:
z = 4 ' moves towards end of routine
@ INT_RETURN
end


simple

Loading the timer: I have read somewhere (datasheet maybe?) that it is good practice to have the timer running before you initially start an interrupt which I do in the setup. I then enable interrupt and turn the timer off so that I can preload and then turn it back on when I am ready to start the stopwatch.
I have tried it another way which is to setup prescale and leave timer off /then preload and when I am ready to use it I start timer with the enable interrupt on the next line, regrettably the same thing happens.
I cannot help feeling I am missing something really fundamental. This problem has been around for me for a couple of weeks now, I am ready to stich the module back into the main compilation... feeling pretty dispondent and mentally tired.... i really appeciate your input.

duncan303
- 11th December 2007, 15:52
Hi Darrel,

Thanks just got your reply, although I using the comparators to feed the CCp modules. As you say the cmp interrupt is on *any change on either comparator*

so i am using the cmp as a sort of interrupt on change on both analog pins. It is then inportant to disable the cmp interrupt as soon as possible. I did have one comaparator output (the one i felt most probable to set) linked to portb internal interrupt but it oscillated like crazy, I get little or no bounce using this setup. I had been disabling the cmp_int "inside" it own handler routine but felt that this was bad practice (any thought?)which I why I try to keep the sub routines as simple as posible ie Z=1 or Z=2.

I have tried introducing delays without using pause (small count loops) to allow the interrupt disable to settle.

but I guesss that whilst I have been concentrating on timer0 as the culprit I should be back looking at CMP_INT to see if there is any way this could be responsible. But this loopback is happening 206ms after I have disabled CMP.

I also check that Z variable that I use as a progress gate is not corrupted, that is to say that even though Z = 1 the program is passing through a conditional IF's that should prevent it, confused........ I am totally.

duncan303
- 11th December 2007, 18:55
well it looks as if I have found a workaround, it seems as if the first line after the
@ INT_ENABLE CMP_INT is being ignored furthermore placing Z = 0 at any position from start to the @ INT_ENABLE CMP_INT will also cause a problem so I have to place a dummy line after the enable and everything works as it should do....... or so it appears on the surface to.


@ INT_ENABLE CMP_INT
Z = 0 'dummy line ignored
Z = 0
Waiting:
if Z = 0 then Waiting

I have only one variable in the example. I do not think I can face it but I have a feeling that I may have to check the stability of all my variables before and after an interrupt implementation .

I have just pulled the whole house down to find a needle ......... but for the want of that needle.... I am cold wet and have nothing to cook on!!!

think I will go down the road and post a christmas card to myself

Darrel Taylor
- 11th December 2007, 23:35
I had been disabling the cmp_int "inside" it own handler routine but felt that this was bad practice (any thought?)
That's the correct way.
Comparators can give many interrupts right at the point where it switches (hundreds even, if the analog signal is slow). If it's allowed to return from the interrupt without disabling, it'll end up right back in the handler again until it's past the switching point of the comparator. External hysterisis can be added to the comparator to eliminate that, but it's not needed in this case.

Also, much like the PORTB change interrupt, you should read the CMCON register inside the handler to end the mismatch condition. Typically, the handler would do that anyways to determine which comparator fired.

And,
before enabling the comparator the first time. Read CMCON, then Reset the interrupt flag.
Then be sure to clear it again before re-enabling later. The flag may have been set during the time it was Disabled.


that I may have to check the stability of all my variables before and after an interrupt implementation No need,
Nothing happens to your other variables during an interrupt, unless you specifically change them in the handler.
<br>

duncan303
- 16th December 2007, 16:45
Hi Darrel

Thankyou for your help..., again. I was experiencing occasional hysterisis whilst using the internal comparators but by slightly increasing the speed of the analog signal along with placing two bypass caps on each VDD pin of the MCU the internal bounce was brought easily under control.


By executing strict good housekeeping with respect to the flags and reading the cmcon register as you advised (it is in the Datasheet) together with re-setting all the registers prior to re-enabling I now have all six interrupts functioning perfectly within the same sub-routine and all being disabled upon exit. I am delighted and relieved, i almost feel a poem coming on but I note you recently penned something apt.

I can fly effortlesly ..... so until I have to learn how to land I am enjoying the moment.