Hallo, Ich programmiere in Assembler. Wenn ich hintereinander 8 Kanäle messen will, muss ich immer nach Umstellung des Kanals (in ADMUX) einen Moment warten, sonst überschneiden sich die Kanäle. Habt Ihr Erfahrung mit dem Problem. Meine Lösung bisher: Mein Programm kontrolliert ständig (ähnlich Windows) Tasten, Anzeige, Ausgabe usw. auch die AD-Eingänge, stellt dann den nächsten Eingang ein und eine Wartezeit und kehrt wieder zurück, um die anderen Sachen zu machen. Also kein Warten - das Programm ist ständig aktiv, kontrolliert permanent "Timer" und wenn abgelaufen, macht es eben diese Dinge. Das geht schon ganz gut ... Trotzdem meine Frage -- nach dem Zeitproblem, wie lange braucht der MC zum Umschalten in den nächsten Kanal. Auch wenn ich ADIF und ADEN abfrage, löse ich es nicht. Danke
> Wenn ich hintereinander 8 Kanäle messen will, muss ich immer nach > Umstellung des Kanals (in ADMUX) einen Moment warten, sonst > überschneiden sich die Kanäle. Das wäre mir neu. > Mein Programm kontrolliert ständig (ähnlich Windows) Tasten, > Anzeige, Ausgabe usw. auch die AD-Eingänge, stellt dann den > nächsten Eingang ein und eine Wartezeit und kehrt wieder zurück, > um die anderen Sachen zumachen. Ich hoffe mal, daß Windows das nicht so macht. > Trotzdem meine Frage -- nach dem Zeitproblem, wie lange braucht > der MC zum Umschalten in den nächsten Kanal. Eigentlich sollte das Umschalten sofort gehen, es sei denn, eine Wandlung ist gerade am Laufen. Dann wird gewartet, bis die zu Ende ist.
>> Wenn ich hintereinander 8 Kanäle messen will, muss ich immer nach >> Umstellung des Kanals (in ADMUX) einen Moment warten, sonst >> überschneiden sich die Kanäle. >Das wäre mir neu. das hängt vom Konzept des (Multichannel) DAC ab, ob die einzelnen Kanäle jeweils durch einen S&H gepuffert sind oder brutal per MUX die Kanäle auf einen S&H gewürfelt werden, um dann gewandelt zu werden. Viele Grüße Olaf
Hi! Benutz doch einfach einen Timerinterrupt und stoss dort alle x ms die Wandlung an. Dann speicher die Werte in globalen Variablen also zb int adc_0 int adc_1 ... (oder auch nen array) Die Timerroutine updatet nach und nach die 8 adc Variablen. Evtl brauchst du noch nen Flag das angibt welcher wert gerade geupdatet wird oder so. Könntest auch den ADC Conversion Interrupt nehmen, nach einer Wandlung wird der aufgerufen, globale var gesetzt, neue Wandlung gestartet. Bye, Simon
Wenn Du direkt nach dem Starten des A/Ds einen kleinen Moment wartest (so 5 NOPs, je nach ADC-Vorteiler, ausprobieren) und dann den nächsten MUX-Kanal anwählst, während der A/D noch zuendewandelt, gewinnst Du einiges an Zeit. Guck doch nochmal in´s Datenblatt, ich denke S/H ist nach 1,5 ADC-Clocks gegessen und direkt danach kannst Du auch den Kanal schon umschalten.
Wozu warten. Vor dem Umschalten auf einen anderen Kanal einfach das Bit ADSC abfragen ob low (0). Es wird zwar durch setzen auf 1 damit eine Wandlung gestartet bleibt aber so lange auf 1 bis die Wandlung fertig ist. Wenn fertig, setzt der Controller das Bit automatisch auf 0. Also einfach mit "SBIC ADCSR,ADSC" prüfen, ob die vorige Wandlung fertig ist. Als zweiter Befehl kommt so was wie ein "RJMP ADC-Busy" oder so was den Teil zum Umschalten und Start einer Wandlung überspringt was nach dem RJMP beginnt. MfG Andi
@andi: es ging doch gerade darum, Zeit zu sparen - wenn Du auf die komplette Wandlung wartest, hast Du doch nichts gekonnt - besser wäre es, den Mux WÄHREND der noch laufenden Wandlung umzuschalten...
Danke allen, die letzte Meinung scheint mir am sinnvollsten, ich will keine nops und Warteschleifen einbauen und auf keine Flags warten müssen (zumal das eben nicht funktioniert mit Warten auf ADSC - warum auch immer). So ähnlich habe ich das auch gemacht ... der AVR muss immerhin noch "nebenbei" eine Wavedatei und/oder Midi ausgeben und Daten aus Eeproms holen usw. Ich dachte ja nur, dass das Problem irgendwo genauer beschrieben ist, als im Datenblatt. ...
Wer hat denn von warten geschrieben? Ich sicher nicht! Folgendes: SBIC ADCSR,ADSC ;Ist die aktuelle Wandlung fertig (ADSC=0)? RJMP ADC-Busy ;Wenn nicht, dann weiter zu anderen Dingen. ..... ;Ansonsten Mux umschalten und Wandlung starten. ADC_Busy: ..... ;Andere Dinge (bereits vorhandene) erledigen. Hier wird im "vorbeigehen" geprüft, ob eine Wandlung fertig ist, und wenn nicht, werden in der Main-Loop die anderen Dinge ab "ADC_Busy" erledigt. Wenn eine Wandlung fertig ist und die nächste gestartet wird geht es danach von selber zur Marke "ADC_Busy" zu den anderen Dingen. KEIN Warten vor der nächsten Wandlung nur ein Check ob die letzte fertig ist. MfG Andi
Danke Andi, das ist es, was ich will, aber komischer Weise stellen sich eigenartige Dinge ein. Ich lasse alle 8 Kanäle in dieser Art abfragen und speichere sie im SRAM ab. Jedesmal wenn sich was ändert sende ich die neuen Ergebnisse zum Terminal mit einem Erkennungsbyte vorneweg (Kanal1 Wert1 usw.). Jetzt passiert es aber, dass Kanal1 auch Kanal2 beeinflusst bis dahin, dass der Wert von Kanal2 z.B. im Kanal1 steht usw., also eine gegenseitige Beeinflussung stattfindet. Ich danke ja, dass das Umschalten zu früh passiert oder Zeit fordert. Hier eine Skizze! des Programms ... rcall AD_Wandeln ;auch mit Warten auf Bits (ADIF usw.) ;schieben und einen 8Bitwert machen rcall WennAndersDannSenden ;ggf. alt=neu und in SRAM abspeichern ldi temp,2 ;umschalten out ADMUX,temp rcall AD_Wandeln ... usw. ... sobald ich hinter AD_Wandlen eine kleine Pause einschiebe, geht alles wunderbar
Hier ein Auszug über die Kanaländerung aus dem ATMega8: "Changing Channel or Reference Selection The MUXn and REFS1:0 bits in the ADMUX Register are single buffered through a temporary register to which the CPU has random access. This ensures that the channels and reference selection only takes place at a safe point during the conversion. The channel and reference selection is continuously updated until a conversion is started. Once the conversion starts, the channel and reference selection is locked to ensure a sufficient sampling time for the ADC. Continuous updating resumes in the last ADC clock cycle before the conversion completes (ADIF in ADCSRA is set). Note that the conversion starts on the following rising ADC clock edge after ADSC is written. The user is thus advised not to write new channel or reference selection values to ADMUX until one ADC clock cycle after ADSC is written. If both ADFR and ADEN is written to one, an interrupt event can occur at any time. If the ADMUX Register is changed in this period, the user cannot tell if the next conversion is based on the old or the new settings. ADMUX can be safely updated in the following ways: 1. When ADFR or ADEN is cleared. 2. During conversion, minimum one ADC clock cycle after the trigger event. 3. After a conversion, before the Interrupt Flag used as trigger source is cleared. When updating ADMUX in one of these conditions, the new settings will affect the next ADC conversion." Soll wohl heißen, das man nach dem Umschalten des Kanals mindestens 1 ADC-Clock warten muß bevor die nächste Konvertierung gestartet wird. Also bei einem Prescaler von 64 wären das dann 64 Takte. Dann trifft das von TravelRec zu wo der ADC-Kanal im voraus während einer ADC-Wandlung umgeschaltet wird. Also nach dem man die Konvertierung von Kanal 0 gestartet hat, 5 Takte später auf den Kanal 1 umschalten und weiter den Kanal 0 Wandeln lassen usw. MfG Andi
Hallo. Wenn ich so die Diskussion verfolge, schleicht sich bei mir der Eindruck ein: Scheinbar sind Interrupts out. Die AD-Wandler lassen sich herrlich transparent mit dem ADC-Ready-Interrupt steuern. Mit der ADC-Taktfrequenz lässt sich prima vorwählen, in welchem Takt die Wandlung und damit die Anzahl Messungen pro (Milli-)Sekunde passieren soll. Nix mit irgendwelchen Warteschleifen oder andauerndem Polling. 16 Bytes im SRAM dürften auch noch frei sein, da legt der AD-Wandler dann seine Ergebnisse ab. Und man holt sie völlig asynchron dort ab, wenn man sie gerade braucht. Aber wie geschrieben: Interrupts scheinen (AT-)mega-out zu sein. Warum nur? mfg gerd
Interrupts sind nicht out, müssen aber verstanden werden, was für den Anfänger nicht so einfach ist. Dein Vorschlag ist gut, habe ich auch schon gemacht. Bevor man aber in die höhere Programmkunst einsteigt, sollte man sich erstmal über den zeitlichen Ablauf der A/D-Wandlung und der entsprechenden Peripherie und über die Interpretation des Datenblatt-Textes im Klaren sein.
Ich programmiere wirklich schon lange und komplizierte Sachen. Natürlich habe ich den Interrupt probiert. Mir geht es einzig darum, wann ich den AD-Kanal umschalten kann. Denn leider klappt es nicht, nach einem Interrupt den Kanal umzuschalten und eine neue Wandlung zu starten. Dann ist beim nächsten Interrupt meist ein nicht gültiger Wert. Sicher ich kann dann mehrere Interrupts abwarten, Werte vergleichen usw. -- nur wollte ich wissen, ob jemand auch diese Problem kennt/hat. Aber vielleicht beschäftige ich mich noch mal intensiv damit. Danke allen:
@Andi: Das Warten von einem ADC clock cycle bezieht sich ausschließlich auf den Fall, dass ADSC bereits gestartet wurde und danach der Kanal umgeschaltet werden soll. Wenn der ADC-Start nicht automatisch erfolgt, sondern im Single Conversion Mode per ADSC gestartet wird, ist es nicht nötig, zwischen MUX und ADSC länger zu warten. Zu den schwankenden Werten: Ich habe bisher mit ATmega8 und 16 die Erfahrung gemacht, dass die Messwerte bei gleichbleibender Spannung um ein Digit rauf oder runter klappern. Keinesfalls klappern mehr Bits. Wenn das der Fall ist, würde ich den Fehler bei der externen Hardware suchen (HF-Einstrahlung auf dem Eingangssignal, mangelndes Abblocken der AD-Versorgung über Drossel/Kondensator und ähnliches). Eine Fehlerquelle bei der Software kann noch sein, wenn beim Interrupt-Betrieb SLEEP-Instruktionen verwendet werden. Wenn ADEN an ist, startet SLEEP die ADC-Wandlung ebenfalls, und das unabhängig von anderen Einstellungen der ADC-Einheit. Eine etwas abstruse Konstruktion von Atmel. Das stört erheblich die Synchronisation mit einem Timer. Da hilft es nur, ADEN abzuschalten und gleichzeitig mit ADSC wieder einzuschalten (wird mit verlängerter Wandlungszeit bestraft). mfg gerd
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.