Archiv verlassen und diese Seite im Standarddesign anzeigen : A/D Wandler freerun ADC0 und ADC1 ohne Interrupt
guenter1604
13.12.2009, 21:33
Hallo,
um meinen timingkritischen Code zu schonen, will ich weder einen Interrupt bei fertiger AD-Wandlung setzen, noch auf eine einzelne Wandlung warten. Deshalb habe ich folgendes ausgeknobelt:
Ich möchte ADC0 und ADC1 abfragen, deshalb setze ich abwechselnd die Register. Je nach gesetztem Register und ob das Readyflag gesetzt ist, fülle ich eine Variable.
Im Datasheet steht zum löschen des Adcsra.adif ich solle 1 reinschreiben!?!
Ich frage nach 1 ab und setze dann 1 !?!
Stimmt das so oder ist das kompletter Rossmist?
If Admux = &B01000000 And Adcsra.adif = 1 Then
Adcsra.adif = 1
Data_array(6) = Adcl
Admux = &B01000001 'ADC1 setzen
Data_array(5) = Adch
Elseif Admux = &B01000001 And Adcsra.adif = 1 Then
Adcsra.adif = 1
Data_array(8) = Adcl
Admux = &B01000000 'ADC0 setzen
Data_array(7) = Adch
End If
Günter
Wenn ich deinen Code im Simulator laufen lasse, dann brauchen die beiden If-Abfragen schon jeweils 28 Takte.
Ein GetADC(0) dagegen nur 27.
Falls dies auch in Hardware so ist, solltest du vielleicht doch den Standard-Befehl nehmen.
guenter1604
13.12.2009, 22:53
Das leuchtet ein!
Also Rossmist ;-)
Sehr ressourcenintensiv sind Arrays, ohne die sollte das nicht mehr Rossmist sein.
mfg
guenter1604
13.12.2009, 23:05
Wenn doch schon die IF's so lang brauchen...
MagicWSmoke
14.12.2009, 11:39
Das mit GetADC kann man so nicht ganz stehen lassen.
GetADC würde 28 Zyklen brauchen, wenn die Wandlung selbst nicht auch noch dauern würde. In Deinem Code steht leider nix von wegen Prozessortakt oder ADC Prescaler, aber mal angenommen 8MHz CPU Takt, bei 10Bit Genauigkeit gehen laut Datenblatt maximal 200kHz ADC Clock, macht einen möglichen ADC Prescaler von 64. Eine normale Wandlung dauert 13 ADC Takte, also 13 * 64 = 832 CPU Takte.
GetADC(Ch) macht zur Sicherheit immer 2 Wandlungen hintereinander, also ist die Ausführungsdauer 28 + 2 * (64*13) = 1692 CPU Takte, da musst Du Dir wegen 28 Takten für die If's nun wirklich keine Gedanken machen :D
Das eigentliche Problem aber ist, daß GetADC den Ablauf blockiert, bis die Wandlung abgeschlossen ist.
Den Vorteil, den man beim manuellen Starten des ADC gewinnen kann, ist daß man Hauptcode ausführen kann, während der ADC im Hintergrund wandelt. Das ADIF abzufragen ist unnötig und aufwändiger, da man es rücksetzen muss, nimm lieber den Einzelwandlungsmode und starte immer wieder eine Wandlung, nachdem die vorige Wandlung beendet wurde.
Das geschieht mit ADCSRA.ADSC = 1, wenn ADSC wieder 0 ist, dann wurde die Wandlung beendet.
Beim Umschalten des Mux darauf achten, die erste Wandlung zu verwerfen.
guenter1604
14.12.2009, 11:49
Mist rein, Mist raus, also was denn nun? ;-)
Also ich baue das jetztmal auf und schalte einen Ausgangspin um.
Dann kann ich das mit dem Oszi nachmessen.
Außerdem lasse ich in einem Interrupt einen Pin Toggeln, dann sehe ich inwieweit Interrupts beeinflusst werden.
Dann haben wir Klarheit.
Günter
MagicWSmoke
14.12.2009, 13:01
Mist rein, Mist raus, also was denn nun? ;-)
Probier's aus, dann wirst Du sehen, daß GetADC schon ein bisserl braucht. Lies auch mal ADCSRA aus, damit Du siehst, welchen ADC Prescaler von Bascom gewählt wird, ich nehm' an Du hast "Auto" in Config ADC eingestellt.
Interrupts werden nicht beeinflusst, da diese die Warteschleife unterbrechen, in der GetADC während einer Wandlung läuft.
Bau so etwas in Deinen Code rein, dann wird im Hintergrund gewandelt, darin musst Du Dich auch noch um die Mux Umschaltung, bzw. Verwerfen des ersten Ergebnisses nach der Umschaltung kümmern.
If ADCSRA.ADSC = 0 Then
ADC_result = ADC
...
ADCSRA.ADSC = 1
End If
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.