What PIC do you use and how fast do you run it?
I use a 16f690 @20Mhz
The 16F690's Comparator 1 receives the non lagged signal (set to internal VREF to trip at about 1/2 VCC)
The 16F690's Comparator 2 receives the phase lagged signal (set to internal VREF to trip about 1/2 VCC too)
Identical signals are fed into both comparators (bar the phase lag)
DT's interrupts enabled for CMP1 & CMP2.
On the scope the lag time measures about 20us - below which Comp2 will not decrement.
I don't know enough about what's going on under the hood wrt interrupts (or timer1 zero-ing) to shine any more light on why the comp2 count won't go below 336...when clearly it should as the leading edge of the lagged signal gets close to zero lag. So being a bit wet nehind the ears, is there any other possible method I can use that circumvent this problem?
Last edited by HankMcSpank; - 25th September 2010 at 15:02.
So on the picture and data on post#15 things were looking honky-dory (you were measuring at least down to 161 counts on CMP2). Your new posts state that now CMP2 will not go below 336. Basic question; what changed?
Apologies...I've only just seen your question from a day or so ago - firstly that's very sharp of you to pick up on that detail
What changed?
I wish I knew....when it looked hunky dory...I didn't probe to deeply (I guess the - at the time - relief overcame me & I was a bit premature saying all was well!), I sort of put it to one side...a couple of nights later I came back to it & couldn't get the darned count down.
I've not changed the circuit....and have only window dressed the code (I can't genuinely say what I might have benn window dressed - but it will have been minimal!), but early indications here since getting home is that it might be related to the amount of text I'm squirting out with the HSEROUT command (which I queried myself the other night...and acetronics spotted earlier today!)
I only had a slim window of opprtunity before domestic commitments kicked in....but when 1000Hz (a nice round number to work with) was fed into comp1 I saw the count drop from 5,000 to something like 4600 when I put an Hserout in amongst the count storing! So is it related to amount of debug text I wonder?
I'm using Paul's excellent idea of keeping it simple & plagiarising the simple code he kindly provided (less his one typo!) ...first step is to get a good solid Comp 1 derived timer count for 1000Hz (which @20Mhz should be 5000 - and indeed it is using paul's code )...I'll then augment from there (ie bring comp2 into play)
Last edited by HankMcSpank; - 29th September 2010 at 19:35.
Ok, success (of sorts)
By keeping it simple, this code works (many thanks to Paul, whose code sample I used, albeit in McSpank-esque form here)...
ie the C2 count decrements nice & smoothly (& below 336 - yay!) & totally in line with the amount of phase lag....Code:PIR2.5 = 0 'Clear the Comp1 interrupt flag Comp1Time = 0 Main_Loop: WHILE PIR2.5 = 0 GOTO Main_Loop WEND TMR1H = 0 TMR1L = 0 PIR2.5 = 0 Comp1_count: WHILE PIR2.5 = 0 goto Comp1_count wend Comp1Time.Highbyte = TMR1H Comp1Time.Lowbyte = TMR1L TMR1H = 0 TMR1L = 0 PIR2.6 = 0 'HSEROUT [dec Comp1Time,13, 10] Comp2_count: WHILE PIR2.6 = 0 goto Comp2_count wend Comp2Time.Highbyte = TMR1H Comp2Time.Lowbyte = TMR1L TMR1H = 0 TMR1L = 0 HSEROUT ["C1=",dec Comp1Time,9,"C2=", dec comp2time, 13, 10] PIR2.5 = 0 goto Main_Loop
(green trace is comp1 - non lagged, yellow trace is into comp2 & lagged a miniscule amout)
.....I can get all the way down to 13-14(ish) below which the C2 count gets very jittery (ie successive counts eg 5, 11, 6, 12, 5, - you can see some 19s in that stream above)....but a comp2 count of 13 @1kHz is granular enough for me (accuracy to within 0.936 degrees @1kHz). I'm elated...*BUT*
Quite clearly my original way is causing some issues (p& almost certainly to do with my poor sequence &/or coding), so if this way of doing it works, how can I integrate it into my main program?
My first attempt just now failed...
Here's the screen output...
C1=4909 C2=13
C1=4903 C2=13
C1=4909 C2=13
C1=4909 C2=13
hello
C1=4903 C2=13
C1=4909 C2=13
ie that C1 count has dropped?!! (even though the incoming frequency has remained at 1Khz)
here's what I did (disclaimer: I didn't know how to get the main body of program to 'jump' to to the interrupt handler when Comp1 interrupted, so I deferred back to DT's method as the initial 'trigger')...
Code:Comp1Time var word ' used to amalgamate TMR1 High & Low Bytes. Comp2Time var word INCLUDE "DT_INTS-14.bas" ' Base Interrupt System PO90OOO9 INCLUDE "ReEnterPBP.bas" ' Include if using PBP interrupts ASM INT_LIST macro ; IntSource, Label, Type, ResetFlag? INT_Handler CMP1_INT, _Comp1_Int, PBP, yes endm INT_CREATE ; Creates the interrupt processor ENDASM T1CON.0= 1 'start timer Comp1Time = 0 'clear down Comp1Time, prior to starting. comp2Time = 0 'clear down Comp2Time, prior to starting @ INT_ENABLE CMP1_INT ; enable Comparator 1 interrupts PIR2.5 = 0 'Clear the Comp1 interrupt flag Comp1Time = 0 Comp2Time = 0 'Main body of Code**************************************************************** Main: hserout ["hello", 13, 10] pause 20 goto Main END '**********************Comp1 interrupt handler********************************************************* Comp1_Int: Comp1_Loop: WHILE PIR2.5 = 0 GOTO Comp1_Loop WEND TMR1H = 0 TMR1L = 0 PIR2.5 = 0 Comp1_count: WHILE PIR2.5 = 0 goto Comp1_count wend Comp1Time.Highbyte = TMR1H Comp1Time.Lowbyte = TMR1L TMR1H = 0 TMR1L = 0 PIR2.6 = 0 'HSEROUT [dec Comp1Time,13, 10] Comp2_count: WHILE PIR2.6 = 0 goto Comp2_count wend Comp2Time.Highbyte = TMR1H Comp2Time.Lowbyte = TMR1L TMR1H = 0 TMR1L = 0 HSEROUT ["C1=",dec Comp1Time,9,"C2=", dec comp2time, 13, 10] PIR2.5 = 0 @ INT_RETURN
Last edited by HankMcSpank; - 29th September 2010 at 22:25.
This is most excellent.
You may have already corrected this, but on the original code the analog inputs for the comparators are not enabled (ANSEL.6 and ANSEL.7). Minor thing, but shouldn't hurt to follow the datasheet.
I do agree with other suggestions, since the inputs are already digital there is not need to use the comparators. But to use the IOC (interrupt-on-change) you would most likely need to go for PORTA or PORTB (which have individual IOC bits for each input).
General suggestion for interrupt use: keep everything short; do only the absolute minimum inside the interrupt routine.
Even though the use of the HW USART (HSEROUT) is a plus, you should still try to do this outside the interrupt routine. Do the timer stuff inside the interrupt (i.e. clear and set timer, etc). Make a flag that tells you the interrupt "fired"; and in the main loop manipulate the data to be sent out (and send it out). I think the CCP module maybe a much better candidate for what you are doing (duh, except you would need a PIC with two CCP modules - never mind).
Last edited by languer; - 29th September 2010 at 22:15.
I had thought the ANSEL turned on/off the AtoD for a given pin - certainly my comparators have been working with the corresponding ANSEL deselected? I had a similar discussion with Melanie & she considered them digital....
http://www.picbasic.co.uk/forum/show...1127#post81127 extract here....
Since then I've assumed digital & therefore deselected the analog!!
I already use IOC (for switching) in the program that this melarkey is destined for - in my blissfully naive planet of "don't understand", for now, I'd prefer to keep the two interrupt variants apart! (for fear of IOC contention)
I would agree with that, but what I've found is that unless I do stuff inside the routine, then the counts go to pot! (that's not to say I shouldn't strive to do such stuff outside the routine, but as of yet, I'm having the most success keeping it 'controlled' where I know where/when it's going to be used!
I'd love to get that HSEROUT outside....but I think therein lies the possible original problem?
It would be nice to slowly build the picture up to see when the trouble occurs, but to do that I need some clever person to tell me how I can 'trigger' the code that 'works' above into action while the main program is running?
Last edited by HankMcSpank; - 29th September 2010 at 22:31.
Ok, this seems to work (ie it allows a 'main body' of program to run, with an interrupt handler)....
The actual final phase calculation jitters about a bit (but I suspect that down to the somewhat jittery quality of my audio input signal into the PIC comparators)...Code:Comp1Time var word Comp2Time var word phase_shift var word c var word dummy var word T1CON.0= 1 'start timer Comp1Time = 0 'clear down Comp1Time, prior to starting. comp2Time = 0 'clear down Comp2Time, prior to starting PIR2.5 = 0 'Clear the Comp1 interrupt flag INCLUDE "DT_INTS-14.bas" ' Base Interrupt System PO90OOO9 INCLUDE "ReEnterPBP.bas" ' Include if using PBP interrupts ASM INT_LIST macro ; IntSource, Label, Type, ResetFlag? INT_Handler CMP1_INT, _Comp1_Int, PBP, yes endm INT_CREATE ; Creates the interrupt processor ENDASM T1CON.0= 1 'start timer Comp1Time = 0 'clear down Comp1Time, prior to starting. comp2Time = 0 'clear down Comp2Time, prior to starting @ INT_ENABLE CMP1_INT ; enable Comparator 1 interrupts Top: c = 3600 dummy = comp2time * c phase_shift = DIV32 comp1time HSEROUT [" C1=",dec Comp1Time,9," C2=", dec comp2time,9, "phase_shift=", dec phase_shift/10,".",dec phase_shift//10, 13, 10] goto top Comp1_Int: PIR2.5 = 0 Loop1: WHILE PIR2.5 = 0 GOTO Loop1 WEND TMR1H = 0 TMR1L = 0 PIR2.5 = 0 Comp1_count: WHILE PIR2.5 = 0 goto Comp1_count wend Comp1Time.Highbyte = TMR1H Comp1Time.Lowbyte = TMR1L+2 TMR1H = 0 TMR1L = 0 PIR2.6 = 0 'HSEROUT [dec Comp1Time,13, 10] Comp2_count: WHILE PIR2.6 = 0 goto Comp2_count wend Comp2Time.Highbyte = TMR1H Comp2Time.Lowbyte = TMR1L+6 TMR1H = 0 TMR1L = 0 if comp2time> comp1time-23 then comp2time = 0 'HSEROUT ["C1=",dec Comp1Time,9,"C2=", dec comp2time, 13, 10] PIR2.5 = 0 @ INT_RETURN
Now I'm sure there are more efficient ways of doing the above - but for now, it work s& I'm chuffed!
The actual final phase calculation jitters about a bit (but I suspect that down to the somewhat jittery quality of my audio input signal into the PIC comparators!)...
Listen guys - a great collaborative effort there - I can't thank you all enough....hopefully this gives a bit of closure to a long & painful saga!
Last edited by HankMcSpank; - 30th September 2010 at 00:25.
I'm coming into this sort of late, although I've been more-or-less following this thread. Very interesting stuff!
Anyway, here's an idea that may help--just use a single interrupt. When the first comparator causes the interrupt, get your tmr1 count and zero it, then wait in a tight loop, checking PIR2.6. That should reduce latency to an absolute minimum.
something like
You could also add some sort of check so that it would exit the loop if an unreasonable amount of time has elapsed.Code:'Make sure the Comparator 2 interrupt handler is disabled! 'Comparator1 Interrupt Handler++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comp1_Int: Comp1Time.Lowbyte = TMR1L 'Store away the timer1 count - this will be the non lagged signal 'period' count. Comp1Time.Highbyte = TMR1H TMR1H = 0 'Set timer1 value to 0 TMR1L = 0 PIR2.6 = 0 'Clear the Comparator C2 Interrupt Flag bit Keep_Waiting: WHILE PIR2.6 = 0 'Check to see if the Comparator 2 interrupt flag has flipped goto Keep_Wating WEND Comp2Time.Lowbyte = TMR1L 'Store away the timer1 count again (ie once the lagged signal leading edge arrives - this is the lag count) Comp2Time.Highbyte = TMR1H @ INT_RETURN
Best Regards,
Paul
H Paul,
Thank you very much for your input - truthfully, I was was getting too wrapped up in this over the weekend, but after drawing a blank with every avenue explored, I'm taking a self enforced mini break from that particular problem (I often find coming back to a project after a rest sparks new ideas & approaches). re your specific idea...I'll freely admit that I'm sort of out my depth when it comes to the inner working of interrupts (ie Picbasic interrupts vs ASM interrupts vs DT interrupts), but at one stage I do recall getting intensely intimate with the datasheet & having a "what the hell" pop at something *very* similar to what you mention - I saw no difference (but I will revisit in the light of your input)
I could really do with some interrupt big hitters to chime in & outline a little a bit about how to get such time sensitive interrupt timings down to the bare minimum (assuming your suggestion isn't the only attack) ....becuase as it stands right now, I have *NO* (zilch, nada, zero, scratch) idea why that comparator2 interrupt count will not register below 336 when I feed a very slightly phase lagged signal into comp2 ...and alas, the my future (parked) status as a multimillionaire who invented widget X depends on getting that count to reflect the time lag between comp1 & comp2 tripping
I'm in part slightly reticent to even push this one too much in the (highly possible) case there's something inherently wrong in my PIC /PICBasic approach - what I am convinced about is that the inputs to the comparators are without question correct - I may be pants at programming, but I know how to drive a scope, sig gen etc! (I think my youtube video illustrates the issue seems to be a valid one)
if anyone out their in the global 'PIC interest land' feels up to the challenge - they could see themselves what happens when they feed near identically phased signals (ie a clock?) into comparator1 & comparator2 (that said an identical signal might cause problems with a race scenario?...but I concede that most don't have the faciilities or interest to setup an all pass to phase shift the two signals!)...in principle, with identical (phase) signals into both comparators, the count for comparator 2 ought to be very close to zero (like single digits)
But I will come back to this (& first on the list will be your suggestion..if for no other reason thatn your is the only suggestion I have, lol) - I'm presently now working on Project Y - it's not gonna be the blockbuster that Widget X will be ...but got to keep keep my kids in Nike trainers somehow or other
Edit: While I'm publicily declaring my woeful lack of grasp of time sensitive h/w & corresponding code....I also wonder if changing my PIC might help to get that comp2 count down? (I'm using a 16F690 not becuase it's necessarily the most suitable - but it came bundled with my PIKIT2 starter kit & I've stuck with it from new and have started to get the hang of it a little - when your grappling in the dark as often as am, you need a torch that's familiar!), but I see a chart like this http://www.microchip.com/en_us/technology/xlp/ & then wonder, is there a more efficient PIC for doing this type of stuff out there...??? (eg pics optimised for single instructions - not even sure what that means but the bar chart looks like a shocker!)
Last edited by HankMcSpank; - 28th September 2010 at 22:48.
Hi Hank
Since you're stuck, I wonder if you could post/PM your code of now so that I can take a whack at it. I'll see if I can find your problem with the min value of comp2 value.
The barest minimum code which will compile and show the problem is sufficient. I should be able to run it.
Regards
Many thanks Jerson.
The latest version of code was part of a hulking long program, but I found an earlier variant, which is purely deals with the comparator interrupt timer1 counting & therefore makes it a lot easier to look at...
Code:@ __CONFIG _FCMEN_OFF & _HS_OSC & _WDT_OFF & _MCLRE_OFF & _CP_OFF & _IESO_OFF & _BOR_OFF & _PWRTE_OFF DEFINE OSC 20 ' set Oscillator at 20Mhz. DEFINE NO_CLRWDT 1 ' PBP doesn't clear WDT automatically DEFINE HSER_TXSTA 24h ' Enable transmit DEFINE HSER_SPBRG 129 ' set USART to 9600 baud @20Mhz '********************************************************************************* '16F690 Pin Connections.... ' PIN# NAME USE & CONNECTION ' 1 Vdd +5VDC power supply TRISC.4 = 0 ' 6 RC4 C2OUT TRISC.3 = 1 ' 7 RC3 C12IN3- (comparator1 input) TRISC.2 = 1 ' 14 RC2 C12IN2- (comparator2 input) TRISA.2 = 0 ' 17 RA2 C1OUT ' 20 Vss Ground '********************************************************************************* OSCCON.0 = %0001000 txsta = %10100100 'setup the tx register RCSTA.7 = 1 ' Enable RB7 for TX USART INTCON.0 = 0 ' clears the RABIF Flag (to 0), COULD be 1 on reset (unique to F690) ANSEL = 0 'disable AtoD. ANSELH = 0 'disable AtoD. 'Turn on & Set up Comparator 1 CM1CON0.7 = 1 'Comparator 1 on. CM1CON0.6 = 0 'C1OUT POLARITY BIT CM1CON0.5 = 1 '1 = C1OUT is present on the C1OUT pin (pin 17) CM1CON0.4 = 1 'C1OUT logic - 0 is not inverted (1 for inverted) CM1CON0.3 = 0 'unimplemented CM1CON0.2 = 1 'Connect internally to the output of C1VREF (or 0 for the the associated comp 'in' ext pin) CM1CON0.1 = 1 'this bit with bit 1 set the external incoming pin - in this case c12in3- (pin 7) CM1CON0.0 = 1 'this bit with bit 1 set the external incoming pin - in this case c12in3- (pin 7) 'Turn on & Set up Comparator 2 CM2CON0.7 = 1 'Comparator 2 on. CM2CON0.6 = 0 'C1OUT POLARITY BIT CM2CON0.5 = 1 '1 = C2OUT is present on the C2OUT pin (pin 6) CM2CON0.4 = 1 'C1OUT logic is not inverted (1 for inverted) CM2CON0.3 = 0 'unimplemented CM2CON0.2 = 1 'Connect internally to the output of C1VREF (or 0 for the the associated comp 'in' ext pin) CM2CON0.1 = 1 'this bit with bit 1 set the external incoming pin - in this case c12in2- (pin 14) CM2CON0.0 = 0 'this bit with bit 1 set the external incoming pin - in this case c12in2- (pin 14) ' Setup the internal VREF VRCON.7 = 1 'Comparator1 CV Ref enable bit VRCON.6 = 1 'Comparator2 CV Ref enable bit VRCON.5 = 0 'high or low range 0 = High Range, 1 = low range VRCON.4 = 0 '0.6V Reference Enable bit ....0 is disabled VRCON.3 = 0 'these 4 bits set the divider of the VREF ladder 16 values - 7 should yield 1/2 VCC VRCON.2 = 1 'these 4 bits set the divider of the VREF ladder 16 values - 7 should yield 1/2 VCC VRCON.1 = 1 'these 4 bits set the divider of the VREF ladder 16 values - 7 should yield 1/2 VCC VRCON.0 = 1 'these 4 bits set the divider of the VREF ladder 16 values - 7 should yield 1/2 VCC Comp1Time var word ' used to amalgamate TMR1 High & Low Bytes. Comp2Time var word INCLUDE "DT_INTS-14.bas" ' Base Interrupt System PO90OOO9 INCLUDE "ReEnterPBP.bas" ' Include if using PBP interrupts ASM INT_LIST macro ; IntSource, Label, Type, ResetFlag? INT_Handler CMP1_INT, _Comp1_Int, PBP, yes INT_Handler CMP2_INT, _Comp2_Int, PBP, yes endm INT_CREATE ; Creates the interrupt processor ENDASM T1CON.0= 1 'start timer Comp1Time = 0 'clear down Comp1Time, prior to starting. comp2Time = 0 'clear down Comp2Time, prior to starting @ INT_ENABLE CMP1_INT ; enable Comparator 1 interrupts @ INT_ENABLE CMP2_INT ; enable Comparator 2 interrupts 'Main body of Code**************************************************************** Main: HSEROUT ["comp1=",dec Comp1Time,9,"comp2Time=", dec comp2time, 13, 10] PAUSE 80 goto Main end 'Comparator1 Interrupt Handler++++++++++++++++++++++++++++++++++++++++++++++++++++ Comp1_Int: Comp1Time.Lowbyte = TMR1L 'Store timer1 Low into a variable Comp1Time.Highbyte = TMR1H 'Store timer1 high into a variable. TMR1H = 0 'Set the high part of the timer value to 0 TMR1L = 0 'Set the low part of the timer value to 0 @ INT_RETURN 'Comparator2 Interrupt Handler++++++++++++++++++++++++++++++++++++++++++++++++++++ Comp2_Int: Comp2Time.Lowbyte = TMR1L 'Store timer1 Low into a variable Comp2Time.Highbyte = TMR1H 'Store timer1 high into a variable. TMR1H = 0 'Set the high part of the timer value to 0 TMR1L = 0 'Set the low part of the timer value to 0 @ INT_RETURN
Last edited by HankMcSpank; - 29th September 2010 at 08:21.
Hi Hank
I may be wrong here, but, my suspicion is you are losing time in reentering PBP in your ISRs. See, a lot of PBP registers have to be saved even if they are not going to be used because you flagged your ISR to be coded using PBP functions.
I suggest you slim it down by using ASM inside the ISR and avoiding ReEnterPbp. You should see better results.
I might sound like a heretic here, but I prefer coding my ISR in ASM even though it may be painful to code.
Regards
I like Pauls approach, Seems to be the least amount of time between Comp1 and 2. one thing I would do, is program his while loop in ASM. This is because I have no idea how many instructions it takes using PBP. I think this will mask the issue of how long it takes to actually enter the handler. Which is what I think above folks are reffering to with the PBP include.
heres the while loop in asm:
The above will take exactly 1 instruction to enter the loop, then 3 inscrutions to to run per loop. now for some math:Code:BCF PIR2,6 --> clears the comp 2 int flag HERE --> label to jump to BTFSS PIR2,6 --> test if comp 2 int flag is set GOTO HERE --> not set, go back to test CONTINUE --> Comp 2 int occured, do what ever needs to be done
you are running a 20mHz clock, so thats 5MIPS. so 1 instruction takes .0000002 sec to execute. At 1400 htz, each cycle takes .0071428 sec. that devided by 360 = .00000198sec per degree. so you should be able to measure to almost .5 degree. assuming comp2 fires between BCF and BTFSS, thats 3 instrution cycles, or .0000006 sec.(I think BTFSS may take 2 cycles when true)
Someone please check my math, but these numbers show you have far too much overhead somewhere that can only be explained by the above posts.
-Bert
The glass is not half full or half empty, Its twice as big as needed for the job!
http://foamcasualty.com/ - Warbird R/C scratch building with foam!
I agree with the maths...and I agree with the summary (something somewhere is taking way too long). Now that I have a few people interested & feeding in ideas , I will pull the breadboard out of cold storage tonight & try Paul's code.
Bert, re this...
That looks like what will happen when comp2 interrupts....but within my program, how do I setup the 'trigger' condition ...ie to get the program to go and do that when a comp2 interrupt has arrived?Code:BCF PIR2,6 --> clears the comp 2 int flag HERE --> label to jump to BTFSS PIR2,6 --> test if comp 2 int flag is set GOTO HERE --> not set, go back to test CONTINUE --> Comp 2 int occured, do what ever needs to be done
I will feedback the results (it might be late - ie 21.30 GMT-ish .....got to do the 'kids off to bed' rigamrole first! Hey there's an idea...rather than read them Noddy goes to the Seaside, I could read them some of the ASM code put forward by Bert!!)
Last edited by HankMcSpank; - 29th September 2010 at 13:56.
-Bert
The glass is not half full or half empty, Its twice as big as needed for the job!
http://foamcasualty.com/ - Warbird R/C scratch building with foam!
My wife, back when she was studying to be an EMT, would recite her "protocols" (sort of flow charts for emergency medical actions) to get my daughter to go to sleep.
Anyway, I've never used the DT interrupts. I've heard great things about them but never had cause to use them. I would do this by setting the registers for a single interrupt source, i.e. comparator 1. And I would use PBP interrupts (because I am a simple man...) at least at the offset. Once I had that working I would consider something more complicated (ASM interrupts) if the speed wasn't fast enough.
Perhaps in the spirit of keeping it simple, don't use *any* interrupt routine. In the main loop, just keep checking the the state of the Comp1 interrupt flag, something like
Best Regards,Code:PIR2.5 = 0 'Clear the Comp1 interrupt flag Main_Loop: WHILE PIR2.5 = 0 GOTO Main_Loop WEND Comp1Time.Lowbyte = TMR1L 'Store away the timer1 count - this will be the non lagged signal 'period' count. Comp1Time.Highbyte = TMR1H TMR1H = 0 'Set timer1 value to 0 TMR1L = 0 PIR2.6 = 0 'Clear the Comparator C2 Interrupt Flag bit Keep_Waiting: WHILE PIR2.6 = 0 'Check to see if the Comparator 2 interrupt flag has flipped goto Keep_Wating WEND Comp2Time.Lowbyte = TMR1L 'Store away the timer1 count again (ie once the lagged signal leading edge arrives - this is the lag count) Comp2Time.Highbyte = TMR1H HSEROUT ["comp1=",dec Comp1Time,9,"comp2Time=", dec comp2time, 13, 10] PIR2.5 = 0 'Clear the Comp1 interrupt flag goto Main_Loop END
Paul
Ok, just to show you what is involved in ASM interrupts, this is an example for your particular case. This is the first time I am trying something like this using DT_ints, so, I may be off the mark. Most times I do it the hard way - pure asm code. Someone please correct me if I am wrong here. You should be able to realize significant improvement in the values you see. Darrell's wrapper code is cool and if you still need to save some more, look at the generated LST file and you should be able to sneak a trick or two from there. The ISR vector is at location 0004 in the PIC. So, you will find a goto INTHAND at that address.
In your case since you are not doing any math functions or gosubs in the INTs, you could keep the PBP code as-is and do away with the ASM. Can save you some agony
Code:@ __CONFIG _FCMEN_OFF & _HS_OSC & _WDT_OFF & _MCLRE_OFF & _CP_OFF & _IESO_OFF & _BOR_OFF & _PWRTE_OFF DEFINE OSC 20 ' set Oscillator at 20Mhz. DEFINE NO_CLRWDT 1 ' PBP doesn't clear WDT automatically DEFINE HSER_TXSTA 24h ' Enable transmit DEFINE HSER_SPBRG 129 ' set USART to 9600 baud @20Mhz '********************************************************************************* '16F690 Pin Connections.... ' PIN# NAME USE & CONNECTION ' 1 Vdd +5VDC power supply TRISC.4 = 0 ' 6 RC4 C2OUT TRISC.3 = 1 ' 7 RC3 C12IN3- (comparator1 input) TRISC.2 = 1 ' 14 RC2 C12IN2- (comparator2 input) TRISA.2 = 0 ' 17 RA2 C1OUT ' 20 Vss Ground '********************************************************************************* OSCCON.0 = %0001000 txsta = %10100100 'setup the tx register RCSTA.7 = 1 ' Enable RB7 for TX USART INTCON.0 = 0 ' clears the RABIF Flag (to 0), COULD be 1 on reset (unique to F690) ANSEL = 0 'disable AtoD. ANSELH = 0 'disable AtoD. 'Turn on & Set up Comparator 1 CM1CON0.7 = 1 'Comparator 1 on. CM1CON0.6 = 0 'C1OUT POLARITY BIT CM1CON0.5 = 1 '1 = C1OUT is present on the C1OUT pin (pin 17) CM1CON0.4 = 1 'C1OUT logic - 0 is not inverted (1 for inverted) CM1CON0.3 = 0 'unimplemented CM1CON0.2 = 1 'Connect internally to the output of C1VREF (or 0 for the the associated comp 'in' ext pin) CM1CON0.1 = 1 'this bit with bit 1 set the external incoming pin - in this case c12in3- (pin 7) CM1CON0.0 = 1 'this bit with bit 1 set the external incoming pin - in this case c12in3- (pin 7) 'Turn on & Set up Comparator 2 CM2CON0.7 = 1 'Comparator 2 on. CM2CON0.6 = 0 'C1OUT POLARITY BIT CM2CON0.5 = 1 '1 = C2OUT is present on the C2OUT pin (pin 6) CM2CON0.4 = 1 'C1OUT logic is not inverted (1 for inverted) CM2CON0.3 = 0 'unimplemented CM2CON0.2 = 1 'Connect internally to the output of C1VREF (or 0 for the the associated comp 'in' ext pin) CM2CON0.1 = 1 'this bit with bit 1 set the external incoming pin - in this case c12in2- (pin 14) CM2CON0.0 = 0 'this bit with bit 1 set the external incoming pin - in this case c12in2- (pin 14) ' Setup the internal VREF VRCON.7 = 1 'Comparator1 CV Ref enable bit VRCON.6 = 1 'Comparator2 CV Ref enable bit VRCON.5 = 0 'high or low range 0 = High Range, 1 = low range VRCON.4 = 0 '0.6V Reference Enable bit ....0 is disabled VRCON.3 = 0 'these 4 bits set the divider of the VREF ladder 16 values - 7 should yield 1/2 VCC VRCON.2 = 1 'these 4 bits set the divider of the VREF ladder 16 values - 7 should yield 1/2 VCC VRCON.1 = 1 'these 4 bits set the divider of the VREF ladder 16 values - 7 should yield 1/2 VCC VRCON.0 = 1 'these 4 bits set the divider of the VREF ladder 16 values - 7 should yield 1/2 VCC Comp1Time var word ' used to amalgamate TMR1 High & Low Bytes. Comp2Time var word ;-- Place a copy of these variables in your Main program ------------------- ;-- The compiler will tell you which lines to un-comment -- ;-- Do Not un-comment these lines -- ;--------------------------------------------------------------------------- wsave VAR BYTE $20 SYSTEM ' location for W if in bank0 ;wsave VAR BYTE $70 SYSTEM ' alternate save location for W ' if using $70, comment wsave1-3 ' --- IF any of these three lines cause an error ?? ------------------------ ' Comment them out to fix the problem ---- ' -- Which variables are needed, depends on the Chip you are using -- wsave1 VAR BYTE $A0 SYSTEM ' location for W if in bank1 wsave2 VAR BYTE $120 SYSTEM ' location for W if in bank2 ;wsave3 VAR BYTE $1A0 SYSTEM ' location for W if in bank3 ' -------------------------------------------------------------------------- INCLUDE "DT_INTS-14.bas" ' Base Interrupt System PO90OOO9 'INCLUDE "ReEnterPBP.bas" ' Include if using PBP interrupts ASM INT_LIST macro ; IntSource, Label, Type, ResetFlag? INT_Handler CMP_INT, _Comp1_Int, ASM, yes INT_Handler CMP2_INT, _Comp2_Int, ASM, yes endm INT_CREATE ; Creates the interrupt processor ENDASM T1CON.0= 1 'start timer Comp1Time = 0 'clear down Comp1Time, prior to starting. comp2Time = 0 'clear down Comp2Time, prior to starting @ INT_ENABLE CMP1_INT ; enable Comparator 1 interrupts @ INT_ENABLE CMP2_INT ; enable Comparator 2 interrupts 'Main body of Code**************************************************************** Main: HSEROUT ["comp1=",dec Comp1Time,9,"comp2Time=", dec comp2time, 13, 10] PAUSE 80 goto Main end 'Comparator1 Interrupt Handler++++++++++++++++++++++++++++++++++++++++++++++++++++ Comp1_Int: ' Comp1Time.Lowbyte = TMR1L 'Store timer1 Low into a variable ' Comp1Time.Highbyte = TMR1H 'Store timer1 high into a variable. ' TMR1H = 0 'Set the high part of the timer value to 0 ' TMR1L = 0 'Set the low part of the timer value to 0 asm movf TMR1L,w movwf _Comp1Time+0 ; the lsb movf TMR1H,w movwf _Comp1Time+1 ; the msb clrw movwf TMR1L movwf TMR1H endasm @ INT_RETURN 'Comparator2 Interrupt Handler++++++++++++++++++++++++++++++++++++++++++++++++++++ Comp2_Int: ' Comp2Time.Lowbyte = TMR1L 'Store timer1 Low into a variable ' Comp2Time.Highbyte = TMR1H 'Store timer1 high into a variable. asm movf TMR1L,w movwf _Comp2Time+0 ; the lsb movf TMR1H,w movwf _Comp2Time+1 ; the msb endasm @ INT_RETURN
Last edited by Jerson; - 29th September 2010 at 14:38. Reason: :)
Hi Jerson,
So am I getting this right - you are using DT's interrupt as the 'trigger' to enter an actual routine that has ASM within?
Kind of a like hybrid solution?
Apologies for the naive line of questioning, but what's the pros cons of the (3?) type of interrupts available to user of Picbasic....
PICbasic Interrupts
DT's Interrupts,
ASM Interrupts.
hi Paul,
i'm digging that idea about keeping it simple - once we've got to the bottom of the 'overhead', I can think about putting the solution back as an interrupt.
Great stuff guys - I've got a new spring in my step with all this.
Last edited by HankMcSpank; - 29th September 2010 at 14:41.
Bookmarks