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@51:43143a3fc2d7, 2015-01-31 (annotated)
- Committer:
- timmey9
- Date:
- Sat Jan 31 20:17:58 2015 +0000
- Revision:
- 51:43143a3fc2d7
- Parent:
- 50:33524a27e08c
Cleaned up the code a little bit.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
timmey9 | 39:82dc3daecf32 | 1 | #include "adc.h" |
timmey9 | 45:d591d138cdeb | 2 | |
timmey9 | 44:41c262caf898 | 3 | /* |
timmey9 | 44:41c262caf898 | 4 | TODO: remove interrupt handlers |
timmey9 | 48:29f14bc30ba6 | 5 | finish calibration |
timmey9 | 45:d591d138cdeb | 6 | change clock speed |
timmey9 | 44:41c262caf898 | 7 | |
timmey9 | 45:d591d138cdeb | 8 | Possible causes of the triggering problem: |
timmey9 | 45:d591d138cdeb | 9 | more multiplexing somehow? |
timmey9 | 45:d591d138cdeb | 10 | does the ADC interrupt need to be enabled? |
timmey9 | 45:d591d138cdeb | 11 | clock speed? |
timmey9 | 45:d591d138cdeb | 12 | hardware/software trigger |
timmey9 | 45:d591d138cdeb | 13 | channel A or B? |
timmey9 | 45:d591d138cdeb | 14 | single vs continuous mode |
timmey9 | 45:d591d138cdeb | 15 | does asynchronous clock have to do with this? |
timmey9 | 44:41c262caf898 | 16 | */ |
timmey9 | 51:43143a3fc2d7 | 17 | DigitalOut toggle1(PTA0); |
timmey9 | 45:d591d138cdeb | 18 | DigitalOut green(LED_GREEN); |
timmey9 | 45:d591d138cdeb | 19 | DigitalOut red(LED_RED); |
timmey9 | 51:43143a3fc2d7 | 20 | //Serial debug(USBTX,USBRX); |
timmey9 | 51:43143a3fc2d7 | 21 | |
timmey9 | 51:43143a3fc2d7 | 22 | |
timmey9 | 39:82dc3daecf32 | 23 | |
timmey9 | 51:43143a3fc2d7 | 24 | /* The ADCs are setup so that ADC0 and ADC1 are triggered by the PDB. |
timmey9 | 51:43143a3fc2d7 | 25 | * When the conversions are complete, ADC0 and ADC1 then trigger DMA0 |
timmey9 | 51:43143a3fc2d7 | 26 | * and DMA1, respectively. */ |
timmey9 | 45:d591d138cdeb | 27 | void adc_init() |
timmey9 | 39:82dc3daecf32 | 28 | { |
timmey9 | 45:d591d138cdeb | 29 | // red, indicating now ready |
timmey9 | 45:d591d138cdeb | 30 | red = 0; |
timmey9 | 45:d591d138cdeb | 31 | green = 1; |
timmey9 | 45:d591d138cdeb | 32 | |
timmey9 | 39:82dc3daecf32 | 33 | // Turn on the ADC0 and ADC1 clocks |
timmey9 | 39:82dc3daecf32 | 34 | SIM_SCGC6 |= SIM_SCGC6_ADC0_MASK; |
timmey9 | 39:82dc3daecf32 | 35 | SIM_SCGC3 |= SIM_SCGC3_ADC1_MASK; |
timmey9 | 40:bd6d8c35e822 | 36 | |
timmey9 | 45:d591d138cdeb | 37 | // Set ADC hardware trigger to PDB0 |
timmey9 | 48:29f14bc30ba6 | 38 | SIM_SOPT7 = SIM_SOPT7_ADC0TRGSEL(0); // Select triggering by PDB and select pre-trigger A |
timmey9 | 48:29f14bc30ba6 | 39 | SIM_SOPT7 = SIM_SOPT7_ADC1TRGSEL(0); // Select triggering by PDB and select pre-trigger A |
timmey9 | 39:82dc3daecf32 | 40 | |
timmey9 | 45:d591d138cdeb | 41 | // Setup Configuration Register 1 |
timmey9 | 45:d591d138cdeb | 42 | ADC0_CFG1 = 0; // clear register |
timmey9 | 45:d591d138cdeb | 43 | ADC0_CFG1 |= ADC_CFG1_ADICLK(0); // select bus clock |
timmey9 | 45:d591d138cdeb | 44 | ADC0_CFG1 |= ADC_CFG1_MODE(3); // select 16-bit 2's complement output |
timmey9 | 45:d591d138cdeb | 45 | ADC0_CFG1 |= ADC_CFG1_ADIV(0); // select short sample time |
timmey9 | 45:d591d138cdeb | 46 | ADC0_CFG1 &= ~ADC_CFG1_ADLSMP_MASK; // select short sample time |
timmey9 | 45:d591d138cdeb | 47 | ADC0_CFG1 &= ~ADC_CFG1_ADLPC_MASK; // select normal power configuration |
timmey9 | 46:a015ebf4663b | 48 | ADC1_CFG1 = 0; // clear register |
timmey9 | 46:a015ebf4663b | 49 | ADC1_CFG1 |= ADC_CFG1_ADICLK(0); // select bus clock |
timmey9 | 46:a015ebf4663b | 50 | ADC1_CFG1 |= ADC_CFG1_MODE(3); // select 16-bit 2's complement output |
timmey9 | 46:a015ebf4663b | 51 | ADC1_CFG1 |= ADC_CFG1_ADIV(0); // select short sample time |
timmey9 | 46:a015ebf4663b | 52 | ADC1_CFG1 &= ~ADC_CFG1_ADLSMP_MASK; // select short sample time |
timmey9 | 46:a015ebf4663b | 53 | ADC1_CFG1 &= ~ADC_CFG1_ADLPC_MASK; // select normal power configuration |
timmey9 | 45:d591d138cdeb | 54 | |
timmey9 | 45:d591d138cdeb | 55 | // Setup Configuration Register 2 |
timmey9 | 45:d591d138cdeb | 56 | ADC0_CFG2 = 0; // clear register |
timmey9 | 47:54fafe151669 | 57 | ADC0_CFG2 |= ADC_CFG2_ADHSC_MASK ; // select high-speed conversion |
timmey9 | 45:d591d138cdeb | 58 | ADC0_CFG2 &= ~ADC_CFG2_MUXSEL_MASK; // select a channels |
timmey9 | 49:4dcf4717a8bb | 59 | ADC1_CFG2 = 0; // clear register |
timmey9 | 49:4dcf4717a8bb | 60 | ADC1_CFG2 |= ADC_CFG2_ADHSC_MASK ; // select high-speed conversion |
timmey9 | 50:33524a27e08c | 61 | ADC1_CFG2 &= ~ADC_CFG2_MUXSEL_MASK; // select a channels |
timmey9 | 50:33524a27e08c | 62 | |
timmey9 | 39:82dc3daecf32 | 63 | |
timmey9 | 45:d591d138cdeb | 64 | // Setup Status and Control Register 2 |
timmey9 | 47:54fafe151669 | 65 | ADC0_SC2 = 0; // clear register |
timmey9 | 47:54fafe151669 | 66 | ADC0_SC2 |= ADC_SC2_REFSEL(0); // select external voltage reference |
timmey9 | 47:54fafe151669 | 67 | ADC0_SC2 |= ADC_SC2_DMAEN_MASK; // enable DMA |
timmey9 | 45:d591d138cdeb | 68 | ADC0_SC2 &= ~ADC_SC2_ADTRG_MASK; // select software trigger until calibration is complete |
timmey9 | 47:54fafe151669 | 69 | ADC1_SC2 = 0; // clear register |
timmey9 | 47:54fafe151669 | 70 | ADC1_SC2 |= ADC_SC2_REFSEL(0); // select external voltage reference |
timmey9 | 47:54fafe151669 | 71 | ADC1_SC2 |= ADC_SC2_DMAEN_MASK; // enable DMA |
timmey9 | 46:a015ebf4663b | 72 | ADC1_SC2 &= ~ADC_SC2_ADTRG_MASK; // select software trigger until calibration is complete |
timmey9 | 45:d591d138cdeb | 73 | |
timmey9 | 45:d591d138cdeb | 74 | // Setup Status and Control Register 3 |
timmey9 | 45:d591d138cdeb | 75 | ADC0_SC3 = 0; // Hardware Average set to 4 samples averaged |
timmey9 | 45:d591d138cdeb | 76 | // Hardware Average Disabled |
timmey9 | 45:d591d138cdeb | 77 | // select single conversion mode |
timmey9 | 46:a015ebf4663b | 78 | ADC1_SC3 = 0; // Hardware Average set to 4 samples averaged |
timmey9 | 46:a015ebf4663b | 79 | // Hardware Average Disabled |
timmey9 | 46:a015ebf4663b | 80 | // select single conversion mode |
timmey9 | 39:82dc3daecf32 | 81 | |
timmey9 | 45:d591d138cdeb | 82 | // calibrate the ADC |
timmey9 | 45:d591d138cdeb | 83 | ADC0_SC3 |= ADC_SC3_CAL_MASK; // start calibration |
timmey9 | 45:d591d138cdeb | 84 | while(ADC0_SC3&ADC_SC3_CALF_MASK) {} // wait for calibration to complete |
timmey9 | 46:a015ebf4663b | 85 | ADC1_SC3 |= ADC_SC3_CAL_MASK; // start calibration |
timmey9 | 46:a015ebf4663b | 86 | while(ADC1_SC3&ADC_SC3_CALF_MASK) {} // wait for calibration to complete |
timmey9 | 46:a015ebf4663b | 87 | |
timmey9 | 45:d591d138cdeb | 88 | |
timmey9 | 45:d591d138cdeb | 89 | // calculate the gains (see user manual page 864) |
timmey9 | 45:d591d138cdeb | 90 | int16_t gain = (ADC0_CLP0+ADC0_CLP1+ADC0_CLP2+ADC0_CLP3+ADC0_CLP4+ADC0_CLPS); |
timmey9 | 45:d591d138cdeb | 91 | gain = (gain>>1); // divide by 2 |
timmey9 | 45:d591d138cdeb | 92 | gain |= 0x8000; // set the MSB |
timmey9 | 45:d591d138cdeb | 93 | ADC0_PG = gain; |
timmey9 | 45:d591d138cdeb | 94 | |
timmey9 | 46:a015ebf4663b | 95 | gain = (ADC1_CLP0+ADC1_CLP1+ADC1_CLP2+ADC1_CLP3+ADC1_CLP4+ADC1_CLPS); |
timmey9 | 46:a015ebf4663b | 96 | gain = (gain>>1); // divide by 2 |
timmey9 | 46:a015ebf4663b | 97 | gain |= 0x8000; // set the MSB |
timmey9 | 46:a015ebf4663b | 98 | ADC1_PG = gain; |
timmey9 | 46:a015ebf4663b | 99 | |
timmey9 | 45:d591d138cdeb | 100 | gain = (ADC0_CLM0+ADC0_CLM1+ADC0_CLM2+ADC0_CLM3+ADC0_CLM4+ADC0_CLMS); |
timmey9 | 45:d591d138cdeb | 101 | gain = (gain>>1); // divide by 2 |
timmey9 | 45:d591d138cdeb | 102 | gain |= 0x8000; // set the MSB |
timmey9 | 45:d591d138cdeb | 103 | ADC0_MG = gain; |
timmey9 | 39:82dc3daecf32 | 104 | |
timmey9 | 46:a015ebf4663b | 105 | gain = (ADC1_CLM0+ADC1_CLM1+ADC1_CLM2+ADC1_CLM3+ADC1_CLM4+ADC1_CLMS); |
timmey9 | 46:a015ebf4663b | 106 | gain = (gain>>1); // divide by 2 |
timmey9 | 46:a015ebf4663b | 107 | gain |= 0x8000; // set the MSB |
timmey9 | 46:a015ebf4663b | 108 | ADC1_MG = gain; |
timmey9 | 46:a015ebf4663b | 109 | |
timmey9 | 45:d591d138cdeb | 110 | ADC0_SC3 &= ~ADC_SC3_CAL_MASK; // stop calibration |
timmey9 | 46:a015ebf4663b | 111 | ADC1_SC3 &= ~ADC_SC3_CAL_MASK; // stop calibration |
timmey9 | 45:d591d138cdeb | 112 | |
timmey9 | 45:d591d138cdeb | 113 | |
timmey9 | 45:d591d138cdeb | 114 | |
timmey9 | 45:d591d138cdeb | 115 | // yellow indicating calibration complete |
timmey9 | 45:d591d138cdeb | 116 | red = 0; |
timmey9 | 45:d591d138cdeb | 117 | green = 0; |
timmey9 | 45:d591d138cdeb | 118 | |
timmey9 | 45:d591d138cdeb | 119 | ADC0_SC2 |= ADC_SC2_ADTRG_MASK; // select hardware trigger now that calibration is complete |
timmey9 | 46:a015ebf4663b | 120 | ADC1_SC2 |= ADC_SC2_ADTRG_MASK; // select hardware trigger now that calibration is complete |
timmey9 | 45:d591d138cdeb | 121 | |
timmey9 | 50:33524a27e08c | 122 | // Setup Status and Control Register 1A |
timmey9 | 48:29f14bc30ba6 | 123 | ADC0_SC1B = 0; // clear register |
timmey9 | 48:29f14bc30ba6 | 124 | ADC0_SC1B &= ~ADC_SC1_DIFF_MASK; // select single-ended mode |
timmey9 | 48:29f14bc30ba6 | 125 | ADC0_SC1B |= ADC_SC1_AIEN_MASK; // enable interrupt (for debugging) |
timmey9 | 48:29f14bc30ba6 | 126 | ADC0_SC1B |= ADC_SC1_ADCH(13); // select channel 13 |
timmey9 | 50:33524a27e08c | 127 | ADC1_SC1A = 0; // clear register |
timmey9 | 50:33524a27e08c | 128 | ADC1_SC1A &= ~ADC_SC1_DIFF_MASK; // select single-ended mode |
timmey9 | 50:33524a27e08c | 129 | ADC1_SC1A |= ADC_SC1_AIEN_MASK; // enable interrupt (for debugging) |
timmey9 | 51:43143a3fc2d7 | 130 | ADC1_SC1A |= ADC_SC1_ADCH(14); // select channel 14 |
timmey9 | 51:43143a3fc2d7 | 131 | |
timmey9 | 45:d591d138cdeb | 132 | |
timmey9 | 45:d591d138cdeb | 133 | // Check if ADC is finished initializing TODO: This part doesn't seem right, but I did it according to 871 |
timmey9 | 48:29f14bc30ba6 | 134 | while( (ADC0_SC1B&ADC_SC1_COCO_MASK)) {} |
timmey9 | 50:33524a27e08c | 135 | gain = ADC0_RA; // read the register to clear SC1A[COCO] |
timmey9 | 50:33524a27e08c | 136 | while( (ADC1_SC1A&ADC_SC1_COCO_MASK)) {} |
timmey9 | 50:33524a27e08c | 137 | gain = ADC1_RA; // read the register to clear SC1A[COCO] |
timmey9 | 45:d591d138cdeb | 138 | |
timmey9 | 45:d591d138cdeb | 139 | |
timmey9 | 45:d591d138cdeb | 140 | // green indicating calibration and initialization complete |
timmey9 | 45:d591d138cdeb | 141 | red = 1; |
timmey9 | 45:d591d138cdeb | 142 | green = 0; |
timmey9 | 45:d591d138cdeb | 143 | |
timmey9 | 40:bd6d8c35e822 | 144 | // Enable the ISR vector |
timmey9 | 47:54fafe151669 | 145 | //NVIC_SetVector(ADC0_IRQn, (uint32_t)&ADC0_IRQHandler); |
timmey9 | 47:54fafe151669 | 146 | //NVIC_EnableIRQ(ADC0_IRQn); |
timmey9 | 40:bd6d8c35e822 | 147 | } |
timmey9 | 40:bd6d8c35e822 | 148 | |
timmey9 | 51:43143a3fc2d7 | 149 | |
timmey9 | 51:43143a3fc2d7 | 150 | void ADC0_IRQHandler() { |
timmey9 | 51:43143a3fc2d7 | 151 | |
timmey9 | 51:43143a3fc2d7 | 152 | toggle1 = !toggle1; |
timmey9 | 51:43143a3fc2d7 | 153 | } |
timmey9 | 51:43143a3fc2d7 | 154 | |
timmey9 | 51:43143a3fc2d7 | 155 | |
timmey9 | 51:43143a3fc2d7 | 156 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
timmey9 | 51:43143a3fc2d7 | 157 | * DEBUG: This is supposed to put the ADC in continuous * |
timmey9 | 51:43143a3fc2d7 | 158 | * mode so it samples without the PCB. But for * |
timmey9 | 51:43143a3fc2d7 | 159 | * some reason it isn't working. I haven't deleted * |
timmey9 | 51:43143a3fc2d7 | 160 | * it just in case it is needed for debug purposes * |
timmey9 | 51:43143a3fc2d7 | 161 | * in the future. * |
timmey9 | 51:43143a3fc2d7 | 162 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
timmey9 | 41:3e0623d81b9a | 163 | void adc_start() { |
timmey9 | 40:bd6d8c35e822 | 164 | // reset DMA |
timmey9 | 45:d591d138cdeb | 165 | dma_reset(); |
timmey9 | 40:bd6d8c35e822 | 166 | |
timmey9 | 40:bd6d8c35e822 | 167 | // set ADC to continuous mode |
timmey9 | 40:bd6d8c35e822 | 168 | ADC0_SC3 |= ADC_SC3_ADCO_MASK; |
timmey9 | 46:a015ebf4663b | 169 | ADC1_SC3 |= ADC_SC3_ADCO_MASK; |
timmey9 | 45:d591d138cdeb | 170 | |
timmey9 | 45:d591d138cdeb | 171 | // set ADC to software trigger |
timmey9 | 47:54fafe151669 | 172 | ADC0_SC2 &= ~ADC_SC2_ADTRG_MASK; |
timmey9 | 46:a015ebf4663b | 173 | ADC1_SC2 &= ~ADC_SC2_ADTRG_MASK; |
timmey9 | 40:bd6d8c35e822 | 174 | |
timmey9 | 40:bd6d8c35e822 | 175 | // start ADC conversion (SW trigger) |
timmey9 | 50:33524a27e08c | 176 | ADC0_SC1B |= ADC_SC1_ADCH(13); // write to SC1A causing a trigger |
timmey9 | 50:33524a27e08c | 177 | ADC1_SC1A |= ADC_SC1_ADCH(14); // write to SC1A causing a trigger |
timmey9 | 40:bd6d8c35e822 | 178 | } |
timmey9 | 40:bd6d8c35e822 | 179 | |
timmey9 | 51:43143a3fc2d7 | 180 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
timmey9 | 51:43143a3fc2d7 | 181 | * DEBUG: This is supposed to revert back from adc_start() * |
timmey9 | 51:43143a3fc2d7 | 182 | * but because adc_start() isn't working, this * |
timmey9 | 51:43143a3fc2d7 | 183 | * function is good for nothing. I held on to * |
timmey9 | 51:43143a3fc2d7 | 184 | * it just in case it is needed for debug purposes * |
timmey9 | 51:43143a3fc2d7 | 185 | * in the future. * |
timmey9 | 51:43143a3fc2d7 | 186 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
timmey9 | 41:3e0623d81b9a | 187 | void adc_stop() { |
timmey9 | 45:d591d138cdeb | 188 | // set ADC to hardware trigger |
timmey9 | 45:d591d138cdeb | 189 | ADC0_SC2 |= ADC_SC2_ADTRG_MASK; |
timmey9 | 46:a015ebf4663b | 190 | ADC1_SC2 |= ADC_SC2_ADTRG_MASK; |
timmey9 | 45:d591d138cdeb | 191 | |
timmey9 | 45:d591d138cdeb | 192 | // set to single conversion mode effectively stopping the ADC unless a timer triggers the ADC |
timmey9 | 45:d591d138cdeb | 193 | ADC0_SC3 &= ~ADC_SC3_ADCO_MASK; |
timmey9 | 46:a015ebf4663b | 194 | ADC1_SC3 &= ~ADC_SC3_ADCO_MASK; |
timmey9 | 45:d591d138cdeb | 195 | } |
timmey9 | 45:d591d138cdeb | 196 | |
timmey9 | 51:43143a3fc2d7 | 197 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
timmey9 | 51:43143a3fc2d7 | 198 | * DEBUG: This is supposed to trigger a software conversion * |
timmey9 | 51:43143a3fc2d7 | 199 | * and take a single sample. However, it only * |
timmey9 | 51:43143a3fc2d7 | 200 | * worked for ADC1 for some reason. It is here for * |
timmey9 | 51:43143a3fc2d7 | 201 | * possible debug purposes in the future. * |
timmey9 | 51:43143a3fc2d7 | 202 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
timmey9 | 45:d591d138cdeb | 203 | void adc_single_sample() { |
timmey9 | 45:d591d138cdeb | 204 | ADC0_SC3 &= ~ADC_SC3_ADCO_MASK; // single conversion mode |
timmey9 | 46:a015ebf4663b | 205 | ADC1_SC3 &= ~ADC_SC3_ADCO_MASK; // single conversion mode |
timmey9 | 45:d591d138cdeb | 206 | ADC0_SC2 &= ~ADC_SC2_ADTRG_MASK; // set ADC to software trigger |
timmey9 | 46:a015ebf4663b | 207 | ADC1_SC2 &= ~ADC_SC2_ADTRG_MASK; // set ADC to software trigger |
timmey9 | 50:33524a27e08c | 208 | ADC0_SC1B |= ADC_SC1_ADCH(13); // write to SC1B causing a trigger |
timmey9 | 50:33524a27e08c | 209 | ADC1_SC1A |= ADC_SC1_ADCH(14); // write to SC1A causing a trigger |
timmey9 | 50:33524a27e08c | 210 | |
timmey9 | 50:33524a27e08c | 211 | // Set back to hardware trigger |
timmey9 | 50:33524a27e08c | 212 | ADC0_SC2 |= ADC_SC2_ADTRG_MASK; // set ADC to software trigger |
timmey9 | 50:33524a27e08c | 213 | ADC1_SC2 |= ADC_SC2_ADTRG_MASK; // set ADC to software trigger |
timmey9 | 40:bd6d8c35e822 | 214 | } |
timmey9 | 40:bd6d8c35e822 | 215 | |
timmey9 | 51:43143a3fc2d7 | 216 | |
timmey9 | 51:43143a3fc2d7 | 217 | /* |
timmey9 | 51:43143a3fc2d7 | 218 | debug.printf("ADC0_SC1a: %08x\r\n",ADC0_SC1A); //(0x0000004d) |
timmey9 | 51:43143a3fc2d7 | 219 | debug.printf("ADC0_SC1b: %08x\r\n",ADC0_SC1B); //(0x0000001f) |
timmey9 | 51:43143a3fc2d7 | 220 | debug.printf("ADC0_CFG1: %08x\r\n",ADC0_CFG1); //(0x0000000c) |
timmey9 | 51:43143a3fc2d7 | 221 | debug.printf("ADC0_CFG2: %08x\r\n",ADC0_CFG2); //(0x00000004) |
timmey9 | 51:43143a3fc2d7 | 222 | debug.printf("ADC0_RA: %08x\r\n",ADC0_RA); //(0x00000000) |
timmey9 | 51:43143a3fc2d7 | 223 | debug.printf("ADC0_RB: %08x\r\n",ADC0_RB); //(0x00000000) |
timmey9 | 51:43143a3fc2d7 | 224 | debug.printf("ADC0_SC2: %08x\r\n",ADC0_SC2); //(0x00000044) |
timmey9 | 51:43143a3fc2d7 | 225 | debug.printf("ADC0_SC3: %08x\r\n\n",ADC0_SC3); //(0x00000000) |
timmey9 | 51:43143a3fc2d7 | 226 | */ |