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 interrupt,help

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



Joined: 14 Jun 2012
Posts: 8

View user's profile Send private message

Timer0 interrupt,help
PostPosted: Tue Dec 04, 2012 3:47 am     Reply with quote

Help me,please

I have a graphs : y1=c1*z1
c1=const= y1/c1
y1=read_analog - set_high;
z1= y1/c1; (time : second)
Control:
led HIGH on z1 (second)
led HIGH off (time-z1) (second) with time : setpoint (second)
set_high,wd_high,time : set with button.

I use delay_ms but when I use delay_ms, led 7 seg not work.
I think, I can use interrupts, but I'm not understand how to use.

code: I use PIC16f877a, 20Mhz, display 7 segment led
Code:
while(1)
      { 
         a=read_analog(0);
         a= a/div ;
         h=a;
         SET_ENTER();  //Buttons (set value : set_high , wd_high ,time)
         if(setenter==5)   // setenter =5 : end set value
         {
          if(h > (set_high + wd_high))
          { HIGH=1;  LOW=0;   t=1;  }         
         
          if(t==1)
          {
           if(h <= (set_high + wd_high))
            { 
             if(h <= set_high)
              {
                t=0;
               HIGH=0;LOW=0;
              }   

 //   Graphs : y1 = c1* z1

             c1 = wd_high / time;    //coefficient  , variable time : setpoint
             y1 = h - set_high;      // measured value - setpoint  (set_high)
             z1 = y1/c1;             // z1: time (change)      
           
// I want to use interrupt:
            for(k=0;k<z1;k++)
             {
              HIGH=1;  LOW=0;
              delay_ms(1000);
             }
             for(l=0;l<(time - z1);l++)
             {
              HIGH=0; LOW=0;
              delay_ms(1000);
             }
            }                           
          }     
        }   
     }


Last edited by muatuyet_2012 on Thu Dec 13, 2012 4:17 am; edited 2 times in total
Mike Walne



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

View user's profile Send private message

PostPosted: Tue Dec 04, 2012 3:54 am     Reply with quote

A search on the forum will yield loads of answers.

I've contributed more than once on the subject.

You're trying to do two tasks, drive a 7 seg display, and create a delay.

Use interrupts to do either or both.

Mike

EDIT As it stands your code is neither complete nor compilable, so can't offer further help.
asmboy



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

View user's profile Send private message AIM Address

PostPosted: Tue Dec 04, 2012 8:33 am     Reply with quote

a tip:

even ONE of these is a disaster and not a brilliant bit of code inside a timer ISR:
Quote:

delay_ms(1000);
muatuyet_2012



Joined: 14 Jun 2012
Posts: 8

View user's profile Send private message

PostPosted: Thu Dec 06, 2012 2:11 am     Reply with quote

I learned about it. But it don't work correct . Timer is too slow.

In function interrupts:
Code:
#int_timer0
void interrupts_timer0()
{
 set_timer0(0);
 count++;
}


main:
Code:

   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);

   while(1)
      { 
         a=read_analog(0);
         a= a/div ;
         h=a;
         SET_ENTER();
         if(setenter==5)
         {
          if(h > (set_high + wd_high))
          { HIGH=1;  LOW=0;   t=1;  }         
         
         if(t==1)
          {
           if(h <= (set_high + wd_high))
            { 
             if(h <= set_high)
              {
               HIGH=0;LOW=0;
               t=0;
              }     
             c1 = wd_high / time;
             y1 = h - set_high;   
             
             if(count==76)  //  1s
             {               
               if(z1<(y1/c1))
                {
                 HIGH=1;LOW=0;                 
                }
               if(z1>=(y1/c1))
                {               
                 HIGH=0;LOW=0;
                 k++;
                 if(k==(time-(y1/c1)))
                  {
                   z1=0;k=0;
                  }
                }
              z1++;
              count=0;
             }
           }                           
          }     
        }   
     }
Ttelmah



Joined: 11 Mar 2010
Posts: 19498

View user's profile Send private message

PostPosted: Thu Dec 06, 2012 2:33 am     Reply with quote

What chip, what chip, what chip......

On most of the later chips, the RTCC defaults to running as a 16bit timer. So with /256 prescaler will give (master oscillator)/(4*256*65536). There should be an 8bit option in the timer setup, but depends on the chip.

Second, the interrupt occurs when the timer resets to zero. You don't need to set the timer to zero in the handler.

Best Wishes
muatuyet_2012



Joined: 14 Jun 2012
Posts: 8

View user's profile Send private message

PostPosted: Thu Dec 06, 2012 2:39 am     Reply with quote

I use PIC16f877A and crystal 20Mhz

20Mhz / (4*256*256) ~76

I will review. Thanks Mike,Ttelmah,asmboy
muatuyet_2012



Joined: 14 Jun 2012
Posts: 8

View user's profile Send private message

PostPosted: Thu Dec 13, 2012 4:08 am     Reply with quote

I have just repaired it. I improved but delay still slow.

Code:
#int_timer0
  void ngat_timer0()
  {   
   CLEAR_INTERRUPT(INT_TIMER0);
   DISABLE_INTERRUPTS(INT_TIMER0);
    count++;
    if(count>=(76*time))
    {     
     count=0;flag1=0;flag2=0;
    }
   else if(count < (76*z1))
    {
     flag1=1;
    }
   else
    if( (76*z1)< count < (76*time))
    {   
     flag2=1;
    }   
    set_timer0(0);
    ENABLE_INTERRUPTS(INT_TIMER0);
 }


and Main:

Code:
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
   set_timer0(0);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL); 
     while(1)
      { 
         disable_interrupts(GLOBAL); 
         a=read_analog(0);
         a= a/div ;
         h=a;
         SET_ENTER(); 
         if(setenter==5)
         {
          if(h > (set_high + wd_high))
          { HIGH=1;  LOW=0; p=1;}                                                                           
         if(p==1)
          {
            if(h <= (set_high + wd_high))
            {
              if(h<= set_high)
               {
                p=0;
                HIGH=0;  LOW=0;
               }
               else
               {
               c1 = wd_high / time;   
               y1 = h - set_high;
               z1=y1/c1;
              }
            }           
          }     
        }
      enable_interrupts(GLOBAL); 
      if(flag1==1)
       {
        HIGH=1;LOW=0;
        flag1=0;
       }
      else if(flag2==1)
       {
        HIGH=0;LOW=0;
        flag2=0;
       }
     
     }



Please let me know if I have any mistake.
Mike Walne



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

View user's profile Send private message

PostPosted: Thu Dec 13, 2012 5:37 am     Reply with quote

Your code is neither complete nor compilable.

It helps if you post the SHORTEST complete and compilable code which shows the problem you're having.

i.e. We need to see #FUSES, copiler version, everything, so that it's a simple cut and paste job for us.

Mike
ckielstra



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

View user's profile Send private message

PostPosted: Thu Dec 13, 2012 5:41 am     Reply with quote

Code:
if( (76*z1)< count < (76*time))
I'm surprised this compiles as it is invalid C language, you'll have to split it into two lines:
Code:
if ( ((76*z1)< count)
   && (count < (76*time)) )
muatuyet_2012



Joined: 14 Jun 2012
Posts: 8

View user's profile Send private message

PostPosted: Thu Dec 13, 2012 8:51 pm     Reply with quote

I use CCS 4.104. If you find any mistake,please help me.

Code:
#include <16F877A.h>
#include <def_16f877a.h>
#fuses NOWDT,HS,NOPUT,NOPROTECT,NODEBUG,NOBROWNOUT,NOLVP,NOCPD,NOWRT
#use delay(clock=20000000)
#use fast_io(d)  //7 segment led
#use fast_io(a)  //led alarm
#use fast_io(b)  //button and control
#bit UP=PortB.0
#bit DOWN=PortB.1
#bit LEFT=PortB.2
#bit RIGHT=PortB.3
#bit SET=PortB.4
#bit ENTER=PortB.5
#bit HIGH=PortB.6   //port control
#bit LOW=PortB.7   //port control
#bit ON_LEDHIGH=PortA.0 //led alarm
#bit ON_LEDLOW=PortA.1 // led alarm

int16 temp,value,count;
long int a,data,X,h,set_high,set_low;
int8 j,nghin,tram,chuc,dvi,T,count_shift,count_set,setenter,wd_high,wd_low,time,y1,y2,z1,z2,p;
int1 b,flag1=0,flag2=0;
float div,c1,c2;
const unsigned char seg[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};

#int_timer0
  void ngat_timer0()
  {   
   CLEAR_INTERRUPT(INT_TIMER0);
   DISABLE_INTERRUPTS(INT_TIMER0);
    count++;
    if(count>=(76*time))
    {     
     count=0;flag1=0;flag2=0;
    }
   else if(count < (76*z1))
    {
     flag1=1;
    }
   else
    if(((76*z1)< count) && (count < (76*time)))
    {   
     flag2=1;
    }   
    set_timer0(0);
    ENABLE_INTERRUPTS(INT_TIMER0);
 }

// Read ADC LTC1298

void adc_init() {
   output_high(ADC_CS);
}

void write_adc_byte(BYTE data_byte, BYTE number_of_bits) {
   BYTE i;
   delay_us(2);
   for(i=0; i<number_of_bits; ++i) {
      if((data_byte & 1)==0)      output_low(ADC_DIN);
      else                        output_high(ADC_DIN);
      data_byte=data_byte>>1;
      output_high(ADC_CLK);
      delay_us(50);
      output_low(ADC_CLK);
      delay_us(50);
   }
}

BYTE read_adc_byte(BYTE number_of_bits) {
   BYTE i,data;
   data=0;
   for(i=0;i<number_of_bits;++i) {
      output_high(ADC_CLK);
      delay_us(50);
      shift_left(&data,1,input(ADC_DOUT));
      output_low(ADC_CLK);
      delay_us(50);
   }
   return(data);
}

long int read_analog( BYTE channel ) {
   int l;
   long int h;
   delay_us(200);
   output_low(ADC_CLK);
   output_high(ADC_DIN);
   output_low(ADC_CS);

   if(channel==0)
     channel=0x1b;
   else
     channel=0x1f;
   write_adc_byte( channel, 5);
   h=read_adc_byte(8);
   l=read_adc_byte(4)<<4;
   output_high(ADC_CS);
   return((h<<8)|l);
}

void Display()
{
  nghin=data/1000;
  tram=(data%1000)/100;
  chuc=(data%100)/10;
  dvi=data%10;
for(j=0;j<100;j++)
   {
   output_low(PIN_C3);output_high(PIN_C2);output_high(PIN_C1);output_high(PIN_C0);
   portd=seg[dvi];
   delay_us(700);

   output_high(PIN_C3);output_low(PIN_C2);output_high(PIN_C1);output_high(PIN_C0);
   portd=seg[chuc];   
   delay_us(700);
 
   output_high(PIN_C3);output_high(PIN_C2);output_low(PIN_C1);output_high(PIN_C0);
   portd=seg[tram];
   delay_us(700);

   output_high(PIN_C3);output_high(PIN_C2);output_high(PIN_C1);output_low(PIN_C0);
   portd=seg[nghin];
   delay_us(700);
   }
}

void UP_DOWN()
{
   b=0;
   if(UP==0)
      {       
         temp=temp+value;      T++;
         while(UP==0){}     
       }
   else
     if(DOWN==0)
      {           
         temp=temp-value; 
         if(T==0) {b=1;}       T--;             
         while(DOWN==0){}
      }
}
 
void LEFT_RIGHT()
{
   if(LEFT==0)
      {     
          count_shift++;   
         if(count_shift==6) {   count_shift=2;}
         while(LEFT==0){}       
      }     
   else
     if(RIGHT==0)
      {
         count_shift--;   
         if((count_shift==0)|(count_shift==1)) {   count_shift=5;}
         while(RIGHT==0){}
      }
   
   if(count_shift==2)
   { 
      value=1;    T=dvi;     UP_DOWN();        data=X+temp;
      if(T==10)
         {
          T=0;    temp=0;    data=data-10;     X=data;
         }
      if(b==1)
      {
          T=9;    temp=0;    data=data+10;     X=data;   
      }
      if(data > 1400)
      {
       data=1400;            temp=0;           X=data;
      }     
       nhay_dvi();  //blinking unit led
   }   
   else if(count_shift==3)   
   {   
      value=10;   T=chuc;    UP_DOWN();        data=X+temp;
      if(T==10)
         {
           T=0;   temp=0;    data=data-100;     X=data;
         }
      if(b==1)
         {
          T=9;    temp=0;    data=data+100;     X=data;   
         }
      if(data > 1400)
         {
          data=1400;          temp=0;          X=data;
         }
        nhay_chuc(); //blinking ten led
   }   
   else if(count_shift==4)
   {
     value=100;  T=tram;     UP_DOWN();          data=X+temp;
      if(T==10)
         {
          T=0;     temp=0;   data=data-1000;     X=data;
         }
      if(b==1)
         {
          T=9;    temp=0;    data=data+1000;     X=data;   
         }
      if(data > 1400)
        {
         data=1400;          temp=0;             X=data;
        }
         nhay_tram();//blinking hundred led
   } 
   else
      if(count_shift==5)
   {
      value=1000; T=nghin;    UP_DOWN();         data=X+temp;
      if(T==2)
         {
          T=0;    temp=0;      data=data-2000;    X=data;
         }
      if(b==1)
         {
          T=1;    temp=0;      data=data+2000;    X=data;
         }
      if(data > 1400)
         {
          data=1400;           temp=0;            X=data;
         }
          nhay_nghin(); //blinking thousand led
   }
}

void LEFT_RIGHT_TIME()
{
   if(LEFT==0)
      {     
          count_shift++;   
         if(count_shift==3) {   count_shift=2;}
         while(LEFT==0){}       
      }     
   else
     if(RIGHT==0)
      {
         count_shift--;   
         if((count_shift==0)|(count_shift==1)) {   count_shift=2;}
         while(RIGHT==0){}
      }
               
      if(count_shift==2)
      {
      value=10;    T=chuc;     UP_DOWN();          data=X+temp;
      if(T==10)
         {
          T=0;     temp=0;   data=data-100;     X=data;
         }
      if(b==1)
         {
          T=9;    temp=0;    data=data+100;     X=data;   
         }
      if(data > 60)
        {
         data=60;          temp=0;             X=data;
        }
         nhay_chuc();
   }   
}

void SET_ENTER()
{   
   if(SET==0)
    {
      count_set++; count_shift=1;  setenter=0;   p=0;
      if(count_set==6)  { count_set=0;}
      while(SET==0){}
    } 
   
   if(count_set==1)
     {
       ON_LEDHIGH=1;  ON_LEDLOW=0;
       if((count_shift==0)|(count_shift==1))
       {
         X=set_high;  temp=0;   data=X;   Display();
       }         
       LEFT_RIGHT();     
        if(ENTER==0)
          {
             count_set=2;   count_shift=1;  set_high=data;  setenter=1;
             while(ENTER==0){}
          }
     }
   else if(count_set==2)
     {
      if((count_shift==0)|(count_shift==1))
       {
         X=wd_high;  temp=0;   data=X;   Display();
       }         
       LEFT_RIGHT_HYS();     
        if(ENTER==0)
          {
             count_set=3;   count_shift=1;  wd_high=data;  setenter=2;
             while(ENTER==0){}
          }
     }
   else if(count_set==3)
       {         
        ON_LEDHIGH=0;  ON_LEDLOW=1;
         if((count_shift==0)|(count_shift==1))
          {
           X=set_low;    temp=0;  data=X;   Display();
          }       
        LEFT_RIGHT();
        if(ENTER==0)
          {
             count_set=4;  count_shift=1;  set_low=data;  setenter=3;
             while(ENTER==0){}
          }               
       }
   else if(count_set==4)
     {
      if((count_shift==0)|(count_shift==1))
       {
         X=wd_low;  temp=0;   data=X;   Display();
       }         
       LEFT_RIGHT();     
        if(ENTER==0)
          {
             count_set=5;   count_shift=1;  wd_low=data;  setenter=4;
             while(ENTER==0){}
          }
     }
   else if(count_set==5)
    {
        if((count_shift==0)|(count_shift==1))
       {
         X=time;  temp=0;   data=X;   Display();
       }         
       LEFT_RIGHT_TIME();     
        if(ENTER==0)
          {
             count_set=6;   count_shift=1;  time=data;  setenter=5;
             while(ENTER==0){}
          }
     }
     else
       if((count_set==6)|(count_set==0))
       {
       ON_LEDHIGH=0; ON_LEDLOW=0;
       data=h;
       Display();
       count_set=0;
       }       
 }

void main()
{
   disable_interrupts(INT_TIMER1);
   set_tris_d(0x00);
   set_tris_a(0x00);
   set_tris_b(0x3F);
   temp=0;
   count_shift=1;
   count_set=0;
   setenter=0;
   set_high=0;       set_low=0;
   ON_LEDHIGH=0;     ON_LEDLOW=0; 
   HIGH=0;           LOW=0;
   wd_high=0;        wd_low=0;
   time=0;
   adc_init();      //
   div=13.104;
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
   set_timer0(0);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL); 
     while(1)
      { 
         disable_interrupts(GLOBAL); 
         a=read_analog(0);
         a= a/div ;
         h=a;
         SET_ENTER(); 
         if(setenter==5)
         {
           //I only worked with set_high, I will do the same with set_low.
          if(h > (set_high + wd_high))
          { HIGH=1;  LOW=0; p=1;}   
                                                                         
         if(p==1)
          {
            if(h <= (set_high + wd_high))
            {
              if(h<= set_high)
               {
                p=0;
                HIGH=0;  LOW=0;
               }
               else
               {
               c1 = wd_high / time;   
               y1 = h - set_high;
               z1=y1/c1;
              }
            }           
          }     
        }
      enable_interrupts(GLOBAL); 
      if(flag1==1)
       {
        HIGH=1;LOW=0;
        flag1=0;
       }
      else if(flag2==1)
       {
        HIGH=0;LOW=0;
        flag2=0;
       }
     
     }
 }
Code:
ckielstra



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

View user's profile Send private message

PostPosted: Fri Dec 14, 2012 9:03 am     Reply with quote

Mike Walne wrote:
It helps if you post the SHORTEST complete and compilable code which shows the problem you're having.
Your program as posted is NOT short.

A quick look at your program showed one error:
Code:
if((count_shift==0)|(count_shift==1))
Replace '|' by '||'
This at multiple locations in your program.

Then I stopped searching because it gave me a headache to look at your code. Some of the annoyances:
Code:
             count_set=3;   count_shift=1;  wd_high=data;  setenter=2;
Good coding practice is to have only one instruction at a line as it makes reading easier.

Code:
LEFT_RIGHT_TIME();
Write only constants and #defines in capital letters, all other items in lower case (or a mix of lower/upper case).

Code:
int16 temp,value,count;
long int a,data,X,h,set_high,set_low;
int8 j,nghin,tram,chuc,dvi,T,count_shift,count_set,setenter,wd_high,wd_low,time,y1,y2,z1,z2,p;
int1 b,flag1=0,flag2=0;
float div,c1,c2;
Try to use as few global variables as possible:
- Now your code is difficult to follow as we have to constantly scroll to the program start to see the data definitions.
- The compiler can not optimize memory usage of global variables.
- Dangerous, because you are using the same name for local and global variables (data).

Try to use meaningful variable names; e, T, h, b, flag1, c1, c2 What do these do?

You mix 'int16' and 'long int'. Both are the same. Make a choice and stick to it. Preferred is int16 as it is the same in all compilers.

Code:
#int_timer0
  void ngat_timer0()
  {   
   CLEAR_INTERRUPT(INT_TIMER0);
   DISABLE_INTERRUPTS(INT_TIMER0);
Add '#case' to your program. It will make the compiler case sensitive so you use the correct capitalization for each function.

You don't have to clear the timer interrupt in your code, the CCS compiler does this for you (and now is done two times).

Inside the interrupt, the PIC hardware disables the GLOBAL interrupt flag so you are already sure no other interrupt can come in between. It makes no sense to disable and enable the Timer0 interrupt. These two lines can be removed.

Code:
set_timer0(0);
This line is inside the Timer0 interrupt. Why? You get inside the interrupt because the timer overflowed and started counting again at 0. When you get at this location in your code the timer will have already advanced a bit. Resetting again to 0 will cause an extra delay that makes your timer less accurate.

Code:
    if(count>=(76*time))
    {     
     count=0;flag1=0;flag2=0;
    }
   else if(count < (76*z1))
    {
     flag1=1;
    }
   else
    if(((76*z1)< count) && (count < (76*time)))
    {   
     flag2=1;
    }   
 
You can only get into the 3rd if-statement when the other two have failed. Calculations are expensive for the CPU. It makes no sense to do the whole test for both conditions again. Besides, there is a small bug: when count == (76*z1) then no code is executed.

With all that, your interrupt routine can be reduced to:
Code:
#int_timer0
void ngat_timer0()
{   
    count++;
    if (count >= (76*time))
    {
      count=0; flag1=0; flag2=0;
    }
    else if (count < (76*z1))
    {
      flag1=1;
    }
    else
    {
      flag2=1;
    }   
 }


... and then I've only checked the first function of your program.
Sorry, so many things wrong with your program. Have I mentioned the use of Magic Numbers? The lack of comments?
Post a short (50 lines maximum) program that is complete and compilable that demonstrates your problem. Perhaps that we then will have another look into your problem.
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