|
|
View previous topic :: View next topic |
Author |
Message |
hamid9543
Joined: 31 Jan 2013 Posts: 63
|
how reduce execution time in "analog read " |
Posted: Tue Feb 25, 2020 2:13 pm |
|
|
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: 9269 Location: Greensville,Ontario
|
|
Posted: Tue Feb 25, 2020 3:13 pm |
|
|
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
|
Re: how reduce execution time in "analog read " |
Posted: Tue Feb 25, 2020 7:49 pm |
|
|
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
|
Re: how reduce execution time in "analog read " |
Posted: Tue Feb 25, 2020 10:12 pm |
|
|
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
|
|
Posted: Tue Feb 25, 2020 10:17 pm |
|
|
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
|
|
Posted: Wed Feb 26, 2020 1:25 am |
|
|
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: 19588
|
|
Posted: Wed Feb 26, 2020 3:05 am |
|
|
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.... |
|
|
|
|
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
|