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 DSP_200kHz by
adc.cpp
- Committer:
- timmey9
- Date:
- 2015-01-31
- Revision:
- 47:54fafe151669
- Parent:
- 46:a015ebf4663b
- Child:
- 48:29f14bc30ba6
File content as of revision 47:54fafe151669:
#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
ADC0_SC2 &= ~ADC_SC2_ADTRG_MASK;
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
}
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;
}

