Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of Impedance_Fast_Circuitry by
adc.cpp
- Committer:
- timmey9
- Date:
- 2015-01-31
- Revision:
- 46:a015ebf4663b
- Parent:
- 45:d591d138cdeb
- Child:
- 47:54fafe151669
File content as of revision 46:a015ebf4663b:
#include "adc.h" /* TODO: remove interrupt handlers add calibration change clock speed Possible causes of the triggering problem: more multiplexing somehow? does the ADC interrupt need to be enabled? clock speed? hardware/software trigger channel A or B? single vs continuous mode does asynchronous clock have to do with this? */ DigitalOut toggle1(PTC16); DigitalOut green(LED_GREEN); DigitalOut red(LED_RED); Serial debug(USBTX,USBRX); void adc_init() { // red, indicating now ready red = 0; green = 1; // 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); SIM_SOPT7 = SIM_SOPT7_ADC1TRGSEL(0); // Setup Configuration Register 1 ADC0_CFG1 = 0; // clear register ADC0_CFG1 |= ADC_CFG1_ADICLK(0); // select bus clock ADC0_CFG1 |= ADC_CFG1_MODE(3); // select 16-bit 2's complement output ADC0_CFG1 |= ADC_CFG1_ADIV(0); // select short sample time ADC0_CFG1 &= ~ADC_CFG1_ADLSMP_MASK; // select short sample time ADC0_CFG1 &= ~ADC_CFG1_ADLPC_MASK; // select normal power configuration ADC1_CFG1 = 0; // clear register ADC1_CFG1 |= ADC_CFG1_ADICLK(0); // select bus clock ADC1_CFG1 |= ADC_CFG1_MODE(3); // select 16-bit 2's complement output ADC1_CFG1 |= ADC_CFG1_ADIV(0); // select short sample time ADC1_CFG1 &= ~ADC_CFG1_ADLSMP_MASK; // select short sample time ADC1_CFG1 &= ~ADC_CFG1_ADLPC_MASK; // select normal power configuration // Setup Configuration Register 2 ADC0_CFG2 = 0; // clear register ADC0_CFG2 |= ADC_CFG2_ADHSC_MASK ; // select high-speed conversion ADC0_CFG2 &= ~ADC_CFG2_MUXSEL_MASK; // select a channels // Setup Status and Control Register 2 ADC0_SC2 = 0; // clear register ADC0_SC2 |= ADC_SC2_REFSEL(0); // select external voltage reference ADC0_SC2 |= ADC_SC2_DMAEN_MASK; // enable DMA ADC0_SC2 &= ~ADC_SC2_ADTRG_MASK; // select software trigger until calibration is complete ADC1_SC2 = 0; // clear register ADC1_SC2 |= ADC_SC2_REFSEL(0); // select external voltage reference ADC1_SC2 |= ADC_SC2_DMAEN_MASK; // enable DMA ADC1_SC2 &= ~ADC_SC2_ADTRG_MASK; // select software trigger until calibration is complete // Setup Status and Control Register 3 ADC0_SC3 = 0; // Hardware Average set to 4 samples averaged // Hardware Average Disabled // select single conversion mode ADC1_SC3 = 0; // Hardware Average set to 4 samples averaged // Hardware Average Disabled // select single conversion mode // calibrate the ADC 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 // 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>>1); // 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>>1); // 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>>1); // 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>>1); // 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 // yellow indicating calibration complete red = 0; green = 0; ADC0_SC2 |= ADC_SC2_ADTRG_MASK; // select hardware trigger now that calibration is complete ADC1_SC2 |= ADC_SC2_ADTRG_MASK; // select hardware trigger now that calibration is complete // Setup Status and Control Register 1A ADC0_SC1A = 0; // clear register ADC0_SC1A &= ~ADC_SC1_DIFF_MASK; // select single-ended mode ADC0_SC1A |= ADC_SC1_AIEN_MASK; // enable interrupt (for debugging) ADC0_SC1A |= ADC_SC1_ADCH(13); // select channel 13 ADC1_SC1A = 0; // clear register ADC1_SC1A &= ~ADC_SC1_DIFF_MASK; // select single-ended mode ADC1_SC1A |= ADC_SC1_AIEN_MASK; // enable interrupt (for debugging) ADC1_SC1A |= ADC_SC1_ADCH(13); // select channel 13 // Check if ADC is finished initializing TODO: This part doesn't seem right, but I did it according to 871 while( (ADC0_SC1A&ADC_SC1_COCO_MASK)) {} gain = ADC0_RA; // read the register to clear SC1A[COCO] while( (ADC1_SC1A&ADC_SC1_COCO_MASK)) {} gain = ADC1_RA; // read the register to clear SC1A[COCO] // green indicating calibration and initialization complete red = 1; green = 0; debug.printf("ADC0_SC1a: %08x\r\n",ADC0_SC1A); //(0x0000004d) debug.printf("ADC0_SC1b: %08x\r\n",ADC0_SC1B); //(0x0000001f) debug.printf("ADC0_CFG1: %08x\r\n",ADC0_CFG1); //(0x0000000c) debug.printf("ADC0_CFG2: %08x\r\n",ADC0_CFG2); //(0x00000004) debug.printf("ADC0_RA: %08x\r\n",ADC0_RA); //(0x00000000) debug.printf("ADC0_RB: %08x\r\n",ADC0_RB); //(0x00000000) debug.printf("ADC0_SC2: %08x\r\n",ADC0_SC2); //(0x00000044) debug.printf("ADC0_SC3: %08x\r\n\n",ADC0_SC3); //(0x00000000) // Enable the ISR vector NVIC_SetVector(ADC0_IRQn, (uint32_t)&ADC0_IRQHandler); NVIC_EnableIRQ(ADC0_IRQn); } void adc_start() { // reset DMA dma_reset(); // set ADC to continuous mode ADC0_SC3 |= ADC_SC3_ADCO_MASK; ADC1_SC3 |= ADC_SC3_ADCO_MASK; // set ADC to software trigger ADC1_SC2 &= ~ADC_SC2_ADTRG_MASK; // start ADC conversion (SW trigger) ADC0_SC1A |= ADC_SC1_ADCH(13); // write to SC1A causing a trigger ADC1_SC1A |= ADC_SC1_ADCH(14); // write to SC1A causing a trigger //BW_ADC_SC1n_ADCH(0, 0, kAdcChannel13); // trigger the ADC } void adc_stop() { // set ADC to hardware trigger ADC0_SC2 |= ADC_SC2_ADTRG_MASK; ADC1_SC2 |= ADC_SC2_ADTRG_MASK; // set to single conversion mode effectively stopping the ADC unless a timer triggers the ADC ADC0_SC3 &= ~ADC_SC3_ADCO_MASK; ADC1_SC3 &= ~ADC_SC3_ADCO_MASK; } void adc_single_sample() { ADC0_SC3 &= ~ADC_SC3_ADCO_MASK; // single conversion mode ADC1_SC3 &= ~ADC_SC3_ADCO_MASK; // single conversion mode ADC0_SC2 &= ~ADC_SC2_ADTRG_MASK; // set ADC to software trigger ADC1_SC2 &= ~ADC_SC2_ADTRG_MASK; // set ADC to software trigger ADC0_SC1A |= ADC_SC1_ADCH(13); // write to SC1A causing a trigger ADC1_SC1A |= ADC_SC1_ADCH(14); // write to SC1A causing a trigger } void ADC0_IRQHandler() { toggle1 = !toggle1; }