PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : A/D Wandler Problem



Razer
02.03.2006, 20:11
Hi @ all

Ich hab mich mal mit dem A/D Wandler beschäftigt. Leider fuktioniert das ganze nicht so wie ich mir das vorstelle. :(

Das ist einmal der Code:


#include <avr/io.h>
#include <stdlib.h>
#include "wintek2704.h"

void adc_init(void);
int get_adc (void);
void lcd_put_d(uint8_t dec);

int main (void)
{
DDRC &=~ _BV(PC0);
PINC &=~ _BV(PC0);

uint8_t ergebnis_display;

adc_init();
lcd_init(LCD_DISP_ON);
lcd_puts(" ADC -- Test\n");

while(1)
{
ergebnis_display = get_adc();
lcd_put_d(ergebnis_display);
}
return(0);
}

void lcd_put_d(uint8_t dec)
{
char buffer[6];
itoa(dec, buffer, 10);
lcd_puts(buffer);
}



void adc_init (void)
{
ADCSR = (1 << ADEN) | (1 << ADPS1) | (1 << ADPS2); //Prescaler = 64 TF = 125 kHz
}

int get_adc (void)
{
uint8_t i;
uint16_t ergebnis_adc;

ADMUX = 0; // Vreff = Vcc

ADCSRA |= (1 << ADSC);

while (!(ADCSRA & (1 << ADIF)));

ergebnis_adc = 0;

for(i = 0; i < 5; i++)
{
ADCSRA |= (1 << ADSC);
while(!(ADCSRA & (1 << ADIF)))

ergebnis_adc += ADC;
}
ADCSRA &=~ (1 << ADEN);
ergebnis_adc = ergebnis_adc / 5;

return ergebnis_adc;
}



Am LCD bekomm ich nur Datdenmüll :(
Könnte mir da jaemand helfen???

Danke im Voraus
Gruß Robert

Razer
03.03.2006, 05:39
Hab gestern noch vergessen meine Harsware dazu posten.

CPU: ATMEGA 8
F_CPU = 8 MHz
Poti an PC0

Gruß Robert

SprinterSB
03.03.2006, 07:54
Hinter

while(!(ADCSRA & (1 << ADIF)))

fehlt ein ; bzw. {} ?

ogni42
03.03.2006, 08:02
Kommt in letzter Zeit als Frage hier häufiger vor :)

Razer
03.03.2006, 18:02
Danke O:)

Jedoch verstehge ich eins nicht. Der ADC Wert wird nur nach einem Reset aktualisiert ausgegeben. Wenn ich danach das Poti verdrehe, ändert sich der Wert nicht.

Warum nicht?? Ich lese den A/D Kanal ja in einer Endlosschleife aus.

Könnte mir jemand das erklären?

Danke im Voraus

Gruß Robert

ogni42
03.03.2006, 19:06
Du schaltest nach der ersten Wandlung den ADC ab:

ADCSRA &=~ (1 << ADEN);

Lass die Zeile in get_adc() mall weg. Dann sollte es klappen.

Razer
03.03.2006, 19:22
Arrg. Da hätt ich selber draufkommen können. Hab nämlich vorher die Init in der gleichen Funktionion gehabt.

Danke

Gruß Robert

Razer
03.03.2006, 22:13
Hallo an alle

Ich hab nun die A/D Routine fertig geschrieben .


#include <avr/io.h>
#include <stdlib.h>
#include "wintek2704.h"

void adc_init(void);
int get_adc (void);
void lcd_put_d(uint16_t dec);

int main (void)
{
DDRC &=~ _BV(PC0);
PINC &=~ _BV(PC0);

uint8_t balken3, balken_leer, i, j;
uint16_t ergebnis_display;
uint16_t ergebnis_neu;

adc_init();
lcd_init(LCD_DISP_ON);
lcd_puts(" ADC -- Test\n");
ergebnis_neu = 0;

while(1)
{
ergebnis_display = get_adc();

if (ergebnis_neu > ergebnis_display || ergebnis_neu < ergebnis_display)
{
lcd_gotoxy(0,1);
lcd_puts(" ");
ergebnis_neu = ergebnis_display;
}
lcd_gotoxy(0,1);
lcd_put_d(ergebnis_neu);

balken3 = ergebnis_neu / 37;
balken_leer = 27 - balken3;

lcd_gotoxy(0,2);

for(i = 0; i < balken3; i++)
lcd_puts("=");
for(j = 27; j > balken_leer; j--)
lcd_puts(" ");
}
return(0);
}

void lcd_put_d(uint16_t dec)
{
char buffer[6];
itoa(dec, buffer, 10);
lcd_puts(buffer);
}



void adc_init (void)
{
ADCSR = (1 << ADEN) | (1 << ADPS1) | (1 << ADPS2); //Prescaler = 64 TF = 125 kHz
}

int get_adc (void)
{
uint8_t i;
uint16_t ergebnis_adc;

ADMUX = 0; // Vreff = Vcc

ADCSRA |= (1 << ADSC);

while (!(ADCSRA & (1 << ADIF)));

ergebnis_adc = 0;

for(i = 0; i < 5; i++)
{
ADCSRA |= (1 << ADSC);
while(!(ADCSRA & (1 << ADIF)));

ergebnis_adc += ADC;
}
ergebnis_adc = ergebnis_adc / 5;

return ergebnis_adc;
}


Jedoch überschreibe ich jetzt immer die Zahl vor der Aktualisierung mit 4 leerzeicnen (lcd_puts" "). Denn Wenn ich eine Zahl > 1000 anzeige, bleibt die letzte Stelle hängen wenn der Wert unter 1000 sinkt. Das gleiche bei 100. Deshalb die Überschreibung mit den Leerzeichen.

Gibt es in C ein Möglichkeit die Zahlen formatiert auszugeben zB 0125, 0058, 1024

In BASCOM gibt es ja die Funktion FUSING. Gibt es sowas auch in C

Danke im Voraus

Gruß Robert

SprinterSB
03.03.2006, 23:11
Du könntest sowas machen:

#include <string.h>

void lcd_put_d (uint8_t dec)
{
static char buffer[12];
char len, *str = buffer+6;
itoa (dec, str, 10);

for (len = 5-strlen (str); len > 0; len--)
*(--str) = '0';

lcd_puts (str);
}


Das füllt vorne mit Nullen auf.

Razer
04.03.2006, 09:28
Hallo Sprinter

Danke. Nur die Programmlogik verstehe ich noch nicht ganz. Der Zeiger zeigt auf die Adresse zeigt auf den String. Und an der Stelle des ZEigers wird eine 0 eingefügt. Der Zeiger wandert immere eins weiter.

Sehe ich das richtig??

Gruß Robert

SprinterSB
04.03.2006, 15:46
Den Puffer habe ich von 6 auf 12 Zeichen vergrößert. itoa schreibt sein Ergebnis aber nicht ab dem Abfang des Strings, sondern fängt erst ab Position 6 (dem 7.Zeichen) an.

Wenn itoa fertig ist, schaue ich nach, vieviele Nullen vorne dran müssen, bis die Stringlänge ganze 5 Zeichen ist. str wandert so lange zum Stringanfang und schreibt '0', bis er die 5 Zeichen hat. Dann wird der String ab str (und nicht von ganz Anfang, das wäre buffer) ausgegeben.

Razer
04.03.2006, 16:57
Danke

Gruß Robert