|
|
View previous topic :: View next topic |
Author |
Message |
Charlie U
Joined: 09 Sep 2003 Posts: 183 Location: Somewhere under water in the Great Lakes
|
Setup_timer_0(); with Constants and Variables |
Posted: Tue Mar 18, 2008 8:45 am |
|
|
I stumbled across an interesting "feature" of the compiler last night (actually this morning in the wee hours) and I thought I might see if anyone else has encountered this. I need to measure the frequency of a fairly slow signal. It can range from around 1/2Hz to more than 10Hz. Looking at the data sheet for the 18F8722, I decided to use Timer 0 and its prescalers. It appeared to fit perfectly, but here's my mistake. I tried to be clever and create a function that adjusted the prescaler if the timed value was less than some minimum to maintain resolution or greater than some maximum to avoid possible overflow. Silly me, I looked in the header file and found that the prescale values started with 8 for x1 then 0 for x2, 1 for x4, etc. up to 7 for x256. Cool, I just incremented the value and or'd it with RTCC_INTERNAL and used that as the parameter for setup_timer_0();.
Wrong!!!
It appears that the compiler looks at the predefined constant RTCC_INTERNAL and sets the control register with different value than the actual defined constant. RTCC_INTERNAL is defined as 0 but when the compiler sees this in the setup function is uses 0x80!!!! If there are any parameters other than those defined in device header file, 18F8722.h, it uses the defined value, 0, and or's this with the other parameters. This results in the timer being turned off. Nice!
Curiously, RTCC_OFF is defined as 0x80, which if used directly would enable the timer!?!?
Here's the listing from a test program. The first setup call was created by the Wizard with the RTCC internal box checked and the 0.4usec button selected. This should use the x1 prescaler. Unfortunately, if you don't or in a prescaler value, the default is 0 which yields a x2 prescaler.
The 2nd, 3rd, and 4th use the predefined constants and setup the timer correctly.
The 5th and 6th use a variable to set the parameter. The 6th uses the predefined constants to set the value of the variable. Neither of these setup the timer correctly: it will be disabled.
Code: |
.................... setup_timer_0(RTCC_INTERNAL);
00046: MOVLW 80
00048: MOVWF FD5
.................... setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
0004A: MOVLW 88
0004C: MOVWF FD5
.................... setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2);
0004E: MOVLW 80
00050: MOVWF FD5
.................... setup_timer_0(RTCC_INTERNAL|RTCC_DIV_8);
00052: MOVLW 82
00054: MOVWF FD5
.................... t0setup = 0x02;
00056: MOVLW 02
00058: MOVWF 05
.................... setup_timer_0(RTCC_INTERNAL|t0setup);
0005A: MOVFF 05,FD5
.................... t0setup = RTCC_INTERNAL|RTCC_DIV_8;
0005E: MOVLW 02
00060: MOVWF 05
.................... setup_timer_0(t0setup);
00062: MOVFF 05,FD5
|
|
|
|
nurquhar
Joined: 05 Aug 2006 Posts: 149 Location: Redditch, UK
|
|
Posted: Mon Apr 07, 2008 3:19 am |
|
|
I have just encounter this problem too !!! I am using PCH 3.249 with an 18F67J10.
This line runs the timer0 in 8bit mode :
Code: | setup_timer_0(RTCC_INTERNAL|RTCC_8_BIT|RTCC_DIV_32); |
This line does not start the timer running, ie it does not set the enable bit (bit7) of T0CON.
Code: | unsigned int div ;
div = RTCC_INTERNAL | RTCC_8_BIT | RTCC_DIV_32 ;
setup_timer_0(div); |
However the apparent fix required to make it work is to specifcaly include something to set bit7. ie :-
Code: | unsigned int div ;
div = 0x80 | RTCC_INTERNAL | RTCC_8_BIT | RTCC_DIV_32 ;
setup_timer_0(div); |
|
|
|
Ttelmah Guest
|
|
Posted: Mon Apr 07, 2008 4:06 am |
|
|
This is quite common!.
What CCS do, is XOR bit 7, if the value is a constant, but _not_ if it is a variable. I think the XOR, was a 'kludge' introduced when the newer bits were added to some timers, to 'retain compatibility' with the older constants already in use....
It happens on several of the latter register settings.
Best Wishes |
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
Re: Setup_timer_0(); with Constants and Variables |
Posted: Mon Apr 07, 2008 5:00 am |
|
|
This is another example of why it is often better to ignore CCS library functions and write to the SFRs yourself. Then you know for sure what is going on. The chip documentation for Timer 0 SFRs is simple enough that it does not need a layer of compiler junk to isolate you from it.
Robert Scott
Real-Time Specialties |
|
|
|
|
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
|