Christoph2
19.09.2009, 14:37
Hallo!
Ich schreibe gerade ein Programm, das die Lichtstärke und die Luftfeuchtigkeit misst uns sie auf einem Display anzeigt.
Es funktioniert problemlos, wenn man nur eine der beiden größen ausliest. Sobald ich aber beide hintereinander auslese und anzeige, funktioniert es aber nichtmehr. Er zeigt dann für beide größen den selben Wert an, den er von einem eingang ermittelt.
Der verwendete Controller ist ein Mega8 mit 4 Mhz. Die ADC-Pins sind auf Port C. An die ADC-Pins 0 und 1 habe ich je ein Poti angeschlossen.
Hier ist mein code:
#include <avr/io.h>
#include <stdlib.h>
#include <stdint.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <uart.h>
#include <avr/pgmspace.h>
#include <pwm.h>
#include <lcd.h>
#include <i2cmaster.h>
#include <uart.h>
uint16_t adc(uint8_t);
void lcd_var16(uint16_t);
int main(void)
{
DDRB |= (1<<1) | (1<<2) | (1<<4); // B1, B2, B4 auf Ausgang
DDRC=0x00;
uint16_t lichtstaerke_a;
uint16_t feuchtigkeit;
lcd_init(LCD_DISP_ON);
while(1) // Beginn der Hauptschleife
{
lcd_clrscr();
lcd_gotoxy(0,0);
lcd_puts("Hallo Welt");
lichtstaerke_a = adc(0);
lcd_gotoxy(15,0);
lcd_var16(lichtstaerke_a);
feuchtigkeit = adc(1);
lcd_gotoxy(15,1);
lcd_var16(feuchtigkeit);
_delay_ms(300);
} // Ende der Hauptschleife (Endlosschleife)
return 0;
}
//################################################## ##############################################
uint16_t adc(uint8_t mux)
{
uint8_t i;
uint16_t result;
ADMUX |= (mux & 0b00000111); // Kanal waehlen
ADMUX &= ~(1<<REFS0);
ADMUX |=(1<<REFS1);
//Frequenzvorteiler setzen auf 32 und ADC aktivieren
ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS0);
ADCSRA &=~ (1<<ADPS1);
// Dummy-readout
ADCSRA |= (1<<ADSC); // eine ADC-Wandlung
while ( ADCSRA & (1<<ADSC) )
{ ; // auf Abschluss der Konvertierung warten
}
result = ADCW;
//----------------------------------------------------------------------------
// Eigentliche Messung - Mittelwert aus 2 aufeinanderfolgenden Wandlungen
result = 0;
for( i=0; i<4; i++ )
{ ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
while ( ADCSRA & (1<<ADSC) )
{; // auf Abschluss der Konvertierung warten
}
result += ADCW; // Wandlungsergebnisse aufaddieren
}
ADCSRA &= ~(1<<ADEN); // ADC deaktivieren
result /= 4; // Summe durch 10 teilen = arithm. Mittelwert
return result;
}
//################################################## ##############################################
void lcd_var16(uint16_t var)
{
char buffer[5]; // array für Zeichen definieren
uint8_t i;
for(i=0; i<5; i++)
{ buffer[i]=0;
}
itoa(var, buffer, 10); // int in einen String umwandeln (zur Basis 10 -> dezimal)
lcd_puts(buffer); // char ausgeben
}
An der Ausgabe am Display und der umwandlung ing->string kann es nicht liegen, wenn ich nämlich statt adc(0); und adc(1); zwei zahlen hinschreibe, stehen auch die richtigen zahlen am Display.
Mir ist außerdem aufgefallen, dass nach einem reset ganz kurz die beiden richtigen werte am display aufblitzen, danach nimmt der zweite wert aber automatisch den wert des anderen adc wertes an und beide haben den selben wert...
Kann es sein dass man bei der Umschaltung zwischen den ADC Kanälen irgendetwas beachten muss?
lg Christoph
Ich schreibe gerade ein Programm, das die Lichtstärke und die Luftfeuchtigkeit misst uns sie auf einem Display anzeigt.
Es funktioniert problemlos, wenn man nur eine der beiden größen ausliest. Sobald ich aber beide hintereinander auslese und anzeige, funktioniert es aber nichtmehr. Er zeigt dann für beide größen den selben Wert an, den er von einem eingang ermittelt.
Der verwendete Controller ist ein Mega8 mit 4 Mhz. Die ADC-Pins sind auf Port C. An die ADC-Pins 0 und 1 habe ich je ein Poti angeschlossen.
Hier ist mein code:
#include <avr/io.h>
#include <stdlib.h>
#include <stdint.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <uart.h>
#include <avr/pgmspace.h>
#include <pwm.h>
#include <lcd.h>
#include <i2cmaster.h>
#include <uart.h>
uint16_t adc(uint8_t);
void lcd_var16(uint16_t);
int main(void)
{
DDRB |= (1<<1) | (1<<2) | (1<<4); // B1, B2, B4 auf Ausgang
DDRC=0x00;
uint16_t lichtstaerke_a;
uint16_t feuchtigkeit;
lcd_init(LCD_DISP_ON);
while(1) // Beginn der Hauptschleife
{
lcd_clrscr();
lcd_gotoxy(0,0);
lcd_puts("Hallo Welt");
lichtstaerke_a = adc(0);
lcd_gotoxy(15,0);
lcd_var16(lichtstaerke_a);
feuchtigkeit = adc(1);
lcd_gotoxy(15,1);
lcd_var16(feuchtigkeit);
_delay_ms(300);
} // Ende der Hauptschleife (Endlosschleife)
return 0;
}
//################################################## ##############################################
uint16_t adc(uint8_t mux)
{
uint8_t i;
uint16_t result;
ADMUX |= (mux & 0b00000111); // Kanal waehlen
ADMUX &= ~(1<<REFS0);
ADMUX |=(1<<REFS1);
//Frequenzvorteiler setzen auf 32 und ADC aktivieren
ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS0);
ADCSRA &=~ (1<<ADPS1);
// Dummy-readout
ADCSRA |= (1<<ADSC); // eine ADC-Wandlung
while ( ADCSRA & (1<<ADSC) )
{ ; // auf Abschluss der Konvertierung warten
}
result = ADCW;
//----------------------------------------------------------------------------
// Eigentliche Messung - Mittelwert aus 2 aufeinanderfolgenden Wandlungen
result = 0;
for( i=0; i<4; i++ )
{ ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
while ( ADCSRA & (1<<ADSC) )
{; // auf Abschluss der Konvertierung warten
}
result += ADCW; // Wandlungsergebnisse aufaddieren
}
ADCSRA &= ~(1<<ADEN); // ADC deaktivieren
result /= 4; // Summe durch 10 teilen = arithm. Mittelwert
return result;
}
//################################################## ##############################################
void lcd_var16(uint16_t var)
{
char buffer[5]; // array für Zeichen definieren
uint8_t i;
for(i=0; i<5; i++)
{ buffer[i]=0;
}
itoa(var, buffer, 10); // int in einen String umwandeln (zur Basis 10 -> dezimal)
lcd_puts(buffer); // char ausgeben
}
An der Ausgabe am Display und der umwandlung ing->string kann es nicht liegen, wenn ich nämlich statt adc(0); und adc(1); zwei zahlen hinschreibe, stehen auch die richtigen zahlen am Display.
Mir ist außerdem aufgefallen, dass nach einem reset ganz kurz die beiden richtigen werte am display aufblitzen, danach nimmt der zweite wert aber automatisch den wert des anderen adc wertes an und beide haben den selben wert...
Kann es sein dass man bei der Umschaltung zwischen den ADC Kanälen irgendetwas beachten muss?
lg Christoph