Forum: Mikrocontroller und Digitale Elektronik MSP430F2012 10 Bit AD Wandler nutzen?


von Heiko (Gast)


Lesenswert?

Hallo Forumsmitglieder,

ich nutze seit längerem den MSP430F447 mit dem 12 Bit AD Wandler.
Dort hatteich nie Probleme die AD Wandler anzusprechen und vernünftige 
Ergebnisse zu erhalten.

Seit kurzem teste ich den MSP430F2012 mit dem 10 Bit AD Wandler.
Dieser lässt sich leider nicht richtig ansprechen, ich erhalte stets den 
Messwert 0.

Vielleicht ist euch ein Fehler ersichtlich.

Vielen Dank!

Anbei meine AD Routine in Assembler:


// -- AD Wandler 
----------------------------------------------------------
// MSP 430F2012 Port P1.2 als AD Eingang A2 nutzen
// 
------------------------------------------------------------------------

AD2;
            bic.w   #ENC,&ADC10CTL0         ; ENC Bit auf Null setzen, 
um
                                            Steuerbits verändern zu 
können
            bis.w   #SREF_1,&ADC10CTL0      ; Interne Referenz auswählen
            bis.w   #REF2_5V,&ADC10CTL0     ; 2,5 V Referenz auswählen
            bis.w   #REFON,&ADC10CTL0       ; Interne Referenz 
einschalten
            bis.w   #ADC10SHT_2,&ADC10CTL0  ; Anzahl der Taktzyklen für
                                            eine Wandlung (4, 8, 16, 64)
            bis.w   #ADC10ON,&ADC10CTL0     ; ADC einschalten

            bis.w   #ADC10DIV_3,&ADC10CTL1  ;
            bis.w   #INCH_2,&ADC10CTL1      ; Wahl des AD Eingangs
                                            (0,1,2,3)
            bis.w   #SHS_1,&ADC10CTL1       ; Sample / Hold Source 1
            bis.w   #CONSEQ_2,&ADC10CTL1    ; Wiederholte Messung eines 
AD-
                                            Kanals

            bis.b   #04h,&ADC10AE0          ; P1.2 ADC10 option select

            bis.w   #ENC,&ADC10CTL0         ; Einschalten des ADC
                                            (Steuerefehle blockiert)
            bis.w   #ADC10SC,&ADC10CTL0     ; Start sampling/conversion
            mov.w   &ADC10MEM,R8            ; AD Wandler Ergebnis 
speichern
ret

von Jörg S. (joerg-s)


Lesenswert?

Kann es sein das du überhaupt nicht abwartest bis die Wandlung fertig 
ist?

von Heiko (Gast)


Lesenswert?

Hallo Jörg,

mhm, bei dem MSP430F447 habe ich keine spezielle Pause eingebracht und 
die AD Wandler arbeiten dort.
Wo sollte ich hier eine Pause einplanen?
Ich habe bis jetzt ehr das Gefühl das ich bei der Initialisierung einen 
Fehler habe, und evtl. den Falschen Port ect. messe.


Schönen Gruß, Heiko.

von Jörg S. (joerg-s)


Lesenswert?

>mhm, bei dem MSP430F447 habe ich keine spezielle Pause eingebracht und
>die AD Wandler arbeiten dort.
>Wo sollte ich hier eine Pause einplanen?
Du solltest warten bis der AD Wandler mit der Messung fertig ist bevor 
du den Wert abholst :)
Aber wenn ich das richtig sehe machst du Dauermessung, da ist das kein 
Problem. Dein Code mit dem lesen von ADC10MEM passt halt nicht dazu...


> bis.w   #ENC,&ADC10CTL0         ; Einschalten des ADC
> bis.w   #ADC10SC,&ADC10CTL0     ; Start sampling/conversion
Es scheint so als würdest du ENC setzen und danach versuchen auf
ADC10CTL0 zu schreiben. Geht natürlich nicht, wie du selbst im Code 
Kommentiert hast :)

von Heiko (Gast)


Lesenswert?

Jörg S. schrieb:
>> bis.w   #ENC,&ADC10CTL0         ; Einschalten des ADC
>
>> bis.w   #ADC10SC,&ADC10CTL0     ; Start sampling/conversion
>
> Es scheint so als würdest du ENC setzen und danach versuchen auf
>
> ADC10CTL0 zu schreiben. Geht natürlich nicht, wie du selbst im Code
>
> Kommentiert hast :)

Das ADC10SC-Bit ist eines der Steuerbits die sich auch mit gesetztem ENC 
Bit beschreiben lassen. Zumindest ist das beim 12 Bit ADC vom 447 so, wo 
es sich ADC12SC nennt.
Ich finde leider niergendwo ein vernünftiges Beispiel für den AD 
Wandler.
Die Texas Beispiele sind meist nicht kommentiert und man kann nicht 
nachvollziehen was dort welcher Befehl genau macht...

von Jörg S. (joerg-s)


Lesenswert?

Heiko schrieb:
> Das ADC10SC-Bit ist eines der Steuerbits die sich auch mit gesetztem ENC
> Bit beschreiben lassen. Zumindest ist das beim 12 Bit ADC vom 447 so, wo
> es sich ADC12SC nennt.
Ja, stimmt...
Wobei der User Guide sagt: "ADC10SC and ENC may be set together with one 
instruction."

> Die Texas Beispiele sind meist nicht kommentiert ...
Ich würde sagen die Beispiele sind schon sehr gut kommentiert.

von Uhu U. (uhu)


Lesenswert?

Bei mir funktioniert der 2012-ADU prima. Ich hab mich bei der 
Programmierung an die TI-Beispiele gehalten.

von Heiko (Gast)


Lesenswert?

Ich habe mal die Reihenfolge der Steuerbefehle getauscht, das ENC-Bit 
als letztes wieder gesetzt, leider ohne Erfolg.
Die Texas Beispiele laufen bei mir ebenfalls, dennoch wird aus ihnen 
nicht genau ersichtlich welcher Steuerbefehl genau für welche Aktion 
zuständig ist.
Ich benötige eine Messung an P1.2 ohne Interrupts oder Timernutzung.
Solch ein Beispiel gibt es leider nicht...

@Uhu Hast du eine asm Routine die Port P1.2 nutzt?

Schönen Gruß!

von Jörg S. (joerg-s)


Lesenswert?

Was willst du denn jetzt eigentlich machen? Dauermessung auf einem Kanal 
oder nur Einzelmessung?

von Heiko (Gast)


Lesenswert?

Da die Anwendung weder Zeitkritisch noch Energietechnisch relevant ist, 
wollte ich den AD Kanal dauerhaft messen.
Die Routiene des AD Kanals wird dann ca. 40 mal aufgerufen, eine 
Mittelwert berechnet und das Ergebnis ausgewertet.

Das ganze Soll auf P1.2 gemessen werden. Evtl. wird später noch ein 
zweiter AD Eingang benötigt, den ich über eine getrennte Routine, mit 
weniger Messdurchläufen abrufen möchte.

von Jörg S. (joerg-s)


Lesenswert?

Heiko schrieb:
> Die Routiene des AD Kanals wird dann ca. 40 mal aufgerufen, eine
> Mittelwert berechnet und das Ergebnis ausgewertet.
Wieso willst du die Routine ständig aufrufen? Es reicht doch die Routine 
zu beginn einmalig aufzurufen und dann einfach nur noch ADC10MEM zu 
lesen. Genau darum geht es doch bei der Dauermessung, das du eben gerade 
NICHT ständig den AD Wandler neu einstellen musst.

von Heiko (Gast)


Lesenswert?

Mhm, das stimmt schon. Ich kann auch nur ADC10MEN mehrmals auslesen.
Aber das ändert nichts daran, das ich bis jetzt nur 0 als Wert 
erhalte...
Sofern ich dort etwas messen könnte, wäre das mehrmalige Abrufen des MEM 
eine einfache Sache.

von Uhu U. (uhu)


Lesenswert?

Ja, ich hab in auf P1.2 und P1.3 laufen.

Hier mal die wesentlichen Codefragmente, die den ADC10 bedienen:
1
#define HumiditySensor  0x04    // P1.2  / Pin 4:  SHS A5 humiditiy
2
#define CondSensor  0x08    // P1.3  / Pin 5:  SHS A5 conductance
3
4
#define INCH_HumiditySensor  INCH_2    // ADC10 Input channel select for HumiditySensor
5
#define INCH_CondSensor    INCH_3    // ADC10 Input channel select for CondSensor
6
7
  ; Initialize ADC10
8
  mov.w  #SREF_0+ADC10SHT_3+ADC10SR+ADC10ON, ADC10CTL0
9
    ; SREF_0  Ref. Voltage.      VR+ = Vcc and VR- = Vss
10
    ; ADC10SHT_3  Sample & hold time.    64 x ADC10CLKs = 4µs
11
    ; ADC10SR  Sampling Rate: 50ksps
12
    ; ~REFOUT  Reference output
13
    ; ~REFBURST  Reference burst
14
    ; ~ADC10MSC  Multiple sample and conversion
15
    ; ~REF2_5V  Reference generator: 1.5 V
16
    ; ~REFON  Reference off
17
    ; ADC10ON  ADC10 on      on
18
    ; ~ADC10IE  ADC10 interrupt enable
19
    ; ~ADC10IFG  ADC10 interrupt flag
20
    ; ~ENC    Enable conversion
21
    ; ~ADC10SC  ADC10 start conversion
22
  mov.b  #CondSensor+HumiditySensor, ADC10AE0  ; ADC10 sensor input pins
23
24
25
; ------------------------------------------------
26
27
CmpSt_4 ; Conductivity sensor complete - store result
28
  ; Store conductivity data
29
    mov.w  ADC10MEM, CondSensData    ; Store ADC10 result

Ich hoffe, es nützt dir was.

von Heiko (Gast)


Lesenswert?

Vielen Dank für die Antworten.

Ich habe das Problem lösen können.

Das SHS_1 Bit darf NICHT gesetzt sein. Ist dieses gesetzt wartet der AD 
Wandler auf einen Interrupt durch Timer A. Dieser wird in der simplen 
Routiene nicht angesprochen und so wartet er bis in alle Ewigkeit......

Hier noch mal den richtigen Code mit Erläuterung zu jedem Befehl:

//Wandlung an Port P1.2 (A2)
//__________________________
            bic.w   #ENC,&ADC10CTL0         ; ENC Bit auf Null setzen, 
um Steuerbits verändern zu können
            bis.w   #SREF_1,&ADC10CTL0      ; Interne Referenz auswählen 
= (1) VCC = (2)
            bis.w   #REF2_5V,&ADC10CTL0     ; 2,5 V Referenz auswählen
            bis.w   #REFON,&ADC10CTL0       ; Interne Referenz 
einschalten
            bis.w   #ADC10SHT_2,&ADC10CTL0  ; Anzahl der Taktzyklen für 
eine Wandlung (4, 8, 16, 64)
            bis.w   #ADC10SR,&ADC10CTL0     ; Samplingrate des AD 
Wandlers auf 50 kbs
            bis.w   #ADC10ON,&ADC10CTL0     ; ADC einschalten


            call    #ZEIT3$                 ; Wartezeit aufrufen


            bis.w   #ADC10DIV_0,&ADC10CTL1  ; ADC Taktteilung
            bic.w   #SHS_1,&ADC10CTL1       ; Sample / Hold Source 1 nur 
bei Timer auslösung aktivieren!
            bis.w   #CONSEQ_2,&ADC10CTL1    ; Wiederholte Messung eines 
AD-Kanals

            bis.w   #INCH_2,&ADC10CTL1      ; Wahl des AD Eingangs 
(0,1,2,3)
            bis.b   #04h,&ADC10AE0          ; P1.2 ADC10 option select

            bis.w   #ENC,&ADC10CTL0         ; Einschalten des ADC 
(Steuerefehle blockiert)
            bis.w   #ADC10SC,&ADC10CTL0     ; Start sampling/conversion

            call    #ZEIT3$                 ; Wartezeit aufrufen

            mov.w   &ADC10MEM,R8             ; AD Wandler Ergebnis 
speichern
ret

von Uhu U. (uhu)


Lesenswert?

Heiko schrieb:
1
> bis.w   #SREF_1,&ADC10CTL0      ; Interne Referenz auswählen
2
> = (1) VCC = (2)
3
>             bis.w   #REF2_5V,&ADC10CTL0     ; 2,5 V Referenz auswählen
4
>             bis.w   #REFON,&ADC10CTL0       ; Interne Referenz
5
> einschalten
6
>             bis.w   #ADC10SHT_2,&ADC10CTL0  ; Anzahl der Taktzyklen für
7
> eine Wandlung (4, 8, 16, 64)
8
>             bis.w   #ADC10SR,&ADC10CTL0     ; Samplingrate des AD
9
> Wandlers auf 50 kbs
10
>             bis.w   #ADC10ON,&ADC10CTL0     ; ADC einschalten

Du weißt, daß du diese fünf Befehle in einen einzigen packen kannst? 
(Bei den kleinen Controllern kommt man recht schnell ans Ende der 
Fahnenstange.)

von Heiko (Gast)


Lesenswert?

Ja klar, ich habe sie extra auseinander gezogen um sie übersichtlich 
darzustellen.
Die CTL0 und CTL1 Steuerbefehle lassen sich in zwei Zeilen zusammen 
fassen.
Ist halt nur nicht so übersichtlich...
Bei der Anwendung ist der Programmspeicher mehr als ausreichend, zumal 
ich in Assembler schreibe und von daher eh weniger Code kompiliere.

von Uhu U. (uhu)


Lesenswert?

Heiko schrieb:
> Bei der Anwendung ist der Programmspeicher mehr als ausreichend, zumal
> ich in Assembler schreibe und von daher eh weniger Code kompiliere.

Na ja, wenn die Anwendung einfag genug ist... Ich habe mit ASM schon mal 
einen voll gekriegt, bevor die Anwendung fertig war.

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
Noch kein Account? Hier anmelden.