![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
jpos99
Joined: 10 Aug 2012 Posts: 14
|
Timer5 |
Posted: Sun Oct 23, 2016 10:41 am |
|
|
Hello,
I'm having some problems with the Timer5.
I was working with 8Mhz internal clock and receiving from modbus the value for the period for the timer5, and I was able to have 8hz minimal frequency and the maximum I wanted was 200 hz and no problem. I use the timer5 interrupt to run a PWM single shot from the Power PWM module.
I do like this because I want low frequency's and short pulses.
Part of the code
Code: |
void main()
{
setup_timer_5 (T5_INTERNAL | T5_DIV_BY_4);
T = 500000 / make8 (hold_regs [1],1);
t1 = (T) & 0xff;
t2 = ((T) >> 8 ) & 0xff;
#ASM
movff t2,PR5H
movff 0,PR5L
#ENDASM
#int_global
#int_timer5
void isr()
{
setup_power_pwm(PWM_CLOCK_DIV_4 | PWM_SINGLE_SHOT | PWM_DEAD_CLOCK_DIV_16, 1,0,3000,0,1, 63);
}
|
Then I had to change the clock to 2 Mhz to be able to run at lower frequency, i.e., because before the timer counter rolled over after 132 ms and I need 1s to do 1 hz signal.
So the new prescaler is 8, and I multiply the freq value by 8 and now I'm able to do 1hz signal.
Code: |
void main()
{
setup_timer_5 (T5_INTERNAL | T5_DIV_BY_8);
T = 500000 / (freq*8);
t1 = (T) & 0xff;
t2 = ((T) >> 8 ) & 0xff;
#ASM
movff t2,PR5H
movff t1,PR5L
#ENDASM
#int_global
#int_timer5
void isr()
{
setup_power_pwm(PWM_CLOCK_DIV_4 | PWM_SINGLE_SHOT | PWM_DEAD_CLOCK_DIV_16, 1,0,3000,0,1, 63);
}
|
The problem is at 31 hz the counter looks to roll over again and I cant do higher frequency then that. And for my calculations at 32hz the register should not roll over only at 62.5khz more or less.
It looks like that the count instead of be a 16 bit register is a 11 bit one.
Example:
This is the value generated with the value introduced
- Freq:32hz
- T= 500000/ ( 32 *8) = 1953
My calculations
1/(2E6/8) = 4 us clock cycle
4us * 4 = 16 us per instruction
16us * 2^16 = 1.04s or 1Hz
and if a consider only one cycle is 16us is 62.5khz.
Any suggestion?
Thanks |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Oct 23, 2016 12:05 pm |
|
|
Post your PIC and post your variable declarations. For example, what is
the data type of 'T' ?
Quote: |
#ASM
movff t2,PR5H
movff 0,PR5L
#ENDASM |
You don't have to use ASM to load registers in CCS. Not at all.
Use #byte with getenv() to set the register address. Then write to
the register in your program. Or, more likely, use a built-in CCS function.
Quote: |
#int_global
#int_timer5
void isr()
{
|
#int_global is not used this way, and you should not be using it in your
program. Remove it. From the CCS manual:
Quote: |
#INT_GLOBAL
Purpose:
This directive causes the following function to replace the compiler interrupt dispatcher. The function is normally not required and should be used with great caution. When used, the compiler does not generate start-up code or clean-up code, and does not save the registers. |
|
|
![](templates/subSilver/images/spacer.gif) |
jpos99
Joined: 10 Aug 2012 Posts: 14
|
|
Posted: Sun Oct 23, 2016 1:42 pm |
|
|
Hello,
The PIC is 18F4431.
T is a int16.
The rest I will try. Have any more idea why is rolling over at those values?
Regards |
|
![](templates/subSilver/images/spacer.gif) |
jpos99
Joined: 10 Aug 2012 Posts: 14
|
|
Posted: Mon Oct 24, 2016 4:36 pm |
|
|
Hello PCM programmer,
Today I run some more test and figure out that the problem is not on the timer counter but on the values I entered on the PR5 register.
I did the following, for a frequency of 100hz
Code: |
T = 500000 / (100*8);
PR5H = make8(T,1);
PR5L = make8(T,0);
|
and the result was the same as before, then I did,
Code: |
T = 625;
PR5H = make8(T,1);
PR5L = make8(T,0);
|
and the result is OK. I have a 100 hz signal on the output.
So my problem is on the variable T.
It is declared before void main and I tried int16, long and always the same result.
Any idea.
Thanks |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19366
|
|
Posted: Tue Oct 25, 2016 12:43 am |
|
|
Obvious thing. There is no problem with 'T', just with your maths....
50000/(100*8) = 62.5 (62 in integer), not 625.
No wonder you don't get what you expect!.
The best way of setting the PR5 register is:
Code: |
#word PR5=getenv("SFR:PR5L")
//Then to set it:
PR5=T;
|
|
|
![](templates/subSilver/images/spacer.gif) |
jpos99
Joined: 10 Aug 2012 Posts: 14
|
|
Posted: Tue Oct 25, 2016 1:46 am |
|
|
Thanks Ttelmah,
But I forgot one zero, :P
500000 / ( 100 * 8) = 625
Your suggestion for the PR5 how can I use it on a 16 bit register?
Because what I know that is used to define a name to a register, but PR5 is 2 registers HIGH and LOW.
And I think, my problem is that one but I don't know why, I can't write correctly to each register??
Thanks again. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19366
|
|
Posted: Tue Oct 25, 2016 3:21 am |
|
|
That's the whole point about using #word.
#byte defines a byte at a memory location. #word defines a 16bit word at a location.
In fact #byte can also generate a 16bit word (or a 32bit value as well):
Code: |
int16 PR5;
#byte PR5=getenv("SFR:PR5L")
|
The 'int16 PR5' line, says that PR5 is a 16bit variable, then the following #byte, locates this 16bit variable at the PR5 location. This is exactly what #word does for you in one command. Neat thing is though that #byte used like this (with the variable size predefined), can locate any size variable. So you can even put an int32 'at' a location like this.
You don't even need 'T':
Code: |
#word PR5=getenv("SFR:PR5L")
//Then to set it:
PR5=500000/(100*8);
|
PR5 is just a 16bit variable like any other, except that it is mapped 'at' the location of the internal registers.
If you look in the processor include file, you will find that several of the lines are done this way to map standard things like the CCP registers for you. |
|
![](templates/subSilver/images/spacer.gif) |
jpos99
Joined: 10 Aug 2012 Posts: 14
|
|
Posted: Tue Oct 25, 2016 6:36 am |
|
|
Hi,
Solved the problem.
The declaration of the variable 'freq' was before the void main() and I don't know why it's not working correctly.
When I declared it on the main program everything started to work fine.
Now the Timer5 counter is working ok.
Thanks to all for the help, and if you care to comment this issue please do it because I need to understand.
Regards |
|
![](templates/subSilver/images/spacer.gif) |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|