can any 1 tel me where the wrong in program ADC pic16f882 internal adc

Status
Not open for further replies.

parimi.ravikiran

Newbie level 4
Joined
Dec 4, 2010
Messages
7
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Location
Pune
Activity points
1,352
unsigned int low_value, hig_value;
void main()
{
OSCCON=0X60; // INTERNAL CLOCK FREQ 4MHZ
TRISA=1; // ADC INPUT PORTA
TRISB=0; //ADC O/P PORTB FOR LOWER BITS (0-1) USING LEFT JUSTIFIED
TRISC=0; // ADC O/P HIGHER BITS (2-9)
PORTB=0X00; // make o/p ports clear
PORTC=0X00; // make o/p ports clear
while(1)
{
ADCON0=0b01000000; //AN0 SELECT , clk Fosc/8
ANSEL=0x01; // ANALOG HAS BEEN SELECTED
ADCON0=0B01000001; // CLK FOSC/8 , Analog channel AN0,ADC ON
ADCON1=0X00; // Vref use vss , vdd
PIR1=0X00; // clr interrupt flag
delay_ms(30); // wait for 4.67uS ACQUISITION MIN TIME
//ADCON0=0x41; //make adc ON--- (not used now)
//ADCON0=0B01000011; // to make adc start.-- (not used now)
//while(PIR1=0b01000000) // check for IF bit is set or not-- (not used now)
for(; {
//ADCON0=0x43; // initiate conversion on the channel 0 , go/done bit=1
ADCON0|=2; //set bit go =1
//while(GO); // Wait conversion done
//while(Go&0x00);
while(ADIF); //checking that go bit is clear or not . is conversion over?
{
portb=ADRESL; // send lower 2 bits 0-1 to portb
//portb=low_value;
portc=ADRESH; //send 2-9 bits higher bits to portc. msb last
//PORTC=hig_value;
PIR1=0X00; // clear IF( Interrupt flag)
}
}
}
}
 

It is a lot easier to understand if you put the A/D conversion into a single separate function.

Divide and conquer!

This also promotes reusable code, once you have a peripheral function debugged and working, next time you need it, it's a cut and paste job.


Code:
/*--- Read A/D conversion ---*/

unsigned int read_ad(unsigned char channel)
  {
  unsigned int result = 0U;
  unsigned char acquisition_time = 3U;

  ADCON1 = 0x80U;   /* 10 bit Right justified result, Vdd as ref */
  ADCON0 = 0x81U;   /* Conversion clock Fosc/32 */

  ADCON0 |= (unsigned char)(channel << 2U);  /* Select channel */ 
        
  while(acquisition_time--){ /* Sample channel */
    ;
    }
    
  GODONE = 1U;    /* Start conversion */
  
  while(GODONE){  /* Wait for conversion end */
    ;
    }
    
  result = ADRESH;
  result <<= 8U;
  result |= ADRESL;
  return result;
  }

/*--- End of Function ---*/
 

Thanks dude ...

small doubt in the main while calling the read_ad(?); the parameters need to give
bcoz
ADCON0 |= (unsigned char)(channel << 2U); /* Select channel */

it takes the channel here.. i am not getting this line
 

The channel is the A/D input you want to read.
So you would define them something like this:

Code:
#define SUPPLY_VOLTAGE  0    /* A/D channel AN0 */
#define MOTOR_CURRENT   1    /* A/D channel AN1 */

/* Call A/D routine */

psu_volts = read_ad(SUPPLY_VOLTAGE);  /* Read A/D channel AN0 */

current  = read_ad(MOTOR_CURRENT);    /* Read A/D channel AN1 */

Or you could just use the channel number

result = read_ad(4); /* Read A/D channel AN4 */


ADCON0 |= (unsigned char)(channel << 2U); /* Select channel */

The channel number is shifted into the correct position and ored with the register.
The U after the 2 tells the compiler that the 2 is an unsigned variable.
 
Last edited:

Thanks a lot man

i got it ..u r explanation is superb..

got the result
 

Just i want to know,while next time receiving the adc o/p with different voltage input from Variable pot the ARSESH and ADRESL are giving the previous result only why so?
 

Don't know?

Show us what code you are using.
 

i am using miKroC compiler pic16f882.
simulation in Proteus is showing some o/p but its not correct
Hard ware shows nothing o/p

my code::

unsigned int result1;
unsigned int read_ad(char);
unsigned char acquisition_time = 3U;
void main()
{
OSCCON=0X71; // INTERNAL CLOCK FREQ 8MHZ,SCS Internal oscillator is used for system clock
TRISA=1; // ADC INPUT PORTA
TRISB=0; //ADC O/P PORTB FOR LOWER BITS (0-7) USING RIGHT JUSTIFIED
TRISC=0; // ADC O/P HIGHER BITS (8-9)
ANSEL=0x10; //ANS4 Analog i/p
PORTB=0X00; // make o/p ports clear
PORTC=0X00; // make o/p ports clear
portb|=2; //my optional
delay_ms(1000); //my optional
out=read_ad(4);

// send the 0-7 bits of adc result to the portb ( LSB 1st) *
PORTB=out; // portb will contain the result of adc (1-8)lsb 1st
//portc=out>>8;
// send the 8-9 bits of adc result to the portb (MSB END)

}

/* calling function*/
unsigned int read_ad(unsigned char channel)
{
unsigned int result = 0U;
unsigned char acquisition_time = 3U;

ADCON1 = 0x80U; /* 10 bit Right justified result, Vdd as ref */
ADCON0 = 0x81U; /* Conversion clock Fosc/32 */

ADCON0 |= (unsigned char)(channel << 2U); /* Select channel */
while(acquisition_time--) /* Sample channel */
{;
}

//GO=0x01; or GO=1; /* Start conversion */ It is not working for me miKroC
//GO=1;
ADCON0|=2; //go=1
portb=0x00; //optional
portc|=2; //my optional
//while((ADIF&0x01)&(GO&0x00))
//while(ADIF==1&GO==0x00)
//while(ADIF&0x01)/* Wait for conversion end */
while(GO&0x00) // while(GO) is not working here
{
;
}
portc=0x00; //my optional
PORTC=ADRESH; //msb bit (10, 9 ) send to portc
result1 = ADRESH;
result1 <<= 8U;
result1 |= ADRESL;
//portb=ADRESL; //bit (8, 1 ) send to portb
return result1;
}
 

read This example code reads analog value from channel 2 and displays it on PORTB and PORTC. this is work perfectly then try to understand your code that it is included necessary codes

unsigned int temp_res;

void main() {
ANSEL = 0x04; // Configure AN2 pin as analog
ANSELH = 0; // Configure other AN pins as digital I/O
C1ON_bit = 0; // Disable comparators
C2ON_bit = 0;

TRISA = 0xFF; // PORTA is input
TRISC = 0; // PORTC is output
TRISB = 0; // PORTB is output

do {
temp_res = ADC_Read(2); // Get 10-bit results of AD conversion
PORTB = temp_res; // Send lower 8 bits to PORTB
PORTC = temp_res >> 8; // Send 2 most significant bits to RC1, RC0
} while(1);
}
 

Thanks both of u , finally it is working ..
here is my code any fineness is required just tell me
All i have observed the o/p on led
now i have 2 work on taking this data to the LCD

CODE:IC16F882 INTERNAL ADC USING MIKROC

unsigned int result1,temp_result;
unsigned int read_ad(char);
unsigned char acquisition_time = 3U;
void main()
{
OSCCON=0X61; // INTERNAL CLOCK FREQ 4MHZ,SCS Internal oscillator is used for system clock
TRISA=0XFF; // ADC INPUT PORTA
TRISB=0; //ADC O/P PORTB FOR LOWER BITS (0-7) USING RIGHT JUSTIFIED
TRISC=0; // ADC O/P HIGHER BITS (8-9)
ANSEL=0x10; //ANS4 Analog i/p
ANSELH=0; //Configure other AN pins as digital I/O
PORTB=0X00; // make o/p ports clear
PORTC=0X00; // make o/p ports clear
C1ON_BIT=0; // disable comparator
C2ON_BIT=0;

do
{
temp_result=read_ad(4); //Read the adc function

// send the 0-7 bits of adc result to the portb ( LSB 1st) *
PORTB=temp_result; // portb will contain the result of adc (1-8)lsb 1st
PORTC=temp_result>>8; // send the 8-9 bits of adc result to the portc(RC0,RC1) (MSB END)
}while(1);
}

/* calling function*/
unsigned int read_ad(unsigned char channel)
{
unsigned int result = 0U;
unsigned char acquisition_time = 3U;

ADCON1 = 0x80U; /* 10 bit Right justified result, Vdd as ref */
ADCON0 = 0x81U; /* Conversion clock Fosc/32 */

ADCON0 |= (unsigned char)(channel << 2U); /* Select channel */
while(acquisition_time--) /* Sample channel */
{;
}

GO_DONE_BIT = 1U;
//while((ADIF&0x01)&(GO_DONE_BIT&0x00))
//while(ADIF&0x01)/* Wait for conversion end */
while(GO_DONE_BIT) // use this for mikroC
{
;
}

result1 = ADRESH;
result1 <<= 8U;
result1 |= ADRESL;
return result1;
}
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…