PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : AD-Wandlung mehrerer Kanäle



FSTII
20.11.2006, 18:52
Hallo zusammen,

nachdem ich mittlerweile schon einige Zeit in Foren und Tutorien verbracht habe, habe ich jetzt versucht ein Programm zur AD-Wandlung zu schreiben.

Hier der Code:


#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/delay.h>

volatile uint16_t ADCRaw = 0;

SIGNAL(SIG_ADC)
{
ADCRaw = ADC;

ADCSRA |= (1 << ADSC);

}

void Init_ADC(void)
{
DDRF &= ~(1<<DDF0);
PORTF |= (1<<PF0);

ADMUX = (1<<REFS1);

ADCSRA = (1<<ADEN)|(1<<ADSC)|(1<<ADIF)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);

ADCSRA |= (1 << ADSC);

sei();

}

void Init_Output(void)
{

DDRA = (1<<DDA0);
}

int main (void)
{
Init_Output();
Init_ADC();

while (1)
{
if(ADCRaw >= 512)
{
PORTA = (1<<PB0);
}
else
{
PORTA &= ~(1<<PB0);
}

}

return 0;
}





Allerdings wird hier nur ein Eingang gemessen. Da ich eigentlich einen Beschleunigungssensor auslesen will, müsste ich aber drei Kanäle nacheinander einlesen und die Ergebnisse auch getrennt voneinander ausgeben können.
Kann mir da jemand einen Tipp geben wie das zu realisieren ist, da ich noch nichts dazu gefunden habe was mir wirklich weiterhilft.

Gruß Matthias

SprinterSB
21.11.2006, 11:55
Eigentlich genau so wie du es jetzt hast. In der ADC-ISR verbindest du den ADC mit dem Port, den du samplen willst. Die Verbindung wird hergestellt über den ADC Input-Multiplexer. Anstatt ein Wert adc_raw gibt es dann eben (z.B) ein Array adc_raw[3], das die gesampleten Werte transportiert.

Noch was. Den Zugriff auf adc_raw in deinem Hauptprogramm hast du atomar? Falls nicht, liest du u.U unsinnige Werte.

FSTII
21.11.2006, 18:06
Den Zugriff auf adc_raw in deinem Hauptprogramm hast du atomar?

Wie müsste ein atomarer Zugriff denn aussehen? Da ich mich erst seit kurzem mit der Programmierung beschäftige kann ich damit nicht viel anfangen.
Wenn ich das in einem anderen Beitrag richtig verstanden habe, folgendermaßen:


volatile uint16_t ADC_raw;

SIGNAL (SIG_ADC)
{
ADC_raw = ADC;
}

// Lesen:
...
uint16_t wert;

wert = adc_wert;
...
if (wert >= 512)
...


oder habe ich da was falsch verstanden?

Gruß Matthias

SprinterSB
21.11.2006, 18:26
Lies mal
https://www.roboternetz.de/wissen/index.php/Fallstricke_bei_der_C-Programmierung#Nicht-atomarer_Code

FSTII
22.11.2006, 14:44
Man muss halt immer erst mal wissen, wonach man suchen soll.



Eine Möglichkeit dem zu begegnen ist, den ganzen betroffenen Block ununterbrechbar (atomar) zu machen. Oder je nach Programmstruktur sichert man den Wert, z.B. in eine lokale Variable ...


...was doch dann in etwa so aussieht, wie oben beschrieben?


Gruß Matthias

SprinterSB
22.11.2006, 15:54
// Lesen:
...
uint16_t wert;
...
{
uint8_t sreg = SREG;
wert = adc_wert;
SREG = sreg;
}
...
if (wert >= 512)
...