PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Problem mit wiederholter ADC Abfrage



the_Ghost666
27.05.2010, 22:29
Moin zusammen.

Ich habe mir eine Platine gemacht, auf der ein Atmega8L sitzt, der mit einem 8Mhz Quarz getaktet ist und mit 3,3V versorgt wird. Die AVCC ist wie im Datenblatt stabilisiert und auf der anderen Seite hab ich ein Bluetoothmodul, was Daten über USART an einen PC sendet und empfängt.
Nun das Problem:
Ich lasse in einer Endlosschleife das Hauptprogramm ohne Interrupts laufen.
Ich habe sowohl eine automatische Abfrage alle X ms, als auch eine gesteuerte probiert, die den ADC nur dann ausliest, wenn vorher ein Zeichen emfangen wurde. Bei beiden Varianten ist das Verhalten so, dass scheinbar die erste Wandlung nach einem Reset erfolgreich ist. Jedoch führt jede weitere Wandlung unabhängig von der Spannung immer zum gleichen Wert wie dem Ersten. Stelle ich das Poti auf einen Wert, und resete ich, stimmt das Ergebnis, verstelle ich das Poti dann im Betrieb ändert sich nichts.

Ich habe bereits Probleme beim USART, beim sprintf und bei der speicherung von ADCL und ADCH in ein INT geprüft, das klappt alles.
Hat jemand eine Idee, was hier schief geht und warum sich die Werte nicht ändern?


#ifndef F_CPU
#define F_CPU 8000000
#endif




#include <avr/io.h> //General IO Functions
#include <avr/eeprom.h> //EEProm Access Functions
#include <util/delay.h> //Delay Loops
#include <avr/interrupt.h>
#include <stdio.h>
#include "USART_lib.h"

#define LEDGreen PB1
#define LEDRed PB2
#define EDA_CHANNEL 0


void Init(void); //Init the hardware
void Init_ADC(void);
int getADC(char channel);

void setLEDGreen(char STATE);
void toggleLEDGreen(void);

void setLEDRed(char STATE);
void toggleLEDRed(void);

char Message[20];
int test=1234;

int main (void){
Init();

while(1){
// sprintf(&Message[0],"%u;\r\n",getADC(2));

// USART_String(&Message[0]);

USART_Receive();
test= getADC(2);
USART_Send(test>>8);
USART_Send(test & 0xFF);
// USART_String(&Message[0]);

setLEDGreen(0);
_delay_ms(150);
setLEDGreen(1);
_delay_ms(150);


}
return 0;
}


void Init(){
DDRB |=(1<<LEDGreen)|(1<<LEDRed); //LEDs off
PORTB &= ~(1<<LEDGreen)|(1<<LEDRed);

USART_Init();
Init_ADC();

// DDRC &=~ (1<<EDA_CHANNEL);
// PORTC &=~(1<<EDA_CHANNEL);

// DDRC &=~ (1<<PC2);
// PORTC &=~(1<<PC2);

DDRC |= (1<<PC1);
PORTC|=(1<<PC1);

DDRC |= (1<<PC3);
PORTC|=(1<<PC3);

}


void Init_ADC(void){
ADMUX = 0x40;
ADCSRA = 0x80; //not Free Running, max prescaler and on
}

int getADC(char channel){
ADMUX = 0x40 | (0x0F & channel);
_delay_ms(1);
ADCSRA |= (1<<ADSC);
_delay_us(1);
while((ADCSRA & (1<<ADSC))!=0);

return ADCH*256 + ADCL;
}

void setLEDGreen(char STATE){
if(STATE != 0)
PORTB |= (1<<LEDGreen);
else
PORTB &= ~(1<<LEDGreen);
}

void setLEDRed(char STATE){
if(STATE != 0)
PORTB |= (1<<LEDRed);
else
PORTB &= ~(1<<LEDRed);
}

void toggleLEDGreen(void){
PORTB ^= (1<<LEDGreen);
}

void toggleLEDRed(void){
PORTB ^= (1<<LEDRed);
}

sternst
27.05.2010, 23:01
return ADCH*256 + ADCL;Bei einem solchen Konstrukt ist in keiner Weise sichergestellt, dass die beiden Register in der richtigen Reihenfolge gelesen werden. Mach daraus einfach ein simples "return ADCW;".

the_Ghost666
28.05.2010, 05:59
Ah! VIELEN VIELEN DANK! Das scheint das Problem gelöst zu haben!
Jetzt wo ich weiß was das Problem ist, finde ich auch die Passage im Datenblatt, die darüber eine Aussage macht.