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

! Problem with UART and TIMER1 interrupt

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



Joined: 18 Mar 2012
Posts: 4
Location: Serbia

View user's profile Send private message

! Problem with UART and TIMER1 interrupt
PostPosted: Wed Jun 13, 2012 4:39 pm     Reply with quote

Hi guys,
in title of this topic you can see what is my problem.

I'm using PIC18F4431 and write code for motion controller. CCS C v4.120
My code is:


Code:

#include "18F4431.h"

#define    RS485_RW            PIN_C0
#define      RX_PIN            PIN_C7
#define      TX_PIN            PIN_C6

#device   ADC = 10
#fuses   HS,FCMEN,IESO,NOPUT,NOBROWNOUT,NOWDT,NOWINEN,NOPWMPIN,HPOL_HIGH,LPOL_HIGH,T1LOWPOWER,FLTAD4,SSP_RC,NOPWMPIN,MCLR,NOLVP,NODEBUG
#use delay(clock = 20MHZ)
#use rs232(baud=115200, xmit=TX_PIN, rcv=RX_PIN, enable=RS485_RW)

#define     H_BRIDGE_ENABLE()      output_low(PIN_D0);
#define     H_BRIDGE_DISABLE()      output_high(PIN_D0);
#define     BRAKE_ENABLE()         output_high(PIN_D5);
#define     BRAKE_DISABLE()         output_low(PIN_D5);
#define     ENCODER_ENABLE()      output_low(PIN_D6);
#define     ENCODER_DISABLE()      output_high(PIN_D6);
#define     ENCODER_TTL()         output_high(PIN_D7);
#define     ENCODER_DIFF()         output_low(PIN_D7);

#define     RCV_OFF()            disable_interrupts(INT_RDA);

#define     C1               PIN_E0
#define     C2               PIN_E1

#define     POWER_PWM_PERIOD  249
#define     PWM_HALF          498

#define     SAMPLE_TIME       0.0015         // Ts = 1.5ms
#define     t                 0.01           // t = 10ms             

#define INPUT_BUFFER_SIZE     9         // Velicina receive bufera
#define OUTPUT_BUFFER_SIZE    32

#bit QEI_DIR=0xFB6.5

#include "DataConversion.c"

void Serial_isr(void);
void ComputeCRC8(BYTE*, BYTE);
void SendPacket(BYTE*,BYTE);
void RCV_ON(void);
void Init(void);
void SaveNewADR(void);
void SaveNewParams(void);
void Timer1_isr(void);
void QEI_Index(void);
void GoToPosition(float);
void Movement(short &enable, int16 &pwm, short &dir);
void DataSend(BYTE*);
struct params
{
   BYTE ID;
   BYTE MP0;
   BYTE POWER_SUPPLY;
   BYTE MOTOR_VOLTAGE;
   BYTE ENC_MAX_H;
   BYTE ENC_MAX_L;
   BYTE MP1;
   BYTE GEAR_N;
   BYTE GEAR_M;
};

struct controls
{
   signed int16 PWM;
   short DIRECTION;     // DIRECTION = true, CW
   short ENABLE;
};

signed int pFactor = 0;
signed int dFactor = 0;

int16 adcRef = 0;
int16 adcValue = 0;
signed int16 adcOffset = 0;

signed int16 filteredDataADCV = 0;
signed int16 lastSampleADCV = 0;
signed int16 newSampleADCV = 0;

signed int16 filteredDataREF = 0;
signed int16 lastSampleREF = 0;
signed int16 newSampleREF = 0;

signed int16 filteredDataFS = 0;
signed int16 lastSampleFS = 0;
signed int16 newSampleFS = 0;

unsigned int16 iTermLimit = 0;
float alfa = 0.2206; //0.00934;// 1Hz | 0.2206; //30Hz

//PID controler variables
signed int16 currentFeedback = 0;
signed int16 errorTerm = 0;
int16 currentSetPoint = 0;
BYTE  pGain = 40;
signed int16 pTerm = 0;
signed int16 lError = 0;
BYTE  dGain = 60;
signed int16 dTerm = 0;
signed int16 aError = 0;
BYTE  iGain = 40;
signed int16 iTerm = 0;
signed int16 mPWM = 0;
//End of PID controler variables

int16 forceSensor = 0;
signed int16 encoderIndex = 0;
float position = 0;
float stepSize = 0.000666;     

float positionIEEE = 0;

BYTE  AUTO_FUNCTION = 0;
short STOP_EXTRACTION = FALSE;
short EXTARCTION_FINISHED = FALSE;
int extractionLogTimer = 0;

float newPosition = 0;


BYTE c;
BYTE   iBufferCount = 0;

BYTE crc = 0;

short NEW_MESSAGE_RECEIVE = FALSE, START_BYTE = FALSE;
BYTE iBuffer[9], tBuffer[9];

struct params p;
struct controls con;

#priority rda, timer1, ic2qei

/************* Encoder index detect *****************/
#INT_IC2QEI
void QEI_Index()
{
   clear_interrupt(INT_IC2QEI);
   if (QEI_DIR)
   {
      encoderIndex += 1;
   }
   else
   {
        encoderIndex -= 1;
   }
}

/************* TIMER1 overflow interrupt ************/


   
#INT_TIMER1
void Timer1_isr()
{
   int16 countPos;
   signed int16 eIndexCopy = encoderIndex;
   //float sVoltage,refVoltage, mVoltage, pCurrent;
   
   set_timer1(58036);
   disable_interrupts(GLOBAL);
   disable_interrupts(INT_TIMER1);
   
   set_adc_channel(1);
   adcValue = read_adc() + adcOffset;        // ovo je stari deo koda
   newSampleADCV = adcValue;
   //adcValue = newSampleADCV;
   filteredDataADCV = (int16)(lastSampleADCV + alfa * (newSampleADCV - lastSampleADCV));
   lastSampleADCV = filteredDataADCV;
   
   set_adc_channel(0);
   adcRef = read_adc();       // ovo je stari deo koda
   newSampleREF = adcRef;
   //adcRef = newSampleREF;
   filteredDataREF = (int16)(lastSampleREF + alfa * (newSampleREF - lastSampleREF));
   lastSampleREF = filteredDataREF;
   
   //set_adc_channel(5);
   //forceSensor = 0;//read_adc();
   /*newSampleFS = forceSensor;
   //adcRef = newSampleREF;
   filteredDataFS = (int16)(lastSampleFS + alfa * (newSampleFS - lastSampleFS));
   lastSampleFS = filteredDataFS;*/
   
   
   
   position = eIndexCopy * 4.00;
   countPos = qei_get_count(QEI_GET_POSITION_COUNT);
   position = position + (stepSize * countPos);        // Ovde mi blokira prekid i pravi ITOFF temp promenljivu
   position = pFactor * position;                       // za novu mehaniku dodato mFactor
   // Racunanje struje na osnovu vrednosti ocitane sa ADC pravi mi dodatnu promenljivu DIVFF i stopira prekid
   //sVoltage = ((float)(adcValue)) * 0.0048828125;
   //refVoltage = ((float)(adcRef)) * 0.0048828125;
   
   //mVoltage = sVoltage - refVoltage;
   
   /*pCurrent = mVoltage/83.0;
   pCurrent = pCurrent * 20.0;
   pCurrent = pCurrent/0.625;*/
   //currentFeedback = adcValue - adcRef;     //signed int16 currentFeedback
   currentFeedback = filteredDataADCV - filteredDataREF;
   if (currentFeedback < 0)
      currentFeedback = (-1) * currentFeedback;
     
   switch(AUTO_FUNCTION)
   {
      /***************************************/
      /*         Kalibracija enkodera        */
      /***************************************/
      case 1:
         if (currentFeedback < 160)             //0.3A
         {
            con.ENABLE = TRUE;
            con.PWM = 150;
            con.DIRECTION = FALSE;
         }
         else
         {
            encoderIndex = 0;
            qei_set_count(0);
           
            con.PWM = 0;
            con.DIRECTION = TRUE;
            con.ENABLE = FALSE;
           
            AUTO_FUNCTION = 0;
           
            GoToPosition(60);
         }
         break;
      /***************************************/
      /*      Odlazak u zadatu poziciju      */
      /***************************************/
      case 2:
         if ( !(((newPosition-0.1)<position) && (position<(newPosition+0.1))) )
         {
            if (position < newPosition)
            {
               con.PWM = 150;
               con.DIRECTION = TRUE;
               con.ENABLE = TRUE;
            }
            else
            {
               con.PWM = 150;
               con.DIRECTION = FALSE;
               con.ENABLE = TRUE;
            }
         }
         else
         {
            AUTO_FUNCTION = 0;
            con.PWM = 0;
            con.DIRECTION = TRUE;
            con.ENABLE = FALSE;
         }
         break;
   }
   //Movement(con.ENABLE, con.PWM, con.DIRECTION);
   if (con.ENABLE)
   {
      H_BRIDGE_ENABLE();
   }
   else
   {
      H_BRIDGE_DISABLE();
   }
   if (con.DIRECTION)
   {
      set_power_pwm0_duty(PWM_HALF - (dFactor * con.PWM));
      set_power_pwm2_duty(PWM_HALF + (dFactor * con.PWM));
   }
   else
   {
      set_power_pwm0_duty(PWM_HALF + (dFactor * con.PWM));
      set_power_pwm2_duty(PWM_HALF - (dFactor * con.PWM));     
   }
   
   clear_interrupt(INT_TIMER1);
   enable_interrupts(INT_TIMER1);
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);
   
}

/*********** UART data received interrupt ***********/
#INT_RDA
void Serial_isr()
{
   int i = 0;
   disable_interrupts(GLOBAL);
   disable_interrupts(INT_RDA);
   
   c = getc();
   if ((!START_BYTE) && (c == 0x21))
      START_BYTE = TRUE;
     
   if (START_BYTE)
   {
      if (iBufferCount < 8)
      {
         iBuffer[iBufferCount] = c;
         ++iBufferCount;
      }
      else
      {
         iBuffer[iBufferCount] = c;
         NEW_MESSAGE_RECEIVE = TRUE;
         for (i=0;i<9;++i)
         {
            tBuffer[i] = iBuffer[i];
            ibuffer[i] = 0;
         }
         iBufferCount = 0;
         START_BYTE = FALSE;
      }
   }
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);
}

/**** Funkcija racuna CRC8 za zadati niz bajtova ****/
/* *buff - pokazivac na prvi element niza za koji   */
/*         se CRC racuna                            */
/* buffLength - broj bajtova za koje se CRC racuna  */
/****************************************************/
/*void ComputeCRC8(BYTE *buff, BYTE buffLength)
{
   int j=0;
   crc = 0;
   if (buffLength > 0)
   {
      for (j=1;j<buffLength;j++)
      {
         crc = table[(crc ^ buff[j])];
      }
   }
}*/

/********** Slanje podataka na seriski port *********/
/* *data - pokazivac na prvi element niza           */
/* dataLength - broj bajtova za koje treba poslati  */
/****************************************************/
/*void SendPacket(BYTE *data,BYTE dataLength)
{
   int k;
   RCV_OFF();
   
   for (k=0;k<dataLength;k++)
   {
      putc(data[k]);
   }
   
   RCV_ON();
}*/

void DataSend(byte *data)
{
   int i = 0;
   for (i=0;i<9;i++)
   {
      putc(data[i]);
   }
}

/********* Prebacivanje u Receive mod RS485 *********/
void RCV_ON()
{
   clear_interrupt(INT_RDA);
   enable_interrupts(INT_RDA);
}

/********* Inicijalizacija mikrokontrolera **********/
void Init()
{
   
   set_tris_a(0b11111111);
   set_tris_b(0b00000000);
   //set_tris_c(0b10000000);
   set_tris_d(0b00000000);
   set_tris_e(0b00000011);
   delay_ms(1);
   
   ENCODER_ENABLE();
   ENCODER_TTL();
   BRAKE_ENABLE();//BRAKE_DISABLE();
   H_BRIDGE_DISABLE();
   delay_ms(1);

   setup_adc_ports(sAN0 | sAN1 | VSS_VDD);                                             // Treba dodati i AN5
   setup_adc(ADC_CLOCK_INTERNAL);
   
   // Brake control
   /*setup_timer_2(T2_DIV_BY_1,249,1);      //20KHz
   setup_ccp1(CCP_PWM);
   set_pwm1_duty(716);*/

   setup_power_pwm_pins(PWM_COMPLEMENTARY, PWM_COMPLEMENTARY, PWM_OFF,PWM_OFF);
   // Mode = Free Run 
   // Postscale = 1   (1-16) Timebase output postscaler
   // TimeBase = 0   (0-65355) Initial value of PWM Timebase
   // Period = 250  (0-4095) Max value of PWM TimeBase
   // Compare = 0     (Timebase value for special event trigger)
   // Compare Postscale = 1 (Postscaler for Compare value)
   // Dead Time
   setup_power_pwm(PWM_FREE_RUN, 1, 0, POWER_PWM_PERIOD, 0, 1,10);

   set_power_pwm0_duty(PWM_HALF);
   set_power_pwm2_duty(PWM_HALF);

   setup_qei(QEI_MODE_X4 | QEI_RESET_WHEN_MAXCOUNT | QEI_VELOCITY_MODE_DISABLED, QEI_FILTER_ENABLE_QEA | QEI_FILTER_ENABLE_QEB | QEI_FILTER_ENABLE_INDX | QEI_FILTER_DIV_16, 5999);
   delay_ms(1);
   qei_set_count(0);
   // SAMPLE_TIME interrupt generator, interrupts on every 1.5ms
   setup_timer_1 (T1_INTERNAL | T1_DIV_BY_1);

   p.ID = read_eeprom(0x00);
   /***************************************/
   /* FIRST START INIT DEFAULT PARAMETERS */
   /***************************************/
   if (read_eeprom(0xff) == 255)
   {
      p.MP0 = 0;
      write_eeprom(0x01,p.MP0);
      p.POWER_SUPPLY = 35;
      write_eeprom(0x02,p.POWER_SUPPLY);
      p.MOTOR_VOLTAGE = 24;
      write_eeprom(0x03,p.MOTOR_VOLTAGE);
      p.ENC_MAX_H = 0;
      write_eeprom(0x04,p.ENC_MAX_H);
      p.ENC_MAX_L = 0;
      write_eeprom(0x05,p.ENC_MAX_L);
      p.MP1 = 0;
      write_eeprom(0x06,p.MP1);
      p.GEAR_N = 0;
      write_eeprom(0x07,p.GEAR_N);
      p.GEAR_M = 0;
      write_eeprom(0x08,p.GEAR_M);
     
      con.ENABLE = FALSE;
      con.DIRECTION = FALSE;
      con.PWM = 0;
     
      write_eeprom(0xff,100);
   }
   else
   {
      p.MP0 = read_eeprom(0x01);
      /*if ((p.MP0 & 0x02) == 0x02)
         ENCODER_ENABLE();
      else
         ENCODER_DISABLE();
      if ((p.MP0 & 0x04) == 0x04)
         ENCODER_TTL();
      else
         ENCODER_DIFF();
      if ((p.MP0 & 0x08) == 0x08)
         BRAKE_ENABLE();
      else
         BRAKE_DISABLE();*/
      p.POWER_SUPPLY = read_eeprom(0x02);
      p.MOTOR_VOLTAGE = read_eeprom(0x03);
      p.ENC_MAX_H = read_eeprom(0x04);
      p.ENC_MAX_L = read_eeprom(0x05);
      p.MP1 = read_eeprom(0x06);
      p.GEAR_N = read_eeprom(0x07);
      p.GEAR_M = read_eeprom(0x08);
     
     
     
      con.ENABLE = FALSE;
      con.DIRECTION = FALSE;
      con.PWM = 0;
   }
   
   delay_ms(500);
   set_adc_channel(0);
   adcRef = read_adc();
   set_adc_channel(1);
   adcValue = read_adc();
   
   adcOffset = adcRef - adcValue;
   delay_ms(500);
   
   set_timer1(58036); //58036 za 1.5ms sample time
   clear_interrupt(INT_TIMER1);
   enable_interrupts(INT_TIMER1);
   
   clear_interrupt(INT_IC2QEI);
   enable_interrupts(INT_IC2QEI);
   
 
   enable_interrupts(INT_RDA);
   clear_interrupt(INT_RDA);
 
   enable_interrupts(GLOBAL);
   if (read_eeprom(0x09) != 0xff)                        // Ukoliko je drajver podesen moze da se izvrsi kalibracija
   {
      switch (read_eeprom(0x09))
      {
         case 100:
            pFactor = -1;
            dFactor = 1;
            break;
         case 150:
            pFactor = 1;
            dFactor = -1;
            break;
         case 200:
            pFactor = -1;
            dFactor = 1;
            break;
      }
      //AUTO_FUNCTION = 1;                                 // Komanda za kalibraciju enkodera u ovoj verziji srki ovo inicira
   }
}

/**************** Snimanje parametara ***************/
/* Funkcija snima parametre drajvera u EEPROM       */
/****************************************************/
void SaveNewParams()
{
   write_eeprom(0x01,p.MP0);
   write_eeprom(0x02,p.POWER_SUPPLY);
   write_eeprom(0x03,p.MOTOR_VOLTAGE);
   write_eeprom(0x04,p.ENC_MAX_H);
   write_eeprom(0x05,p.ENC_MAX_L);
   write_eeprom(0x06,p.MP1);
   write_eeprom(0x07,p.GEAR_N);
   write_eeprom(0x08,p.GEAR_M);
}

/**************** Automatsko kretanje ***************/
/* Motor se okrece do zadate pozicije pos           */
/****************************************************/
void GoToPosition(float pos)
{
   newPosition = pos;
   AUTO_FUNCTION = 2; 
}

void GoToPosition1(float pos)
{
   newPosition = pos;
   AUTO_FUNCTION = 2; 
}

short CRCCheck(byte *data)
{
   int i = 0, crc = 0;
   for (i=0;i<8;++i)
   {
      crc ^= data[i];
   }
   
   return crc == data[8];
}

void CRCGet(byte *data)
{
   int i = 0, crc = 0;
   for (i=0;i<8;++i)
   {
      crc ^= data[i];
   }
   
   data[8] = crc;
}

 

void main()
{
   int  j = 0;
   BYTE f2b[4] = {0, 0, 0, 0};
   int16 pwmmm;
   delay_ms(100);
   Init();
   
   while (TRUE)
   {
      if (NEW_MESSAGE_RECEIVE)
      {
         if (CRCCheck(tBuffer))
         {
            if (tBuffer[1] == p.ID)
            {
               switch (tBuffer[2])
               {
                  /***************************************/
                  /*      INIT POSITION      */
                  /***************************************/
                  case 5:
                     if (tBuffer[3] == 0x01)
                     {
                        AUTO_FUNCTION = 1;
                     }
                     break;
                  /***************************************/
                  /*      GO TO POSITION      */
                  /***************************************/                 
                  case 4:
                     GoToPosition1((float)tBuffer[3]);
                     break;
                  /***************************************/
                  /*      SET PWM     */
                  /***************************************/
                  case 1:
                     pwmmm = tBuffer[3] * 256 + tBuffer[4];
                     if (pwmmm > 368)
                        con.PWM = 368;
                     else
                        con.PWM = pwmmm;
                     break;
                  /***************************************/
                  /*      SET DIRECTION      */
                  /***************************************/                 
                  case 2:
                     if (tBuffer[3] == 0x01)
                        con.DIRECTION = TRUE;
                     else
                     {
                        if (tBuffer[3] == 0x02)
                           con.DIRECTION = FALSE;
                     }
                     break;
                  /***************************************/
                  /*      ENABLE DISABLE      */
                  /***************************************/
                  case 3:
                     if (tBuffer[3] == 0x01)
                        con.ENABLE = TRUE;
                     else
                     {
                        if (tBuffer[3] == 0x00)
                           con.ENABLE = FALSE;
                     }
                     break;
                  /***************************************/
                  /*      GET POSITION     */
                  /***************************************/
                  case 6:
                     positionIEEE = position;
                     toIEEE(&positionIEEE);
                     
                     for (j = 0; j < 4; j++)
                        f2b[j] = *((int8*)&positionIEEE + j);
                     tBuffer[3] = f2b[3];
                     tBuffer[4] = f2b[2];
                     tBuffer[5] = f2b[1];
                     tBuffer[6] = f2b[0];
                     
                     CRCGet(tBuffer);
                     break;
               }
               DataSend(tBuffer);
            }
           
         }
         NEW_MESSAGE_RECEIVE = FALSE;
      }
   }   
}


When I reset the microcontroller everything is fine before I send some data to uart. After couple of packages INT_RDA interrupt stop to work. I masked INT_TIMER1 interrupt and find that it is a problem. But I can not understand what is the problem. When I disable timer interrupt, rda interrupt going fine without errors.

Can somebody check this code above and tell me were I make mistake?

Every suggestion will be appreciated.

Thanks.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 13, 2012 4:47 pm     Reply with quote

Get rid of all the lines where you enable/disable interrupts inside the
interrupt routines. That's causing your problem. Never do this in CCS.

Also add the ERRORS parameter to your #use rs232() statement.
Mike Walne



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

View user's profile Send private message

PostPosted: Wed Jun 13, 2012 5:14 pm     Reply with quote

You're doing far too much in timer1 ISR.

(1) Keep isr's as short as possible, get in, set flags, get out.
(2) Do most of work in main().
(3) There's no need to enable / disable interrupts in ISR, CCS compiler does all the work for you.
(4) You also should not need to control tris, for same reason.
(5) You are enabling RDA interrupt in timer1 ISR.
(6) Avoid maths in ISR, floats take ages.

Reduce code to a few lines which show problem, rather than having to wade through pages of it.

Mike
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Thu Jun 14, 2012 1:45 am     Reply with quote

To re-iterate, ignoring the much too long routine, and the general enable/disables, which are unnecessary, the one that is the killer, is the line:

enable_interrupts(GLOBAL);

in the ISR. This must _never_ _ever_ be done in a PIC. Basically, the standard PIC cannot have interrupts at the same operating 'level' occurring inside themselves. In order to _ensure_ this does not happen, the _hardware_ disables the global interrupt bit, when the interrupt handler is called. There is then a special 'return from interrupt' instruction, which re-enables this bit _after_ the return is executed. Enabling it before the return, _will_ kill the code completely.

It is just worth emphasising, just how 'bad' this is. It really is 'shooting yourself in the foot', to do this.

Best Wishes
mikimtb



Joined: 18 Mar 2012
Posts: 4
Location: Serbia

View user's profile Send private message

PostPosted: Thu Jun 14, 2012 8:21 am     Reply with quote

Thanks for support.
I change everything you said, and now it's going better. But again after I don't know, sometimes 20, sometimes 30, sometimes 4 packages UART receive stop to operate.

I knew that ISR has to be as short as possible. But as you can see on source code, I have a couple of sensors connected to the uC.

One of tasks is to have to keep a constant motor current from point A to point B. Because of that I have implemented PID controller. As you know PID controller is working in discrete time domain and in my case it's 1.5ms sample time. In that time I have to read sensors output and calculate PID which is motor pwm. Because of that I have a lot of math in ISR routine. Is there some other way to synchronize the PID and sensors outside ISR routine?

Thanks one more time.
Best regards.
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Thu Jun 14, 2012 8:57 am     Reply with quote

First, remember interrupts only respond to signaled events. You can always do the same things in the main code, by testing interrupt bits. On my own PID's, I commonly trigger the maths at the instant the cycle finishes. in the main.
However realistically the first key thing is to get rid of FP. This is _not_ needed for a PID. Microchip have a number of examples, doing all the PID maths, using scaled integers. Typically treating the integer values as 1/256th step values. Your position code is a killer.
Then look at taking your ADC readings _while_ other things are being done.
There are also problems _with_ your ADC readings. You are selecting a channel, then reading it immediately. This will give incorrect readings. The internal capacitor _must_ be connected to the incoming voltage for Tacq, _before_ you start a reading.
As another comment, ADC_CLOCK_INTERNAL, is usually _slower_ than using the right divisor off the master clock, and is not legal for clock rates above 1MHz.....

This is where the commands:
read_adc(ADC_START_ONLY);
read_adc(ADC_READ_ONLY);
adc_done();

come in.

You can (for example):

1) select you next required ADC channel.
2) Perform other operations that take at least Tacq.
3) Perform 'read_adc(ADC_START_ONLY)'.
4) _Immediately select the next channel_. This will be connected to the ADC as soon as the conversion finishes, reducing the need to wait next time.
5) Do other things for the time the ADC takes to perform the reading.
6) If you are sure you have taken longer than than the acquisition time, then perform:
val=read_adc(ADC_READ_ONLY);

If you are not sure, then check adc_done() first.

etc..

The point is that the ADC takes 13 cycles of it's master clock. Typically 2 to 4uSec/cycle for the internal oscillator (selecting master clock/32, gives you instead just 1.6uSec/cycle). Say 3uSec for your current clock, so the conversion takes 39uSec. For the whole of this time, you can be doing other things, which then don't have to be done later. Parallel tasking!....

You still show the enable/disable interrupt code in the interrupt routines.
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