Hallo,
der ADC dieses PIC hat Differenzeingänge und zwei Muxer. Du musst also
mindestens ZWEI Eingänge programmieren.
Das tut man mit CH0SA für den positiven Eingang und CH0NA für den
negativen EIngang. Oder CH0SB und CH0NB für MUX_B.
Wenn du ganz klassich single-ended messen willst, kannst du CH0NA
einfach mit Masse verbinden, indem du einfach 11101 auf CH0NA
programmierst, und dann einfach CH0SA auf den gewünschten Port Mappen.
Beispiel:
Du willst AN3 gegen Masse messen: CH0SA = 3; CH0NA = 0;
Du willst AN3 gegen AN2 messen : CH0SA = 3; CH0NA = 2;
Tipp:
Das Diagramm Fig. 24-1 betrachten.
Folgender Code läuft auf einem PIC24FJ128GA204, der den gleichen ADC
hat:
1 | void initadc(uint8_t init)
|
2 | {
|
3 | if(init != 0){
|
4 |
|
5 | aVBATT = tVBATT = 1;
|
6 | aVUSB = tVUSB = 1;
|
7 |
|
8 | AD1CON1 = 0;
|
9 | AD1CON1bits.ADSIDL = 0; //Stopp in idle
|
10 | AD1CON1bits.MODE12 = 1; //12Bit Mode
|
11 | AD1CON1bits.FORM = 0b00; //dezimales Format
|
12 | AD1CON1bits.SSRC = 0b0111; //Autoconvert
|
13 |
|
14 | AD1CON2 = 0x00;
|
15 | AD1CON3 = 0x00;
|
16 | AD1CON3bits.SAMC = 0b10000; //SampleTime 16 TAD (TAD = Taktperiode)
|
17 | AD1CON3bits.ADCS = 0b00000101; // TAD = 4 * TCY (ADCCLOCK = 4MHz / 4)
|
18 |
|
19 | AD1CON5 = 0x0000;
|
20 | AD1CON5bits.LPEN = 1; //Zurück in Low Power Mode nach sscan
|
21 | AD1CON5bits.BGREQ = 1; //Bandgap Referenz einschalten
|
22 |
|
23 |
|
24 | AD1CHSbits.CH0NA = 000; //<<-- damit erden wir den neg. Eingang von MUXA
|
25 | AD1CON1bits.ADON = 0; //dont switch ADC on for now
|
26 | }
|
27 | else{
|
28 | AD1CON1 = AD1CON2 = AD1CON3 = AD1CON5 = 0;
|
29 | }
|
30 | }
|
31 |
|
32 |
|
33 | unsigned int ADCSample(uint16_t *OUT, unsigned int Channel)
|
34 | {
|
35 | unsigned int CNT = 0;
|
36 | if(Channel >=31)
|
37 | { //report invalid value
|
38 | return 1;
|
39 | }
|
40 | AD1CHSbits.CH0SA = Channel; //<<<<-- damit wählen wir den postiven EIngang aus
|
41 | AD1CON1bits.ADON = 1; //Enable ADC
|
42 | //__delay_us(80);
|
43 | AD1CON1bits.SAMP = 1; //Sample
|
44 | //__delay_us(80);
|
45 | //wait for result with timeout
|
46 | while(!AD1CON1bits.DONE && (CNT < TIMEOUT)){CNT++;};
|
47 | if(CNT >= TIMEOUT)
|
48 | { //Timeout
|
49 | AD1CON1bits.ADON = 0; //disable ADC
|
50 | return 2;
|
51 | }
|
52 | *OUT = ADC1BUF0;
|
53 | AD1CON1bits.ADON = 0; //disable ADC
|
54 | return 0;
|
55 | }
|
Das ist Pfusch, und sehr simpel, funktioniert aber. Für meinen Zweck
(Batteriespannung messen) hat es immer getan.