Hallihallo, ich stehe gerade etwas auf dem Schlauch :D Ich möchte Spannungen am ADC des SAMD21J17D messen. Folgende Einstellungen gelten für den ADC: VRef = 3,3V / 2 Resolution 12 Bit Hardwaremäßiger Mittelwertbildung (1024 mal gemessen und addiert, dann durch 1024 geteilt) Mein Oszi sagt je nachdem was ich einstelle liegen -80mV .. 1,9V an. Das eingestelltes ADC sagt mir (raw werte) 470 für 0V und etwa 1000..1024 für 1,5V an. Erhöhe ich die Spannung nur leicht, dann scheint es einen wrap around zu geben und er springt gegen 0. Ich verstehe nicht was hier passiert. Musste der ADC-Wert um die 0V nicht 0 sein? Sollte nach der Überschreitung der Referenzspannung der ADC-Wert nicht sättigen? Müsste der Maximalwert bei 12Bit nicht bei 2^12 = 4096 liegen? Ich hab das spaßenhalber mal auf 8bit umgeschalten. da habe ich die gleichen effekte nur, dass der wrap-around bei 64 stattfinden...
Zeige mal den Quelltext, damit wir sehen wie du den ADC konfiguriert
hast.
Der Code mit dem du den Mittelwert bildest wäre auch von Interesse.
> Müsste der Maximalwert bei 12Bit nicht bei 2^12 = 4096 liegen?
ja
1 | void adc_init() { |
2 | |
3 | |
4 | /* Temperature Sensor Enable bit VREF.TSEN |
5 | Bandgap Reference Voltage Generator VREF.BGOUTEN */ |
6 | REG_SYSCTRL_VREF = 6; // BGOUTEN | TSEN |
7 | |
8 | REG_ADC_CTRLA = 1; // reset ADC |
9 | while(REG_ADC_STATUS); |
10 | |
11 | |
12 | #define REFCTRL_INT1V 0x00 |
13 | #define REFCTRL_INTVCC0 0x01 |
14 | #define REFCTRL_INTVCC1 0x02 |
15 | #define REFCTRL_VREFA 0x03 |
16 | #define REFCTRL_VREFB 0x04 |
17 | REG_ADC_REFCTRL = REFCTRL_INTVCC1; |
18 | while(REG_ADC_STATUS); |
19 | |
20 | |
21 | #define AVGCTRL_AVG1 0x0 |
22 | #define AVGCTRL_AVG8 0x3 || 0x03 << 4; |
23 | #define AVGCTRL_AVG128 0x7 || 0x04 << 4; |
24 | #define AVGCTRL_AVG1024 0xA || 0x04 << 4; |
25 | REG_ADC_AVGCTRL = AVGCTRL_AVG1024; |
26 | while(REG_ADC_STATUS); |
27 | |
28 | |
29 | REG_ADC_SAMPCTRL = 0; // Sample_Time = 2 * (val + 1) / (F_ADC) |
30 | while(REG_ADC_STATUS); |
31 | |
32 | REG_ADC_INTENSET = 1; // enable RESRDY (result ready interrupt) |
33 | while(REG_ADC_STATUS); |
34 | |
35 | #define PRE_DIV4 0 << 8 |
36 | #define PRE_DIV64 4 << 8 |
37 | #define PRE_DIV512 7 << 8 |
38 | #define RESSEL12BIT 0 << 4 |
39 | #define RESSEL16BITAVG 1 << 4 |
40 | #define RESSEL10BIT 2 << 4 |
41 | #define RESSEL8BIT 3 << 4 |
42 | #define CORREN 1 << 3 // Digital Correction Logic Enabled |
43 | #define FREERUN 1 << 2 |
44 | #define LEFTADJ 1 << 1 // Left-Adjusted Result |
45 | #define DIFFMODE 1 << 0 |
46 | REG_ADC_CTRLB = RESSEL12; |
47 | while(REG_ADC_STATUS); |
48 | } |
1 | ui8 adc_get(ui16*adc_val, ui32 inputctrl) { |
2 | |
3 | REG_ADC_INPUTCTRL = inputctrl; |
4 | while(REG_ADC_STATUS); |
5 | |
6 | REG_ADC_CTRLA = 2; // enable ADC |
7 | while(REG_ADC_STATUS); |
8 | |
9 | REG_ADC_SWTRIG = 2; // start conversion |
10 | while(REG_ADC_STATUS); |
11 | |
12 | wait(1000); |
13 | |
14 | if(REG_ADC_INTFLAG & 1) { |
15 | REG_ADC_INTFLAG = 0xf; |
16 | *adc_val = REG_ADC_RESULT; |
17 | state = init1; |
18 | result = TRUE; |
19 | } |
20 | |
21 | return 0; |
22 | } |
der Aufruf zum messen (INPUTCTRL im zweiten Argument): adc_get(&adc_value, 0x05 | (0x19 << 8) | 0xf << 24);
Für mich sieht das alles stimmig aus, außer der von dir beobachtete Fehler. Ich kann ihn nicht erklären.
Hallo, Ich bin ein Stückchen weiter. Den Offset kann ich beseitigen indem ich den Prescaler erhöhe. Ka weshalb. Im Datenblatt steht leider auch nichts dazu welchen mindestwerte im Prescaler vorliegen sollen. Die anderen Fehler waren Folgefehler, in einem Codeschnippsel den ich hier nicht veröffentlicht habe. Ich habe die adc werte aufsummiert und durch die anzahl geteilt. hier hätte ich besser aufpassen müssen, denn auch irgendwann ist einmal eine 32bit variable übergelaufen und .. das war der wrap around :D
Aber ich verstehe nicht wieso der offset größer wird, wenn der ADC mit nen schneller takt läuft.
Der ADC basiert ja darauf, dass er schrittweise mit einem DAC Spannungen zum Vergleich erzeugt und diese mittels Komparator mit deinem Input vergleicht. Wenn das zu schnell passiert, vergleicht er Grütze mit deinem Input. Oder die Ausgabe des Komparator wird zu früh verarbeitet, während er noch mit Vergleichen beschäftigt ist. Das Resultat sind ziemlich zufällige Ergebnisse.
...kommt ggf. auch drauf an, was Du da misst und wie der ADC Eingang beschaltet ist.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.