CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Timer5

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
jpos99



Joined: 10 Aug 2012
Posts: 14

View user's profile Send private message

Timer5
PostPosted: Sun Oct 23, 2016 10:41 am     Reply with quote

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
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Oct 23, 2016 12:05 pm     Reply with quote

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.
jpos99



Joined: 10 Aug 2012
Posts: 14

View user's profile Send private message

PostPosted: Sun Oct 23, 2016 1:42 pm     Reply with quote

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
jpos99



Joined: 10 Aug 2012
Posts: 14

View user's profile Send private message

PostPosted: Mon Oct 24, 2016 4:36 pm     Reply with quote

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
Ttelmah



Joined: 11 Mar 2010
Posts: 19510

View user's profile Send private message

PostPosted: Tue Oct 25, 2016 12:43 am     Reply with quote

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;
jpos99



Joined: 10 Aug 2012
Posts: 14

View user's profile Send private message

PostPosted: Tue Oct 25, 2016 1:46 am     Reply with quote

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.
Ttelmah



Joined: 11 Mar 2010
Posts: 19510

View user's profile Send private message

PostPosted: Tue Oct 25, 2016 3:21 am     Reply with quote

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. Smile

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.
jpos99



Joined: 10 Aug 2012
Posts: 14

View user's profile Send private message

PostPosted: Tue Oct 25, 2016 6:36 am     Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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