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

timer1 with interrupt

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



Joined: 08 Apr 2010
Posts: 11

View user's profile Send private message

timer1 with interrupt
PostPosted: Fri Jun 03, 2011 1:10 pm     Reply with quote

Hi everyone,
I need to built a timer that start to run on a push of a inputA(pin_a2) and stop time when inputB(pin_b0) pressed. I want to use pin_b0 on the External Interrupt that way I can free the micro to do other task.

I would like the accurate to 100micro second. Is it possible?

My plan is to modify the RTC function that I found on this forum to calculate the instruction cycle to time. Then serialize it via uart1 to pc terminal and LCD.

My current pic chip is PIC18F4680 with internal clock 8Mhz.

I currently have some code but the accuracy isn't there. I use the oscilloscope (200Mhz) with channel1 monitor the pressed of start button (pin_a2) and channel2 monitor the pin_b0. By manually measuring the edge of pin_a2 and pin_b0, I'm always off by at least 50mS and up.

Anyway can I improve this? Please give me some guidance.
thank you
Olivier
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jun 03, 2011 3:58 pm     Reply with quote

Quote:
I'm always off by at least 50mS and up.

Post your current test program. (complete and compilable).

What is the duration of the input test signal ? What are the voltage levels ?
What pin (or pins) is the test signal connected to on the PIC ?

Quote:

My plan is to modify the RTC function that I found on this forum

Post a link to this RTC code.

Also post your compiler version.
andrewg



Joined: 17 Aug 2005
Posts: 316
Location: Perth, Western Australia

View user's profile Send private message Visit poster's website

PostPosted: Fri Jun 03, 2011 9:18 pm     Reply with quote

Also, what are switching the pins? Are they digital signals or actual switches? In the latter case, have you considered the problem of contact bounce?
_________________
Andrew
olivier



Joined: 08 Apr 2010
Posts: 11

View user's profile Send private message

PostPosted: Mon Jun 06, 2011 12:54 pm     Reply with quote

Code:

#include <Delay Time Counter.h>
#include <Flex_LCD16x2.c>

#include <float.h>
#include <limits.h>
#include <locale.h>
#include <math.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>

#define   START_SW   PIN_A2
#define   STOP_SW   PIN_B0
#define   RESET_SW   PIN_A3
#define   ERROR_LED   PIN_A1
#define  EXT_INT   PIN_C1
#define  TMR_INT  PIN_A4
#define   XTAL_FREQUENCY  8000000
//#define   INTERNAL_FREQUENCY (XTAL_FREQUENCY / 4)

int Seconds = 0;
char Interrupt_Flag = 0, interruption_time = 0;
float executed_time = 0.00000;
int32 Inst_Cycle_Per_Second = 0, INTERNAL_FREQUENCY = 0;


void my_time_ms (char i,j,k);
void LCD_Pwr_Initialze(void);
void Power_On_Chk (void);
void RTC_Initialize (void);
Final_Delay_Time ();
void Start_Up_Screen();
void Blink_LED (char number_flash, int flash_duty_cycle);

void main()
{
//   int timer1_16bit = 65535;
//   float delay_time = 0.00000;
//   int i;
   float delay_time = 0;
   int32 temp;
   setup_adc_ports(AN0|VSS_VDD);
   setup_adc(ADC_CLOCK_INTERNAL|ADC_TAD_MUL_20);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4);
//   setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
   setup_timer_2(T2_DIV_BY_16,255,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   disable_interrupts(INT_TIMER1);
   disable_interrupts(INT_EXT);
   ext_int_edge(INT_EXT_H2L);   
   disable_interrupts(GLOBAL);
   setup_oscillator(OSC_8MHZ|OSC_INTRC|OSC_31250|OSC_PLL_ON);

   // TODO: USER CODE!!
   INTERNAL_FREQUENCY = XTAL_FREQUENCY/4;
   LCD_Pwr_Initialze();
   Start_Up_Screen ();
   Power_On_Chk ();
   while (TRUE)
   {
      Seconds = 0;                // clear all global variables before next test             
      Interrupt_Flag = 0;
      interruption_time = 0;
      executed_time = 0;
      RTC_Initialize();
      lcd_gotoxy (7,2);   
      printf (lcd_putc, "READY !     ");      //do nothing
      while (input(START_SW) == 1)
      {
         ;
      }
 
      clear_interrupt(int_timer1);
      set_timer1(0);
      clear_interrupt(INT_EXT);
      enable_interrupts(GLOBAL);
     
      while (input(STOP_SW) == 1)
      {
/*      delay_ms(100);
      lcd_gotoxy (7,2);
      printf (lcd_putc, "\\");
      delay_ms(100);     
      lcd_gotoxy (7,2);
      printf (lcd_putc, "|");
      delay_ms(100);     
      lcd_gotoxy (7,2);
      printf (lcd_putc, "/");
 */
      ;
   }
      temp = get_timer1() + (INTERNAL_FREQUENCY - Inst_Cycle_Per_Second);
      printf ("Internal Frequency Loop: %Ld\n\r", INTERNAL_FREQUENCY);
      printf ("Instruction Cycle: %Ld\n\r", Inst_Cycle_Per_Second);
      printf ("Timer 1: %Ld\n\r", get_timer1());
   //   temp = get_timer1() + (INTERNAL_FREQUENCY - Inst_Cycle_Per_Second);
      printf ("temp_val: %Ld \n\r",temp);
      executed_time = temp * (1/INTERNAL_FREQUENCY);
      printf ("Executed Time: %4.3f \n\r",executed_time);
      delay_time = Seconds + executed_time;
      lcd_gotoxy (7,2);
      printf (lcd_putc, "%6.5f \n",delay_time);   
      printf ("Delay Time: %7.7f \n\r",delay_time);
      while (input(RESET_SW) == 1)
      {
         ;//do nothing and wait for reset switch pressed to start new test
      }
//     for (i = 0; i <=10; i++)
//     {
//         printf (lcd_putc, "\b");   //clear lcd screen
         Start_Up_Screen ();
//      }
   } //end of main while loop
}//end of main

/******************************************************************************
******  16x2 LCD first line address 0x00
******           second line address 0x40
*******************************************************************************
*/
void LCD_Pwr_Initialze(void)
{
   lcd_init();
   printf (lcd_putc, "\fInitialize!\nPlease Wait");
   delay_ms (1000);
}

void Start_Up_Screen (void)
{
   printf (lcd_putc, "\fFUZE DELAY TIMER");
   printf (lcd_putc, "\nTime: READY !   \n");
}
/*******************************************************************
**  function that check the status of all i/o at power on.        **
**  Pin_B0 = 1 = good; Pin_B0 = 0 = bad; Message: Start SW Error  **
**  Pin_B1 = 1 = good; Pin_B1 = 0 = bad; Message: Stop SW Error   **
********************************************************************
*/
void Power_On_Chk (void)
{
   char error_flag = 0;
   do
   {
      if (input(START_SW) == 0)
      {
         lcd_gotoxy(0,2);
         printf (lcd_putc, "\fStart Switch Error");
           error_flag = 1;
      }
      else
         if (input(STOP_SW) == 0)
            {
               lcd_gotoxy(0,2);
               printf (lcd_putc, "\fStop Switch Error");
               error_flag = 1;
            }
   }   while (error_flag != 0); 
}

void RTC_Initialize (void)
{
   Inst_Cycle_Per_Second = INTERNAL_FREQUENCY;                  // initialize clock counter to number of clocks per second
   setup_timer_1( T1_INTERNAL | T1_DIV_BY_1 ); // initialize 16-bit Timer1 to interrupt
                                              // exactly every 65536 clock cycles
                                              // (about 76 times per second)
   enable_interrupts( INT_TIMER1 );            // Start RTC
   clear_interrupt(int_timer1);
   disable_interrupts(GLOBAL);
}

Final_Delay_Time ()
{
   float delay_time = 0, i = 0.0000005;
   int32 temp;
   temp = get_timer1() + (INTERNAL_FREQUENCY - Inst_Cycle_Per_Second); 
   printf ("Internal Frequency Loop: %Ld\n\r", INTERNAL_FREQUENCY);
   printf ("Instruction Cycle: %Ld\n\r", Inst_Cycle_Per_Second);
   printf ("Timer 1: %Ld\n\r", get_timer1());
//   temp = get_timer1() + (INTERNAL_FREQUENCY - Inst_Cycle_Per_Second);
   printf ("temp_val: %Ld \n\r",temp);
   executed_time = temp * i;
   printf ("Executed Time: %7.6f \n\r",executed_time);
   delay_time = Seconds + executed_time;
   lcd_gotoxy (7,2);
   printf (lcd_putc, "%7.7f \n",delay_time);   
   printf ("Delay Time: %7.7f \n\r",delay_time);
   Blink_LED (3,100);
   return(delay_time);
}

void Blink_LED (int8 number_flash, int flash_duty_cycle)
{
   char i;
   for ( i = 0; i <= number_flash; i++)
   {
      output_high (ERROR_LED);
      delay_ms (flash_duty_cycle);
      output_low (ERROR_LED);
      delay_ms (flash_duty_cycle);
   }
}

#int_TIMER1
void  TIMER1_isr(void)
{
  Inst_Cycle_Per_Second -= 65536;                        // Decrement ticker by clocks per interrupt
//  interruption_time++;
  output_toggle (TMR_INT);
  if ( Inst_Cycle_Per_Second < 65536 )                   // If second has expired
  { 
      Inst_Cycle_Per_Second += INTERNAL_FREQUENCY;          //   Increment ticker by clocks per second
      Seconds++;                           //   Increment number of seconds
//        interruption_time = 0;
  }
}

#int_EXT
void  EXT_isr(void)
{
   output_high (EXT_INT);
   if (input(STOP_SW)==0)
   {
      if (input (STOP_SW) == 0)
      {
         Interrupt_Flag = 0b00000001;
         disable_interrupts(GLOBAL);
      }
   }
   else
   {
      while (true)
      {
         output_toggle (ERROR_LED);
         my_time_ms (10,20,30);
      }
   }
}


void my_time_ms (char i,j,k)
{
   char x,y,z;
   for (x =0; x <= i; x++)
   {
      for (y=0;y<=j;y++)
      {
         for (z=0;z<=k;z++)
         {
            ;
         }
      }
   }   
}

Above is my completed test code that has problem in timing.

PCM programmer,
My input test signal is an actual switch. It pulls the RA2 to ground to start the count.
The stop button is also an actual switch that pull the RB0 to ground.
The voltage level at each pins is 5.0v. When I pressed any button, it goes to ground and trembling for about 100uS.

As far as assembly language goes, I have the code (write with Microchip assembly) that polling at RA2 to start the time and it just go as soon as the 5v line drop to 0v and ignore the switch bouncing.

My concern, why there is such a large delay offset ? I try to find out what cause the offset.

andrewg,
I do consider contact bounce however, in my application if I do the debounce, I lost the actual switch contact starting at the very first contact.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Jun 06, 2011 2:25 pm     Reply with quote

You have this enormous program and all you want to do is measure the
time between two events. I confess I didn't try to understand it all.
But I'm sure it can be done with less code.

What's the range of time intervals that you want to be able to measure ?
What is the minimum expected time, and the maximum expected time ?
Is it from 1ms up to 10 seconds, or what ?
olivier



Joined: 08 Apr 2010
Posts: 11

View user's profile Send private message

PostPosted: Wed Jun 08, 2011 8:45 pm     Reply with quote

PCM PRogrammer,

Yes, my program is massive and not effective. as of right now, I am a very very very new and learn every line in coding so effectiveness isn't there at all. I do take your mocking however, it is a good critic in away for me to push myself more in learning and more efficient.

However, the time I would like to measure is such
start switch pressed
time starts
print time on lcd while wait for interruption on external interrupt line RB0 which connect to stop switch.
stop switch pressed
time stop
calculate time and print to lcd

i need to display time from 0.0001 second to 15 seconds.

my code is long and ridiculous for a simple function of a stop watch.
Fusillade



Joined: 02 Aug 2007
Posts: 31

View user's profile Send private message

PostPosted: Thu Jun 09, 2011 6:36 am     Reply with quote

olivier wrote:
PCM PRogrammer,

Yes, my program is massive and not effective. as of right now, I am a very very very new and learn every line in coding so effectiveness isn't there at all. I do take your mocking however, it is a good critic in away for me to push myself more in learning and more efficient.

However, the time I would like to measure is such
start switch pressed
time starts
print time on lcd while wait for interruption on external interrupt line RB0 which connect to stop switch.
stop switch pressed
time stop
calculate time and print to lcd

i need to display time from 0.0001 second to 15 seconds.

my code is long and ridiculous for a simple function of a stop watch.


Just a quick glance, it appears that the external interrupt is disabled and that you are just looping on the status of the stop switch. As a result, the accuracy of the switch press doesn't seem like it could be any better than 300mS.

Before you start looping on the stop switch, add this code and tell me what happens.

Code:
...
clear_interrupt(int_timer1);
set_timer1(0);
clear_interrupt(INT_EXT);
enable_interrupts(INT_EXT);        // NEW LINE
enable_interrupts(GLOBAL);

while(input(STOP_SW) == 1)
{
...


You might also consider just setting a flag in the interrupt routine and looping on the flag status instead of the input switch. It is possible to press and release the switch before the loop is complete.

If I missed where you enable INT_EXT, I apologize in advance.
_________________
New:

Compiler Version: 5.078
IDE Version: MPLAB X V4.15
Devices: PIC18LF****

Old:

Compiler Version: 4.121
IDE Version: MPLAB IDE V8.63
Devices: PIC18LF****
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jun 09, 2011 12:45 pm     Reply with quote

I would do it with the CCP modules. Switch 1 would be on CCP1, and
switch 2 on CCP2. Each CCP would be set to trigger on the falling edge
of the switch. This is the first edge that occurs when the switch is pressed.
(You might need to debounce it with an external RC circuit). I would
extend Timer1 to 24 or 32 bits by adding an #int_timer1 routine to
increment the upper byte (or word).
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