hallo, habe bisher nicht soviel mit dem adc gemacht ausser mal ne single conversation. jetzt habe ich mal probiert das ganze über einen free run zu machen aber dann kam das entsetzen: in assembler sieht das so aus: ldi temp, 237 out ADCSRA, temp also bis auf bit 1 und 4 alle einschalten das bedeutet: ADC ENable: set ADC Start Convers: set ADC free running: set die letzen dienen dem prescaler jetzt zum problem: so wie es da steht wird jetzt nach den 25 zyklen der interrupt ausgewählt. danach verschwindet jedoch das start conversation bit. muss man dieses jedesmal beim interrupt wieder neu setezn oder mach ich gerade irgendwie grundlegend was falsch?? free running hiess für mich bisher das er alls 13 cyklen automatisch den nexten wert einliest. lag ich da falsch?? grüsse thomas
Im Free-Run-Mode wird kein Interrupt genutzt. Der ACD "klappert" im Hintergrund gemütlich vor sich hin und interessiert sich nicht dafür, ob und wann das Programm den Messwert ausliest... In einem Programm, das nebenbei die Betriebsspannung (Akku) am Mega8 ermittelt und in % am LCD anzeigt, initialisiere ich den ADC so: ldi wl,(1<<adlar)+14 ;linksbündig, Bandgap als Messquelle out admux,wl ;an ADC legen ldi wl,(1<<aden)|(1<<adsc)|(1<<adfr)+6 ;ADC freilaufend mit out adcsra,wl ;Vorteiler 64 einschalten In diesem Fall wird die (konstante) innere Bandgap-Spannung in Bezug auf die Betriebsspannung gemessen. Das eigentliche Auslesen geschieht dann als Job in der Mainloop (niedrige Priorität), über ein Flag synchronisiert von einem Timer-Interrupt (alle 10ms), der auch noch andere Aufgaben hat (Tastenentprellung, Zeitzählung, Synchronisierung der LCD-Ausgabe uvm.): akkutest: ;Akku-Zustand messen (Vergleich Vcc mit V_bandgap) cbr flags,1<<hundertstel ;Flag löschen, Job wird erledigt ldi wl,80 ;Basiswert Akkuladezustand in wh,adch ;ADC einlesen (60...80) sub wl,wh ;(0...20) mov wh,wl ;Kopie lsl wl ;mal lsl wl ;4, add wl,wh ;nochmal dazu entspricht mal 5 lds r0,batt1 ;Mittelwert aus SRAM holen lds wh,batt0 ;Nachkommastellen auch sub wh,r0 ;1/256 subtrahieren sbc r0,null ;Übertrag auch add wh,wl ;Neuwert/256 addieren adc r0,null ;Übertrag auch sts batt1,r0 ;zurück sts batt0,wh ;ins SRAM rjmp mainloop ;fertig... Hierbei wird der Mittelwert über 256 Messungen emittelt. Die Ausgabe an das LCD geschieht in einem anderen Job alle volle Sekunde, ist also hier nicht zu sehen. Beim Auslesen des ADC via Timer-Interrupt ist lediglich abzusichern, dass zwischen den Auslesezugriffen mindestens eine neue Wandlung stattgefunden hat. Dies erreicht man aber leicht durch geschicktes Anpassen von Timer und ADC-Vorteiler. ...
hallo hannes, init ist die gleiche, nur das ich noch das adie flag (interrupt enable) setze um bei jeder conversation einen neuen wert zu lesen...dazu ist der interrupt doch da oder irre ich?? im simulator funzt das auch, nur der chip misst anscheinend nur ein einziges mal im programm wird der counter 0 mit prescaler 8 initialisiert prescaler vom adc ist 32 (bei 2MHz) nach 25 zyklen ist die erste auswertung des adc abgeschlossen (ca 800 Prozessortakte), die erste conversation ist also schneller abgeschlossen als der erste timer overflow(255x8 = 2040prozessortakte). der simulator springt in den adc interrupt, übergibt dort neue werte und rechnet kurz. im worst case steht der timer dann bei 0xA0 am ende der adc interrupt routine..also noch weit vor dem overflow. beim timer overflow will ich den adc dann gleich am anfang wieder starten lassen (neue messung), also setz ich da bit 6 im adcsra... schöne theorie, funzt nur nicht real..aber im simulator flags sehen dann wie folgt aus prescaler 0-2: 1, 0, 1 adc enable: 1; der bleibt auch immer an adsc: 1 ; wird dann bei jeden timer ofl neu gesetzt adie: 1 ; interrupts enable bleibt auch immer 1
habe mein prog mal zusammengeschnitten und diese version auf den chip gebrannt. er misst einfach nur einmal den wert...kann mir wer sagen warum?? egal ob ich free running oder single conversation einstelle..er misst nur ein einziges mal, ruft die routine aber immer auf alles was ich will ist die ausgabe der (hier) unteren 8 bit des adc an port d bei jedem vollständigen (10bit) adc wert. der timer soll dann eine neue berechnung starten...im simulator klappts, nur auf dem chip nicht...wieso?!?!? ich verzweifel noch dran
Du wirst dich schon entscheiden müssen, ob du free-Run oder Interrupt willst. Willst du Interrupt, dann wirst du wohl in der ISR die nächste Conversion starten müssen. ...
ich möchte einfach das ich bei jeden timer overflow des timer 0 eine neue conversation starte. wenn die 10bit eingelesen sind im adc dann will ich diese weiter verarbeiten... ich seh gerade echt nicht das problem im meiner init des adc...helf mir mal auf die sprünge..falsch initialisisert für den interrupt oder wie??
habe jetzt mal deine initialisierung versucht und lade beim timer0 überlauf die werte raus...so meintest du das bei nir im 2ten beitrag oder?? läuft auf meinem chip so auch nur ein einziges mal durch
habe inzwischen leider so den verdacht das mein adc nicht so richtig funktioniert... einfache portausgabe über leds an portb hab ich mal getestet: setze ich das adlar flag und lese das adch aus geht der adc lösche ich das flag, und lese das adcl aus gehts nicht mehr extern werden an aref 5V eingespeist und ich werte gerade von 2,4-2,5 volt..also müssten sich allemal irgendwelche bits ändern msb...also das bit das für 2,5V in meinem fall steht ist das bit 9 wenn das adlar flag gelöscht ist oder??
Puhhhh... Dein ADC ist sicherlich nicht kaputt... Aber deine Programmbeispiele sind etwas durcheinander. Free-Run braucht keinen ADC-Interrupt, dafür aber den Timer-Interrupt, der dafür sorgt, dass der ADC nicht zu oft hintereinander ausgelesen wird. Du liest den ADC jedoch in der Mainloop alle paar Takte aus. Rechne doch mal aus, wieviele Takte eine Conversion dauert... Und wenn du ein vernünftiges Programm schreiben willst, kommst du an einen Timer-Int sowiso nicht vorbei. Den brauchst du halt für viele Zwecke, angefangen von der Tastenentprellung über Verzögerungen usw... Schau dir mal dieses Beispiel an: http://www.mikrocontroller.net/forum/read-1-140519.html#140585 Da werden 8 ADC-Kanäle per Timer-Int abgefragt. Erst abfragen, dann Quelle ändern, bis zur nächsten Abfrage (Timer-ISR) vergeht so viel Zeit, dass bereits einige neue Conversionen stattgefunden haben. ...
es stimmte schon wie anfangs geschrieben..inzwischen läuft das teil :) des rätsels lösungwar eigentlich ganz einfach: beim lesen des ADC's ändert sich die reihenfolge in der man die beiden regsister auslesen muss... adlar = 0 muss das lowbyte gelesen und danach muss (!!) das highbyte gelesen werden... bei adlar = 1 andersrum das war das problem, sonst sperrt der controller die nächste auslesung so long
Nööö... ADLAR bestimmt lediglich, ob der 10-Bit-Wert im 16-Bit-Register linksbündig oder rechtsbündig angeordnet wird. Linksbündig wird genutzt, wenn man nur 8 Bit Auflösung braucht. Dann kann man nämlich auf das untere Byte (mit den 2 unteren Bits) verzichten und nur das obere Byte (mit den oberen 8 Bits) einlesen und verarbeiten. ...
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.