Gast
#3804061
Hallo Leute,
Ich verwende den Atmel XMEGA32A4U Mikrocontroller. Ich versuche den ADC
zu laufen zu bekommen, jedoch will Dieser noch nicht fehlerfrei
funktionieren.
Ich habe den ADC den Input Mode auf Single Ended gestellt und den Gain
auf x1. Ich benutze keine Interruptroutine sondern starte die
Digitalisierung von einem Werte und polle dann das dazugehörige
Interruptflag. Sofern die Digitalisierung abgeschlossen ist lösche ich
das Interruptflag und lese dann den Messwert aus. Demnach benutze ich
keine Eventstruktur und keinen Sweep.
Das Ergebnis soll ein unsigned 12 Bit Wert sein (right adjust).
Hier mein Quellcode:
// Calibration values are stored at production time
// Load the calibration value for 12 Bit resolution from the signature
row
ADCA.CALL = read_calibration_byte(PROD_SIGNATURES_START +
ADCACAL0_offset);
ADCA.CALH = read_calibration_byte(PROD_SIGNATURES_START +
ADCACAL1_offset);
//Clock frequency: 2000,000 kHz
ADCA.PRESCALER = ADC_PRESCALER_DIV16_gc;
// Refere4nce: Set Vref to internal 1.00 V Bandgab
// With effectively 11-bit resolution, this means each LSB
// will represent approximately 0.5mV.
// Temperature reference: Off
ADCA.REFCTRL = ADC_REFSEL_INT1V_gc | (1<<ADC_BANDGAP_bp) |
(0<<ADC_TEMPREF_bp);
// Enable ADC, module A
ADCA.CTRLA = ADC_ENABLE_bm; // 0x01
// Insert a delay to allow the ADC common mode voltage to stabilize
delay_us(2);
// Gain stage impedance mode: High-impedance sources
// Current consumption: Apply no limit to ADC sample rate
// Conversion mode: Unsigned
// Free Running mode: Off (single conversion upon trigger)
// Resolution: Resolution is set to 12-bit, right justified (11-bit
effective in signed mode)
ADCA.CTRLB = (0<<ADC_IMPMODE_bp) | ADC_CURRLIMIT_NO_gc |
(0<<ADC_CONMODE_bp) | (0<<ADC_FREERUN_bp) |ADC_RESOLUTION_12BIT_gc;
// Not implementing Event System so ensure EVCTRL is reading zeros
// AD conversion is started by software
ADCA.EVCTRL = ADC_EVACT_NONE_gc; // 0x00
// Ensure the ADC complete flag is cleared (by writing a '1' to it)
ADCA.INTFLAGS = ADC_CH3IF_bm | ADC_CH2IF_bm | ADC_CH1IF_bm |
ADC_CH0IF_bm; // 0x0F
// ADC channel 0, 1, 2, 3 gain: 1
// ADC channel 0, 1, 2, 3 input mode: Single-ended positive input signal
ADCA.CH0.CTRL = (0<<ADC_CH_START_bp) | ADC_CH_GAIN_1X_gc |
ADC_CH_INPUTMODE_SINGLEENDED_gc; // 0x01;
ADCA.CH1.CTRL = (0<<ADC_CH_START_bp) | ADC_CH_GAIN_1X_gc |
ADC_CH_INPUTMODE_SINGLEENDED_gc; // 0x01;
ADCA.CH2.CTRL = (0<<ADC_CH_START_bp) | ADC_CH_GAIN_1X_gc |
ADC_CH_INPUTMODE_SINGLEENDED_gc; // 0x01;
ADCA.CH3.CTRL = (0<<ADC_CH_START_bp) | ADC_CH_GAIN_1X_gc |
ADC_CH_INPUTMODE_SINGLEENDED_gc; // 0x01;
// ADC channel 0 positive input: ADC0 pin
// ADC channel 0 negative input: GND
// ADC channel 1 positive input: ADC1 pin
// ADC channel 1 negative input: GND
// ADC channel 2 positive input: ADC2 pin
// ADC channel 2 negative input: GND
// ADC channel 3 positive input: ADC3 pin
// ADC channel 3 negative input: GND
ADCA.CH0.MUXCTRL = ADC_CH_MUXPOS_PIN0_gc; // 0x00;
ADCA.CH1.MUXCTRL = ADC_CH_MUXPOS_PIN1_gc; // 0x10
ADCA.CH2.MUXCTRL = ADC_CH_MUXPOS_PIN2_gc; // 0x20
ADCA.CH3.MUXCTRL = ADC_CH_MUXPOS_PIN3_gc; // 0x30
// Channel 0, 1, 2, 3 interrupt: Disabled
ADCA.CH0.INTCTRL = ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_OFF_gc;
// 0x00
ADCA.CH1.INTCTRL = ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_OFF_gc;
// 0x00
ADCA.CH2.INTCTRL = ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_OFF_gc;
// 0x00
ADCA.CH3.INTCTRL = ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_OFF_gc;
// 0x00
void get_adc_sample(unsigned char *new_adc_sample)
{
PORTD.OUTSET = 0x08;
ADCA.CH0.MUXCTRL = ADC_CH_MUXPOS_PIN0_gc;
ADCA.CH1.MUXCTRL = ADC_CH_MUXPOS_PIN1_gc;
ADCA.CH2.MUXCTRL = ADC_CH_MUXPOS_PIN2_gc;
ADCA.CH3.MUXCTRL = ADC_CH_MUXPOS_PIN3_gc;
// Start the AD conversion on channel 0, 1 ,2 ,3
ADCA.CTRLA |= 0x3C;
// Wait for the AD conversion to complete
while ((ADCA.INTFLAGS & 0x0F) == 0);
// Clear the interrupt flag
ADCA.INTFLAGS = ADCA.INTFLAGS;
new_adc_sample[0] = ADCA.CH0.RESH;
new_adc_sample[1] = ADCA.CH0.RESL;
new_adc_sample[2] = ADCA.CH1.RESH;
new_adc_sample[3] = ADCA.CH1.RESL;
new_adc_sample[4] = ADCA.CH2.RESH;
new_adc_sample[5] = ADCA.CH2.RESL;
new_adc_sample[6] = ADCA.CH3.RESH;
new_adc_sample[7] = ADCA.CH3.RESL;
}
Der ADC läuft auch jedoch erhalte ich sehr häufe große 256 oder 512
Digit Sprünge. Dies kann ich mir nicht erkären. Ich habe die Samplerate
bereits von 2MBit auf ca 65kHz reduziert. Den Low-Impedanz Mode
ausprobiert hat jedoch alles nichts gebracht. Ich habe direkt am
Mikrocontroller Pin mit einem Oscilloscope gemessen. Dort konnte ich
keine Sprünge erkennen. Ich habe bereits auch das Errata durchgelesen
und beim ADC schein alles laut Datenblatt ok zu sein.
