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

how reduce execution time in "analog read "

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



Joined: 31 Jan 2013
Posts: 63

View user's profile Send private message

how reduce execution time in "analog read "
PostPosted: Tue Feb 25, 2020 2:13 pm     Reply with quote

i use pic18f46k22 and internal clock 64 mhz
how reduce execution time in "analog read "?
Is there any other way to run code in less time?
Code:

#include <18F46K22.h>
#FUSES NOWDT,NOBROWNOUT,NOPUT,PLLEN                     
#device ADC=8

#use delay(internal=64mhz)

#define cal_key !input(pin_e2)


rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=pin_a4,bits=8,stream=blt)//b

unsigned int8 njl_value;
unsigned int16 AN[20]={13,11,9,8,10,12,26,25,24,19,17,23,22,21,20,4,3,2,1,0},min_njl[20],max_njl[20],cal_done=0;

int1 njl[20];




void main()
{
 
   set_analog_pins(PIN_A0,PIN_A1,PIN_A2,PIN_A3,PIN_A5,PIN_B0,PIN_B1,PIN_B2,PIN_B3,PIN_B4,PIN_B5,PIN_C5,PIN_C7,PIN_D0,PIN_D1,PIN_D2,PIN_D3,PIN_D4,PIN_D5,PIN_D6);
   setup_adc(ADC_CLOCK_DIV_8|ADC_TAD_MUL_0);

   delay_ms(500);
   

   

      for(int i=0;i<20;i++)
      {
         threshold[i]=read_eeprom(i);
         min_njl[i] = 255;
         max_njl[i] = 0;
      }
                   

   
   while(True)
   {   
         ;
     
      if(cal_key && cal_done==0)
      {
         while (cal_key);     
         while (!cal_key)
         {
            for(int i=0;i<20;i++)
            {   
               set_adc_channel(AN[i]);
               delay_us(10);
               njl_value=read_adc();
               if( njl_value>max_njl[i])      max_njl[i]= njl_value;
               if( njl_value<min_njl[i])      min_njl[i]= njl_value;
            }

         }
         
         for(int i=0;i<20;i++)
         {
           //threshold[i]= (min_njl[i]+max_njl[i])/2;
           threshold[i]= max_njl[i]+10;Ůž
           write_eeprom(i,threshold[i]);
           delay_us(10);
         }
         cal_done=1;
      }
           
      for(int i=0;i<20;i++)
       {   
         set_adc_channel(AN[i]);
         delay_us(10);
         njl_value=read_adc();     
       if(njl_value>(threshold[i]))           {njl[i]=1;}
       else if(njl_value<(threshold[i]))       njl[i]=0;
     
       }
       for(int a=0;a<20;a++) printf("%u",njl[a]);
      printf("\n\r");       
     
             
   }
}


     

temtronic



Joined: 01 Jul 2010
Posts: 9205
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Feb 25, 2020 3:13 pm     Reply with quote

couple of 'issue'...
1) the recommended adc clock is Fosc/64 NOT Fosc/8 as you have......
Check the ADC section, Table 17-1 , .....

2) do all the calculations first, THEN store as a 'block' with one write eeprom command.

3) looks like ADC is in 8 bit mode , so the ADC result buffer only needs to be 8 bit ,not 16 bits
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

Re: how reduce execution time in "analog read "
PostPosted: Tue Feb 25, 2020 7:49 pm     Reply with quote

hamid9543 wrote:

How reduce execution time in "analog read "?
Is there any other way to run code in less time?


for(int i=0;i<20;i++)
{
set_adc_channel(AN[i]);
delay_us(10);
njl_value = read_adc();
if( njl_value > max_njl[i] ) max_njl[i] = njl_value;
if( njl_value < min_njl[i] ) min_njl[i] = njl_value;
}

You are doing a large number of indirect array accesses, as shown in
bold above.
Look at the amount of ASM code in your loop that's shown below.
It's enormous. The PIC is very inefficient at indirect array accesses.
Code:

.....    set_adc_channel(AN[i]);
002C8:  BCF    STATUS.C
002CA:  RLCF   i,W
002CC:  CLRF   @03
002CE:  ADDLW  AN
002D0:  MOVWF  FSR0L
002D2:  MOVLW  AN+-5
002D4:  ADDWFC @03,W
002D6:  MOVWF  FSR0H
002D8:  MOVFF  PREINC0,@@9C
002DC:  MOVF   POSTDEC0,F
002DE:  MOVFF  INDF0,@@9B
002E2:  RLCF   @@x9B,W
002E4:  MOVWF  @00
002E6:  RLCF   @@x9C,W
002E8:  MOVWF  @01
002EA:  RLCF   @00,F
002EC:  RLCF   @01,F
002EE:  MOVLW  FC
002F0:  ANDWF  @00,F
002F2:  MOVF   ADCON0,W
002F4:  ANDLW  83
002F6:  IORWF  @00,W
002F8:  MOVWF  ADCON0


Code:

......   if( njl_value>max_njl[i])      max_njl[i]= njl_value;
0030C:  BCF    STATUS.C
0030E:  RLCF   i,W
00310:  CLRF   @03
00312:  ADDLW  max_njl
00314:  MOVWF  FSR0L
00316:  MOVLW  max_njl+-85
00318:  ADDWFC @03,W
0031A:  MOVWF  FSR0H
0031C:  MOVFF  PREINC0,03
00320:  MOVF   POSTDEC0,F
00322:  MOVFF  INDF0,01
00326:  MOVF   @03,F
00328:  BNZ   0348
0032A:  MOVF   njl_value,W
0032C:  SUBWF  @01,W
0032E:  BC    0348
00330:  BCF    STATUS.C
00332:  RLCF   i,W
00334:  CLRF   @03
00336:  ADDLW  max_njl
00338:  MOVWF  FSR0L
0033A:  MOVLW  max_njl+-85
0033C:  ADDWFC @03,W
0033E:  MOVWF  FSR0H
00340:  CLRF   PREINC0
00342:  MOVF   POSTDEC0,F
00344:  MOVFF  njl_value,INDF0


Code:

.....      if( njl_value<min_njl[i])      min_njl[i]= njl_value;
00348:  BCF    STATUS.C
0034A:  RLCF   i,W
0034C:  CLRF   @03
0034E:  ADDLW  min_njl
00350:  MOVWF  FSR0L
00352:  MOVLW  min_njl+-45
00354:  ADDWFC @03,W
00356:  MOVWF  FSR0H
00358:  MOVFF  PREINC0,03
0035C:  MOVF   POSTDEC0,F
0035E:  MOVFF  INDF0,01
00362:  MOVF   @03,F
00364:  BNZ   036C
00366:  MOVF   @01,W
00368:  SUBWF  njl_value,W
0036A:  BC    0384
0036C:  BCF    STATUS.C
0036E:  RLCF   i,W
00370:  CLRF   @03
00372:  ADDLW  min_njl
00374:  MOVWF  FSR0L
00376:  MOVLW  min_njl+-45
00378:  ADDWFC @03,W
0037A:  MOVWF  FSR0H
0037C:  CLRF   PREINC0
0037E:  MOVF   POSTDEC0,F
00380:  MOVFF  njl_value,INDF0
00384:  INCF   i,F
00386:  BRA    02C2
.....      }
00388:  BRA    02BA
hamid9543



Joined: 31 Jan 2013
Posts: 63

View user's profile Send private message

Re: how reduce execution time in "analog read "
PostPosted: Tue Feb 25, 2020 10:12 pm     Reply with quote

is it ok?

Code:

void read_sensor{
        set_adc_channel(13);
         delay_us(10);
         njl_value=read_adc();
         if(njl_value>(threshold[0]))     {njl[0]=1;on_line++;}
   else if(njl_value<(threshold[0]))       njl[0]=0;
   
         set_adc_channel(11);
         delay_us(10);
         njl_value=read_adc();
         if(njl_value>(threshold[1]))     {njl[1]=1;on_line++;}
   else if(njl_value<(threshold[1]))       njl[1]=0;
   
         set_adc_channel(9);
         delay_us(10);
         njl_value=read_adc();
         if(njl_value>(threshold[2]))     {njl[2]=1;on_line++;}
   else if(njl_value<(threshold[2]))       njl[2]=0;
   
         set_adc_channel(8);
         delay_us(10);
         njl_value=read_adc();
         if(njl_value>(threshold[3]))     {njl[3]=1;on_line++;}
   else if(njl_value<(threshold[3]))       njl[3]=0;
   
         set_adc_channel(10);
         delay_us(10);
         njl_value=read_adc();
         if(njl_value>(threshold[4]))     {njl[4]=1;on_line++;}
   else if(njl_value<(threshold[4]))       njl[4]=0;
   
         set_adc_channel(12);
         delay_us(10);
         njl_value=read_adc();
         if(njl_value>(threshold[5]))     {njl[5]=1;on_line++;}
   else if(njl_value<(threshold[5]))       njl[5]=0;
   
          set_adc_channel(26);
         delay_us(10);
         njl_value=read_adc();
         if(njl_value>(threshold[6]))     {njl[6]=1;on_line++;}
   else if(njl_value<(threshold[6]))       njl[6]=0;
   
         set_adc_channel(25);
         delay_us(10);
         njl_value=read_adc();
         if(njl_value>(threshold[7]))     {njl[7]=1;on_line++;}
   else if(njl_value<(threshold[7]))       njl[7]=0;

         set_adc_channel(24);
         delay_us(10);
         njl_value=read_adc();
         if(njl_value>(threshold[8]))     {njl[8]=1;on_line++;}
   else if(njl_value<(threshold[8]))       njl[8]=0;
   
         set_adc_channel(19);
         delay_us(10);
         njl_value=read_adc();
         if(njl_value>(threshold[9]))     {njl[9]=1;on_line++;}
   else if(njl_value<(threshold[59]))       njl[9]=0;
   
         set_adc_channel(17);
         delay_us(10);
         njl_value=read_adc();
         if(njl_value>(threshold[10]))     {njl[10]=1;on_line++;}
   else if(njl_value<(threshold[10]))       njl[10]=0;
   
         set_adc_channel(23);
         delay_us(10);
         njl_value=read_adc();
         if(njl_value>(threshold[11]))     {njl[11]=1;on_line++;}
   else if(njl_value<(threshold[11]))       njl[11]=0;   
   
         set_adc_channel(22);
         delay_us(10);
         njl_value=read_adc();
         if(njl_value>(threshold[12]))     {njl[12]=1;on_line++;}
   else if(njl_value<(threshold[12]))       njl[12]=0;

         set_adc_channel(21);
         delay_us(10);
         njl_value=read_adc();
         if(njl_value>(threshold[5]))     {njl[13]=1;on_line++;}
   else if(njl_value<(threshold[5]))       njl[13]=0;
   
         set_adc_channel(20);
         delay_us(10);
         njl_value=read_adc();
         if(njl_value>(threshold[5]))     {njl[14]=1;on_line++;}
   else if(njl_value<(threshold[5]))       njl[14]=0;
   
         set_adc_channel(4);
         delay_us(10);
         njl_value=read_adc();
         if(njl_value>(threshold[15]))     {njl[15]=1;on_line++;}
   else if(njl_value<(threshold[15]))       njl[15]=0;
   
         set_adc_channel(3);
         delay_us(10);
         njl_value=read_adc();
         if(njl_value>(threshold[16]))     {njl[16]=1;on_line++;}
   else if(njl_value<(threshold[16]))       njl[16]=0;
   
         set_adc_channel(2);
         delay_us(10);
         njl_value=read_adc();
         if(njl_value>(threshold[17]))     {njl[17]=1;on_line++;}
   else if(njl_value<(threshold[17]))       njl[17]=0;
   
         set_adc_channel(1);
         delay_us(10);
         njl_value=read_adc();
         if(njl_value>(threshold[18]))     {njl[18]=1;on_line++;}
   else if(njl_value<(threshold[18]))       njl[18]=0;
   
         set_adc_channel(0);
         delay_us(10);
         njl_value=read_adc();
         if(njl_value>(threshold[19]))     {njl[19]=1;on_line++;}
   else if(njl_value<(threshold[19]))       njl[19]=0;
}
hamid9543



Joined: 31 Jan 2013
Posts: 63

View user's profile Send private message

PostPosted: Tue Feb 25, 2020 10:17 pm     Reply with quote

temtronic wrote:
couple of 'issue'...


2) do all the calculations first, THEN store as a 'block' with one write eeprom command.


Please give more explanation
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Feb 26, 2020 1:25 am     Reply with quote

Quote:
is it ok?

Compile it and look at the .LST file in your project folder.
See if the amount of ASM code is low enough for your requirements.
Ttelmah



Joined: 11 Mar 2010
Posts: 19451

View user's profile Send private message

PostPosted: Wed Feb 26, 2020 3:05 am     Reply with quote

Two comments:

First, Tacq for the chip is 7.45uSec, so you can save 2uSec on each sample
by reducing the delay to 8uSec instead of 10uSec. Small but significant.

However the biggest saving is to make use of the time.
Code:

            set_adc_channel(AN[0]);
            delay_us(8);
            read_adc(ADC_START_ONLY);
            //Now takes 12 Tad cycles to perform conversion
            //12uSec at Fosc/64.
            delay_us(4);
            for(int i=0;i<20;i++)
            {   
               delay_us(8);
               njl_value=read_adc(ADC_READ_ONLY);             
               set_adc_channel(AN[i+1]); //select next channel
               delay_us(8);
               read_adc(ADC_START_ONLY); //start next conversion
               if( njl_value>max_njl[i])      max_njl[i]= njl_value;
               if( njl_value<min_njl[i])      min_njl[i]= njl_value;
            }

Now the key point here is you start by reading a value that has already been converted. You then select the next channel. Wait Tacq, and start a new
conversion. Then while this conversion is happening, you perform
the time expensive array accesses.
Now I did a quick 'count', and with the Tad at Fosc/64 (which is what is
required at this clock rate), a conversion takes about 12uSec. The
array accesses take about 4uSec. So you still have to delay about 8uSec
before the conversion will be complete. However you are then actually
converting _while_ you are doing these accesses. Result much more
efficient....
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