Hallo, ich bin am verzweifeln, probiere nun schon Wochen einen Atmege8 Analogeingang zu Programmieren aber er will nicht so richtig. Wenn ich ganz ehrlich bin es tut sich eigentlich gar nichts. Hier mein C-Code #define F_CPU 1e8 #include <util/delay.h> // Include Datei für die Verzögerungsfunktion #include <avr/io.h> int main (void) { int sample,value; // Varieblen defination DDRB = 0xFF; // PORTB als Ausgabeport ADMUX = (0<<REFS1 |(0<<REFS0)); // Exterme Referenzspannung ADMUX = (0<<MUX0 | (0<<MUX1 | (0<<MUX2 |(0<<MUX3)))); //Kanal0,Pin PC0 while (1) { sample=0; // setzt den Sampelwert auf 0 ADCSRA |= (1<<ADSC); // ADC einschalten value = ADCW; if (value<0) PORTB=0x04; } } Hoffe es kann mir einer weiter Helfen Schon mal Danke im vorraus.
:
Verschoben durch User
Hallo, habe das jetzt schon ein paar mal durchgelesen ausprobiert und komme trotzdem nicht weiter. Ich weiß einfach nicht weiter. Wäre nett wenn mir noch einer ein paar Tipps oder Programm Verbesserungen sagen bzw. was falsch ist.
Den ADC aktivieren kann man mit ADEN =1. Ich weiß aber nicht, wie das in "C" formuliert werden muss. Das sehe ich nicht im Programm. Eventuell liegt es daran. MfG Paul
> #define F_CPU 1e8 Du lässt den Mega8 mit 100 Mhz laufen? > while (1) > { > sample=0; // setzt den Sampelwert auf 0 Wozu benötigst du die Variable "sample"? Ich vermute, dass du hier nicht den kompletten Code geposted hast. > ADCSRA |= (1<<ADSC); // ADC einschalten Vielleicht solltest du den ADC auch enablen (ADEN). > value = ADCW; Bevor du versuchst das Wandlungsergebnis auszulesen musst du erst einmal das Ende der Wandlung abwarten. > if (value<0) Die Variable "value" ist ein Integer (ohne Vorzeichen). Diese Variable kann also niemals kleiner 0 sein. > PORTB=0x04; Somit wird diese Anweisung auch nie ausgeführt werden.
Knoddelpusch schrieb: > Hallo, > > habe das jetzt schon ein paar mal durchgelesen ausprobiert und komme > trotzdem nicht weiter. Hast du offensichtlich nicht. Denn im Beispiel-Code, den du quasi 1:1 hättest übernehmen können, steht doch:
1 | ADCSRA |= (1<<ADEN); // ADC aktivieren |
2 | ...
|
3 | ADCSRA |= (1<<ADSC); // eine ADC-Wandlung |
das hätte dich zumindest mal kurz zum nachdenken bringen müssen. Denn ADEN hast du gar nicht verwendet und hinter "ADCSRA |= (1<<ADSC);" steht irgendwie ein Kommentar das bei dir anders aussieht. Und im Datenblatt hättest du auch gesehen, dass das so nicht ganz richtig sein kann.
Hallo, Sind 100 Mhz zu viel? Habe jetzt alles noch mal nach geschaut und habe diverse abänderungen gemacht. Ich habe hier jetzt noch ein mal das überarbeitete Programm. #define F_CPU 1e8 #include <util/delay.h> // Include Datei für die Verzögerungsfunktion #include <avr/io.h> int main (void) { int value; // Varieblen defination DDRB = 0xFF; // PORTB als Ausgabeport ADMUX = (0<<REFS1 |(0<<REFS0)); // Exterme Referenzspannung ADMUX = (0<<MUX0 | (0<<MUX1 | (0<<MUX2 |(0<<MUX3)))); // Kanal 0, Pin PC0 while (1) { ADCSRA = ADEN; // ADC einschalten ADCSRA |= (1<<ADSC); // eine AD-Wandlung while (ADCSRA & (1<<ADSC) ) {} // auf Abschluss der Konvertierung warten value = ADCW; if (value>0) PORTB=0x04; } } Bekomme es aber immer noch nicht zu laufen. Den Frequenzvorteiler brauch man ja bei dem Programm nicht oder? Möchte eine Eingangsspannung von 2,5 V abfragen bzw. wenn eine Spannung am Eingang liegt soll eine Lampe angehen.
Knoddelpusch schrieb: > #define F_CPU 1e8 Bitte tu dir den Gefallen und arbeite erstmal da Tuttorial durch. Und solange du nicht sattelfest in der Materie bist, würde ich dir raten, die Beispiele 1 zu 1 aus dem Tutorial kopieren und testen, BEVOR du sie veränderst.
Knoddelpusch schrieb: > Sind 100 Mhz zu viel? Dein ATmega8 wird bestimmt nicht mit 100 MHz laufen. > #define F_CPU 1e8 Warum immer noch? > #include <util/delay.h> // Include Datei für die Verzögerungsfunktion Wozu bindest du krampfhaft die Delay-Lib ein, wenn du sie nicht benutzt? > while (1) > { > ADCSRA = ADEN; // ADC einschalten Das "ADCSRA = ADEN;" setzt du noch VOR den Endlos Loop. > if (value>0) > PORTB=0x04; > Möchte eine Eingangsspannung von 2,5 V abfragen bzw. wenn eine Spannung > am Eingang liegt soll eine Lampe angehen. Das Wandlungsergebnis auf >0 zu prüfen ist dann ziemlicher Quatsch. Wie groß ist die von dir extern zur Verfügung gestellte Referenzspannung? > Bekomme es aber immer noch nicht zu laufen. Wundert mich nicht. > Den Frequenzvorteiler brauch man ja bei dem Programm nicht oder? Der ADC-Takt sollte für die volle 10 Bit Auflösung <= 200 kHz sein. Wenn du den Prescaler mit "0" fütterst, teilt dieser durch 2. Das bedeutet, dass dein Prozessortakt nicht größer als 400 kHz sein darf. --> Mit welchem Takt versorgst du den Controller?
> Das "ADCSRA = ADEN;" setzt du noch VOR den Endlos Loop.
Die Position wäre ja egal, er kann den ADC ja beliebig of einschalten.
Allerdings funktioniert das so nicht, da es
ADCSRA = (1<<ADEN);
sein sollte, da ADEN nur die Bitnummer ist.
Den ADC kann man auch übertakten, wenn man möchte, die Genauigkeit geht
halt flöten.
Allerdings verstehe ich den TO nicht. Er könnte einfach mal das Beispiel
aus dem Tutorial kopieren und ausprobieren. Danach kann er es ja von mir
aus ändern und zwischendurch austesten, ob es noch läuft.
Allgemein denke ich aber, dass da massiv Grundlagen in Form der
vorhergegangenen Tutorialkapiteln fehlt.
:-)
Timmo H. schrieb: > http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Analoge_Ein-_und_Ausgabe Knoddelpusch schrieb: > habe das jetzt schon ein paar mal durchgelesen ausprobiert und komme > trotzdem nicht weiter. das is halt schlichtweg gelogen... > Wäre nett wenn mir noch einer ein paar Tipps oder Programm > Verbesserungen sagen bzw. was falsch ist. deine vorgehensweise. LIES das tutorial und zwar von anfang an!
Hallo, auch ich habe ein Problem mit dem Programm... Unter dem AVR Studio 4 bricht er mit dem fehler ab, dass adcw nicht definiert ist... im avr studio 6 kommt folgende fehlermeldung: ------ Build started: Project: Batterieprüfer, Configuration: Debug AVR ------ Build started. Project "Batterieprüfer.cproj" (default targets): Target "PreBuildEvent" skipped, due to false condition; ('$(PreBuildEvent)'!='') was evaluated as (''!=''). Target "CoreBuild" in file "D:\Programme\Atmel\Atmel Studio 6.0\Vs\Compiler.targets" from project "C:\Users\Steven\Desktop\Batterieprüfer\Batterieprüfer\Batterieprüfer.cp roj" (target "Build" depends on it): Using "RunCompilerTask" task from assembly "D:\Programme\Atmel\Atmel Studio 6.0\Vs\Compiler.Task.dll". Task "RunCompilerTask" D:\Programme\Atmel\Atmel Studio 6.0\make\make.exe all make: *** No rule to make target `Batteriepr├╝fer.o', needed by `Batteriepr├╝fer.elf'. Stop. Done executing task "RunCompilerTask" -- FAILED. Done building target "CoreBuild" in project "Batterieprüfer.cproj" -- FAILED. Done building project "Batterieprüfer.cproj" -- FAILED. Build FAILED. ========== Build: 0 succeeded or up-to-date, 1 failed, 0 skipped ========== Ideen?
Vermeide bei - Dateinamen - Verzeichnisse - Make Targets - Variablen - Funktionen - Definitionen Leerzeichen, Sonderzeichen und alle Zeichen, die nicht im 7Bit US-ASCII Zeichensatz enthalten sind. Also beschränke Dich auf 0-9, A_Z, a-z und _.
Das gilt übrigens auch für den Windows-Benutzernamen, wenn man unbedingt auf dem Dektop arbeiten muss...
Hallo, habe das jetzt soweit umgebastelt... aber irgendwie gibt er mir als ergebnis immer 0 aus... Habe ein Stk 500 und einen AtMega16
1 | #include <avr/io.h> |
2 | #include <inttypes.h> |
3 | |
4 | |
5 | |
6 | void ADC_Init(void) { |
7 | |
8 | uint16_t result; |
9 | |
10 | // interne Referenzspannung als Refernz für den ADC wählen:
|
11 | ADMUX = (1<<REFS1) | (1<<REFS0); |
12 | |
13 | // Bit ADFR ("free running") in ADCSRA steht beim Einschalten
|
14 | // schon auf 0, also single conversion
|
15 | ADCSRA = (1<<ADPS1) | (1<<ADPS0); // Frequenzvorteiler |
16 | ADCSRA |= (1<<ADEN); // ADC aktivieren |
17 | |
18 | /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
|
19 | also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
|
20 | |
21 | ADCSRA |= (1<<ADSC); // eine ADC-Wandlung |
22 | while (ADCSRA & (1<<ADSC) ) { // auf Abschluss der Konvertierung warten |
23 | }
|
24 | /* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten
|
25 | Wandlung nicht übernommen. */
|
26 | result = ADCW; |
27 | }
|
28 | |
29 | /* ADC Einzelmessung */
|
30 | unsigned int ADC_Read( unsigned char channel ) |
31 | {
|
32 | |
33 | // Kanal waehlen, ohne andere Bits zu beeinflußen
|
34 | ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F); |
35 | ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion" |
36 | while (ADCSRA & (1<<ADSC) ) { // auf Abschluss der Konvertierung warten |
37 | }
|
38 | return ADCW; // ADC auslesen und zurückgeben |
39 | }
|
40 | |
41 | /* Beispielaufrufe: */
|
42 | |
43 | int main() |
44 | {
|
45 | DDRB = 255; |
46 | PORTB = 0; |
47 | PORTB = ~PORTB; |
48 | |
49 | unsigned int Ergebnis; |
50 | ADC_Init(); |
51 | |
52 | while( 1 ) { |
53 | |
54 | Ergebnis = ADC_Read(0); // Kanal 0 |
55 | // mach was mit adcval
|
56 | |
57 | if (Ergebnis<100) |
58 | {
|
59 | PORTB|=(0<<PB0); |
60 | }
|
61 | }
|
62 | }
|
Steven S. schrieb: > ja, und auf deutsch? das bisschen nachdenken war wohl zu anstrengen. keine minute nach dem hinweis schon die frage - gratuliere. wie naiv zu erwarten, du würdest zu Steven S. schrieb: > habe das jetzt soweit umgebastelt... aber irgendwie gibt er mir als > ergebnis immer 0 aus... Habe ein Stk 500 und einen AtMega16 noch eine fehlermeldung posten. nein, die müssen wir schon erraten... http://www.zeit.de/wissen/2009-9/vorurteile-namen-grundschullehrer du darfst dich hier gleich einreihen...
Steven S. schrieb: > habe das jetzt soweit umgebastelt... aber irgendwie gibt er mir als > ergebnis immer 0 aus... Habe ein Stk 500 und einen AtMega16 Ich habe mir der Einfachheit halber jetzt nur mal deine main() angesehen. Deine Abfrage > if (Ergebnis<100) > { > PORTB|=(0<<PB0); > } setzt dir den Portpin auf 1 sobald auch nur ein einziges Wandlungsergebnis kleiner als 100 ist. Der Portpin wird jedoch niemals wieder auf 0 gesetzt wenn die Wandlung ein Ergebnis >= 100 liefert! Versuche es mal mit if (Ergebnis<100) { PORTB|=(0<<PB0); } else { PORTB&= ~(0<<PB0); }
Magnus M. schrieb: > Deine Abfrage > >> if (Ergebnis<100) >> { >> PORTB|=(0<<PB0); >> } > > setzt dir den Portpin auf 1 Nope. Das setzt überhaupt nichts auf 1. An den Port kann er 0 zuweisen bis er schwarz wird. Der Pin wird niemals 1 (bzw. 0, was wohl die eigentliche Absicht gewesen sein dürfte). Egal was vom ADC kommt. @Frager Womit wir wieder beim Punkt angelangt wären: Lies das Tutorial von Anfang an! Es ist sinnlos, sich mit komplizierteren Projekten zu befassen, solange du nicht die allerersten, einfachsten Grundlagen sicher im Griff hast. Einen Pin gezielt auf 0 oder 1 zu setzen ist etwas, das DARF dir keine Probleme mehr verursachen! Bitmanipulation
Karl Heinz Buchegger schrieb: > Magnus M. schrieb: > >> Deine Abfrage >> >>> if (Ergebnis<100) >>> { >>> PORTB|=(0<<PB0); >>> } >> >> setzt dir den Portpin auf 1 > > Nope. > > Das setzt überhaupt nichts auf 1. Oh shit.... ich hatte doch glatt die "0<<" übersehen... Wie auch immer: selbst wenn dort "1<<" gestanden hätte, wäre es murks gewesen.
So, Problemchen hat sich erledigt... Habe das wie folgt gemacht. Und so läuft das Programm ohne probleme ;-) #include <avr/io.h> int main() { DDRB = 255; //make portB all output PORTD = 0; PORTD = ~PORTD; ADMUX=(1<<REFS0)|(1<<ADLAR); //Make AVcc the reference, make the //bit value left aligned and select //ADC0 channel. ADCSRA=(1<<ADEN)|(1<<ADCSRA)|(1<<ADPS2); //Enable Analog convertor, //set prescaler to 16 //and free running mode while(1) { uint16_t Wert; uint8_t Ausg; ADCSRA|=(1<<ADSC); //start conversion Wert = ADCW; Ausg = 0; if (Wert>15000) { Ausg |= (1 << 0); } if (Wert>15500) { Ausg |= (1 << 1); } if (Wert>16000) { Ausg |= (1 << 2); } if (Wert>16500) { Ausg |= (1 << 3); } if (Wert>17000) { Ausg |= (1 << 4); } if (Wert>18000) { Ausg |= (1 << 5); } if (Wert>19000) { Ausg |= (1 << 6); } if (Wert>20000) { Ausg |= (1 << 7); } PORTB = ~Ausg; } return 1; }
Das ist Murks
1 | ADCSRA|=(1<<ADSC); //start conversion |
2 | |
3 | Wert = ADCW; |
wenn du eine Wandlung startest, musst du schon auch abwarten bis die Wandlung fertig ist. Gut, bei dir spielt das jetzt keine große Rolle, weil dann eben das Ergebnis der aktuell gestarteten Wandlung im nächsten Durchlauf zur Verfügung steht (und dann die nächste Wandlung schon wieder läuft). Aber spätestens dann, wenn du mehrere Wandlungen auf bunt gemixten ADC-Eingängen brauchst, gibt das Ergebnis-Salat. Wenn schon dann machs lieber so rum ...
1 | Wert = ADCW; // Ergebnis der letzten Wandlung holen ... |
2 | ADCSRA|=(1<<ADSC); // und gleich die nächste Wandlung starten ... |
3 | // dann kann der ADC Wandler arbeiten, während
|
4 | // das Ergebnis der letzten Wandlung ausgewertet
|
5 | // wird
|
... denn dann ist auch klar, dass diese Parallelverarbeitung beabsichtigt ist. aber ganz ehrlich: um ein paar LED zu schalten, spielen die paar ADC-Takte Verzögerung, die man mit 'Wandlung starten - Ergebnis abwarten - Ergebnis holen' hat nicht wirklich die große Rolle.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.