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!