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

timer0()

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



Joined: 02 Jun 2007
Posts: 11

View user's profile Send private message

timer0()
PostPosted: Mon Jun 04, 2007 10:06 pm     Reply with quote

hello, i want to use the timer (timer0) for the 16f690 in order to keep track of the amount of time in between interrupts (in this case the inturrupt happens when a button is pressed). when the inturrupt is executed it should read the time of timer0 and average it with a preset delaylength that is used to delay the length of leds shining in main() but for some reason it doesnt do that. it just ends up going amazingly slow, more than the length of time i spend in between inturrupts. delaylength is an global variable.

here is my code.

thanks for the help.

EDIT: ccs vr. 4.013

Code:
#include "C:\Program Files\PICC\Projects\16f690.h"
#int_RA
#fuses INTRC_IO,NOPROTECT, NOWDT, NOMCLR
#use delay (clock=20000000)

int delaylength;

RA3_isr()
{
       int8 c;
       int time;

       //get the time since last call to isr
       time=get_timer0();

       //set clock to zero
       set_timer0(0);
       //average old dleay with new one
       delaylength=((delaylength+time)/2);

       c = input_a();
}

void main()
{
   int c;

   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF);
   setup_spi(FALSE);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);

   c=input(PIN_A3);
   clear_interrupt(INT_RA3);

   enable_interrupts(INT_RA3);
   enable_interrupts(GLOBAL);
   setup_oscillator(False);

   set_timer0(0); //set timer to zero

   delaylength=2; //an initial value

   //loop the leds 0-1-2-3-2-1-0
   while (1)
   {
       output_high(PIN_C0);
       delay_ms(delaylength);
       output_low(PIN_C0);

       delay_ms(delaylength/2);

       output_high(PIN_C1);
       delay_ms(delaylength);
       output_low(PIN_C1);

       delay_ms(delaylength/2);

       output_high(PIN_C2);
       delay_ms(delaylength);
       output_low(PIN_C2);

       delay_ms(delaylength/2);

       output_high(PIN_C3);
       delay_ms(delaylength);
       output_low(PIN_C3);

       delay_ms(delaylength/2);

       output_high(PIN_C2);
       delay_ms(delaylength);
       output_low(PIN_C2);

       delay_ms(delaylength/2);

       output_high(PIN_C1);
       delay_ms(delaylength);
       output_low(PIN_C1);

       delay_ms(delaylength/2);

   }
}
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Tue Jun 05, 2007 2:25 am     Reply with quote

Are you sure your processor is running at 20MHz? I didn't check but think such high frequencies are not supported for the RC clock option.
random guy



Joined: 02 Jun 2007
Posts: 11

View user's profile Send private message

PostPosted: Tue Jun 05, 2007 9:32 am     Reply with quote

well i am kinda new to this but i looked at the beginning of the data sheet

http://ww1.microchip.com/downloads/en/devicedoc/41262A.pdf

and on page 3 it says

Quote:
Operating speed:
- DC – 20 MHz oscillator/clock input


so i used that as the clock. is there somewhere else i should check?
Ttelmah
Guest







PostPosted: Tue Jun 05, 2007 10:25 am     Reply with quote

Note the word _input_.
The INT_RC oscillator, is the _internal_ oscillator. It runs at 8MHz _max_. You can run the chip at '20MHz', but only by feeding it with an external 20MHz oscillator.
With the current settings, the compiler cannot satisfy your specified clock rate, using the internal oscillator, so the default rate will be selected. 32KHz...

Best Wishes
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Jun 05, 2007 2:38 pm     Reply with quote

The latest 16F690 data sheet is the Rev. D version.
http://ww1.microchip.com/downloads/en/DeviceDoc/41262D.pdf

You can get the latest data sheet by going to the "Data Sheet Finder"
page on the Microchip website. There's a link to it at the top of the
main page:
http://www.microchip.com
Then use the drop-down box to get to the page for the 16F690.
Download the data sheet, and look in Section 3.0 on the Oscillator Module.
There are several drawing in there that show the frequency choices
for the internal oscillator. The highest freq is always shown at 8 MHz.
random guy



Joined: 02 Jun 2007
Posts: 11

View user's profile Send private message

PostPosted: Tue Jun 05, 2007 9:13 pm     Reply with quote

hmm well i changed the clock to

#use delay (clock=8000000)

but it still was experiencing the same problem of seemingly not continueing the led sequence. in my last test i tried dividing the variable time (should be the amount of time since the start to the inturrupt and then from there on in between inturrupts) by a large number

delaylength=((delaylength+(time/10000000000000000000000000))/2);

still took a while. i waited like 2 or 3 min and it continued the led sequence after that long amount of time staying at that point in the sequence. after that the variable delay didnt seem to be changed (kept blinking at same speed) and inturrupt button didnt do anything after that.

here is the code. thank you for the help.

Code:
#include "C:\Program Files\PICC\Projects\16f690.h"
#int_RA
#fuses INTRC_IO,NOPROTECT, NOWDT, NOMCLR
#use delay (clock=8000000)

int delaylength;

RA3_isr()
{
       int8 c;
       int time;

       //get the time since last call to isr
       time=get_timer0();

       //set clock to zero
       set_timer0(0);
       //average old dleay with new one
       delaylength=((delaylength+(time/10000000000000000000000000))/2);

       c = input_a();
}

void main()
{
   int c;

   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF);
   setup_spi(FALSE);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);

   c=input(PIN_A3);
   clear_interrupt(INT_RA3);

   enable_interrupts(INT_RA3);
   enable_interrupts(GLOBAL);
   setup_oscillator(False);

   set_timer0(0); //set timer to zero

   delaylength=2; //an initial value

   //loop the leds 0-1-2-3-2-1-0
   while (1)
   {
       output_high(PIN_C0);
       delay_ms(delaylength);
       output_low(PIN_C0);

       delay_ms(delaylength/2);

       output_high(PIN_C1);
       delay_ms(delaylength);
       output_low(PIN_C1);

       delay_ms(delaylength/2);

       output_high(PIN_C2);
       delay_ms(delaylength);
       output_low(PIN_C2);

       delay_ms(delaylength/2);

       output_high(PIN_C3);
       delay_ms(delaylength);
       output_low(PIN_C3);

       delay_ms(delaylength/2);

       output_high(PIN_C2);
       delay_ms(delaylength);
       output_low(PIN_C2);

       delay_ms(delaylength/2);

       output_high(PIN_C1);
       delay_ms(delaylength);
       output_low(PIN_C1);

       delay_ms(delaylength/2);

   }
}


EDIT: it does seem kinda weird that a delay of 2 miliseconds (or at least it should be) isnt super fast. the leds are staying bright and pausing for less than a second but staying much longer than the small time of 2 miliseconds. i dont so much mind what units the time is stored in or how long it thinks a milisecond is so long as it is consistant so that i can average the amounts of time between inturrupts and have the speed of the leds blinking minic that speed.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Jun 05, 2007 10:13 pm     Reply with quote

Quote:
delaylength=((delaylength+(time/10000000000000000000000000))/2);

You need to learn the datatypes in CCS. You can't just do anything.
CCS will only work with specific data types, and each data type can
hold a specified maximum value.

Download the CCS manual.
http://www.ccsinfo.com/downloads/ccs_c_manual.pdf
Read the section on Data Types. Note that the largest integer type
is an int32 (unsigned).

Run the calculator that comes with Windows. Type in 2, the press
the x^y key. Then type in 32 and press the = key. That's the largest
number that can be put into an int32.

If you want a language in which you can do anything (or at least, a lot),
then you want Basic.
C is constrained. You have to learn the rules.

C tutorials:
http://www2.its.strath.ac.uk/courses/c/
http://cslibrary.stanford.edu/101/EssentialC.pdf

Note that CCS is not full ANSI C. It's a subset of that, with some
extensions (invented by CCS) for the PIC.
random guy



Joined: 02 Jun 2007
Posts: 11

View user's profile Send private message

PostPosted: Tue Jun 05, 2007 11:23 pm     Reply with quote

well that was more or less just a test to see if it was counting microseconds, nanoseconds or something. since adding delaylength (which was 2) to time (some number) and dividing it by 2 was producing such a large number i was assuming from a mathematical standpoint that time must be a large number. but there seems to be something else wrong. i get that feeling because after the one long delay the value of delaylength isnt changed nor does the code enter the inturrupt after that (or doesnt seem to since it doesnt produce the same result as the first time it is pressed or the result that i am seeking).

i tried removing the division and making time a 32 bit int just in case whatever form the timer is counting up by might produce a number too big for 8 bits. didnt work though. hope the overflow isnt so bad that it doesnt fit in 32 bits, would explain why it is acting contrary to how it should though.

thanks for the help so far and the reading material, may be usful to brush up on my c and such.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Wed Jun 06, 2007 2:53 am     Reply with quote

Code:
   setup_oscillator(False);
This will disable the internal oscillator. I'm surprised your code is doing anything at all. Remove this line.


Code:
#int_RA
#fuses INTRC_IO,NOPROTECT, NOWDT, NOMCLR
#use delay (clock=8000000)

int delaylength;

RA3_isr()
{
Keep the line #int_RA as close as possible to the function start, don't put other unrelated keywords in between as this makes the code hard to read and could confuse the compiler.


It's good programming practice to declare variables with keywords that define the exact variable type. You are mixing both int8 and int which are the same in the CCS compiler but when porting to another compiler the int specifier might be equal to a signed int32.


Code:
       delaylength=((delaylength+(time/10000000000000000000000000))/2);
As PCM already told you this is not going to work, the large number is larger than what fits in an int32. Even so, for an integer division the result of time (an int8) divided by the large number will equal 0. This means that after a few interrupts your averaged delaylength will go to zero as well.
Your previous averaging algorithm was better:
Code:
delaylength=((delaylength+time)/2);
But this has a potential problem of int8 overflow in the addition. Prevent the overflow by casting one of the int8 variables to an int16:
Code:
delaylength= ( ((int16)delaylength + time) / 2);


Check the timer0 rate. I don't know what is connected to pin_A3 but you might have overflow problems. At 8MHz and a prescaler of 256 Timer0 will increment every 128us, having an 8 bits size it will overflow every 32ms.

Compiler version 4.013 is to be considered a beta release and has many known problems. Around release 4.030 the v4.xxx compiler became more or less useable. Save everyone a lot of time by downgrading to v3.249 (the last stable release and still available for download from the website) or upgrade to at least v4.030.

Note: I'm surprised by the large number of people all using the same old 4.013 release. CCS must have sold a lot of these without upgrade support... Confused
random guy



Joined: 02 Jun 2007
Posts: 11

View user's profile Send private message

PostPosted: Wed Jun 06, 2007 8:08 pm     Reply with quote

ok great those tips really helped, A3 is a button actually, at least for the moment. later i am going to exchange it with a light sensor and set it up such that i can pick up the reflections of water droplets dripping at a fast rate (almost a constant stream of water but be separated enough to be individual drops).

when i test it out now the delay length is definetly changing which is good. but i do have the overflow issue since it isnt being activated within 32ms each time (i think that is the only problem). anyway i can change it to allow for a longer amount of time, maybe by changing it from 8 bit to 32 bit. 32ms might be pushing it a little with when i switch to the other form of input, definetly too short for the tests i am doing now with it being a button press. a few seconds would be good.

i am trying to build up hte application gradually such that i dont get overly confused. here is the latest revision of my code in case anyone wanted to see.



Code:
#include "C:\Program Files\PICC\Projects\16f690.h"
#fuses INTRC_IO,NOPROTECT, NOWDT, NOMCLR
#use delay (clock=8000000)
int delaylength;
#int_RA

RA3_isr()
{
       int8 c;
       int32 time;

       //get the time since last call to isr
       time=get_timer0();

       //set clock to zero
       set_timer0(0);
       //average old delay with new one
       delaylength= ( ((int32)delaylength + time) / 2);

       c = input_a();
}

void main()
{
   int c;

   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF);
   setup_spi(FALSE);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);

   c=input(PIN_A3);
   clear_interrupt(INT_RA3);

   enable_interrupts(INT_RA3);
   enable_interrupts(GLOBAL);

   set_timer0(0); //set timer to zero

   delaylength=2000; //an initial value

   //loop the leds 0-1-2-3-2-1-0
   while (1)
   {
       output_high(PIN_C0);
       delay_ms(delaylength);
       output_low(PIN_C0);

       delay_ms(delaylength/2);

       output_high(PIN_C1);
       delay_ms(delaylength);
       output_low(PIN_C1);

       delay_ms(delaylength/2);

       output_high(PIN_C2);
       delay_ms(delaylength);
       output_low(PIN_C2);

       delay_ms(delaylength/2);

       output_high(PIN_C3);
       delay_ms(delaylength);
       output_low(PIN_C3);

       delay_ms(delaylength/2);

       output_high(PIN_C2);
       delay_ms(delaylength);
       output_low(PIN_C2);

       delay_ms(delaylength/2);

       output_high(PIN_C1);
       delay_ms(delaylength);
       output_low(PIN_C1);

       delay_ms(delaylength/2);

   }
}
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu Jun 07, 2007 4:39 am     Reply with quote

Code:
       int32 time;

       //get the time since last call to isr
       time=get_timer0();
timer0 is 8 bit. assigning to an int32 is overkill and a waste of resources. Same applies to the cast to an int32 you are doing, an int16 will do the job. Why did you change my example code?

Code:
   delaylength=2000; //an initial value
delaylength is an int8, the value of 2000 doesn't fit and will be truncated to 2000/256 = 7.

An easy way to extend the 32ms timer0 period is by lowering the clock frequency. To do this change the #use delay() directive to the desired clock frequency, for example 1MHz. Check chapter 3.5.4 of the PIC16F690 datasheet for all allowed clock frequencies.
Ttelmah
Guest







PostPosted: Thu Jun 07, 2007 5:16 am     Reply with quote

Actually, as a small 'comment', 2000, will give 208, not 7. It is 2000%256, that gets stored.

Best Wishes
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