Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] problem in ADC for AVR (ADC result lost due to pending read)

Status
Not open for further replies.

mahm150

Full Member level 1
Joined
Dec 14, 2010
Messages
98
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,288
Location
Cairo, Egypt, Egypt
Activity points
2,001
this message appear in proteus ADC result lost due to pending read

#define ADC_VREF_TYPE 0x40
ADMUX=ADC_VREF_TYPE;
ADCSRA=0x82;
i use this function
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input|ADC_VREF_TYPE;
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
delay_us(100); // make this delay but not solve this problem
ADCSRA |=0x10;
Tadc=(Tadc<< 8)| ADCL;
return ADCW;
}
 

Hi,
It would be more helpful if you could upload the complete code. You also need to mention which AVR you're using.

I've tried with this code for ATMEGA8:
Code:
#include <avr/io.h>
#include <avr/delay.h>
#define ADC_VREF_TYPE 0x40

unsigned int read_adc(unsigned char adc_input)
{
ADMUX= ADC_VREF_TYPE | adc_input;
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
_delay_us(100); // make this delay but not solve this problem
ADCSRA |=0x10;
//Tadc=(Tadc<< 8)| ADCL;
return ADCW;
}

main(){
    unsigned int ADR;

    ADMUX=ADC_VREF_TYPE;
    ADCSRA=0x82;
    DDRD = 0xFF;
    DDRC = 0;
    do{
        ADR = read_adc(1) >> 2;
        PORTD = ADR;
    }while(1);
}

And it's fine. The line:
Code:
Tadc=(Tadc<< 8)| ADCL;
doesn't build properly as there is no register or variable named Tadc.

Hope this helps.
Tahmid.
 

i define the Tadc as global variable
unsigned int Tadc;
void main(void)
{
while (1)
{
Tadc=read_adc(0) ;
tst_value();
}
}
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input|ADC_VREF_TYPE;
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete

while ((ADCSRA & 0x10)==0);
delay_us(100);
ADCSRA |=0x10;

// Tadc=(Tadc<< 8)| ADCL;
return ADCW;
}
void tst_value()
{
if (Tadc<410)
{
relay1 =0;
relay2 =1;
TCCR1B=0x19;
OCR1AH=0x01;// 1
OCR1AL=0xff;// ff
PORTD |= (ADCL & 0x7c);

}
// if (615>Tadc && Tadc>410)
// { TCCR1B=0x00; }
if (Tadc>=460)
{
relay1 =1;
relay2 =0;
TCCR1B=0x19;
OCR1AH=0x00;// 1
OCR1AL=0xff;// ff
PORTD|=ADCL & 0x7f;
}
}

---------- Post added at 19:06 ---------- Previous post was at 19:05 ----------

#define relay1 PORTB.0
#define relay2 PORTD.7
 

Which compiler? AVR-GCC on AVR Studio?

---------- Post added at 00:08 ---------- Previous post was at 00:07 ----------

And which AVR are you using?
 

i use atmega8
i still have some problem in PWM but let solve this problem first

---------- Post added at 19:10 ---------- Previous post was at 19:09 ----------

codevisionAVR
 

Please wait. I'm downloading CodeVision AVR. After I'm done, I'll try to fix the problem in the program.

---------- Post added at 01:00 ---------- Previous post was at 00:13 ----------

I've fixed the code. This shows no error and the program works. However, I do not understand what you are trying to do in PORTD.

Code:
#include <mega8.h>
#include <delay.h>
#include <stdio.h>

unsigned int Tadc;
unsigned char dummyH;
unsigned char dummyL;

#define relay1 PORTB.0
#define relay2 PORTD.7

#define ADC_VREF_TYPE 0x40

unsigned int read_adc(unsigned char adc_input){
    ADMUX=adc_input|ADC_VREF_TYPE;
    // Start the AD conversion
    ADCSRA.ADSC = 1;
    // Wait for the AD conversion to complete

    while (ADCSRA.ADIF==0);
    ADCSRA.ADIF = 1;
                              
    dummyL = ADCL;
    dummyH = ADCH;
    //Tadc=(Tadc<< 8)| ADCL;
return ADCW;
}


void tst_value(){
    if (Tadc<410){
        relay1 =0;
        relay2 =1;
        TCCR1B=0x19;
        OCR1AH=0x01;// 1
        OCR1AL=0xff;// ff  
        PORTD |= (dummyL & 0x7c);
    }

    // if (615>Tadc && Tadc>410)
    // { TCCR1B=0x00; }
    if (Tadc>=460){
        relay1 =1;
        relay2 =0;
        TCCR1B=0x19;
        OCR1AH=0x00;// 1
        OCR1AL=0xff;// ff  
        PORTD|=dummyL & 0x7f;
    }
}

void main(void){
    DDRC.0 = 0;
    DDRD = 0xFF; 
    DDRB.0 = 1;   
    
    ADMUX=ADC_VREF_TYPE;
    ADCSRA=0x82;
    
    while (1){
        Tadc=read_adc(0);
        tst_value();
    }
}

Hope this helps.
Tahmid.
 

i use PORTD JUST TO SEE THE VALUE OF the adc register,about my problem it appear with me in protues (ADC result lost due to pending read), what the error in my code

---------- Post added at 18:53 ---------- Previous post was at 18:50 ----------

you test this code in protues
 

Did you try with the code I just posted above? This code works fine in Proteus with no error message shown.
 

not yet but i will test it, but i didnt find the main difference in my code and the code you post so where is the problem
 

ADCSRA.ADSC not define in codevision

---------- Post added at 19:06 ---------- Previous post was at 19:05 ----------

and ADCSRA.ADIF which code vision version you use
 

Try it. There's a difference. Try it and then I'll show the difference.

Why is it a secret?

ADCSRA.ADSC not define in codevision

---------- Post added at 19:06 ---------- Previous post was at 19:05 ----------

and ADCSRA.ADIF which code vision version you use

I have never seen anything like that in codevision

Alex
 

I used CodeVision AVR v2.05.3a Evaluation Version. Here's a screenshot:


The difference is, in the previous program, the function returns the value of ADCW and then ADCL is read, however ADCH is not read. But in my program, in the ISR, both the values of ADCH and ADCL are stored in registers, so a complete read is done.
From the datasheet (pg 208):
When ADCL is read, the ADC Data Register is not updated until ADCH is read. Consequently, if
the result is left adjusted and no more than 8-bit precision is required, it is sufficient to read
ADCH. Otherwise, ADCL must be read first, then ADCH.

Why is it a secret?
I was writing another program and thought that I'd explain after he'd tried out the program. Anyways, I showed the difference now. So, all's good.

Hope this helps.
Tahmid.
 

The code generated by codevision is


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
// Read the AD conversion result
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCW;
}



I don't see the reason to do the dummy reads of the high and low byte, the code below works fine


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <mega8.h>
 
#include <delay.h>
 
#define ADC_VREF_TYPE 0x00
 
// Read the AD conversion result
unsigned int read_adc(unsigned char adc_input)
{
    ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
// Delay needed for the stabilization of the ADC input voltage
    delay_us(10);
// Start the AD conversion
    ADCSRA|=0x40;
// Wait for the AD conversion to complete
    while ((ADCSRA & 0x10)==0);
    ADCSRA|=0x10;
    return ADCW;
}
 
// Declare your global variables here
 
void main(void)
{
 
// ADC initialization
// ADC Clock frequency: 125,000 kHz
// ADC Voltage Reference: AREF pin
    ADMUX=ADC_VREF_TYPE & 0xff;
    ADCSRA=0x86;
 
    while (1)
    {
        // Place your code here
        read_adc(0);
        delay_ms(1);
    };
}

 

for tahmid i update the code as
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input|ADC_VREF_TYPE;
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
// Tadc=(Tadc<< 8)| ADCL;
dummyL=ADCL;
dummyH=ADCH;
return ADCW;
}
but still the same problem
and for alexan_e i test your code but give the smae error
 

Then it is your proteus version because in version 7.7 there is no warning and the code I have posted works fine.

Alex
 

i test my code in real world but not work ok, i think that adc make only one conversion then not work after that,
 

Can you zip and attach the code, I have only seen parts of the code in the previous posts.

Alex
 

#include <mega8.h>
#include <delay.h>
#define ADC_VREF_TYPE 0x40
// Declare your global variables here
unsigned int Tadc;
unsigned char dummyH,dummyL;
//void intialize_adc(void);
unsigned int read_adc(unsigned char adc_input);
void tst_value(void);
interrupt [15] void ADC_READ(void)
{
PORTD |= (ADCL & 0x7c);
ADCSRA |=0x10;
// PORTB=ADCH ;
// while(1);
}
#define relay1 PORTB.0
#define relay2 PORTD.7
void main(void)
{
// Declare your local variables here

PORTB=0x00;
DDRB=0xff;

PORTC=0xFF;
DDRC=0x00;

PORTD=0x00;
DDRD=0xff;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 11059.200 kHz
// Mode: Fast PWM top=FFh
// OC0 output: Non-Inverted PWM
TCCR0=0x6b;
TCNT0=0x00;
//OCR0=0x71;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
SREG=0X80;
ACSR=0x80;
SFIOR=0x00;
ADMUX=ADC_VREF_TYPE;
ADCSRA=0x82;
relay1 =0;
relay2 =1;
//intialize_adc();
//PORTB=0xa0;
while (1)
{
//intialize_adc();
Tadc=read_adc(0) ;
tst_value();
};
}
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input|ADC_VREF_TYPE;
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
// Tadc=(Tadc<< 8)| ADCL;
dummyL=ADCL;
dummyH=ADCH;
return ADCW;
}
void tst_value()
{
if (ADCL<128)
{
relay1 =0;
relay2 =1;
TCCR1B=0x19;
OCR1AH=0x01;// 1
OCR1AL=0xff;// ff
PORTD |= (ADCL & 0x7c);

}

if (ADCL>=128)
{
relay1 =1;
relay2 =0;
TCCR1B=0x19;
OCR1AH=0x00;// 1
OCR1AL=0xff;// ff
PORTD|=ADCL & 0x7f;
}
}
 
Last edited:

If you use Tadc in the tst_value() it works fine, the problem is caused by ADCL reading


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void tst_value()
{
    if (Tadc<128)
    {
        relay1 =0;
        relay2 =1;
        TCCR1B=0x19;
        OCR1AH=0x01;// 1
        OCR1AL=0xff;// ff
        //PORTD |= (ADCL & 0x7c);
 
    }
 
    if (Tadc>=128)
    {
        relay1 =1;
        relay2 =0;
        TCCR1B=0x19;
        OCR1AH=0x00;// 1
        OCR1AL=0xff;// ff
        //PORTD|=ADCL & 0x7f;
    }
}



Alex
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top