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
Diff: adc.cpp
- Revision:
- 45:d591d138cdeb
- Parent:
- 44:41c262caf898
- Child:
- 46:a015ebf4663b
--- a/adc.cpp Fri Jan 30 14:56:58 2015 +0000 +++ b/adc.cpp Sat Jan 31 07:25:52 2015 +0000 @@ -1,107 +1,153 @@ #include "adc.h" -#include "dma.h" + /* TODO: remove interrupt handlers add calibration - change clock speed (possible with PIT) + 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 blah(LED_BLUE); -DigitalOut craw(LED_GREEN); -DigitalOut toggle(PTC16); +DigitalOut toggle1(PTC16); +DigitalOut green(LED_GREEN); +DigitalOut red(LED_RED); +Serial debug(USBTX,USBRX); -void adc_init(PinName pin) +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; - // enable interrupt - ADC0_SC1A |= ADC_SC1_AIEN_MASK; - ADC1_SC1A |= ADC_SC1_AIEN_MASK; + // Set ADC hardware trigger to PDB0 + SIM_SOPT7 = SIM_SOPT7_ADC0TRGSEL(0); - // enable the DMA - ADC0->SC2 |= ADC_SC2_DMAEN_MASK; - ADC1->SC2 |= ADC_SC2_DMAEN_MASK; + // 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 + + // 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 - // calibrate ADC - ADC0->SC3 = 0; // Reset SC3 - ADC1->SC3 = 0; // Reset SC3 - /*do { - ADC0->SC3 |= (1<<7); // start calibration - while(ADC0->SC3&(1<<7)) {} // wait for calibration to complete - if((ADC0->SC3)&(1<<6)) pc.printf("Calibration Failed\r\n"); - } while(ADC0->SC3&(1<<6)); - */ // the calibration may be failing because ADC0_SC2 has the Vref set to external pins + // 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 + + // Setup Status and Control Register 3 + ADC0_SC3 = 0; // Hardware Average set to 4 samples averaged + // Hardware Average Disabled + // select single conversion mode - ADC0->CFG1 |= ADC_CFG1_ADLPC_MASK; // high power mode for faster frequencies - ADC1->CFG1 |= ADC_CFG1_ADLPC_MASK; // high power mode for faster frequencies + // calibrate the ADC + ADC0_SC3 |= ADC_SC3_CAL_MASK; // start calibration + while(ADC0_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 = (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; - ADCName adc = (ADCName)pinmap_peripheral(pin, PinMap_ADC); - uint32_t instance = adc >> ADC_INSTANCE_SHIFT; - clock_manager_set_gate(kClockModuleADC, instance, true); - uint32_t bus_clock; - clock_manager_get_frequency(kBusClock, &bus_clock); - uint32_t clkdiv; - for (clkdiv = 0; clkdiv < 4; clkdiv++) { - if ((bus_clock >> clkdiv) <= MAX_FADC) - break; - } - if (clkdiv == 4) { - clkdiv = 0x7; //Set max div - } - // adc is enabled/triggered when reading. - adc_hal_set_clock_source_mode(instance, (adc_clock_source_mode_t)(clkdiv >> 2)); - adc_hal_set_clock_divider_mode(instance, (adc_clock_divider_mode_t)(clkdiv & 0x3)); - adc_hal_set_reference_voltage_mode(instance, kAdcVoltageVref); - adc_hal_set_resolution_mode(instance, kAdcSingleDiff16); - adc_hal_configure_continuous_conversion(instance, false); // true=continuous conversion mode, false = single conversion mode - adc_hal_configure_hw_trigger(instance, false); // true=hw trigger, false=sw trigger - adc_hal_configure_hw_average(instance, false); - adc_hal_set_hw_average_mode(instance, kAdcHwAverageCount4); - adc_hal_set_group_mux(instance, kAdcChannelMuxB); // only B channels are avail - - pinmap_pinout(pin, PinMap_ADC); - /* - pc.printf("ADC0_SC1a: %08x\r\n",ADC0_SC1A); // module disabled - pc.printf("ADC0_SC1b: %08x\r\n",ADC0_SC1B); // module disabled - pc.printf("ADC0_CFG1: %08x\r\n",ADC0_CFG1); // alternate clock2 selected, 16-bit 2's complement selected, short sample time, clock divide ration is input/8, low power mode selected - pc.printf("ADC0_CFG2: %08x\r\n",ADC0_CFG2); // ADxxa channels selected - pc.printf("ADC0_RA: %08x\r\n",ADC0_RA); - pc.printf("ADC0_RB: %08x\r\n",ADC0_RB); - pc.printf("ADC0_SC2: %08x\r\n",ADC0_SC2); // hw trigger and dma enabled. Compare function disabled and Vref set to external pin - pc.printf("ADC0_SC3: %08x\r\n\n",ADC0_SC3); - */ + ADC0_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 + + // 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 + + // 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] + + + + + + + // 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_SetVector(ADC1_IRQn, (uint32_t)&ADC1_IRQHandler); NVIC_EnableIRQ(ADC0_IRQn); - NVIC_EnableIRQ(ADC1_IRQn); } void adc_start() { // reset DMA - dma.reset(); + 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; // start ADC conversion (SW trigger) - BW_ADC_SC1n_ADCH(0, 0, kAdcChannel13); // This corresponds to starting an ADC conversion on channel 12 of ADC 0 - which is A0 (PTB2) - BW_ADC_SC1n_ADCH(1, 0, kAdcChannel14); // This corresponds to starting an ADC conversion on channel 14 of ADC 1 - which is A2 (PTB10) + //ADC0_SC1A |= ADC_SC1_ADCH(13); // write to SC1A causing a trigger + //BW_ADC_SC1n_ADCH(0, 0, kAdcChannel13); // trigger the ADC } void adc_stop() { - ADC0_SC3 &= ~ADC_SC3_ADCO_MASK; // set to single conversion mode effectively stopping the ADC - ADC1_SC3 &= ~ADC_SC3_ADCO_MASK; // set to single conversion mode effectively stopping the ADC + // set ADC to hardware trigger + ADC0_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; +} + +void adc_single_sample() { + ADC0_SC3 &= ~ADC_SC3_ADCO_MASK; // single conversion mode + ADC0_SC2 &= ~ADC_SC2_ADTRG_MASK; // set ADC to software trigger + ADC0_SC1A |= ADC_SC1_ADCH(13); // write to SC1A causing a trigger } void ADC0_IRQHandler() { - //toggle = !toggle; - //craw = !craw; -} -void ADC1_IRQHandler() { - //toggle = !toggle; - //blah = !blah; + toggle1 = !toggle1; } \ No newline at end of file