PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : adc-wert regelmässig auslesen mit interrupt



pebisoft
04.08.2005, 19:23
hallo, am adc-0 (avr16) wird durch ein rad-encoder immer ein wert zwischen 60 und 240 ausgegeben. beim wert unter 100 soll die variable hochgezählt werden und bei einem wert über 200 soll die variable hochgezählt werden.
kann keine lösung über interrupt finden.
mfg pebisoft

izaseba
04.08.2005, 19:38
Und wo liegt das Problem?
Mach einen freilauf ADC, und werte in der Interruptroutine die Werte aus. Bei Bedarf kann ich Dir ein Codeschnipsel schicken,
Gruß Sebastian

pebisoft
04.08.2005, 19:51
was ist ein freilauf-adc . komme mit dieser adc-auswertung im interrupt nicht klar.
mfg pebisoft

izaseba
04.08.2005, 20:14
Ganz einfach :

Freilauf ADC -> der wert wird ständig ausgelesen
Ich weiß zwar nicht in welcher Sprache Du progst, aber ich mach es so in Assembler:

ldi tmp,(1<< ADEN) | (1<<ADFR) | (1<<ADIE) | (1<<ADSC) | (1<<ADPS0) | (1<<ADPS1) | (1<<ADPS2)
out ADCSRA,tmp
ldi tmp,(1<<REFS0) | (1<<ADLAR) | (1<<MUX0)
out ADMUX,tmp

Der ADFR bit schaltet Free Run modus ein.

Du mußt Dir auch noch den passenden Interruptvektor einrichten


.org ADCCaddr
rjmp ADCcomplete ; ADC Interrupt Vector Address


Jetzt Springt er nachdem er jedesmal fertig ist mit ADC nach ADCcomplete

in ADCcomplete routine:


in tmp,ADCL
in tmp,ADCH


Es wird zwar der LOW Byte überschrieben, das macht aber nichts weil der wert linksgerichtet ist (sehe ADLAR Bit in ADMUX) und die zwei unteren bits kann man ruhig hier weglassen.

Jetzt prüfst Du den Wert in tmp nach Deinen >100 oder <200 und änderst den Zähler entsprechend.
Zum schluß reti und fertig.

Hoffe, daß es verständlich war, wenn Du C benutzt wird es wohl auch kein Problem sein die Assembler schnipsel zu verstehen.

Gruß Sebastian

pebisoft
04.08.2005, 20:35
ich progge in winavr-c.
mfg pebisoft

izaseba
04.08.2005, 20:57
ich progge in winavr-c.

Dann ist das wohl kein Problem das von mir geschriebene umzusetzen.

mach doch etwa so :


ADCSRA=(1<< ADEN) | (1<<ADFR) | (1<<ADIE) | (1<<ADSC) | (1<<ADPS0) | (1<<ADPS1) | (1<<ADPS2);
ADMUX = (1<<REFS0) | (1<<MUX0);



Der Interrupthandler


SIGNAL (SIG_ADC) {
int result;
result = ADCL + (ADCH << 8);
if (result < 100){
zaehler++;
} else if (result > 200) {
zaehler--;
}
}


Dein Zähler muß Du nur volatile Deklarieren, damit er im Interrupt auch zugänglich ist.
Naja und sonstige headers nicht vergessen (signal.h interrupt.h)

Ich hoffe, daß es Dir weiterhilft

Gruß Sebastian

pebisoft
04.08.2005, 21:29
sag mal : 1<<ADFR kennt er nicht, gibt es für ADFR noch einen anderen ausdruck.
"adc_lcd.c:44: error: `ADFR' undeclared (first use in this function)"
mfg pebisoft

izaseba
04.08.2005, 21:47
Ein Auszug aus meiner iom16.h :


#define ADCSRA _SFR_IO8(0x06)
#define ADPS0 0
#define ADPS1 1
#define ADPS2 2
#define ADIE 3
#define ADIF 4
#define ADATE 5
#define ADSC 6
#define ADEN 7


Der ADFR ist dabei Bit Nr. 5 also muß es heissen (1<<ADATE) und nicht (1<<ADFR)

Komisch, warum das so ist weiß ich nicht, ich dachte, daß wäre 1:1 von den Bits des AVR´s
übernommen.
Ist es ein Bug, oder warum haben sie den Namen geändert ?
Na ja versuch es mit ADATE

Gruß Sebastian


EDIT:

Ups, stimmt alles nicht so ganz, also :
es gibt wirklich kein ADFR bei MEGA 16 sondern ADATE:


Bit5 - ADATE: ADC Auto Trigger Enable
When this bit is writen to one Auto Triggering of the ADC is enabled.


also ADATE doch einschalten


Und wann er dann Triggerd bestimmt der Register SFIOR
Für Free Running mode sieht es dann so aus

SFIOR &= ~(1<<ADTS0) | (1<<ADTS1) | (1<<ADTS2);

Sehe auch Dattenblatt Seite 215.
Damit hast Du den Free Running eingeschaltet.

Ich habe es mit Dattenblatt von Mega 8 verglichen, wußte nicht, daß sie das bei Mega 16
sooooo verändert haben #-o

pebisoft
04.08.2005, 22:44
hallo, funktioniert klasse, vielen dank für deine schnelle hilfe.
mfg pebisoft
ps:
Und wann er dann Triggerd bestimmt der Register SFIOR
Für Free Running mode sieht es dann so aus
SFIOR &= ~(1<<ADTS0) | (1<<ADTS1) | (1<<ADTS2);

was ist das.
habe es nicht eingesetzt, es läuft trotzdem automatisch mit dem interrupt.

izaseba
04.08.2005, 22:48
O:) Freut mich.

Gruß Sebastian

izaseba
04.08.2005, 23:30
SFIOR &= ~(1<<ADTS0) | (1<<ADTS1) | (1<<ADTS2);

was ist das.
habe es nicht eingesetzt, es läuft trotzdem automatisch mit dem interrupt.

Es wird so sein:

Alle Register haben beim einschalten den Wert 0x00

und
SFIOR &= ~(1<<ADTS0) | (1<<ADTS1) | (1<<ADTS2);
setzt die Bits ADTS0 ADTS1 ADTS2 auf null.

Mithin setzt Du null auf null, ist zwar blöd, aber ich mach es immer so, man weiß ja nie,
und außerdem sieht man im Programm daß die Bits auf Null stehen müssen um Freerun einzuschalten.

Deswegen wird es auch ohne diese Zeile Funktionieren.

Gruß Sebastian

pebisoft
17.08.2005, 07:24
ich möchte auch zu dem radencoder an mux1(adc2) noch 2 weitere adc auslesen und zwar für 2x sharpsensoren (sind an adc0 und adc1).
was muss in der main() in dem aufruf geändert werden und was in der signal-routine, oder kann man die 2xsharp auch ohne signal(sig_adc) abfragen, nur in der main() mit dem jetzigen code.

SIGNAL (SIG_ADC)
{
ADMUX = (1<<REFS0) | (1<<MUX1);
adc2_wert = ADC;
if ((adc2_wert >400) &&( toggle==1))
{
radzaehler++;
toggle=0;
}
if ((adc2_wert <100) &&( toggle==0))
{
radzaehler++;
toggle=1;
}
}



int main(void)
{

cli();
ADCSRA=(1<< ADEN) | (1<<ADATE) | (1<<ADIE) | (1<<ADSC) |
(1<<ADPS0) | (1<<ADPS1) | (1<<ADPS2);
sei();
}

sep
17.08.2005, 07:51
Lies das verdammte Handbuch! Da steht dass alles haarklein drin :)

SIGNAL (SIG_ADC)
{
ADMUX = (1<<REFS0) | (1<<MUX...);

immer schön das MUX anpassen, je nachdem was du auslesen willst.

Allerdings braucht der A/D -Wandler u.U. noch einen (bereits begonnenen) Zyklus bis der Kanal umgeschalten wird.
Aber ich meine mich erinnern zu können, dass der Kanal sofort umgeschalten wird, wenn der alte Wandel-Zyklus noch nicht beendet ist (ADC noch nicht ausgelesen)

pebisoft
21.08.2005, 11:12
hallo :
#define ADMUX _SFR_IO8(0x07)
#define MUX0 0
#define MUX1 1
#define MUX2 2
#define MUX3 3
#define MUX4 4
#define ADLAR 5
#define REFS0 6
#define REFS1 7

mux4 ist demnach der 6. pin von adca , wie spreche ich den 7. und 8. pin von adca an.
mfg pebisoft

linux_80
21.08.2005, 12:14
Hi,
gelegentlich hilft es ins Datenblatt zu guggen,
in diesem nach dem Register ADMUX zu suchen,
die folgenden Zeilen beschreiben die Verwendung von MUX0..4

HTH