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

Timer interrupt on pic16f877a
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
ccslearner



Joined: 12 Jan 2013
Posts: 10

View user's profile Send private message AIM Address ICQ Number

Timer interrupt on pic16f877a
PostPosted: Sun Jan 20, 2013 12:42 am     Reply with quote

Can anyone help me solve my problem ? I am using ccs compiler and PIC 16F877A. The assignment that was given to me is, write a program to glow LEDs in the following order, simultaneously:

LED1 - ON EVERY 5 sec and OFF EVERY 5 sec
LED2 - ON EVERY 2 sec and OFF EVERY 2 sec

Important, it should happen simultaneously, using timer2 interrupt.
Here I post my code also.
Code:

#include <timer1.h>
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)

int1 two_sec_timer_flg = FALSE,five_sec_timer_flg =FALSE;
unsigned int16 two_sec_count= FALSE ,five_sec_count = FALSE;

#INT_TIMER2
void timer2_isr()
{
two_sec_count++;
five_sec_count++;
{
if(two_sec_count == 200)
{
two_sec_count = 0;
two_sec_timer_flg = TRUE;
}
if(five_sec_count==1000)
{
five_sec_count=0;
five_sec_timer_flg=TRUE;
}
}
}
void main ()
   {
  //setup_timer_2(T2_DIV_BY_4,78,16);//setup up timer2 to interrupt every 1ms
   setup_timer_2(T2_DIV_BY_4,250,5); //setup up timer2 to interrupt every 1ms
  //setup_timer_2 (mode, period, post scale)
  //mode - T2_DISABLED, T2_DIV_BY_1, T2_DIV_BY_4, T2_DIV_BY_16
  //period is a int 0-255 that determines when the clock value is reset,
  //post scale is a number 1-16 that determines how many timer overflows before
  //an interrupt: (1 means once, 2 means twice, and so on).
 
  // calculating timer reload value to generate 1 msec interrupt
  // T = 1/f
  // T = 1/4MHZ = 1/4* 1000000
  // But Microcontroller hardware will divide the clock by 4
  // and if we chosen T2_DIV_BY_4 then again there will
  // one more division happen by 4
  // So T = 1/(4 * 1000000)/ 4 * 4 /   T=4/4*1000000
  // T = 4*4/4*1000000 = 0.000004 sec = 0.4 usec //4 usec
  // ************************************************
  // At 4mhz, the timer will increment every 0.4 us // 4 usec *// 0.000004 sec
  // ************************************************
 
  // ********************************************************
  // if period is chosen 250 then timer wi
 //ll overflow every *
  // 4 * 250 = 25 usec  // 1000 usec //1 msec                              *
  // ********************************************************
 
  // *******************************************************************
  // And if we chosen post scalar as 5 then timer interrupt will occur *
  // 25 usec  * 5 = 125 usec // 5000 usec /// 5 msec
  // *******************************************************************

  enable_interrupts(INT_TIMER2);   // enable timer2 interrupt   
  enable_interrupts(GLOBAL);
   
   putc('Z');
   //infine loop
   while (1)
   {
      if( two_sec_timer_flg == TRUE)
      { 
         printf("I am in 2 sec  \n\r");
       
         output_b (0x1);
         delay_ms(2000);
         output_b(0x00);
         delay_ms (2000);
      }
      if( five_sec_timer_flg == TRUE)
      {
         printf ("I  am in 5 sec \n\r" );
         
         output_b (0x2);
         delay_ms(5000);
         output_b (0x00);
         delay_ms (5000);
      }
   }
         
   }

I was compiling this code but the output does not come simultaneously. Please cite me to what mistake I made and correct it please. Thanks.
Ttelmah



Joined: 11 Mar 2010
Posts: 19403

View user's profile Send private message

PostPosted: Sun Jan 20, 2013 2:05 am     Reply with quote

If your interrupt is being called every mSec, then the interrupt code is being executed every mSec. You have two 16bit additions here and two 16bit tests. A total of about 16uSec of code. Then about another 30uSec to get into and out of the interrupt handler, so just under 50uSec/mSec of code. So delays in the main code would run slow by about 5%.
Then in your 2 second code, you sit for 4 seconds (actually more like 4.2 seconds because of the above), plus about 15mSec for the serial, before calling the 'five second' code which then takes about 11 seconds to run. By which time you will have missed both a 2 second timer, and a 10 second timer....
You need to use either interrupt timings, _or_ software timings.

So, something like:
Code:

#include <timer1.h>
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)

int1 two_sec_timer_flag = FALSE,five_sec_timer_flag = FALSE;

#INT_TIMER2
void timer2_isr(void) {
   //Keep variables that are local _local_
   static int8 tick=100;
   static int8 two_sec=2;
   static int8 five_sec=5;
   if (--tick == 0) {
      //Here once per second
      tick=100;
      if (--two_sec==0){
         output_toggle(PIN_B0);
         two_sec=2;
         two_sec_timer_flag^=1;
      }
      if (--five_sec==0){
         output_toggle(PIN_B1);
         five_sec=5;
         five_sec_timer_flag^=1;
      }         
   }
}

void main (void) {
   int1 last_2sec, last_5sec;
   setup_timer_2(T2_DIV_BY_16,125,5); //setup up timer2 to interrupt every 10ms
   //Don't do things faster than you have to
   //remember the period counts from _0_ to the count, so you need period -1
   //*************************
   //100*per second. 4000000/100 = 40000
   //40000/4=10000 - so total count wants to be 10000.
   //16*125*5 = 10000
   //So prescale /16, period 124, postscale 5
   last_2sec=two_sec_timer_flag;
   last_5sec=five_sec_timer_flag;
   enable_interrupts(INT_TIMER2);   // enable timer2 interrupt   
   enable_interrupts(GLOBAL);
   
   putc('Z');
   //infinite loop
   while (TRUE) {
      if(two_sec_timer_flag!=last_2sec) {
         //here flag has _changed_
         last_2sec=two_sec_timer_flag;
         printf("I am in 2 sec  \n\r");
      }
      if( five_sec_timer_flag!=last_5sec){
         last_5sec=five_sec_timer_flag;
         printf ("I am in 5 sec \n\r" );   
      }
   }
}

Now notice that the only variables that are global, are the two flags. The local variables to the interrupt are static variables inside this routine. Reduces the risk of the wrong thing changing things.

Best Wishes
ccslearner



Joined: 12 Jan 2013
Posts: 10

View user's profile Send private message AIM Address ICQ Number

PostPosted: Sun Jan 20, 2013 8:35 am     Reply with quote

Thankyou so much mr Ttelmah actually i am in the beginning stage of ccs codes and also i understand again thank u u .. . ,
ccslearner



Joined: 12 Jan 2013
Posts: 10

View user's profile Send private message AIM Address ICQ Number

PostPosted: Sun Jan 20, 2013 8:46 am     Reply with quote

pease cite me to my code what code i changed to get output? please sent me
Ttelmah



Joined: 11 Mar 2010
Posts: 19403

View user's profile Send private message

PostPosted: Sun Jan 20, 2013 9:05 am     Reply with quote

It already gives an output.
The 'output_toggle' lines in the interrupt, toggle the B0 (2second), and B1 (5 second) connections.
The only reason this wouldn't work, is if the lines are overloaded (what resistor value are you using to drive the LED's).

Best Wishes
ccslearner



Joined: 12 Jan 2013
Posts: 10

View user's profile Send private message AIM Address ICQ Number

PostPosted: Sun Jan 20, 2013 9:11 am     Reply with quote

Thank you for your valuable reply. Sorry to interrupt again, can you tell me any tutorial or books to learn embedded C for PIC mcu ?
ckielstra



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

View user's profile Send private message

PostPosted: Sun Jan 20, 2013 10:18 am     Reply with quote

https://www.ccsinfo.com/content.php?page=books
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Sun Jan 20, 2013 10:29 am     Reply with quote

The CCS examples folder shows you how to drive many of the PIC peripehrals.

Try them out for starters.

Won't cost you much. Just need access to a few standard bits and pieces.

Mike
ccslearner



Joined: 12 Jan 2013
Posts: 10

View user's profile Send private message AIM Address ICQ Number

PostPosted: Sun Jan 20, 2013 12:33 pm     Reply with quote

thanks to all to reply i ask any link for read free like tutorials for PIC16F877A
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Sun Jan 20, 2013 4:25 pm     Reply with quote

ccslearner wrote:
thanks to all to reply i ask any link for read free like tutorials for PIC16F877A
To a large extent CCS insulates you from the differences between PICs.

You can find the specifics for your PIC in its data sheet.
(The data sheet tells you which peripherals are available)
The '877A is a mature product, there should be few (if any) compiler bugs.

You'll learn a lot by simply playing with (experimenting/modifying) the CCS examples.

Mike
ccslearner



Joined: 12 Jan 2013
Posts: 10

View user's profile Send private message AIM Address ICQ Number

PostPosted: Mon Jan 21, 2013 10:56 am     Reply with quote

Thanks mike actually i know already all peripherals are available in pic data sheet. As a beginner i am asking to best link for programming PIC16F877A in c because i am lacking in programming not hardware.
Anyway thanks
Noorul
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Mon Jan 21, 2013 11:10 am     Reply with quote

One of us is missing the point.

The CCS examples show you how to program almost any PIC to get its peripherals to do what you want.

The only reason for needing the data sheet is to discover what each pin does.
(For example the uart on an 18F1320 is on different pin names and numbers to your 16F877A, but the programming is similar in CCS.)

To a large extent it doesn't matter which PIC you're using.

Other compilers force you to know a lot more about the individual PIC you're using.

Mike
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Mon Jan 21, 2013 1:38 pm     Reply with quote

Interrupt density, that is - how many times /second - does the interrupt fire - is a very important aspect of program design.

My general rule of thumb is to make the timer #INT service be as infrequent as possible, given the required resolution of your MAIN(), timed activity. If i was doing your school work, i would opt to use a timer interrupt rollover of 250 msecs or there about.

Higher than required timer interrupt density degrades the performance of all aspects of your MAIN program and its called functions.

just my 2 cents
ccslearner



Joined: 12 Jan 2013
Posts: 10

View user's profile Send private message AIM Address ICQ Number

To modify my code
PostPosted: Wed Jan 23, 2013 11:44 am     Reply with quote

Code:

#include <timer1.h>
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)

int1 two_sec_timer_flag = FALSE,five_sec_timer_flag =FALSE,ten_sec_timer_flag = FALSE ;
int16 two_sec_count,five_sec_count,ten_sec_count;

#INT_TIMER2
void timer2_isr()
{
two_sec_count++;
five_sec_count++;
ten_sec_count++;
{
if(two_sec_count == 400)   // 400 * 5 msec = 2000 msec = 2 sec
{
two_sec_count = 0;
two_sec_timer_flag = TRUE;
}
if(five_sec_count==1000)     /// 1000 * 5 msec = 5000 msec = 5 sec
{
five_sec_count=0;
five_sec_timer_flag=TRUE;
}
if(ten_sec_count == 2000)    // 2000 * 5 =10000 msec = 10 sec
{
ten_sec_count = 0 ;
ten_sec_timer_flag = TRUE;
}
}
}
void main ()
   {
   int1 last_2sec,last_5sec,last_10sec;
 
  //setup_timer_2(T2_DIV_BY_4,78,16);//setup up timer2 to interrupt every 1ms
  setup_timer_2(T2_DIV_BY_4,255,5); //setup up timer2 to interrupt every 1ms
  //setup_timer_2 (mode, period, post scale)
  //mode - T2_DISABLED, T2_DIV_BY_1, T2_DIV_BY_4, T2_DIV_BY_16
  //period is a int 0-255 that determines when the clock value is reset,
  //post scale is a number 1-16 that determines how many timer overflows before
  //an interrupt: (1 means once, 2 means twice, and so on).
 
  // calculating timer reload value to generate 1 msec interrupt
  // T = 1/f
  // T = 1/4MHZ = 1/4* 1000000
  // But Microcontroller hardware will divide the clock by 4
  // and if we chosen T2_DIV_BY_4 then again there will
  // one more division happen by 4
  // So T = 1/(4 * 1000000)/ 4 * 4 /   T=4/4*1000000
  // T = 4*4/4*1000000 = 0.000004 sec = 0.4 usec //4 usec
  // ************************************************
  // At4mhz, the timer will increment every 0.4 us // 4 usec *// 0.000004 sec
  // ************************************************
 
  // ********************************************************
  // if period is chosen 250 then timer wi
 //ll overflow every *
  // 4 * 250 = 25 usec  // 1000 usec //1 msec                              *
  // ********************************************************
 
  // *******************************************************************
  // And if we chosen post scalar as 5 then timer interrupt will occur *
  // 25 usec  * 5 = 125 usec // 5000 usec /// 5 msec
  // *******************************************************************
   last_2sec=FALSE;
   last_5sec=FALSE;
   last_10sec=FALSE;
  enable_interrupts(INT_TIMER2);   // enable timer2 interrupt
  enable_interrupts(GLOBAL);
  output_b(0x0); // off all theLEDS
    putc('z');
   //infine loop
   while (1)
   {
   
      if( two_sec_timer_flag == TRUE)
      {
         two_sec_timer_flag = FALSE;
         //printf("I am in 2 sec  \n\r");
         
         last_2sec = ~last_2sec; 
         if ( last_2sec == TRUE)
         {
             output_b( (input_b() | 0x01)); // ON LED 1 alone
         }
         else
            {
             output_b( (input_b() & 0xFE)); // OFF LED 1 alone
            }
         
      }
      if( five_sec_timer_flag == TRUE )
      {
         five_sec_timer_flag = FALSE;
        // printf ("I  am in 5 sec \n\r" );
         last_5sec = ~last_5sec; 
         if ( last_5sec == TRUE)
         {
             output_b( (input_b() | 0x02)); // ON LED 2 alone
         }
         else
            {
             output_b( (input_b() & 0xFD)); // OFF LED 2 alone
            }
             
      }
      if( ten_sec_timer_flag == TRUE)
      {
            ten_sec_timer_flag = FALSE;
            //printf("i am in 10 sec \n\r");
            last_10sec = ~last_10sec;
            if(last_10sec==TRUE)
         {
            output_b( (input_b() | 0x04)  ); // ON LED3 alone
         }
            else
            {
             output_b( (input_b() & 0xFB)); // OFF LED 3 alone
            }

         
         
       
     
   
   } // end of while
     
         
   } // end of main
   
   }

Hai to all pofessional experts this is my code to blink 3 led simultaneously:
led 1 2_sec ON and OFF
led 2 5_sec ON and OFF
LED 3 10_sec ON and OFF
this are clear to get my output. My question is how to change these code to get output like given below:

Write a program to turn Led 1 ON for 3 sec and OFF for 5 sec? And repeat the same sequence.

THANKS
Noorul(BEGINNER)
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Wed Jan 23, 2013 2:32 pm     Reply with quote

You've (or your tutor's) changed the rules.

So, you either extend the present scheme or change to something more general purpose.

Mike
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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