AD-Wandler multiplexen (BASCOM / ATmega8)

SchakKlusoh

Neues Mitglied
01. Feb. 2009
8
0
0
Sprachen
Hallo,

um zu prüfen, ob ich die AD-Wandler-HW und die dazugehörigen Register richtig verstanden habe, habe ich den ATmega8 folgendermassen beschaltet.
AVcc = AVref = Vcc
PC0, PC1, PC2, PC3 jeweils ein Poti (22kOhm, 0-5V)

Die Wandlungswerte sollen als Zeitvorgabe für zwei PWM-Signale benutzt werden, weil man die (je nach Zeitbasis) gut mit einer LED oder dem Oszi beobachten kann.
ADC0 = high für PortB0
ADC1 = low für PortB0
ADC2 = high für PortB1
ADC3 = low für PortB1

Code:
On ADC OnAdc 'ADC-Interrupt-Routine festlegen
'
'--[Variablen]---------------------------------------------
Dim AdChannel as Byte
'AD-Wandlerwerte
Dim highPortB0 as Integer
Dim highPortB1 as Integer
Dim lowPortB0 as Integer
Dim lowPortB1 as Integer
'
Dim hiPortB0Zaehler as Integer
Dim hiPortB1Zaehler as Integer
Dim PortB0Zaehler as integer
Dim PortB1Zaehler as Integer
'
'----------------------------------------------------------
'Initialisierung
'----------------------------------------------------------
PORTB = &B00000011
DDRB = &B00000011
'
'Bits7+6=01: Aref ist intern verbunden
'Bit5=1: LeftAdjust, nur 8 Bit in ADCH
'Bits3..0=0000: Pin ADC0 wählen
ADMUX = &B01100000
AdChannel = 0
'Bit7=1:AdcAn
'Bit6=1:Start
'Bit5=1:Freilaufend
'Bit3=1:InterruptAn
'Bits2..0=111: AdcClock=AvrClock/128
ADCSRA = &B11101111
ADCSRA = &B11101111
'
'Globale Interrupt-Freigabe
SREG.7 = 1

'----------------------------------------------------------
'Hauptprogramm
Do
    IF PortB0Zaehler <= 0 THEN
      PortB0Zaehler = lowPortB0 + highPortB0 'Taktlaenge
      hiPortB0Zaehler = highPortB0 'high-Zeit
      PortB = PortB OR &B00000001 'PortB0 = high
    ELSE
      decr PORTB0ZAEHLER
      IF hiPortB0Zaehler <= 0 THEN 'high-Zeit vorbei
        PortB = PortB AND &B11111110 'PortB0 = low
      ELSE
        decr hiPORTB0ZAEHLER
      ENDIF 'Ende: high-Zeit
    ENDIF 'Ende: Taktlaenge

Loop 'Ende: Hauptschleife

'--[Interrupt]---------------------------------------------
OnAdc:                                                      'ADC-Interrupt-Routine
'Kanal-Weiterschaltung
ON AdChannel GOTO ADCHANNEL0 , ADCHANNEL1 , ADCHANNEL2 , ADCHANNEL3

ADCHANNEL0:
highPortB0 = ADCH
AdChannel = 1
GOTO END_OnAdc

ADCHANNEL1:
lowPortB0 = ADCH
AdChannel = 2
GOTO END_OnAdc

ADCHANNEL2:
highPortB1 = ADCH
AdChannel = 3
GOTO END_OnAdc

ADCHANNEL3:
lowPortB1 = ADCH
AdChannel = 0
GOTO END_OnAdc

END_OnAdc:
ADMUX = &B01100000 OR AdChannel
Return

Ergebnis: Die Wandlungsergebnisse sind richtig. Die Kanäle sind aber um eine Position verschoben.
ADC3 = high für PortB0
ADC0 = low für PortB0
ADC1 = high für PortB1
ADC2 = low für PortB1

Wo liegt mein Denkfehler? Was für einen Bock habe ich geschossen?

Danke im Voraus

Schak
 
Dann gebe ich mir jetzt selbst die Antwort:
<<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 reterence 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 dock cycle before the conversion completes (ADIF in ADCSRA is set). Note that the conversion Starts on the following rising ADC dock 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.>> [Quelle: Atmel-Spezifikation]

Soll heissen, nach dem Interrupt beginnt sofort die nächste Wandlung. Die Umstellung des Kanals am Ende der Interruptroutine kommt zu spät. Sie gilt nicht für die augenblicklich laufende Wandlung sondern erst für die nächste.
 
Hallo Schak,

danke dass Du die Antwort zur Fragestellung gleich selbst gepostet hast. Damit bleibt die Frage nicht offen im Thread stehen.
Meinen Glückwunsch auch, dass Du so schnell eine Antwort gefunden hast!

Grüße,
Markus
 
Hallo Markus,

<< Once the conversion starts, the Channel and reference selection is locked to ensure a sufficient sampling time for the ADC. >>
Zwei Mal gelesen und nicht verstanden.

Code:
ADCHANNEL0: 
lowPortB1 = ADCH 
AdChannel = 1 
GOTO END_OnAdc 

ADCHANNEL1: 
highPortB0 = ADCH 
AdChannel = 2 
GOTO END_OnAdc 

ADCHANNEL2: 
lowPortB0 = ADCH 
AdChannel = 3 
GOTO END_OnAdc 

ADCHANNEL3: 
highPortB1 = ADCH 
AdChannel = 0 
GOTO END_OnAdc
So funktioniert es.

Grüße

Schak
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)