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

delay_ms affects timer2 operation?

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



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

delay_ms affects timer2 operation?
PostPosted: Wed Jun 22, 2005 8:45 am     Reply with quote

I have run into this several times but usually found a way around the issue. The following code is essentailly written to wait for a pulse and then run timer2 for ~40 mS and count how many pulses occur in that time frame. At the end report the count if > a set value. I would like to wait ~50 mS before executing the routine again so I added a delay_ms but when I add this line, the timer2 operation fails to run for the expected duration. Is this a known issue and is there a fix for this?

CCS PCM C Compiler, Version 3.130, 17162

Code:


#include <16f877.h>

#use delay(clock=4000000)
#fuses HS,NOWDT,PUT
#use standard_io(B)

#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,errors)

//
//
const char Build_Date[] = __DATE__;
const char Build_Time[] = __TIME__;


////////////////////////////////////////////////////
// Constants and variables
#byte PORTB = 6
#byte PORTC = 7 
#byte PORTD = 8

#bit test = PORTC.3
#bit input = PORTD.0


//variable for lcd driver
#define    WORD unsigned long     // Data type definitions

//general code variables
int1      Read_Switch_Flag = False;
int       duration=1;         //
int      count=0;
int      trigger_count = 10;
//int      time;


///////////////////////////////////////////////////////
// General prototypes //


// local prototypes

void send_build();
WORD getnum(void);


///////////////////////////////////////////////////
// TIMER2 ISR
#int_TIMER2
void timer_isr(){
   test = 0;
   Read_Switch_Flag = FALSE;
   set_timer2(duration);
   
}


/////////////////////////////////////////////////////


///////////////////////////////////////////////////
// serial port ISR
#int_rda
rda_isr(){
   switch (getc()){      
      case 'B': send_build();break;      
      case 'h': printf("HELP - switch jiggle switch evaluation (triggers active high)\r\n");
         printf("B for code build date and time\r\n");
         printf("t for trigger count change\r\n");
         break;
      case 't': printf("\r\ntrigger count?, was %u\r\n",trigger_count);
         trigger_count = getnum();
         printf("\r\n%u\r\n",trigger_count);
         break;      
   }
}

///////////////////////////////////////////////////////

void wait_to_begin(){
   while(!input);
   test = 1;
   count=1;
   Read_Switch_Flag = TRUE;
}   
   
////////////////////////////////////////////////////////////
void wait_for_low_to_high() {
   while(!input) ;          
   delay_us(3);                 
}
////////////////////////////////////////////////////////////
void wait_for_low() {
   delay_us(3);                 
   while(input);       
}
///////////////////////////////////////////////////////////

void main() {
   
   disable_interrupts(global);
   set_tris_b(0);
   test = 0;
   
   setup_timer_2(T2_DIV_BY_16,150,16);
   set_timer2(duration);   

   enable_interrupts(INT_RDA|INT_TIMER2);
   enable_interrupts(global);
   printf("\r\n jiggle switch evaluation \r\n");   // serial display
   printf("pull port D.0 (P3.1) high and then low to time\r\n");
   printf("\r\nPress h for help \r\n");      // serial display
   
     
   do {
   printf("\n\rWaiting...\n\r");
   wait_to_begin();
   set_timer2(duration);
   enable_interrupts(INT_TIMER2);

   do {
      wait_for_low_to_high();
      delay_us(3);
     
            wait_for_low();
      count += 1;

   } while (Read_Switch_Flag);

   disable_interrupts(INT_TIMER2);
   test = 0;
   if (count >= trigger_count)
      printf("%2u\n\n\r", count);
   count=0;   
   //delay_ms(50);
   } while(TRUE);
}
   
   

//////////////////////////////////////////////////////
// function sends build data via serial port
void send_build(){
   printf("Build: %s %s\r\n", Build_Date,Build_Time);  //serial
}

/* Get a 8-bit decimal number from the console - 3 digits
** Return it when any non-numeric key is pressed (except backspace) */
WORD getnum(void)
{
    WORD val=0;
    char c, buff[3];
    int n=0, i=0;
   
    do {
        c = getchar();
        if (c>='0' && c<='9')
        {
            if (n < sizeof(buff))
            {
                buff[n++] = c;
                putchar(c);
            }
        }
        else
            c = 0;
    } while (c);
    while (n--)
        val = (val * 10) + buff[i++] - '0';
    return(val);
}


Thanks in advance for any help

Dan
ckielstra



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

View user's profile Send private message

PostPosted: Wed Jun 22, 2005 4:02 pm     Reply with quote

One possible error in your code is that in the serial receive interrupt you are transmitting serial data. This is trouble waiting to happen! You are receiving data at the same rate as you are transmitting. On reception of the first character you are transmitting more than a single character, this will cause queueing problems. The UART is capable of buffering 3 bytes and then will stall unless (unless you use the ERRORS directive in the #use rs232 statement).

Your timing problem might not be related to the above, but as an easy test, try disabling the RDA interrupt and see whether the timing problem still exists.
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Wed Jun 22, 2005 7:03 pm     Reply with quote

Thanks for your input. I have already tried that without any change. The serial routines are really just for initial setup and then not really used during operation.

I have actually narrowed the problem down a little. It appears that the problem isn't in the delay_ms routine but actually in the interrupt servicing for the timer. For some reason the timer2 interrupt status is not being reset when the timer2 value is being set and then the int_timer2 is being enabled. As soon as the code hits that line the timer2 ISR is being executed.

enable_interrupts(INT_RDA|INT_TIMER2);
enable_interrupts(global);
printf("\r\n jiggle switch evaluation \r\n"); // serial display
printf("pull port D.0 (P3.1) high and then low to time\r\n");
printf("\r\nPress h for help \r\n"); // serial display


do {
printf("\n\rWaiting...\n\r");
wait_to_begin();
set_timer2(duration);
enable_interrupts(INT_TIMER2);

do {
wait_for_low_to_high();
delay_us(3);

wait_for_low();
count += 1;

} while (Read_Switch_Flag);

I already removed the INT_TIMER2 from the first enable_interrupts but the issue remains.

I am looking into the datasheet to see how to clear the interrupts manually before I enable that interrupt. If you have any insight on that, it would be helpful.

Rgds,

Dan
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Wed Jun 22, 2005 7:04 pm     Reply with quote

Thanks for your input. I have already tried that without any change. The serial routines are really just for initial setup and then not really used during operation.

I have actually narrowed the problem down a little. It appears that the problem isn't in the delay_ms routine but actually in the interrupt servicing for the timer. For some reason the timer2 interrupt status is not being reset when the timer2 value is being set and then the int_timer2 is being enabled. As soon as the code hits that line the timer2 ISR is being executed.

enable_interrupts(INT_RDA|INT_TIMER2);
enable_interrupts(global);
printf("\r\n jiggle switch evaluation \r\n"); // serial display
printf("pull port D.0 (P3.1) high and then low to time\r\n");
printf("\r\nPress h for help \r\n"); // serial display


do {
printf("\n\rWaiting...\n\r");
wait_to_begin();
set_timer2(duration);
enable_interrupts(INT_TIMER2);

do {
wait_for_low_to_high();
delay_us(3);

wait_for_low();
count += 1;

} while (Read_Switch_Flag);

I already removed the INT_TIMER2 from the first enable_interrupts but the issue remains.

I am looking into the datasheet to see how to clear the interrupts manually before I enable that interrupt. If you have any insight on that, it would be helpful.

Rgds,

Dan
ckielstra



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

View user's profile Send private message

PostPosted: Thu Jun 23, 2005 3:13 am     Reply with quote

Check this thread regarding double posting.

Disabling the interrupts doesn't stop the timer, that's why the interrupt request flag is active on re-enabling the interrupts again. One solution is to add a call to clear_interrupt(INT_TIMER2) before enabling the interrupt.
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Thu Jun 23, 2005 5:40 am     Reply with quote

Yah, I read the post but I was working at home and didn't have time to go back in and remove the double post. My bad.

Thanks for the info on clearing the interrupts. I knew that the timer2 continued to run with disable_interrupts but I thought that kept the interrupt flags from being set. I also didn't know about the clear_interrupt(INT_TIMER2) command. Thanks a lot for that, very helpful.

Rgds,

Dan
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Thu Jun 23, 2005 5:48 am     Reply with quote

I tried adding the clear_interrupt(INT_TIMER2) and the compiler doesn't recognize it. Is that a CCS command or a custom routine? Anyhow, I should be able to manually clear the interrupt with the PIR1 register bit 1.

Dan
ckielstra



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

View user's profile Send private message

PostPosted: Thu Jun 23, 2005 7:19 am     Reply with quote

Sorry, I didn't see you are using an old compiler version. The clear_interrupt() function has been introduced somewhere around v3.180.
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