PDA

View Full Version : DT interrupt/pulse generator



Adrian
- 18th August 2008, 11:42
I have used Darrel's interrupts to generate a 1KHz pulse stream. As I'm using TOGGLE the interrupts needs to be at a 2KHz rate. Using PicMultiCalc with 7 instructions and 20MHz oscillator this gives Timer reload as 63043. Using this I get 959 Hz. I have to load 63150 to get about 1,000Hz. 107 ticks seems a long way out to me. Can someone please tell me why the great discrepancy and/or what I'm doing wrong. Many thanks
Adrian

skimask
- 18th August 2008, 13:59
I have used Darrel's interrupts to generate a 1KHz pulse stream. As I'm using TOGGLE the interrupts needs to be at a 2KHz rate. Using PicMultiCalc with 7 instructions and 20MHz oscillator this gives Timer reload as 63043. Using this I get 959 Hz. I have to load 63150 to get about 1,000Hz. 107 ticks seems a long way out to me. Can someone please tell me why the great discrepancy and/or what I'm doing wrong. Many thanks
Adrian

Looks about right to me...
20Mhz oscillator = 5Mhz instruction rate/Timer increment rate
5,000,000 / ( 65536-63043) = 2005 Hz
5,000,000 / ( 65536-63150) = 2095 Hz

Neither number above compensates for the 7 instructions, but the idea is the same.
You've got the numbers right...or at least it looks like it.

Adrian
- 18th August 2008, 16:48
Thanks Skimask

The reload criteria seem to be right, as you also concur, but for the life of me I still can't understand why it is over 100 ticks out. I have measured the frequency both on a counter and on a scope so I think we can be pretty sure that's OK. I hope I can solve this rather than it just goes down as one of life's little mysteries.....!
Thanks

Adrian

skimask
- 18th August 2008, 16:59
Thanks Skimask

The reload criteria seem to be right, as you also concur, but for the life of me I still can't understand why it is over 100 ticks out. I have measured the frequency both on a counter and on a scope so I think we can be pretty sure that's OK. I hope I can solve this rather than it just goes down as one of life's little mysteries.....!
Thanks

Adrian

What do you mean by '100 ticks out'?
Do you mean that it's over 100 ticks off of what you calculated to be the reload value?
If that's the case, you might be forgetting about the overhead of the program itself (2 cycles to jump in, 2 cycles out, a couple of cycles to reload the timer itself, and so on)...
Or something different?
Maybe your 20Mhz is off?

Adrian
- 18th August 2008, 18:59
What do you mean by '100 ticks out'?
Do you mean that it's over 100 ticks off of what you calculated to be the reload value?
If that's the case, you might be forgetting about the overhead of the program itself (2 cycles to jump in, 2 cycles out, a couple of cycles to reload the timer itself, and so on)...
Or something different?
Maybe your 20Mhz is off?

Yes - that's what I meant. I imagined that the programme overhead would mop up 'some' 'ticks' but I was surprised when it ended up at 107 adrift. The oscillator frequency is a good point - I'll check that. At the end of the day I can adjust the programme to get the frequency as close as I need so I guess I shouldn't be too concerned

Thanks for your input

Adrian

skimask
- 18th August 2008, 19:32
I imagined that the programme overhead would mop up 'some' 'ticks' but I was surprised when it ended up at 107 adrift.
You can count that out yourself. Just look at the .lst file, run thru the instructions manually and count them (branches, goto's, returns, retfie, all take 2 cycles, check the datasheet).
If you know that number down to the exact cycle, you should be able to program in a specific frequency and check your oscillator frequency against that with a reasonable amount of accuracy.

Darrel Taylor
- 18th August 2008, 20:17
Adrian,

All latencies can be easily compensated for, by ADDING the reload value to the timer instead of just copying the value to the time.

At the time the interrupt occurs, the value of the timer is 0, and it continues counting while the chip is doing what ever it has to do to get to the Handler.

When it gets to the handler, and is ready to reload the timer, the timer already has an EXACT count of how long it took to get there. So when you ADD the const to the timer, it actually subtracts the time it took from the const and EVERYTHING is accounted for.

Take a look at this page ...
http://www.darreltaylor.com/DT_INTS-14/TimerTemplate.html

That program has everything you need, but at a minimum, check out the ReloadTMR1 routine which shows an easy 8 instruction cycle adding reload.

hth,

Adrian
- 18th August 2008, 20:45
Darrel

Thank you very much. I have taken a look and 'instantly' it doesn't look so easy to understand, however it also appears to be very crafty and very useful. I am going to plug away at your code until it IS understood and then add this new-found knowledge to the ever increasing store of accumulated wisdom from all of you experts.

Many thanks again to you for enlightening me and of course to Skimask for his valuable input

Adrian

Darrel Taylor
- 18th August 2008, 21:22
I have taken a look and 'instantly' it doesn't look so easy to understand, ...

It does look a bit confusing at first, but it couldn't be easier. :)
A complete understanding of how it works will come later after getting it to work.

This is really the only section you need to digest.
Set Freq to 2000, Prescaler to 1, and T1CON to 0. Fill in the Main program and T1handler that gets called on each interrupt.

Done deal.



;--- Change these to match the desired interrupt frequency -------------------
;--- See http://DarrelTaylor.com/DT_INTS-14/TimerTemplate.html for more Info.
@Freq = 2000 ; Frequency of Interrupts in Hz
@Prescaler = 1 ; Timers Prescaler setting
T1CON = $00 ; $00 = Prescaler 1:1, TMR1 OFF
; $00=1:1, $10=1:2, $20=1:4, $30=1:8 -- Must match @Prescaler value

@ INT_ENABLE TMR1_INT ; enable Timer 1 interrupts
GOSUB StartTimer ; Start the Timer

;____Your Main Program goes here______________________________________________
Main:
; ---- Your Main Program goes here ----
GOTO Main

;____This routine is Called on each TMR1 Interrupt____________________________
T1handler:
; ---- Your interrupt routine goes here ----

@ INT_RETURN

Adrian
- 19th August 2008, 13:25
Darrel

Many thanks - the programme worked spotlessly up to 1KHz. I put Freq as 1000, T1CON as 0 and Prescaler as 1 plus I just added TOGGLE PORTB.0 in the T1Handler section. With any frequency up to 1000Hz the output on PORTB.0 is (as would be expected) exactly half the frequency value. At any frequency above 1000Hz, which appears to be a magical threshold, the output is not half. e.g. at 2000 it is 1042; at 1500 it is 781; at 1200 it is 625 and even at a small increase over 1000 Hz it is still wrong ie at 1020 it is 521. What is the logical explanation for this, or am I barmy?
PS I'm using and defining a 20Mhz osc but have tried with same results on 4 and 8 Mhz
Some rational explanation would be greatly appreciated!

Thanks

adrian

Darrel Taylor
- 20th August 2008, 01:10
Hmmm, I'm not sure Adrian.

I've double checked it here on a 16F88 and I can go up to 12khz with a 20mhz OSC. Or 25khz by changing the Handler's "TYPE" to ASM.

I did find some inaccuracy in the math,

This line ...
TimerReload = MaxCount - ((25000 / Freq) * (OSC*10/Prescaler))

Should be like this...
TimerReload = MaxCount - OSC*1000000/4/Prescaler/Freq

but that shouldn't cause what you've described.

Which PIC are you using?
<br>

Adrian
- 20th August 2008, 08:19
I'm using the ubiquitous 16F877A. Using the time difference between you and the UK I will change the maths anyway and try different frequencies again. I will also double check everything on the development board and will report back...!! Did you try with TOGGLE in the TIHandler? I wondered if that instruction was somehow slowing it down. Thank you for your help...this is bugging me!

Adrian

Darrel Taylor
- 20th August 2008, 09:22
Yes, just a TOGGLE in the handler, and nothing in the Main loop.

The only other thing I added was a CONFIG line for HS oscillator mode, and LVP OFF.
<br>

Adrian
- 20th August 2008, 09:36
Hi Darrel
I changed the bit of maths and hey presto the programme instantly came good. It is cycle accurate all the way up. I'm really pleased...so many thanks. Now I'll get back to studying your programme to see how it works. The bit that is confusing is adding the reload value to the timer value - I didn't realise it then subtracted the timer value to the point of reset. You did this using ASM. Presumably this could also be done in PBP?
Regards Adrian

Darrel Taylor
- 20th August 2008, 21:13
I changed the bit of maths and hey presto the programme instantly came good. It is cycle accurate all the way up. I'm really pleased...so many thanks.

That's Great!
Didn't think that was it, but now I'm glad it was.
Thanks for helping me find the problem! :)

> You did this using ASM. Presumably this could also be done in PBP?

It can be done with only PBP statements. But it's difficult to know exactly how many instructions it uses for the reload. You'd have to search the .LST file to figure that out. Then as the program grows, that code may move to a different "Page" and change the timing without you knowing about it. With the ASM version, you always know it takes 8 instructions.

With 2000 interrupts per second, a difference of 1 count in the load routine translates to an error of 2000 counts per second. Not good for long term timing.