Page 1 of 1

ADC interrupt

Posted: 29 Jan 2010 08:29
by asnl1987
I want to read voltage at AN0->AN3 then display on PORTC and PORTD
adc_data[] stores AD conversion result
This is my program
unsigned int adc_data[4];
unsigned char analog_selected=0;
unsigned char adc_flag=0;
void interrupt()
{ if(PIR1.ADIF==1)
adc_flag=1;
{if((analog_selected==0) && (adc_flag==1))
{adc_data[0]=(ADRESH << 8) | ADRESL; // read dadta from channel 0
analog_selected++; // increase channel index
adc_flag=0;
ADCON0=0b11001001; // select channel 1
}
if((analog_selected==1)&&(adc_flag==1))
{adc_data[1]=(ADRESH << 8) | ADRESL; // read dadta from channel 1
analog_selected++; // increase channel index
adc_flag=0;
ADCON0=0b11010001; // select channel 2;
}
if((analog_selected==2)&&(adc_flag==1))
{adc_data[2]=(ADRESH << 8) | ADRESL; // read dadta from channel 2
analog_selected++; // increase channel index
adc_flag=0;
ADCON0=0b11011001; // select channel 3;
}
if((analog_selected==3)&&(adc_flag==1))
{adc_data[3]=(ADRESH << 8) | ADRESL; // read dadta from channel 3
analog_selected=0;
adc_flag=0; // return channel 0
ADCON0=0b11000001; // select channel 0;
}
Delay_Cyc(3); //wait acquisition time
ADCON0.F2=1; //start conversion again
PIR1.ADIF=0; // clear AD interrupt flag
}
}
void main()
{unsigned int i=0,temp;
TRISA=0xFF;
TRISE=0x0F;
TRISB=0xFF;
TRISD=0;
TRISC=0;
PORTD=0;
PORTC=0;
ADCON1=0x82; // AN0->AN4 selected as analog input
ADCON0=0b11000001; // Configue analog mode
INTCON.GIE = 1; //Enable global interrupt
INTCON.PEIE = 1; //Enable peripheral interrupt
PIE1.ADIE = 1; //Enable ADC interrupt
Delay_us(20); //wait for acquisition time
ADCON0.F2=1; //start conversion
while(1)
{ temp=adc_data[i]; // read data from channel i
i++;
if(i==4) i=0;
PORTD = temp; // Send lower 8 bits to PORTD
PORTC = temp >> 2; // Send 2 most significant bits to RB7, RB6
delay_ms(1000);
}

}


But it doesn't run. Please hepl me. Thank so much

Posted: 03 Feb 2010 11:27
by anikolic
Hi,
Can you please specify what chip are you using, so I might also test the
program on hardware, and correct it if necessary.

Thank you.
Aleksandar

Posted: 04 Feb 2010 02:55
by asnl1987
I use 16f877A, clock 8Mhz

Posted: 04 Feb 2010 15:01
by anikolic
Hi,
Your code works just fine, I have tested it on following hardware/software:
1. EasyPIC6
2. PIC16F877A @ 8MHz, HS oscillator
3. Both mikroC for PIC and mikroC PRO for PIC
I have a suggestion how you can also re-organize your code within interrupt, so it is more readable and more clear at first glance:

Code: Select all

unsigned int adc_data[4];
unsigned char analog_selected = 0;

void interrupt(){
  if (PIR1.ADIF) {
    PIR1.ADIF=0; // clear AD interrupt flag
    switch (analog_selected){
      case 0:
        adc_data[0] = (ADRESH << 8) | ADRESL; // read dadta from channel 0
        analog_selected++; // increase channel index
        ADCON0 = 0b11001001; // select channel 1
        break;
      case 1:
        adc_data[1] = (ADRESH << 8) | ADRESL; // read dadta from channel 1
        analog_selected++; // increase channel index
        ADCON0 = 0b11010001; // select channel 2;
        break;
      case 2:
        adc_data[2] = (ADRESH << 8) | ADRESL; // read dadta from channel 2
        analog_selected++; // increase channel index
        ADCON0 = 0b11011001; // select channel 3;
        break;
      case 3:
        adc_data[3] = (ADRESH << 8) | ADRESL; // read dadta from channel 3
        analog_selected = 0; // return channel 0
        ADCON0 = 0b11000001; // select channel 0;
        break;
    }
    Delay_Cyc(3); //wait acquisition time
    ADCON0.F2=1; //start conversion again
  }
}
void main(){
  unsigned int i=0, temp;
  
  TRISA=0xFF;
  TRISE=0x0F;
  TRISB=0xFF;
  TRISD=0;
  TRISC=0;
  PORTD=0;
  PORTC=0;
  ADCON1 = 0x82; // AN0->AN4 selected as analog input
  ADCON0 = 0b11000001; // Configue analog mode
  INTCON.GIE = 1; //Enable global interrupt
  INTCON.PEIE = 1; //Enable peripheral interrupt
  PIE1.ADIE = 1; //Enable ADC interrupt
  Delay_us(20); //wait for acquisition time
  ADCON0.F2 = 1; //start conversion
  
  while(1){
    temp = adc_data[i]; // read data from channel i
    i++;
    if (i==4)
      i=0;
    PORTD = temp; // Send lower 8 bits to PORTD
    PORTC = temp >> 2; // Send 2 most significant bits to RB7, RB6
    delay_ms(100);
  }
}
Best regards,
Aleksandar