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 support@ccsinfo.com

problem with timer configuration

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



Joined: 04 May 2008
Posts: 260

View user's profile Send private message

problem with timer configuration
PostPosted: Sat Nov 22, 2008 3:03 pm     Reply with quote

Hi

I would like work with timers but I don't understand how this work.

For example with PIC18F452 with clock 40Mhz, I like calculate how many times I push one switch in 20 sec.

Some one can explain me what kind of calculations I need make? and after what kind of code I need write?

kind regards, Filipe
Ttelmah
Guest







PostPosted: Sun Nov 23, 2008 3:48 am     Reply with quote

This is not really anything to do with 'timers' as such. You may well use one, but only as the background 'clock' to your main work. The first thing you need to do, is work out how to detect a key 'press'. This is _not_ a simple matter of reading the input, since 'real' keys will exhibit faults, such as 'bounce', when they are made/released. Hence the detection code, will need to have a 'debounce' strategy, so that the key is only genuinely detected, when it is pressed for a few moments, and the multiple small pulses that may well appear as it is made, are ignored. This is called 'debouncing', and a search here will find examples, both using timers, and using simple delay counts.
Once you have key detection sorted, then it becomes a simple matter to increment a counter when the key is seen.
Then, you will not find any hardware timers that can give time intervals like 20 seconds, without using external hardware. Instead, the normal solution, would be to create a 'heartbeat' clock, typically at some frequency like 100 ticks per second. Again, once this is working, it becomes a simple matter to add a counter to this. If using 100Hz, you would set the counter for this to 200, set the key counter to 0, then when the heartbeat timer reaches zero, the number in the key counter, is the number of keys 'seen' in this time.
Now, the individual parts of this, have all been posted here in the past. You need to ue the search engine, and find the components, then see if you can put them together. What you describe, need not be a large program, but will probably be perhaps 100 lines in total. Nobody, is going to write it for you, you need to start to understand the program, and write it yourself. Come back, and ask individual questions, when you get stuck. This is what learning is about.

Best Wishes
filjoa



Joined: 04 May 2008
Posts: 260

View user's profile Send private message

PostPosted: Sun Nov 23, 2008 6:20 am     Reply with quote

Hi

thank for your answer Ttelmah

I can use for example 555 for count time but I try use timers because I think more simple. But I don't understand timers...

for example:

Quote:

int16 TIME; // Variavel Global de Relogio - 1mS

#int_TIMER2 // a cada 1mS incrementa TIME
void TIMER2_isr(void)
{
TIME++;
}


void main()
{

setup_timer_2(T2_DIV_BY_16,39,16);
enable_interrupts(INT_TIMER2);

while(TRUE)
{
TIME=0;
while (TIME <= 20000)
{
if (input(PIN_B7) == 1)
{
count++;
}
}

if (count==3)
{
codeok();
}else fstop();
}
}



This example I make with wizard of PICC and try numbers for have +-1us in timer, but it don't work and I continue understand this procedure.

In my idea where I have "while (TIME <= 20000) " it is the same with program while 20sec read how many times I press PIN_B7.

My idea stay wrong? Crying or Very sad

Regards, Filipe
Ttelmah
Guest







PostPosted: Sun Nov 23, 2008 2:12 pm     Reply with quote

OK.
Much better.
The reason this doesn't work, is you need to enable the GLOBAL interrupt flag as well as the timer interrupt.
Other problem, it won't count the key presses. It''ll count how many times it goes round the 'while' loop, while the key is pressed. You need to detect the key _changing_, not just being pressed.
The interrupt will occur 976.56 times per second. Chose values to give a more accurate time. Also, even with a 'fast' processor, it'll be spending a lot of time in the interrupt running at 1KHz. I'd suggest somewhat slower.
So, something like:
Code:

int16 time; // Variavel Global de Relogio - 1mS

#int_TIMER2 // 2mSec interrupt
void TIMER2_isr(void) {
    if (time) --time;
    //This means to counter will stop when it gets to zero
}

void main(void) {
    int1 oldip;
    setup_timer_2(T2_DIV_BY_8,249,10);
    //40000000/(4*8*250*10) = 500
    enable_interrupts(INT_TIMER2);
    enable_interrupts(GLOBAL);
    oldip=input(PIN_B7);
   
    while(TRUE) {
         time=10000;
         count=0;
         while (time) {
             if (input(PIN_B7) == 1)
                 {
                 if (oldip==0) {
                      //Here pin has _changed_ to ==1
                      oldip=1;
                      count++;
                 }
             }
             else
                 oldip=0;
         }
         if (count==3)
             codeok();
         else
             fstop();
    }
}

This will still potentially have problems with seeing multiple 'makes' if there is keybounce, but should get close to working.

Best Wishes
filjoa



Joined: 04 May 2008
Posts: 260

View user's profile Send private message

PostPosted: Sun Nov 23, 2008 3:57 pm     Reply with quote

Hi

One more time thanks Ttelmah

This is for simulating calculation of Car ABS sensor but now I have this on prototype and have a simple switch where I press "x"times.

When you suggest
Quote:

if (oldip==0) {
//Here pin has _changed_ to ==1
oldip=1;
count++;
}


This is for case I press slowly the button, correct? But if I call for example interrupts in ports RB0, RB1 or RB2 (PIC18F452) for detect this impulse you think this better?


Now about timers :P
when you configure setup timers:
Quote:

setup_timer_2(T2_DIV_BY_8,249,10);
//40000000/(4*8*250*10) = 500


How you use "4", "250", "10" and result "500" what this mean? or what you don't use other values?

and after you tell
Quote:
#int_TIMER2 // 2mSec interrupt

I don't understand where appear 2msec.

I can use for example same process for timer0 and timer1?

Sorry my stupid questions but I like know how timers work...

kind regards
Ttelmah
Guest







PostPosted: Sun Nov 23, 2008 4:23 pm     Reply with quote

The point is that your main code is looping. You test for the button being made (==1), but it'll be made all the time, when it is pressed. Remember that the loop takes only a few instructions. Even the _quickest_key press will last for thousands of processor instructions. You would never see '3' without this, since it'll shoot past this, before you can physically release the button, even if you are 'faster than a speeding bullet'.
It'd actually take a typical bullet, something over 50uSec to pass 'through' a button. Counting in the loop, without a test for the change being present, I'd expect a bullet to probably give about 10 counts. Hence this type of test is _essential_...

Now, on the timing. There is a balancing act. If the interrupt is too fast, you will spend most of your time in the interrupt. 1mSec, is possible, but probably 'pushing things', hence I suggest dropping to 2mSec. Now the timer calculation, is that you have the master clock (40000000), which is divided by four, before it goes to the timer circuit (hence the first four. Then, you are looking for a set of numbers, that multiply together to give a value close to 20000, and if the timing is to be accurate, want to give _exactly_ 20000. On your original code, which was meant to give 1mSec (requiring 10000), the numbers actually give 16*40*16 = 10240.
Using 8*250*10, givesexactly 20000. You could also use 16*125*10, but there are only a few combinations that give exact decimal results like this.

the result number, is how many times the interrupt will occur a second. 500* = 2mSec interval.

On the other timers, you don't have the interrupt 'postscaler', or the ability to automatically reset the counters at a value. Generally they will only give binary counts.

Yes, you can use an interrupt on change to detect the button, but with this, debouncing will become even more essential.

Best Wishes
filjoa



Joined: 04 May 2008
Posts: 260

View user's profile Send private message

PostPosted: Tue Nov 25, 2008 11:07 am     Reply with quote

hi

I try use this code on ISIS Proteus but it don't work.

Other problem is... I change PIC18F452 for PIC18F252 and CCS give an error on "setup_timer_2(T2_DIV_BY_8,249,10);" and for correct this I change to "setup_timer_2(T2_DIV_BY_4,249,10);".

My code at this moment for test timers is:
Code:

#include <18F252.h>
#fuses EC_IO,NOWDT,NOPROTECT,NOLVP,BROWNOUT,STVREN
#use delay(clock=40000000)
#use rs232(baud=115200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)


#build(reset=0x200)
#build(interrupt=0x208)
#org 0x0000,0x01ff
void bootloader() {
#asm
  nop
#endasm
} // Reserve space for the bootloader

//###### VARIAVEIS #####
int16 time; // Variavel Global de Relogio - 1mS

//###### IN PORTS ######
#define DOOR PIN_B7
#define HBREAK PIN_B6
#define RFID PIN_B5
#define IGN PIN_B4
#define ABS PIN_B0

//###### OUT PORTS ######
#define RED PIN_B1
#define GREEN PIN_B2
#define R1 PIN_C0 //relé de falha
#define R2 PIN_C1 //relé bi-estavel de corte
#define R3 PIN_C2
#define R4 PIN_C3


#int_TIMER2 // 2mSec interrupt
void TIMER2_isr(void) {
    if (time) --time;
    //This means to counter will stop when it gets to zero
}


void codeok()
{
output_high(R1);
delay_ms(1000);
output_low(R1);
delay_ms(1000);
output_high(R1);
delay_ms(1000);
output_low(R1);
delay_ms(1000);
}
void fstop()
{
output_high(R2);
delay_ms(1000);
output_low(R2);
delay_ms(1000);
output_high(R2);
delay_ms(1000);
output_low(R2);
delay_ms(1000);
}


void main()
{
    int1 oldip;
    int8 count;
   
    setup_timer_2(T2_DIV_BY_4,249,10); //40000000/(4*4*250*10) = 1000
    enable_interrupts(INT_TIMER2);
    enable_interrupts(GLOBAL);
   
   
oldip=input(DOOR);

While(TRUE)
{
         time=10000;
         count=0;
         
         while (time) {
             if (input(DOOR) == 1)
                 {
                 if (oldip==0) //Here pin has _changed_ to ==1
                 {
                      oldip=1;
                      count++;
                 }
             }
             else
                 oldip=0;
         }
         if (count==3)
             codeok();
         else
             fstop();

}

}



This is the circuit on Proteus:


Someone can help me to correct them?

kind regards
filjoa



Joined: 04 May 2008
Posts: 260

View user's profile Send private message

PostPosted: Tue Nov 25, 2008 11:48 am     Reply with quote

Hi

I make some tests and problem stay on timers :S

it dont jump from "while(time)" :( and I dont know why....
filjoa



Joined: 04 May 2008
Posts: 260

View user's profile Send private message

PostPosted: Tue Nov 25, 2008 5:54 pm     Reply with quote

Hi

I try make other simple program but now with timer0 but it don´t work Crying or Very sad
Code:

#include <18F252.h>
#fuses EC_IO,NOWDT,NOPROTECT,NOLVP,BROWNOUT,STVREN
#use delay(clock=40000000)
#use rs232(baud=115200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)

#int_TIMER0

int16 time; // Variavel Global de Relogio


void TIMER0_isr(void)
   {
    time++;
   }

void main()
{

   setup_timer_0(RTCC_EXT_L_TO_H|RTCC_DIV_256);       // 1seg
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);

while(1)
{

   time=0;
   while (time <= 20000)
      {
      output_high(PIN_C0);
      }
   output_low(PIN_C0);
   delay_ms(1000);
}
}


With this program PIN_C0 continue infinitely high and never return to low... one more time my timer configuration don't stay correct Confused

For configuration I go to wizard. I make this options:


Please someone can help make this work? and if is possible explain me why this don't work.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Nov 25, 2008 6:25 pm     Reply with quote

'time' is a 16-bit variable that is changed in the #int_timer0 routine.
You need to disable interrupts temporarily when you read or write
the 'time' value in main(). There are two places in your program
where you access 'time'.

The reason is because it takes two ASM instructions to read or write
the two bytes in the 16-bit variable. An interrupt could occur between
these two ASM instructions and the result would be a corruption of the
'time' variable.

More info:
http://www.htsoft.com/resources/articles/techtip_interrupts.php



Also, the #int_timer0 statement should go above the isr routine. Don't
put any other lines of code between them. Example of how to do it:
Quote:
#int_TIMER0
void TIMER0_isr(void)
{
time++;
}
filjoa



Joined: 04 May 2008
Posts: 260

View user's profile Send private message

PostPosted: Tue Nov 25, 2008 6:45 pm     Reply with quote

Hi, thanks

I put the code how you tell but continue without work...

I don't understand what stay wrong with "time" where I destroy this variable?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Nov 25, 2008 7:04 pm     Reply with quote

At some point, you need to be able to understand technical instruction.
Here are two threads that explain the problem.
http://www.ccsinfo.com/forum/viewtopic.php?t=32951
http://www.ccsinfo.com/forum/viewtopic.php?t=28768
filjoa



Joined: 04 May 2008
Posts: 260

View user's profile Send private message

PostPosted: Wed Nov 26, 2008 1:00 pm     Reply with quote

Hi

sorry but I think that I only understand when I see Sad Sad

please, some one can correct one of this program for work, with any timer...
filjoa



Joined: 04 May 2008
Posts: 260

View user's profile Send private message

PostPosted: Thu Nov 27, 2008 5:15 am     Reply with quote

hi

I will try make this and I put there some "stupid" questions, for I try understand timers procedure.

For start I have PIC18F252 at 40Mhz and I try use timer1.

I make this code:
Code:

#include <18F252.h>
#fuses EC_IO,NOWDT,NOPROTECT,NOLVP,BROWNOUT,STVREN
#use delay(clock=40000000)
#use rs232(baud=115200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)


//###### VARIAVEIS #####
int16 time; // Variavel Global de Relogio - 1mS

//###### IN PORTS ######
#define DOOR PIN_B7
#define HBREAK PIN_B6
#define RFID PIN_B5
#define IGN PIN_B4
#define ABS PIN_B0

//###### OUT PORTS ######
#define RED PIN_B1
#define GREEN PIN_B2
#define R1 PIN_C0 //relé de falha
#define R2 PIN_C1 //relé bi-estavel de corte
#define R3 PIN_C2
#define R4 PIN_C3


#int_TIMER1
void TIMER1_isr(void) {
    time++;
}


void codeok()
{
output_high(R1);
delay_ms(1000);
output_low(R1);
delay_ms(1000);
output_high(R1);
delay_ms(1000);
output_low(R1);
delay_ms(1000);
}

void fstop()
{
output_high(R2);
delay_ms(1000);
output_low(R2);
delay_ms(1000);
output_high(R2);
delay_ms(1000);
output_low(R2);
delay_ms(1000);
}


void main()
{
    int1 oldip;
    int8 count;
   
    enable_interrupts(INT_TIMER1);
    setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
 //sets the internal clock as source
 //and prescale as 8. At 20Mhz timer1 will increment
 //every 1.6us in this setup and overflows every
 //104.896ms  (Manual Pag. 77)
   
enable_interrupts(GLOBAL);
   
oldip=input(DOOR);

While(TRUE)
{
         time=0;
         count=0;
       
         while (time<10000)
         {         
             if (input(DOOR) == 1)
                 {
                 if (oldip==0)
                 {
                      oldip=1;
                      count++;
                 }
             }
             else
                 oldip=0;
         }
                 
         if (count==3)
             codeok();
         else
             fstop();

}

}



1º question:
I copy this "setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);" from CCS manual but example work at 20Mhz but my program work at 40Mhz, how I can make this calculations for know when have my timer1?

2º question:
in this example configuration I have one timer every 1.6us what mean have overflows every 104.896ms?

3º question:
in my program if I use this example configuration (at 20Mhz) how many time +- I have on "while (time<10000)"?

Please help me try understand this... I need start timers from zero for I understand.

kind regards, Filipe Abrantes
filjoa



Joined: 04 May 2008
Posts: 260

View user's profile Send private message

PostPosted: Thu Nov 27, 2008 9:38 am     Reply with quote

Sorry but I edit last reply and this don't up the post Cool and I comment now only for this post up Laughing
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