Meine Aufgabenstellung ist eigentlich ganz simpel. Poti an Eingang A des ATmega16 und Binärwert am Ausgang B. Nun wie muss ich aber den AVR konfigurieren, dass er mir den analog Wert des ADCs am Ausgang B als Binärwert angiebt?
Simon Schmid wrote: > Nun wie muss ich aber den AVR konfigurieren, dass er mir den > analog Wert des ADCs am Ausgang B als Binärwert angiebt? Nicht konfigurieren... Programm schreiben(!). Hast du schon mal einen Blick ins Datenblatt des mega16 geworfen? Da stehen sogar kleine Beispielcodes für die Verwendung des ADCs drin. Gruß, Magnetus
Magnus Müller wrote:
> Da stehen sogar kleine Beispielcodes für die Verwendung des ADCs drin.
Ups... hab ich meine Klappe wieder zu früh aufgemacht... da steht gar
kein Beispielcode drin :(
Sorry
Danke Magnus. Es steht ja schon was Kleines drin. Aber ich kann halt all die Grundlagen noch nicht so. Hab erst ein paar Beispiele aus dem Tutorial programmiert. Also so wie ich das versteh, muesst man lediglich den ADC aktivieren, den Kanal angeben und dann wahrscheinlich mit einem Interrupt arbeiten. So dass der Wert bei einer Aenderung in ein Register geschrieben wird. Dieses Register wird dann am Port B ausgegeben. Kenn hier jemand ein kleines Programm in ASSAMBLER oder C?
Simon Schmid wrote: > Also so wie ich das versteh, muesst man lediglich den ADC aktivieren, > den Kanal angeben und dann wahrscheinlich mit einem Interrupt arbeiten. Den Interrupt musst du nicht unbedingt verwenden. Man kann den ADC auch einfach "freilaufend" arbeiten lassen. Der ADC wandelt sich dann zwar dumm und dusselig aber wenn du das ADC-Datenregister ausliest hast du immer den aktuellsten Wert. Diesen musst du dann nur noch am Port B ausgeben. Gruß, Magnetus
Magnus Müller wrote: > Den Interrupt musst du nicht unbedingt verwenden. Man kann den ADC auch > einfach "freilaufend" arbeiten lassen. So habe ich das im Tutorial auch verstanden. Nun, ich mach mich mit dem Tutorial mal ans Programmieren. Die Befehle sind ja zwar fuer den AT90S8535 weiss nicht, ob die auch fuer den ATmega16L gelten. Poste bald meinen Code. Bin gespannt ob ich das so gleich kann, hab bis jetzt nur mit ASSAMBLER Codes gearbeitet, nicht mit C. to be continued ...
Ich etwas programmiert, gemaess Tutorial und ATmega16L Description. Der Aufbau mit dem STK500 sieht folgendermassen aus: Am Port A Liegt ein 20kOhm Poti. Schleifer direkt am Eingang A, Bit 0. Eine Seite Masse, die andere Seite via 330 Ohm an Vcc. Die Leds sind an Port B und zeigen nach Laden des Programms immer den Wert, der in Zeile 10 definiert wird. Aber eigentlich muesste doch der 8Bit Wert von ADCL angezeigt werden. Kann mir jemand weiterhelfen, wo der Fehler liegt? Ich habe anstelle des Potis auch die Switches des STK500 angehaengt, muesste ja eigentlich auch gehen.
Zitat aus dem Datenblatt: "If the result is left adjusted and no more than 8-bit precision is required, it is sufficient to read ADCH. Otherwise, ADCL must be read first, then ADCH, to ensure that the content of the Data Registers belongs to the same conversion. Once ADCL is read, ADC access to Data Registers is blocked. This means that if ADCL has been read, and a conversion completes before ADCH is read, neither register is updated and the result from the conversion is lost. When ADCH is read, ADC access to the ADCH and ADCL Registers is re-enabled." Du liest in deinem Programm immer nur ADCL aus. Wenn du danach nicht auch ADCH ausliest bleibt das ADCL und ADCH-Register des µCs für neue Werte gesperrt. Da du ja sowieso nur 8 Bits verwendest, könntest du den ADC so konfigurieren, dass er das Ergebnis "left adjusted" ausgibt. Du kannst dann die 8 MSBs direkt über ADCH auslesen. Ein Lesezugriff auf ADCH gibt immer auch die beiden Register (ADCH und ADCL) wieder für neue Wandlungsergebnisse frei. Gruß, Magnetus
Servus, ich lerne auch gerade, mit der Hilfe eines Forenmitglieds, AVR-Assembler. Dabei verwende auch ich den ADC. So wie du das mit dem sbi ADCSR, ADSC machst funktioniert das wohl nicht. Das hatte ich auch probiert. Schreibst du aber: ldi temp, (1<<ADEN) | (1<<ADSC) | (1<<ADIE) out ADCSR, temp Dann werden die Bits wohl richtig gesetzt. Wenn du mit dem AVR Studio programmierst, dann wird dir nach dem Drücken von F7 auch angezeigt, an welcher Stelle es hakt und auch was nicht in Ordnung ist. Gruß, André
könnt ihr mir ein code beispiel geben? ich habe ldi temp, (1<<ADEN) | (1<<ADSC) | (1<<ADIE) out ADCSR, temp eingefuegt und nun gibt's beim kompilieren auch keine fehler mehr. jedoch, wie kann ich im avr studio einen analog wert am adc simulieren, um zu sehen das sich an port b etwas tut? und es gibt doch einen befehl um die ersten und zweiten 8bit in ein register zu fuehren. muesste ich nicht das hier machen?
Wie wäre es mit: mov temp, ADCH oder in temp, ADCH und dran denken, erst ADCL, dann ADCH auslesen, wenn du im FreeRunning arbeitest ist das besonders wichtig, sonst geht gar nichts mehr ;) Gruß, André
Den Free Running brauchst du aber gar nicht, wenn du sowieso jede Messung einzeln startest. Free Running benutzt man eigentlich nur dann, wenn der ADC ständig sampeln soll und einen Interrupt auslösen soll wenn er mit einer Messung fertig ist.
Ich habe nun den Code wie André beschrieben hat abgeändert, heisst, ich lese mit in temp, ADCL und in temp, ADCH den Digitalen Wert des Potis ein. ADCL gebe ich an die Leds an PORT B und die Flackern dann auch ganz schön. Nun, möchte ich gerne den eingestellten Wert vergleichen mit einem Vorgegebenen und dann über drei LEDS an PORT B anzeigen, ob der Potiwert kleiner, gleich oder grösser ist als der Vorgegebene. PS. Könnt ihr ein Buch empfehlen, um AVR und Assembler zu lernen, oder ist C besser?
Ich hab das mit dem Vergleich nun so geloest: in temp, ADCL in temp2, ADCH cpi temp, 0b00111111 brlo kleiner cpi temp, 0b00111111 breq gleich cpi temp2,0b00111111 brlo groesser nun hab ich natuerlich das problem, das BIT 9 und 10 des Wertes nicht beruecksichtigt werden. koennt ihr mir helfen, wie ich ADCH und ADCL zusammen führen und als 10Bit Wert vergleichen kann? Obiger Code funktionert, aber natuerlich kommt er waehrend des Poti durchgangs mindesten 6 mal vor. ich bin nun meinem ziel aber schon recht nahe: also nächstes hänge ich zwei transistoren an die Leds 'grösser' und 'kleiner' und dann sollte das motorisierte poti auf knopfdruck immer zurueck an seine stelle fahren.
Nun habe ich den Motor des Volume Potis (Motorisiertes ALPS Poti) über 2 Transistoren (2N2222, lagen gerade rum) an die Pins Bit1 und Bit2 des Ports A gehängt. Wenn das Poti nun nicht mehr auf seiner "Sollwert-Position" steht, dreht es der AVR automatisch an seinen "Sollwert-Position" zurueck. Nun habe ich versucht über die Taster an Port C eine manuelle Korrektur zu erzwingen. Heisst: Taste 1 Poti Volume up Taste 2 Poti Volume down Programmiert habe ich es über: sbis PINC, 0 rjmp kleiner sbis PINC, 2 rjmp groesser Das Problem war nun, dass nach dem Laden/Reset, das Poti immer an den Endanschlag drehte, auch wenn keine Taste gedrueckt wurde. Koennt ihr mir helfen, wie ich am besten eine Taste abfrage und dann wenn sie gedrueckt wird einen rjmp zur Routine ausloese?
Du musst nach dem Reset einfach erst einmal für definierte Zustände sorgen. Musst dir verstellen dass du aus dem Schlaf wach wirst und alles um dich herum ist in Hektik. Also musst du dir erst einmal eine Übersicht verschaffen. So auch hier. Nach dem Reset musst du für einen Ausgangszustand sorgen, von dem aus dann der eigentliche Programmablauf aus gestartet wird. Gruß, André
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.