Hallo,
nachdem nun mein LCD mit Peter Fleurys LCD libary läuft möchte ich gerne die Tasten des RN_Control an PINA7 abfragen und die Werte des ADC ausgeben. Die Ergebnisse sind aber unsinnig. Was ist falsch die Umwandlung oder die Bestimmung des Wertes?
Code:
unsigned int taste = 0;
char tastestr[5];
for(;;)
{
while(taste == 0) {taste = Tastenabfrage();}
Soundirq (500,2000);
lcd_clrscr();
itoa(taste,tastestr,5);
lcd_puts (tastestr);
Sleep (2000);
Sleep (2000);
taste = 0;
}
und die Erhebung des Werts:
Code:
unsigned int Tastenabfrage (void)
{
unsigned char i;
unsigned char Tasternr = 0;
unsigned int Tasteradc = 0;
PORTA |= (1<<PA7); /* internen Pull-Up an PA7 aktivieren */
/*
ADCSRA (ADC Control and Status Register )
Bit
7 6 5 4 3 2 1 0
ADEN ADSC ADATE ADIF ADIE ADPS2 ADPS1 ADPS0 ADCSRA
Read/Write R/W R/W R/W R/W R/W R/W R/W R/W
Initial Value 0 0 0 0 0 0 0 0
ADEN enabeld (aktiviert) die AD- Wandlung
ADSC (ADC Start Conversion) Mit diesem Bit wird ein Messvorgang gestartet.
In der frei laufenden Betriebsart muss das Bit gesetzt werden, um die kontinuierliche
Messung zu aktivieren. Wenn das Bit nach dem Setzen des ADEN-Bits zum ersten Mal gesetzt
wird, führt der Controller zuerst eine zusätzliche Wandlung und erst dann die eigentliche
Wandlung aus. Diese zusätzliche Wandlung wird zu Initialisierungszwecken durchgeführt.
Das Bit bleibt nun so lange auf 1, bis die Umwandlung abgeschlossen ist,
im Initialisierungsfall entsprechend bis die zweite Umwandlung erfolgt ist und geht danach
auf 0.
ADFR (ADC Free Running Select)(ADATE: ADC Auto Trigger Enable) Mit diesem Bit wird die
Betriebsart eingestellt. Eine logische 1 aktiviert den frei laufenden Modus. Der ADC
misst nun ständig den ausgewählten Kanal und schreibt den gemessenen Wert in das
ADC Data Register.
ADIE (ADC Interrupt Enable) Wenn dieses Bit gesetzt ist und ebenso das I-Bit
im Statusregister SREG, dann wird der ADC-Interrupt aktiviert.
ADPS2 bis ADPS0 Der Frequenzvorteiler kennt die Bits ADPS0 bis ADPS2
Dabei sollte die Frequenz für AD-Wandlung zwischen 50Hz und 200HZ liegen.
Um den richtigen Vorteiler zu bestimmen teilt man die Freuquenz des Quarzes durch die
gewünschte AD-Wandler Frequenz und setzt die Bits ADPS0 bis ADPS2.
*/
ADCSRA = (1<<ADEN) | (1<<ADPS2)| (1<<ADPS1) | (1<<ADPS0); // Frequenzvorteiler hier: 128
/*
ADMUX ADC Multiplexer Select Register
Mit diesem Register wird der zu messende Kanal ausgewählt. Beim MEGA16/32 kann jeder
Pin von Port A als ADC-Eingang verwendet werden (=8 Kanäle). (PA 0 bis PA7 und ADC0 bis ADC7)
Das Register ist wie folgt aufgebaut:
Bit 7 6 5 4 3 2 1 0
REFS1 REFS0 ADLAR MUX4 MUX3 MUX2 MUX1 MUX0
Name - - - - - MUX2 MUX1 MUX0
R/W R R R R R R/W R/W R/W
Initialwert 0 0 0 0 0 0 0 0
REFS1 REFS0
Diese Bits stellen die Spannungsreferenz für die ADC ein. Wenn diese Bits
während der Umwandlung verändert werden, wird die Umwandlung nicht durchgeführt bis
die Einstellung abgeschlossen ist (ADIF in ADCSRA is set).
Die Einstelungsmöglichkeiten für die internen Refernzspannungen sollten nicht benutzt
werden, wenn eine externe Refernzspannungen am AREF pin angelgt ist.
REFS1 REFS0 Voltage Reference Selection
0 0 AREF, Internal Vref turned off
0 1 AVCC with external capacitor at AREF pin
1 0 Reserved
1 1 Internal 2.56V Voltage Reference with external capacitor at AREF pin
Bit 5 – ADLAR: ADC Left Adjust Result
Das ADLAR bit beeinflusst die Darstellung presentation des ADC Ergebnisser im
ADC Datenregister.
Wenn 1 in das ADLAR geschrieben wird, wird das Ergebnis linksbündig eingetragen.
Ansonsten wird das Ergebnis rechtsbündig geschrieben.
Die Veränderung des ADLAR Bits beinflusst das ADC Data Register sofort, ohne auf die
laufende Umwandlung zu beachten.
ADLAR = 0
Bit 15 14 13 12 11 10 9 8
– – – – – – ADC9 ADC8 ADCH
ADC7 ADC6 ADC5 ADC4 ADC3 ADC2 ADC1 ADC0 ADCL
ADLAR = 1
Bit 15 14 13 12 11 10 9 8
ADC9 ADC8 ADC7 ADC6 ADC5 ADC4 ADC3 ADC2 ADCH
ADC1 ADC0 – – – – – – ADCL
Mux4..0
Die Werte dieser Bits selects which combination of analog inputs are connected to the
ADC. These bits also select the gain for the differential channels. See Table 84 for
details. If these bits are changed during a conversion, the change will not go in effect
until this conversion is complete (ADIF in ADCSRA is set).
Die Bits MUX2...MUX0 werden für die einzelumwandlung Verwendet
Mit diesem 3 Bits wird der zu messende Kanal bestimmt. Es wird einfach die entsprechende
Pinnummer des Ports eingeschrieben. Wenn das Register beschrieben wird, während dem eine
Umwandlung läuft, so wird zuerst die aktuelle Umwandlung auf dem bisherigen Kanal beendet.
Dies ist vor allem beim frei laufenden Betrieb zu berücksichtigen.
Meine Empfehlung ist deswegen klar diese, dass der frei laufende Betrieb nur bei einem
einzelnen zu verwendenden Analogeingang verwendet werden sollte, wenn man sich Probleme
bei der Umschalterei ersparen will.
*/
ADMUX = (0<<MUX4) |(0<<MUX3) |(1<<MUX2) | (1<<MUX1) | (1<<MUX0);
/* Kanal waehlen hier Kanal 7 als single conversion */
ADMUX &= (0<<ADLAR); // Standard Ausrichtung
ADMUX &= (0<<REFS1) & (0<<REFS0); // Referenzspannung an AREF nutzen
/* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
ADCSRA |= (1<<ADSC); // eine ADC-Wandlung
while ( ADCSRA & (1<<ADSC) ); // auf Abschluss der Konvertierung warten
/* Nun wird die eigentliche Messung durchgeführt */
/* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
for(i=0;i<4;i++)
{
ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
while ( ADCSRA & (1<<ADSC) ); // auf Abschluss der Konvertierung warten
Tasteradc += ADCW; // Wandlungsergebnisse aufaddieren
/*
ADCL,ADCH ADC Data Register
Wenn eine Umwandlung abgeschlossen ist, befindet sich der gemessene Wert
in diesen beiden Registern. Von ADCH werden nur die beiden niederwertigsten
Bits verwendet. Es müssen immer beide Register ausgelesen werden und zwar immer
in der Reihenfolge: ADCL, ADCH. Der effektive Messwert ergibt sich dann zu:
x = ADCL; // mit uint16_t x
x += (ADCH<<8); // in zwei Zeilen (LSB/MSB-Reihenfolge und C-Operatorprioritaet
sichergestellt)
oder
x = ADCW; // je nach AVR auch x = ADC (siehe avr/ioxxx.h)
*/
}
ADCSRA &= ~(1<<ADEN); // ADC deaktivieren (2)
Tasteradc /= 4; // Summe durch vier teilen = arithm. Mittelwert
return Tasteradc;
}
kann jemand helfen?
Dnke
Gruß
Stefan
PS die Komentare stammen aus einem Tutorial das ich zum lernen und anpssen verwendet habe....
Lesezeichen