Hallo, ich wollte als ersten Anwendung mit dem Atmega8 ein Lauflicht machen dessen Geschwindigkeit von einer Poti-Stellung abhängt. Poti hängt zwischen Vcc und Maße und der Schleifer ist am ADC0 Port. Hier der Code der vom AVR Studio 4 fehlerfrei compiliert wird. .include "m8def.inc" ;Definitionsdatei einbinden, ggf. durch ;2333def.inc ersetzen ldi r16,high(ramend) ;Stackpointer auf out sph,r16 ;Ende des SRAM ldi r16,low(ramend) ;setzen out spl,r16 ldi r16, 0xFF ;0xFF ins Arbeitsregister r16 laden out DDRB, r16 ;Inhalt von r16 ins IO-Register DDRB ;initialisierung des ADC sbi ADEN, 1 ;ADC aktivieren sbi ADFR, 1 ;ADC auf Free Run Mode sbi ADPS0, 0 ;Takteiler.. sbi ADPS1, 1 ;..auf 64.. sbi ADPS2, 1 ;..stellen sbi REFS1, 0 ;AVcc with.. sbi REFS0, 1 ;..external Capacitor at AREF sbi ADLAR, 1 ;Result right adjusted sbi MUX0, 0 ;ADC... sbi MUX1, 0 ;..auf.. sbi MUX2, 0 ;..Port ADC0... sbi MUX3, 0 ;..stellen sbi ADSC, 1 ;Wandlung starten anfang: ldi r18,0 ldi r17,0 rcall LED1an schleife: inc r18 brne schleife inc r17 ldi r19, ADCH CP r19, r17 brlo schleife ldi r18,0 ldi r17,0 rcall LED2an schleife2: inc r18 brne schleife2 inc r17 ldi r19, ADCH CP r19, r17 brlo schleife2 ldi r18,0 ldi r17,0 rcall LED3an schleife3: inc r18 brne schleife3 inc r17 ldi r19, ADCH CP r19, r17 brlo schleife3 rjmp anfang LED1an: ldi r16, 0b00000010 ;0b11111100 in r16 laden out PORTB, r16 ;r16 ins IO-Register PORTB ret LED2an: ldi r16, 0b00000100 out portb, r16 ret LED3an: ldi r16, 0b00001000 ;0b11111100 in r16 laden out PORTB, r16 ;r16 ins IO-Register PORTB ret Alle drei LEDs leuchten schwach unabhängig von der Poti Stellung. An jedem Pin sind 1,6V was ja ein drittel von 5 ist und somit nur der RMS Wert, da jeder Pin nur ein drittel der Zeit 5V hat. Frequenz gibt mein Multimeter mit 400Hz an. Unabhängig von der Poti Stellung. Wenn ich den ADC Part entferne und stattdessen eine fixe zweite schleife rein mache läuft das Licht auch...ist aber nicht Sinn der Übung. Was ist am auslesen falsch?
Ich empfehle dir mal ein Studium der Datenblaetter das ATMega8. Insbesondere welches Steuerbit in welchem Steuerregister was genau macht. Weiters empfehle ich dir die Befehlsreferenz von Atmel in der du mal nachlesen solltest, wie eigentlich der sbi Befehl funktioniert.
Zur Not kannst du auch den Abschnitt ueber ADC im AVR-GCC Tutorial auf dieser Site studieren. Aber um das Studium der Befehlsreferenz (wegen sbi) kommst du nicht herum. Der wird naemlich voellig anders verwendet als du dir das vorstellst.
Ich habe zwar (noch) nicht viel Ahnung vom AVR-Assembler, aber du solltest irgendwo abfragen, ob der Messungvorgang des ADC beendet ist. Der Hinweis von Karl-Heinz bzgl. Tutorium ist auch eine Hilfe. Und wie immer gilt: Das Datenblatt ist dein Freund.
Nachdem du das mit dem sbi behoben hast, würde ich dir empfehlen den AD-Wandler erst auszulesen wenn die Wandlung fertig ist. Also entweder auf das entsprechende Flag zu pollen oder noch besser mit interrupt. Noch dazu mit ADLAR=1 Left Adjusted Mfg Matthias
;initialisierung des ADC sbi ADEN, 1 ;ADC aktivieren sbi ADFR, 1 ;ADC auf Free Run Mode sbi ADPS0, 0 ;Takteiler.. sbi ADPS1, 1 ;..auf 64.. sbi ADPS2, 1 ;..stellen sbi REFS1, 0 ;AVcc with.. sbi REFS0, 1 ;..external Capacitor at AREF sbi ADLAR, 1 ;Result right adjusted sbi MUX0, 0 ;ADC... sbi MUX1, 0 ;..auf.. sbi MUX2, 0 ;..Port ADC0... sbi MUX3, 0 ;..stellen sbi ADSC, 1 ;Wandlung starten Hmm, sbi ADCSRA, ADEN sbi ADCSRA, ADFR sbi ADCSRA, ADPS0 ... ... na usw. oder ldi R16,(1<<ADEN)|(1<<ADFR)|... und dann mit "out" den Wert von R16 dem IO-Register ADCSRA zuweisen sbi ADMUX, REFS1 sbi ADMUX, REFS0 ... ... sbi ADCSRA, ADSC zum Schluss. um die Wandlung zu starten soviel zum Thema sbi. Ich hoffe, meine Antwort hat Dir mehr geholfen... @kbuchegg etwas mehr Kooperation wäre hier angebracht gewesen, oder? Das Datenblatt hat er sich angesehen, sbi sieht er sich gerade an, jede Wette. ;-)) AxelR.
@AR Sorry AR. Aber ich bin der Meinung, dass man einem Anfaenger durchaus zumuten kann, dass er sich die Grundlagen selbst erarbeitet. Dass man ihn nicht einfach machen laesst, ist klar. Ein Hinweis wo etwas falsch ist und wo man Information darueber bekommt wie's richtig geht, ist auch OK. Aber man muss nicht alles auf einem Silbertablett servieren. Zumal der Lerneffekt bei 'Selbst-Rausgefundenem' wesentlich groesser ist. Dauert zwar fuer den Lernenden etwas laenger, als wenn er alles mundgerecht zum abtippen vorgeworfen bekommt, dafuer vergisst er es nie wieder. Das ist zumindest meine Erfahrung der letzten 20 Jahre in denen ich Leuten Programmieren beigebracht habe.
@Karl Heinz Ja, Du hast wahrscheinlich Recht! @Sven dranbleiben! GRuß AxelR.
Karl Heinz hat recht... (schade, dass ich nicht zu den Glücklichen gehören durfte, denen er Programmieren beigebracht hatte) Sven, du arbeitest doch mit AVR-Studio. Setz doch mal den Cursor auf einen ASM-Befehl und drück mal die F1-Taste. Trotzdem solltest du dir die Tabellen "instruction set" und "I/O-registers" (oder so ähnlich heißend) aus dem Datenblatt (ziemlich weit unten) ausdrucken. Das sind Infos, die der Neuling immer parat haben muss. ...
@Axel thx, ich weiss solche Antworten zu schätzen. Und ich denke auch nicht dass ich es so eher vergessen werde wenn ich es denn mal richtig weiss als wenn ich es mir über Tage und Wochen des suchens irgendwo doch noch gefunden hätte, da das ja etwas ist was man doch in einer Tour braucht. Ich denke wie sehr man Dinge behält hängt mehr davon ab wie oft man sie braucht als wie man sie lernt. Hilfe zur Selbsthilfe ist natürlich gut, bloss habe ich im Vorfeld bereits im GCC Tut und im Datenblatt nachgeschlagen (daher hab ich die Register und Bits). Bloss das GCC Tut ist für C und ich will das erstmal in Assambler machen. Im Datenblatt ist kein Codebeispiel und im Instruction Set ist das einzige Beispiel zu sbi: out $1E,r0 ; Write EEPROM address sbi $1C,0 ; Set read bit in EECR in r1,$1D ; Read EEPROM data keine große Hilfe. aber zu dem code nochmal, muss ich zuerst sbi ADEN, 1 ;und dann noch sbi ADCSRA, ADEN ;setzen oder letzten Befehl statt des ersten? Eigentlich könnte ich die beiden Register (ADCSRA und ADMUX) doch direkt mit byte per ldi laden, nicht sehr debug freundlich für dritte, aber kurz und handlich.
> Eigentlich könnte ich die beiden Register (ADCSRA und ADMUX) doch > direkt mit byte per ldi laden, nicht sehr debug freundlich für > dritte, > aber kurz und handlich. Selbstverständlich kannst du das. Aber bitte nicht die Bits aus dem Datenblatt zusammenklauben und dann selbst zur Hex-Zahl oder Binärzahl zusammensetzen, das versteht dann keiner. Lieber die Namen aus dem Datenblatt verwenden, die kennt der Assembler nämlich, da sie mit der "m8def.inc" bekannt gemacht werden. Willst du mehrere Bits setzen, dann könnte das so aussehen: ldi wl,(1<<aden)|(1<<adsc)|(1<<adfr)|(1<<mux0) out admux,wl Dabei ist wl der selbst vergebene Name eines oberen Registers. Da ldi (wie auch sbr und cbr) nicht die Bitnummern, sondern die Bitmaske braucht, muss aus der jeweiligen Bitnummer (0..7) ein Wert (1,2,4,8,16,32,64,128) gemacht werden. Dies geschieht durch "Linksschieben einer 1" um den Wert der Bitnummer. Ist etwas gewöhnungsbedürftig, aber dann sehr "sprechend". Leider zeigt die Online-Hilfe des ACR-Studios die Operatoren und Directiven nicht mit der F1-Taste an. Da müsstest du mal über das Help-Menü (help, tools, avr-assembler2, directiven) hingehen und nachlesen. Wenn du dir ein paar ASM-Programmbeispiele ansehen willst, dann schau mal hier, das ist recht üppig kommentiert: http://www.hanneslux.de/avr/divers/index.html Und hier geht es um den ADC, allerdings mit Mega48: http://www.hanneslux.de/avr/mobau/7ksend/7ksend02.html ...
@hannes hab mir deinen code mal angesehn von dem impulsgenerator und dann mit meinem nun umgeschriebenen code verglichen. Bis auf meinen Fehler beim einlesen des result registers ADCH, ldi statt lds zu verwenden sollte es eigentlich stimmen, geht aber immer noch nicht. Vorher haben die 3 LED gleichmäßig schwach geleuchtet, sprich r19 war immer 0. Jetzt läuft das Lauflicht wieder so wie es gelaufen ist als ich einfach nur zwei ineinandergeschachtelte 8bit schleifen hatte. Sprich jetzt ist r19 immer 255, egal wie das poti steht. ADLR hab ich mit 1 und 0 versucht sowie ADCH und ADCL ausgelesen, so wie der code jetzt da steht müsste er während einer Poti drehung 4 mal schneller und wieder langsam werden...passieren tut gar nix. ;initialisierung: ldi r20,0 ldi r20,(1<<REFS0) out ADMUX,r20 ldi r20,0 ldi r20,(1<<ADEN)|(1<<ADFR)|(1<<ADPS1)|(1<<ADPS2)|(1<<ADSC) out ADCSRA, r20 ;auslesen: schleife: inc r18 brne schleife inc r17 lds r19, ADCL CP r19, r17 brlo schleife irgendwelche Fehler ersichtlich? Wüsste nicht was ich noch kontrollieren kann oder anders versuchen.
Ja, ADCL und ADCH liegen beim Mega48 im Extended-I/O-Bereich, der wie SRAM mit STS/LDS angesprochen werden muss. Beim Mega8 liegen alle I/O-Register im normalen I/O-Bereich, die werden dann mit IN/OUT angesprochen. Das ist beim Mega48 zwar blöd, aber ich kann es nicht ändern. Schau dir mal das Beispiel im Anhang an, ist schon etwas älter, ist auch schonmal irgendwo hier im Forum veröffentlicht, ich finde es aber nicht wieder. Es ist für Mega8535, der ist bis auf die Anzahl der I/O-Pins mit dem Mega8 vergleichbar. Schau dir besonders den Timer-Interrupt an, eine solche Zeitbasis braucht fast jedes Programm, mit Warteschleifen (wie in deinem Beispiel) kommst du nicht weit. Das war auch der Grund, weshalb ich das Testprogramm für dich mit einem Timer-Interrupt ausgestattet hatte. Ein Timer-Interrupt im Programm erleichtert das Programmieren gewaltig. Leg doch erstmal den (im Timer-Int) zyklisch eingelesenen ADC-Wert an einen Port, an den du 8 LEDs (mit Vorwiderständen) angeschlossen hast. Damit siehst du sofort jede Änderung des eingelesenen Wertes. ...
danke jetzt klappts :) Dass ein Timer der warteschleife vorzuziehen ist, ist mir klar, nur wollte ich nicht alles auf einmal machen sondern ein Feature des Atmega nach dem anderen kennen lernen. Und nun ist der Timer dran, hab ja dank dir jetzt genügend Material mich damit eingehend damit zu beschäftigen.
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.