Forum: Mikrocontroller und Digitale Elektronik PIC mit externer Referenz an AD-Wandler


von rs1806 (Gast)


Lesenswert?

Hallo,

ich möchte den internen ADC eines dsPIC33 mit einer externen Referenz 
nutzen. Leider werde ich aus dem Datenblatt nicht ganz schlau, welche 
Pins ich am besten für die Referenzvorgabe nutze. Kann ich meine 
Referenzspannungsquelle (2,5 V) einfach direkt an AVDD anschließen und 
GND an AVSS (mit einem dazwischen geschaltetem 100 nF Kondensator) oder 
muss ich VREF+ und VREF- dazu nutzen? Problem ist, dass ich nur noch 
zwei Pins (RA0 und RA1, die gleichzeitig auch VREF+ und VREF- sind) an 
meinem Chip freihabe. D.h. ich kann nicht gleichzeitig VREF+ und VREF- 
nutzen, da ich ja einen Pin noch zum Einlesen der analogen Spannung 
benötige.

Schonmal vielen Dank für die Unterstützung!!!!

von San L. (zwillingsfreunde)


Lesenswert?

Hallo

Das kommt ganz auf dein Programm draufan. Du hast die möglichkeit, deine 
Referenzspannung mithilfe eines Registers selbst zu definieren.

Man kann beispielsweise direkt die Betriebsspannung als Referenz 
verwenden. (VDD & VSS). Problem dabei ist allerdings, dass diese 
Spannung meist nicht sonderlich stabil ist.
Für eine präzise Analog-Digital Messung (Weiss nicht was du vor hast, 
wie prozäise das sein muss) sollte die Referenz möglichst weniger als 
0,1 % schwanken.
Dazu wird meist eine externe Referenz verwendet. Diese wird, wie von dir 
richtig erkannt, an den Pins VREF+ und VREF- angeschlossen.

von Chris B. (dekatz)


Lesenswert?

rs1806 schrieb:
> Hallo,
>
>......Problem ist, dass ich nur noch
> zwei Pins (RA0 und RA1, die gleichzeitig auch VREF+ und VREF- sind) an
> meinem Chip freihabe. D.h. ich kann nicht gleichzeitig VREF+ und VREF-
> nutzen, da ich ja einen Pin noch zum Einlesen der analogen Spannung
> benötige.

Dann wählst du bei der ADC-Configuration die Kombination VREF+ _ AVSS.
AVDD und AVSS verbindest du mit den entsprechenden VDD und VSS Pins.

von San L. (zwillingsfreunde)


Lesenswert?

Chris B. schrieb:
> Dann wählst du bei der ADC-Configuration die Kombination VREF+ _ AVSS.
> AVDD und AVSS verbindest du mit den entsprechenden VDD und VSS Pins.

An das habe ich garnicht Gedacht, funktioniert natürlich auch. ;)

http://ww1.microchip.com/downloads/en/DeviceDoc/70286C.pdf
Auf der Seite 232 findest du die Einstellung von den Referenzspannungen.
Stichwort ADxCON2 Register.

von rs1806 (Gast)


Lesenswert?

Vielen Dank für die schnelle Hilfe!! Eine Referenzspannung von 2,5 V 
habe ich bereits auf meiner Platine. Werde dann, wie ihr geschrieben 
habt, die 2,5 V an VREF+ (RA0) und GND an AVSS anschließen, d.h. VCFG = 
001 im ADXCON2-Register. So habe ich noch einen PIN frei, um die zu 
messende Spannung einzulesen. Ist es sinnvoll noch Kondensatoren zu 
ergänzen?

von San L. (zwillingsfreunde)


Angehängte Dateien:

Lesenswert?

rs1806 schrieb:
> Ist es sinnvoll noch Kondensatoren zu
> ergänzen?

Zwischen VREF und AVSS sollte auf jedenfall ein Kondensator zur 
Stabilisierung hin. Ein 100nF tuts wohl schon, alternativ dazu eine 
Schaltung im Anhang, wie ich meine AVCC Inputs meist beschalte.

von rs1806 (Gast)


Lesenswert?

Leider bekomme ich den AD-Wandler nicht richtig zum laufen. Zum Testen 
habe ich meine Schaltung vorerst mal auf dem Steckbrett aufgebaut. Da 
mir die Referenzspannungsquelle nur als SMD-Bauteil vorliegt, nutze ich 
momentan noch ein zusätzliches Netzteil zur Vorgabe der 
Referenzspannung. Dieses Netzteil ist an den Pin VREF+ angeschlossen und 
über einen 100nF Kondensator mit Ground verbunden. AVdd ist mit der 
Versorgungsspannung des PICs (3,3V) verbunden und AVss liegt auf Ground. 
Um die AD-Wandlung zu kontrollieren, schicke ich die gewandelte Spannung 
an einen DAC und schaue mir das SPI-Signal auf dem Oszi an. Dort sehe 
ich, dass die Wandlung grundsätzlich funktioniert (das SPI-Signal ändert 
sich entsprechend der Spannungsänderung am AN1-Pin). Allerdings habe ich 
Ausreißer, die bis ins 8. oder 9. Bit gehen. Bin mir jetzt nicht sicher, 
ob ich in meinem Programm einen Fehler habe, ob an der Schaltung etwas 
falsch ist, oder ob es einfach nur am Steckbrett und den nicht optimalen 
Bedingungen bezüglich der Referenzspannungsquelle liegt. Noch zum Timing 
des ADC's: Ich bringe einen externen 20MHz Quarz per PLL auf 40MHz. TCY 
müsste dann 50ns sein. Der AD-Wandler benötigt als minimale Clock Period 
117ns. Das dreifache von TCY sollte also reichen.
1
int main (void) {  
2
  
3
  RCONbits.SWDTEN = 0;  
4
  
5
//auf externen Quarz umschalten
6
  PLLFBD = 38;                          //M = 40
7
  CLKDIVbits.PLLPOST = 0b01;                     //N2 = 4
8
  CLKDIVbits.PLLPRE = 0b00011;                  //N1 = 5
9
  __builtin_write_OSCCONH(0x03);
10
  __builtin_write_OSCCONL(OSCCON | 0x01);
11
  while(OSCCONbits.COSC != 0b011);
12
  while(OSCCONbits.LOCK != 1){};  
13
14
//ADC
15
16
  TRISAbits.TRISA0 = 1;                     //VREF+
17
  TRISAbits.TRISA1 = 1;                     //Analog In
18
19
  AD1CON1bits.ADON = 0;                      //AD-Wandler aus
20
  AD1PCFGL = 0xFFFF;                        //alles digital
21
  AD1PCFGLbits.PCFG1 = 0;                   //AN1 für Vin
22
  AD1PCFGLbits.PCFG0 = 0;                   //AN0 für Vref+
23
                  
24
  AD1CON1bits.AD12B = 1;                    //12bit
25
  AD1CON1bits.FORM =0b00;                   //Integer
26
  AD1CON1bits.ASAM = 0;                     //Sampling wenn Samp-Bit = 1
27
  AD1CON1bits.SSRC = 0b111;                 //Internal Counter ends sampling and starts conversion
28
  AD1CON2bits.VCFG = 0b001;                 //Vref+ und AVss als Vref
29
  AD1CON2bits.CHPS = 0b00;                  //Converts CH0
30
  AD1CON3bits.ADRC = 0;                     //Clock derived from System Clock 
31
  AD1CON3bits.SAMC = 0b00100;               //Sample Time 3 TAD
32
  AD1CON3bits.ADCS = 0b00000010;            //TAD = 3 mal TCY = 150ns
33
  AD1CHS0bits.CH0NA = 0;                    //CH0 neagativ: VREFL
34
  AD1CHS0bits.CH0SA = 0b00001;              //CH0 positiv: AN1 
35
36
   IEC0bits.AD1IE = 0;                        //Interrupt deaktiviert
37
   AD1CON1bits.ADON = 1;
38
 
39
   while(1){  }
40
41
}
42
43
44
void __attribute__((interrupt, no_auto_psv)) _T4Interrupt( void ){
45
          int spannung;
46
  
47
    AD1CON1bits.SAMP = 1;
48
    while(!AD1CON1bits.DONE);
49
    spannung = ADC1BUF0;
50
51
          IFS1bits.T4IF = 0;
52
53
}

Nochmals vielen Dank für die Unterstützung!

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.