PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ATtiny26 ADC Problem (Wert über 1023)



HF SHOOTER
10.05.2008, 18:55
Hi,

Ich habe ein Problem. Ich gebe den Wert des ADC auf einem LCD aus.


#include <avr/io.h>
#include <stdlib.h>
#include <util/delay.h>
#include "adc.h"

#define XTAL 1000000 /**< clock frequency in Hz, used to calculate delay timer */
#include "lcd.h"
#include "lcd.c"

int main()
{

DDRA = 0b11111110; // Nur PA0 Ausgang

adc_init();
lcd_init(LCD_DISP_ON);

uint16_t wert;
char buffer[16];

lcd_puts("Hallo Benny!\n");

while(1)
{
_delay_ms(100);
_delay_ms(100);
_delay_ms(100);

lcd_gotoxy(0,1);
lcd_puts(" ");

wert = adc_lesen(2); // PA2 ist Analog
itoa(wert,buffer,10);

lcd_gotoxy(0,1);
lcd_puts(buffer);

}
}


void adc_init (void)
{
ADCSR = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0); // ADC aktivieren, Vorteiler 8
}



/* AD-Wandlung mit 10bit Genauigkeit durchführen und Mittelwert zurückgeben */
/* Kanal 0 = Poti, 1 = Temp, 2 = Licht und 3 = extern */
uint16_t adc_lesen(uint8_t kanal)
{
uint8_t i;
uint16_t wert;

ADMUX = kanal & 0b00011111; // Kanal waehlen und Bit 7 + 6
// sicher auf 0 setzen, da diese
// für die Referenzspg. zuständig
// sind und bei falsche Einstellung
// kann der MC sonst schaden nehmen!
// Bit 5 immer 0 weil, dieses Bit
// bestimmt ob der Wert verdreht
// abgespeichert wird oder nicht.


/* Mittelwert aus 5 aufeinanderfolgenden Wandlungen bilden */

wert = 0;
for( i=0; i<5; i++ )
{
ADCSR |= (1<<ADSC);
while ( ADCSR & (1<<ADSC) )
{
; // auf Abschluss der Konvertierung warten,
// Alternative zu: asm volatile ("nop");
// und leichter zu erklären ;-)
}
wert += ADCW; // nach jeder Wandlung hinzuaddieren
}

wert /= 5; // Mittelwert bilden

return (wert); // Mittelwert aus den 5 Messungen zurückgeben
}

Wenn ich PA2 an Vcc hänge dann zeigt es auf dem Display einen schwankenden Wert, entweder 1201 oder 2201. Eigentlich müsste doch die Obergrenze bei 1023 liegen.
Hänge ich den PA2 an den Reset (verbunden über 100k mit Vcc, ISP Stecker abgezogen) dann bleibt das Display leer (keine 0).

An Vcc habe ich 4,99V, An Reset habe ich 4,60V.
AVcc und beide GNDs sind angeschlossen. Meiner Meinung nach ist der Code auch richtig.

Was könnte die Ursache sein?

mfg
Benny

Besserwessi
10.05.2008, 21:06
Beim Datenrichtungsregister ist ein Fehler. Eine 1 steht für einen Ausgang. Damit wird PA2 ein Ausgang. Das Erklärt das Verhalten mit PA2 an Reset, aber nicht den Falschen wert bei VCC.

Etwas problematisch könnte es eventuell sein itoa mit einem unsigned wert aufzurufen. Da Auslesen des AD Wandlers siehr sonst gut aus. Höchstens ist es unpraktisch 5 Werte zu mitteln, denn da muß man echt teilen. Besser wären 4 oder 8 Werte, dann könnte man shifts verwenden, da gibt kleineren Code. Eventuell man controllieren welche Optimierungsstufe benutzt wird. Ohne Optimierung ist weniger zuverlässig, weil weniger getestet.

Herkulase
10.05.2008, 22:44
DDRA = 0b11111110; // Nur PA0 Ausgang

ich weiß nicht wie das beim tiny26 ist, aber beim ATmega16 schaltet das PORTA 1-7 auf Ausgang und PA0 auf Eingang.... Sonst weiss ich auch nicht, worans liegen könnte...

GErald

oberallgeier
10.05.2008, 23:00
Hi Herkulase, hi HF SHOOTER,



... If DDxn is written logic one, Pxn is configured as an output pin. If DDxn is written logic zero, Pxn is configured as an input pin....

Wie eben immer . . .

HF SHOOTER
11.05.2008, 11:03
Ja klar^^

Oman hab schon etwas länger nichts mehr mit diesen AVRs gemacht und habs mit dem PIC und dem TRISx durcheinander gebracht. Danke.

mfg
Benny

HF SHOOTER
12.05.2008, 17:57
Noch ein Problem.

Das Display zeigt es vertauscht. Also statt 1023 -> 3201, statt 512 -> 215. Woran liegt das denn?

mfg
Benny

Besserwessi
12.05.2008, 18:33
Das sollte dann eher ein Problem der LCD Routine sein. Es könnte auch sein das das verwendete Display die Zeichen anders als üblich durchnummeriert.