Jared Baxter
/
Impedance_Fast_Circuitry
Fork of DSP_200kHz by
DMA_sampling/adc.cpp
- Committer:
- bmazzeo
- Date:
- 2016-02-17
- Revision:
- 55:2526b3317bc8
- Parent:
- 54:1697dc574b96
- Child:
- 74:ebc9f09fda11
File content as of revision 55:2526b3317bc8:
#include "adc.h" /* From page 869 of the user manual: Before the ADC module can be used to complete conversions, an initialization procedure must be performed. A typical sequence is: 1. Calibrate the ADC by following the calibration instructions in Calibration function. 2. Update CFG to select the input clock source and the divide ratio used to generate ADCK. This register is also used for selecting sample time and low-power configuration. 3. Update SC2 to select the conversion trigger, hardware or software, and compare function options, if enabled. 4. Update SC3 to select whether conversions will be continuous or completed only once (ADCO) and whether to perform hardware averaging. 5. Update SC1:SC1n registers to select whether conversions will be single-ended or differential and to enable or disable conversion complete interrupts. Also, select the input channel which can be used to perform conversions. */ DigitalOut green(LED_GREEN); DigitalOut red(LED_RED); Serial debug(USBTX, USBRX); void adc_init() { // Turn on the ADC0 and ADC1 clocks SIM_SCGC6 |= SIM_SCGC6_ADC0_MASK; SIM_SCGC3 |= SIM_SCGC3_ADC1_MASK; // Set ADC hardware trigger to PDB0 SIM_SOPT7 = SIM_SOPT7_ADC0TRGSEL(0); // Select triggering by PDB and select pre-trigger A SIM_SOPT7 = SIM_SOPT7_ADC1TRGSEL(0); // Select triggering by PDB and select pre-trigger A // turn on the clock to the PDB // SIM->SCGC6 |= SIM_SCGC6_PDB_MASK; // set ADC trigger to PDB0 // SIM_SOPT7 = SIM_SOPT7_ADC0TRGSEL(0); // This lets the clocks go to the ADC // SIM_SCGC6 |= SIM_SCGC6_ADC0_MASK; // SIM_SCGC3 |= SIM_SCGC3_ADC1_MASK; /* // This lets the clocks go to the PDB SIM_SCGC6 |= SIM_SCGC6_PDB_MASK; // Set PDB to be enabled and have continous triggers PDB0_SC = PDB_SC_DMAEN_MASK // DMA Enable | PDB_SC_TRGSEL(0xf) // Software trigger | PDB_SC_PDBEN_MASK // Set to continuous mode | PDB_SC_LDOK_MASK; // Loading mask PDB0_SC |= PDB_SC_SWTRIG_MASK; // enable software trigger (start the PDB) // This now routes the triggers SIM_SOPT7 = SIM_SOPT7_ADC0TRGSEL(0); SIM_SOPT7 = SIM_SOPT7_ADC1TRGSEL(0); */ /* From page 853 of the user manual Prior to calibration, the user must configure the ADC's clock source and frequency, low power configuration, voltage reference selection, sample time, and high speed configuration according to the application's clock source availability and needs. */ ADC0_SC1A = 0x0C; //AIEN = 0, DIFF = 0, Channel = AD12 (PTB2) ADC1_SC1A = 0x0E; //AIEN = 0, DIFF = 0, Channel = AD14 (PTB10) ADC0_CFG1 = 0x0C; //ADLPC = 0, ADIV = 0, ADLSMP = 0, MODE = 0b11, ADICLK = 00 (16-bit single-ended) ADC1_CFG1 = 0x0C; //ADLPC = 0, ADIV = 0, ADLSMP = 0, MODE = 0b11, ADICLK = 00 (16-bit single-ended) // ADC0_CFG1 = 0x00; //ADLPC = 0, ADIV = 0, ADLSMP = 0, MODE = 0b00, ADICLK = 00 (16-bit single-ended) // ADC1_CFG1 = 0x00; //ADLPC = 0, ADIV = 0, ADLSMP = 0, MODE = 0b00, ADICLK = 00 (16-bit single-ended) // It is necessary not to have hardware trigger for calbiration ADC0_CFG2 = 0x00; // MUXSEL = 0, ADACKEN = 0, ADHSC = 0, ADLSTS = 0 (does not matter - short sample time) ADC1_CFG2 = 0x00; // MUXSEL = 0, ADACKEN = 0, ADHSC = 0, ADLSTS = 0 (does not matter - short sample time) // Use averaging to make calibration better ADC0_SC3 = 0x07; // CAL = 0, CALF = 0, res[5:4], ADCO = 0 (continuous conversion), AVGE = 1, AVGS = 11 ADC1_SC3 = 0x07; // CAL = 0, CALF = 0, res[5:4], ADCO = 0 (continuous conversion), AVGE = 1, AVGS = 11 // calibrate the ADC (following Joey's code example) ADC0_SC3 |= ADC_SC3_CAL_MASK; // start calibration while(ADC0_SC3&ADC_SC3_CALF_MASK) {} // wait for calibration to complete ADC1_SC3 |= ADC_SC3_CAL_MASK; // start calibration while(ADC1_SC3&ADC_SC3_CALF_MASK) {} // wait for calibration to complete debug.printf("ADC0_CLP0:%d\r\n", ADC0_CLP0); debug.printf("ADC0_CLP1:%d\r\n", ADC0_CLP1); debug.printf("ADC0_CLP2:%d\r\n", ADC0_CLP2); debug.printf("ADC0_CLP3:%d\r\n", ADC0_CLP3); debug.printf("ADC0_CLPS:%d\r\n", ADC0_CLPS); // calculate the gains (see user manual page 864) int16_t gain = (ADC0_CLP0+ADC0_CLP1+ADC0_CLP2+ADC0_CLP3+ADC0_CLP4+ADC0_CLPS); gain = gain / 2; // divide by 2 gain |= 0x8000; // set the MSB ADC0_PG = gain; gain = (ADC1_CLP0+ADC1_CLP1+ADC1_CLP2+ADC1_CLP3+ADC1_CLP4+ADC1_CLPS); gain = gain / 2; // divide by 2 gain |= 0x8000; // set the MSB ADC1_PG = gain; gain = (ADC0_CLM0+ADC0_CLM1+ADC0_CLM2+ADC0_CLM3+ADC0_CLM4+ADC0_CLMS); gain = gain / 2; // divide by 2 gain |= 0x8000; // set the MSB ADC0_MG = gain; gain = (ADC1_CLM0+ADC1_CLM1+ADC1_CLM2+ADC1_CLM3+ADC1_CLM4+ADC1_CLMS); gain = gain / 2; // divide by 2 gain |= 0x8000; // set the MSB ADC1_MG = gain; // ADC0_SC3 &= ~ADC_SC3_CAL_MASK; // stop calibration // ADC1_SC3 &= ~ADC_SC3_CAL_MASK; // stop calibration // Now set up for use in the rest of the program - software trigger ADC0_SC2 = 0x04; // ADACT = 0, ADTRG = 0 (HW trigger), ACFE = 0, ACFGT = 0, ACREN = 0, DMAEN = 1, REFSEL = 00 (DMAEN needs to be asserted) ADC1_SC2 = 0x04; // ADACT = 0, ADTRG = 0 (HW trigger), ACFE = 0, ACFGT = 0, ACREN = 0, DMAEN = 1, REFSEL = 00 (DMAEN needs to be asserted) // ADC0_SC3 = 0x08; // CAL = 0, CALF = 0, res[5:4], ADCO = 1 (continuous conversion), AVGE = 0, AVGS = 00 // ADC1_SC3 = 0x08; // CAL = 0, CALF = 0, res[5:4], ADCO = 1 (continuous conversion), AVGE = 0, AVGS = 00 ADC0_SC3 = 0x00; // CAL = 0, CALF = 0, res[5:4], ADCO = 0 (continuous conversion), AVGE = 0, AVGS = 00 ADC1_SC3 = 0x00; // CAL = 0, CALF = 0, res[5:4], ADCO = 0 (continuous conversion), AVGE = 0, AVGS = 00 // A write to SC1A is necessary as a software trigger ADC0_SC1A = 0x0C; //AIEN = 0, DIFF = 0, Channel = AD12 (PTB2) ADC1_SC1A = 0x0E; //AIEN = 0, DIFF = 0, Channel = AD14 (PTB10) while( (ADC1_SC1A&ADC_SC1_COCO_MASK)) {} //gain = ADC0_RA; // read the register to clear SC1A[COCO] debug.printf("ADC0_RA:%i\r\n", ADC0_RA); debug.printf("ADC0_RB:%i\r\n", ADC0_RB); debug.printf("ADC1_RA:%i\r\n", ADC1_RA); debug.printf("ADC1_RB:%i\r\n", ADC1_RB); /* ADC0_SC1A = 0x0C; //AIEN = 0, DIFF = 0, Channel = AD12 (PTB2) ADC1_SC1A = 0x0E; //AIEN = 0, DIFF = 0, Channel = AD14 (PTB10) while( (ADC1_SC1A&ADC_SC1_COCO_MASK)) {} debug.printf("ADC1_RA:%i\r\n", ADC1_RA); ADC0_SC1A = 0x0C; //AIEN = 0, DIFF = 0, Channel = AD12 (PTB2) ADC1_SC1A = 0x0E; //AIEN = 0, DIFF = 0, Channel = AD14 (PTB10) while( (ADC1_SC1A&ADC_SC1_COCO_MASK)) {} debug.printf("ADC1_RA:%i\r\n", ADC1_RA); */ // Now set up for use in the rest of the program - HARDWARE trigger ADC0_SC2 = 0x44; // ADACT = 0, ADTRG = 1 (HW trigger), ACFE = 0, ACFGT = 0, ACREN = 0, DMAEN = 1, REFSEL = 00 (DMAEN needs to be asserted) ADC1_SC2 = 0x44; // ADACT = 0, ADTRG = 1 (HW trigger), ACFE = 0, ACFGT = 0, ACREN = 0, DMAEN = 1, REFSEL = 00 (DMAEN needs to be asserted) // adebug.printf("Calbiration complete. Hardware continuous conversion running.\r\n"); // The ADCs are now just continuously converting and generating DMA signals after each conversion }