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.

reading from 3 diferent ADC PORT,atmega88

Status
Not open for further replies.

Delpi10

Newbie level 6
Joined
Dec 16, 2012
Messages
12
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,371
Hi everyone, i need to reed values from tree different ADC ports ,and i dont know how to do it,i'm quit stuck .
I know how to read from one port, but when it comes to read from more ports, i dont know how to set it.

this is the code i made until now :

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#define F_CPU 1000000 //
#include "lcd.h"// LCD library 
#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h>
#include <util/delay.h>
#include<avr/interrupt.h>
 
 
 
 
 
unsigned char leitura_AD_1,leitura_AD_2,leitura_AD_3,flag=0;
 
void inic_hardware(void);
 
void inic_hardware(void)
{
 
  
 
    DDRC = 0b00000001;          // Port D pin 0 ouput 
    DDRB = 0b00001000;
    DDRC = 0b11100000;
    PORTD= 0b00000010;
        
    SREG=0b10000000; // INT GLOBAL  
  
 
    TCCR2A=0b10000011;      // Fast PWM, Clear OC2A on Compare Match 
    TCCR2B=0b00000010; 
 
 
 
}
char ler_AD(void)
{
    ADMUX=0b00100000;
    ADCSRA=0b11001011;       //Inicia a conversão
    if(flag==1)
    {
        
        while(ADCSRA==0b11001011);  //Espera o fim da conversão
        
    }
 
    return(leitura_AD_1);
 
    flag=2;
    ler_AD1();
 
}
char ler_AD_1(void)
{
    ADMUX=0b00100001;
    ADCSRA=0b11001011;       //start the conv
    if(flag==2)
    {
        
        while(ADCSRA==0b11001011);  //wait until the end of the conv
        
    }
    return(leitura_AD_2);
 
    flag=0;
}
 
ISR(ADC_vect)
{
    flag=1;
    leitura_AD_1=ADCH;      //Leitura de 8 bits
    leitura_AD_2=ADCH;
    //leitura_AD_3=ADCH;
}
 
int main(void)
{   
    //inicializacao do hardware.
    int a=0,b=0,v_caudal=0;
    //unsigned char sw=0; // variavel para o switch
    inic_hardware(); // inicializa o hardware
    lcd_init(LCD_DISP_ON); // inicializa o display
    lcd_clrscr(); // limpa o ecra
    sw=PORTD&0b00000000; // define o botão switch que corresponde ao PORTD pino 2
    
 
 
char buffer[30]; // buffer para utilizar no envio de msg para o LCD
 
 
while(1) // ciclo infinito
        {
            
        
            a=ler_AD();
            b=ler_AD_1();
            OCR2A=a;
            OCR1B=b;
            v_caudal=a;
            
            //OCR2A=140; // coloca o OCR2A a 0,o que faz com que o LED esteja desligado
        
            lcd_gotoxy(0,0); // faz com que os caracteces sejam escritos na primeira posição do LCD
            lcd_puts("Volcaudal:");
            lcd_gotoxy(16,0);
            lcd_puts(" l\s ");
            lcd_gotoxy(11,0); // faz com que os carateres sejam escritos na linha de baixo
            sprintf(buffer,"%d",v_caudal);
            lcd_puts(buffer);   
        
        }
 
 }


Can anyone help?
Sorry for the bad English.
 
Last edited by a moderator:

Try this


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
/*****************************************************************************
** Function name:   read_adc    
**
** Descriptions:    makes an ADC measurment in the specified channel
**                  
** parameters:      unsigned char adc_input: channel number
** Returned value:  unsigned int: returns 0-1023
** 
*****************************************************************************/
unsigned int read_adc(unsigned char adc_input)
{
    // clear the channel bits ane set the new channel
    ADMUX =  (ADMUX & 0xF8) | adc_input;
    // 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);
 
    // Clear conversion completed flag
    ADCSRA |= 0x10;
 
    // return result
    return ADCW;
}

 

Thank you for your answer,but how i will know what port its being used to read the values? Because i have to show on the LCD the values that i'm reading from 3 diferents sensors,like this
LCD:"
Sensor_1 = Value a
Sensor_2 = Value b
Sensor_3 = Value c "
I'm using 3 sensors that give me 0-5v ,and i want to convert that values using the ADC ports..

PS:sorry i dind know that,i thought i was on the righ section .
 

call the read adc function using as parameter 0,1,2... for input 0,1,2 etc
 

ohhh,ok..Thank you very much to both of you.

Best compliments.
 

Lool sorry,this is not my day!
 

I noticed that you are using a mcu model with PORTC and this is the port which has the JTAG pins in AVR.

Make sure that you have disabled JTAG or you may get some very strange results for PORTC pins
 

I tried this way but it didn't work :

Code:
#define F_CPU 1000000 // define a frequencia do Atmega em 10MHZ
#include "lcd.h"// inclui a biblioteca do LCD no projecto
#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h>
#include <util/delay.h>
//#include<avr/interrupt.h>





unsigned char leitura_AD_1,leitura_AD_2,leitura_AD_3,flag=0;

void inic_hardware(void);

void inic_hardware(void)
{

  

	DDRC = 0b00000001;			// Port D pin 0 ouput 
	DDRB = 0b00001000;
	DDRC = 0b11100000;
	PORTD= 0b00000010;
		
	SREG=0b10000000; // INT GLOBAL	
  

	TCCR2A=0b10000011; 		//Modo Fast PWM, Clear OC2A on Compare Match ,para a intensidade do LED
    TCCR2B=0b00000010; 



}
//char ler_AD(void)
/*{
	ADMUX=0b00100000;
	ADCSRA=0b11001011;		 //Inicia a conversão
	if(flag==1)
	{
		
		while(ADCSRA==0b11001011);  //Espera o fim da conversão
		
	}

	return(leitura_AD_1);

	flag=2;
	ler_AD1();

}*/
unsigned int read_adc(unsigned char adc_input)
{
    // clear the channel bits ane set the new channel
    ADMUX =  (ADMUX & 0xF8) | adc_input;
    // 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);
 
    // Clear conversion completed flag
    ADCSRA |= 0x10;
 
    // return result
    return ADCW;
}

/*ISR(ADC_vect)
{
//	flag=1;
//	leitura_AD_1=ADCH;		//Leitura de 8 bits
//	leitura_AD_2=ADCH;
	//leitura_AD_3=ADCH;
}*/

int main(void)
{	
	//inicializacao do hardware.
	int a=0,b=0,v_caudal=0;
	unsigned char sw=0; // variavel para o switch
	inic_hardware(); // inicializa o hardware
	lcd_init(LCD_DISP_ON); // inicializa o display
	lcd_clrscr(); // limpa o ecra
	sw=PORTD&0b00000000; // define o botão switch que corresponde ao PORTD pino 2
	


char buffer[30]; // buffer para utilizar no envio de msg para o LCD


while(1) // ciclo infinito
		{
		
			a=read_adc(0);
			b=read_adc(1);
			OCR2A=a;
			OCR1B=b;
			v_caudal=a;
			
			//OCR2A=140; // coloca o OCR2A a 0,o que faz com que o LED esteja desligado
		
			lcd_gotoxy(0,0); // faz com que os caracteces sejam escritos na primeira posição do LCD
			lcd_puts("Volcaudal:");
			lcd_gotoxy(16,0);
			lcd_puts(" l\s ");
			lcd_gotoxy(11,0); // faz com que os carateres sejam escritos na linha de baixo
			sprintf(buffer,"%d",v_caudal);
			lcd_puts(buffer);	
		
	 	}

 }

Can you tell where is the problem?
thank you.

PLEASE USE CODE TAGS

- - - Updated - - -

How do i do that?I'm kind a "noob".
 
Last edited by a moderator:

I don't know what the program is supposed to do, I don't know what mcu you are using and I have no idea what "doesn't work" means.
Just saw it in the title, mega88

The ADC function I have provided is fine for 10bit right shifted result but in your code you are using left shifted result so you should only read the ADCH
Code:
ADMUX=0b00100000;

Try with this function that works for left shifted result
Code:
/*****************************************************************************
** Function name:   read_adc8
**
** Descriptions:    makes an ADC measurment in the specified channel and returns the 8bit result 
**					the ADC should be set to left shifted result
**
** parameters:      unsigned char adc_input: channel number
** Returned value:  unsigned char: returns 0-255
** 
*****************************************************************************/
unsigned char read_adc8(unsigned char adc_input)
{
    // clear the channel bits ane set the new channel
    ADMUX =  (ADMUX & 0xF8) | adc_input;
    // 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);
 
    // Clear conversion completed flag
    ADCSRA |= 0x10;
 
    // return result
    return ADCH;
}
 

The mcu i'm using is the Atmega88, with 28 pins, and i use the PORTC for the ADC pins:23->PC0 (ADC0/PCINT8);24->PC1 (ADC1/PCINT9) 25->PC2 (ADC2/PCINT10);
The point of this project is to read from those 3 ports values from 3 different sensors , and show them in the LCD.
What i mean with the "doesn't work",is that i cant read the values with that function that you gave me :\.
See if you can see any mistake on my current code :

Code:
#define F_CPU 1000000 // Define: Clock Freq->10MHZ
#include "lcd.h"// LCD library 
#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h>
#include <util/delay.h>
//#include<avr/interrupt.h>





unsigned char leitura_AD_1,leitura_AD_2,leitura_AD_3,flag=0;

void inic_hardware(void);

void inic_hardware(void)
{

  

	DDRC = 0b00000001;			// Port D pin 0 ouput 
	DDRB = 0b00001000;
	DDRC = 0b11100000;
	PORTD= 0b00000010;
		
	SREG=0b10000000; // INT GLOBAL	
  

	TCCR2A=0b10000011; 		//Modo Fast PWM, Clear OC2A on Compare Match ,para a intensidade do LED
    TCCR2B=0b00000010; 



}

unsigned char read_adc8(unsigned char adc_input)
{
if(flag==1)
	{
    // clear the channel bits ane set the new channel
    ADMUX =  (ADMUX & 0xF8) | adc_input;
    // 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);
 
    // Clear conversion completed flag
    ADCSRA |= 0x10;
 	}
    // return result
    return ADCH;
	flag=0;
}

ISR(ADC_vect)
{
	flag=1;

}

int main(void)
{	
	//inicializacao do hardware.
	int a=0,b=0,c=0,v_caudal=0;
	inic_hardware(); //  hardware initialization 
	lcd_init(LCD_DISP_ON); // display  initialization 
	lcd_clrscr(); // clear screen
	
	


char buffer[30]; // buffer to send the values to LCD

while(1) 
		{
		
			a=read_adc8(0);// values from the PC0
			b=read_adc8(1);// values from the PC1
                        c=read_adc8(2);// values from the PC2
			OCR2A=a;
			OCR1B=b;
			v_caudal=a;
			
			//OCR2A=140; // coloca o OCR2A a 0,o que faz com que o LED esteja desligado
		
			lcd_gotoxy(0,0); // faz com que os caracteces sejam escritos na primeira posição do LCD
			lcd_puts("Volcaudal:");
			lcd_gotoxy(16,0);
			lcd_puts("l\s ");
			lcd_gotoxy(11,0); // faz com que os carateres sejam escritos na linha de baixo
			sprintf(buffer,"%d %d %d",a,b,c);
			lcd_puts(buffer);	
		
	 	}

 }

Thank you.
 

When I gave you the function the following line was not there
Code:
unsigned char read_adc8(unsigned char adc_input)
{
[COLOR="#FF0000"][B]if(flag==1)[/B][/COLOR]
	{
    // clear the channel bits ane set the new channel
    ADMUX =  (ADMUX & 0xF8) | adc_input;
    // 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);
 
    // Clear conversion completed flag
    ADCSRA |= 0x10;
 	}
    // return result
    return ADCH;
	flag=0;
}

That makes the function useless
 

Yes and no,because i'm using interrupts,so when is generated an interrupt by the mcu that flag is equal 1.But the program wont work with or without the flag.
I set it this way now :
(this code doesn't work either )
Code:
#define F_CPU 1000000 // define a frequencia do Atmega em 10MHZ
#include "lcd.h"// inclui a biblioteca do LCD no projecto
#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h>
#include <util/delay.h>
//#include<avr/interrupt.h>





unsigned char a=0,b=0,c=0,flag=0;

void inic_hardware(void);

void inic_hardware(void)
{

  

	DDRC = 0b00000001;			// Port D pin 0 ouput 
	DDRB = 0b00001000;
	DDRC = 0b11100000;
	PORTD= 0b00000010;
		
	SREG=0b10000000; // INT GLOBAL	
  

	TCCR2A=0b10000011; 		//Modo Fast PWM, Clear OC2A on Compare Match ,para a intensidade do LED
    TCCR2B=0b00000010; 



}
//char ler_AD(void)
/*{
	ADMUX=0b00100000;
	ADCSRA=0b11001011;		 //Inicia a conversão
	if(flag==1)
	{
		
		while(ADCSRA==0b11001011);  //Espera o fim da conversão
		
	}

	return(leitura_AD_1);

	flag=2;
	ler_AD1();

}*/
unsigned char read_adc8(unsigned char adc_input)
{

    // clear the channel bits ane set the new channel
    ADMUX =  (ADMUX & 0xF8) | adc_input;
    // 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);
 
    // Clear conversion completed flag
    ADCSRA |= 0x10;
 	
    // return result
    return ADCH;
	
}

ISR(ADC_vect)
{

	flag=1;
	if (flag==1)
		{
		a=read_adc8(0);
		b=read_adc8(1);
		c=read_adc8(2);
		flag=0;
		}

}

int main(void)
{	
	//inicializacao do hardware.
	int v_caudal=0;
	unsigned char sw=0; // variavel para o switch
	inic_hardware(); // inicializa o hardware
	lcd_init(LCD_DISP_ON); // inicializa o display
	lcd_clrscr(); // limpa o ecra
	sw=PORTD&0b00000000; // define o botão switch que corresponde ao PORTD pino 2
	


char buffer[30]; // buffer para utilizar no envio de msg para o LCD


while(1) // ciclo infinito
		{
		
		
			OCR2A=a;
			OCR1B=b;
			v_caudal=a;
			
			//OCR2A=140; // coloca o OCR2A a 0,o que faz com que o LED esteja desligado
		
			lcd_gotoxy(0,0); // faz com que os caracteces sejam escritos na primeira posição do LCD
			lcd_puts("Volcaudal:");
			lcd_gotoxy(16,0);
			lcd_puts("l\s ");
			lcd_gotoxy(11,0); // faz com que os carateres sejam escritos na linha de baixo
			sprintf(buffer,"%d",v_caudal);
			lcd_puts(buffer);	
		
	 	}

 }
 

Your ADC initialization is missing.
The function is just intended to start a conversion and return the result but the ADC should be setup first in your code

- - - Updated - - -

When you use an interrupt you read the result in the interrupt, you don't use the function I gave you

- - - Updated - - -

You also don't enable the global interrupt flag
Code:
// Global enable interrupts
sei();

- - - Updated - - -

You code is kind of a mess.
I suggest you forget the interrupt for now and use the function I gave you but call it after initializing the ADC
 

The SREG=0b10000000; does the same thing that sei();

With the function that you gave me , i only read values from 0 to 3, is it normal?And it only read values from the PC0...
 
Last edited:

The SREG=0b10000000; does the same thing that sei();

It is definitely the first time I see that style used to enable global interrupts.



With the function that you gave me , i only read values from 0 to 3, is it normal?And it only read values from the PC0...
The function I gave you starts a conversion ,waits to be completed and returns the result , every line is commented.
What do you mean by normal, the function converts one channel every time you call it , it is up to you to use 1 or 5 channels
 

Well i finally did it,but as said before it gives small values ,i don't understand ,i tough that would give me values from 0 to 255 :\ and it only read values from 0 to 3 ..
I use SREG in assembly,thats why u dont recognized .
 

Code:
#define F_CPU 1000000 // define a frequencia do Atmega em 10MHZ
#include "lcd.h"// inclui a biblioteca do LCD no projecto
#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h>
#include <util/delay.h>
#include<avr/interrupt.h>



unsigned char a=0,b=0,c=0,leitura,flag=0;

void inic_hardware(void);



void inic_hardware(void)
{

  

	DDRC = 0b00000001;			// Port D pin 0 ouput 
	DDRB = 0b00001000;
	DDRC = 0b11100000;
	PORTD= 0b00000010;
	sei();   		//Activa interrupções globais
	


	OCR2A=0; 			//Inicialização do OCR2A com 0
	OCR1B=0;
	OCR0A=0;
  

	TCCR2A=0b10000011; 		//Modo Fast PWM, Clear OC2A on Compare Match ,para a intensidade do LED
    TCCR2B=0b00000010; 



}
unsigned char ler_AD(unsigned char adc_input)
{
	ADMUX=(ADMUX & 0xF8) | adc_input;
	ADCSRA=0b11001011;
	ADCSRA |= 0x40;		 
	_delay_us(10);
	if(flag==1)
	{
		
		while(ADCSRA==0b11001011);  //Espera o fim da conversão
	
	}

	return ADCH;

	flag=0;


}

ISR(ADC_vect)
{

	flag=1;
	leitura=ADCH;
	
}

int main(void)
{	
	//inicializacao do hardware.
	int v_caudal=0,v_caudal_1=0;
	//adc_init();
	inic_hardware(); // inicializa o hardware
	lcd_init(LCD_DISP_ON); // inicializa o display
	lcd_clrscr(); // limpa o ecra
	
	


char buffer[30]; // buffer para utilizar no envio de msg para o LCD


while(1) // ciclo infinito
		{
			a=ler_AD(0);
			b=ler_AD(1);
			OCR2A=a;// turn the LED on with the values of the ADC
			OCR1A=b;// turn the LED on with the values of the ADC
			v_caudal=a*10;
			v_caudal_1=b*10;
			
			//OCR2A=140; // coloca o OCR2A a 0,o que faz com que o LED esteja desligado
		
			lcd_gotoxy(0,0); // faz com que os caracteces sejam escritos na primeira posição do LCD
			lcd_puts("Volcaudal:");
			lcd_gotoxy(16,0);
			lcd_puts("ls ");
			lcd_gotoxy(11,0); // faz com que os carateres sejam escritos na linha de baixo
			sprintf(buffer,"%d",v_caudal);
			lcd_puts(buffer);	
			lcd_gotoxy(11,1); // faz com que os carateres sejam escritos na linha de baixo
			sprintf(buffer,"%d",v_caudal_1);
			lcd_puts(buffer);	
		
	 	}

 }
 

Unlike the previous code now you are using a right shifted result so refer to https://www.edaboard.com/threads/274660/#post1177732 that returns ADCW

- - - Updated - - -

I have no idea what is the point of using an ADC interrupt since all you do is wait in the ADC function for the interrupt to write a flag in order to read the result.
That is exactly what my function does without the need for any interrupt or flag variable.

Also initialize the ADC just once when the execution starts, not each time you call the ADC function.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top