em_adc.c
Go to the documentation of this file.00001
00034 #include "em_adc.h"
00035 #if defined(ADC_COUNT) && (ADC_COUNT > 0)
00036
00037 #include "em_cmu.h"
00038 #include "em_assert.h"
00039
00040
00045
00051
00052
00053
00054
00058 #define ADC_REF_VALID(ref) ((ref) == ADC0)
00059
00061 #define ADC_MAX_CLOCK 13000000
00062
00064 #define ADC_MIN_CLOCK 32000
00065
00069
00070
00071
00072
00075
00093 static void ADC_CalibrateLoadScan(ADC_TypeDef *adc, ADC_Ref_TypeDef ref)
00094 {
00095 uint32_t cal;
00096
00097
00098
00099
00100 switch (ref)
00101 {
00102 case adcRef1V25:
00103 cal = adc->CAL & ~(_ADC_CAL_SCANOFFSET_MASK | _ADC_CAL_SCANGAIN_MASK);
00104 cal |= ((DEVINFO->ADC0CAL0 & _DEVINFO_ADC0CAL0_1V25_GAIN_MASK) >>
00105 _DEVINFO_ADC0CAL0_1V25_GAIN_SHIFT) << _ADC_CAL_SCANGAIN_SHIFT;
00106 cal |= ((DEVINFO->ADC0CAL0 & _DEVINFO_ADC0CAL0_1V25_OFFSET_MASK) >>
00107 _DEVINFO_ADC0CAL0_1V25_OFFSET_SHIFT) << _ADC_CAL_SCANOFFSET_SHIFT;
00108 adc->CAL = cal;
00109 break;
00110
00111 case adcRef2V5:
00112 cal = adc->CAL & ~(_ADC_CAL_SCANOFFSET_MASK | _ADC_CAL_SCANGAIN_MASK);
00113 cal |= ((DEVINFO->ADC0CAL0 & _DEVINFO_ADC0CAL0_2V5_GAIN_MASK) >>
00114 _DEVINFO_ADC0CAL0_2V5_GAIN_SHIFT) << _ADC_CAL_SCANGAIN_SHIFT;
00115 cal |= ((DEVINFO->ADC0CAL0 & _DEVINFO_ADC0CAL0_2V5_OFFSET_MASK) >>
00116 _DEVINFO_ADC0CAL0_2V5_OFFSET_SHIFT) << _ADC_CAL_SCANOFFSET_SHIFT;
00117 adc->CAL = cal;
00118 break;
00119
00120 case adcRefVDD:
00121 cal = adc->CAL & ~(_ADC_CAL_SCANOFFSET_MASK | _ADC_CAL_SCANGAIN_MASK);
00122 cal |= ((DEVINFO->ADC0CAL1 & _DEVINFO_ADC0CAL1_VDD_GAIN_MASK) >>
00123 _DEVINFO_ADC0CAL1_VDD_GAIN_SHIFT) << _ADC_CAL_SCANGAIN_SHIFT;
00124 cal |= ((DEVINFO->ADC0CAL1 & _DEVINFO_ADC0CAL1_VDD_OFFSET_MASK) >>
00125 _DEVINFO_ADC0CAL1_VDD_OFFSET_SHIFT) << _ADC_CAL_SCANOFFSET_SHIFT;
00126 adc->CAL = cal;
00127 break;
00128
00129 case adcRef5VDIFF:
00130 cal = adc->CAL & ~(_ADC_CAL_SCANOFFSET_MASK | _ADC_CAL_SCANGAIN_MASK);
00131 cal |= ((DEVINFO->ADC0CAL1 & _DEVINFO_ADC0CAL1_5VDIFF_GAIN_MASK) >>
00132 _DEVINFO_ADC0CAL1_5VDIFF_GAIN_SHIFT) << _ADC_CAL_SCANGAIN_SHIFT;
00133 cal |= ((DEVINFO->ADC0CAL1 & _DEVINFO_ADC0CAL1_5VDIFF_OFFSET_MASK) >>
00134 _DEVINFO_ADC0CAL1_5VDIFF_OFFSET_SHIFT) << _ADC_CAL_SCANOFFSET_SHIFT;
00135 adc->CAL = cal;
00136 break;
00137
00138 case adcRef2xVDD:
00139
00140 cal = adc->CAL & ~_ADC_CAL_SCANOFFSET_MASK;
00141 cal |= ((DEVINFO->ADC0CAL2 & _DEVINFO_ADC0CAL2_2XVDDVSS_OFFSET_MASK) >>
00142 _DEVINFO_ADC0CAL2_2XVDDVSS_OFFSET_SHIFT) << _ADC_CAL_SCANOFFSET_SHIFT;
00143 adc->CAL = cal;
00144 break;
00145
00146
00147
00148 default:
00149 break;
00150 }
00151 }
00152
00153
00171 static void ADC_CalibrateLoadSingle(ADC_TypeDef *adc, ADC_Ref_TypeDef ref)
00172 {
00173 uint32_t cal;
00174
00175
00176
00177
00178 switch (ref)
00179 {
00180 case adcRef1V25:
00181 cal = adc->CAL & ~(_ADC_CAL_SINGLEOFFSET_MASK | _ADC_CAL_SINGLEGAIN_MASK);
00182 cal |= ((DEVINFO->ADC0CAL0 & _DEVINFO_ADC0CAL0_1V25_GAIN_MASK) >>
00183 _DEVINFO_ADC0CAL0_1V25_GAIN_SHIFT) << _ADC_CAL_SINGLEGAIN_SHIFT;
00184 cal |= ((DEVINFO->ADC0CAL0 & _DEVINFO_ADC0CAL0_1V25_OFFSET_MASK) >>
00185 _DEVINFO_ADC0CAL0_1V25_OFFSET_SHIFT) << _ADC_CAL_SINGLEOFFSET_SHIFT;
00186 adc->CAL = cal;
00187 break;
00188
00189 case adcRef2V5:
00190 cal = adc->CAL & ~(_ADC_CAL_SINGLEOFFSET_MASK | _ADC_CAL_SINGLEGAIN_MASK);
00191 cal |= ((DEVINFO->ADC0CAL0 & _DEVINFO_ADC0CAL0_2V5_GAIN_MASK) >>
00192 _DEVINFO_ADC0CAL0_2V5_GAIN_SHIFT) << _ADC_CAL_SINGLEGAIN_SHIFT;
00193 cal |= ((DEVINFO->ADC0CAL0 & _DEVINFO_ADC0CAL0_2V5_OFFSET_MASK) >>
00194 _DEVINFO_ADC0CAL0_2V5_OFFSET_SHIFT) << _ADC_CAL_SINGLEOFFSET_SHIFT;
00195 adc->CAL = cal;
00196 break;
00197
00198 case adcRefVDD:
00199 cal = adc->CAL & ~(_ADC_CAL_SINGLEOFFSET_MASK | _ADC_CAL_SINGLEGAIN_MASK);
00200 cal |= ((DEVINFO->ADC0CAL1 & _DEVINFO_ADC0CAL1_VDD_GAIN_MASK) >>
00201 _DEVINFO_ADC0CAL1_VDD_GAIN_SHIFT) << _ADC_CAL_SINGLEGAIN_SHIFT;
00202 cal |= ((DEVINFO->ADC0CAL1 & _DEVINFO_ADC0CAL1_VDD_OFFSET_MASK) >>
00203 _DEVINFO_ADC0CAL1_VDD_OFFSET_SHIFT) << _ADC_CAL_SINGLEOFFSET_SHIFT;
00204 adc->CAL = cal;
00205 break;
00206
00207 case adcRef5VDIFF:
00208 cal = adc->CAL & ~(_ADC_CAL_SINGLEOFFSET_MASK | _ADC_CAL_SINGLEGAIN_MASK);
00209 cal |= ((DEVINFO->ADC0CAL1 & _DEVINFO_ADC0CAL1_5VDIFF_GAIN_MASK) >>
00210 _DEVINFO_ADC0CAL1_5VDIFF_GAIN_SHIFT) << _ADC_CAL_SINGLEGAIN_SHIFT;
00211 cal |= ((DEVINFO->ADC0CAL1 & _DEVINFO_ADC0CAL1_5VDIFF_OFFSET_MASK) >>
00212 _DEVINFO_ADC0CAL1_5VDIFF_OFFSET_SHIFT) << _ADC_CAL_SINGLEOFFSET_SHIFT;
00213 adc->CAL = cal;
00214 break;
00215
00216 case adcRef2xVDD:
00217
00218 cal = adc->CAL & ~_ADC_CAL_SINGLEOFFSET_MASK;
00219 cal |= ((DEVINFO->ADC0CAL2 & _DEVINFO_ADC0CAL2_2XVDDVSS_OFFSET_MASK) >>
00220 _DEVINFO_ADC0CAL2_2XVDDVSS_OFFSET_SHIFT) << _ADC_CAL_SINGLEOFFSET_SHIFT;
00221 adc->CAL = cal;
00222 break;
00223
00224
00225
00226 default:
00227 break;
00228 }
00229 }
00230
00233
00234
00235
00236
00237
00255 void ADC_Init(ADC_TypeDef *adc, const ADC_Init_TypeDef *init)
00256 {
00257 uint32_t tmp;
00258
00259 EFM_ASSERT(ADC_REF_VALID(adc));
00260
00261
00262 adc->CMD = ADC_CMD_SINGLESTOP | ADC_CMD_SCANSTOP;
00263
00264 tmp = ((uint32_t)(init->ovsRateSel) << _ADC_CTRL_OVSRSEL_SHIFT) |
00265 (((uint32_t)(init->timebase) << _ADC_CTRL_TIMEBASE_SHIFT) & _ADC_CTRL_TIMEBASE_MASK) |
00266 (((uint32_t)(init->prescale) << _ADC_CTRL_PRESC_SHIFT) & _ADC_CTRL_PRESC_MASK) |
00267 ((uint32_t)(init->lpfMode) << _ADC_CTRL_LPFMODE_SHIFT) |
00268 ((uint32_t)(init->warmUpMode) << _ADC_CTRL_WARMUPMODE_SHIFT);
00269
00270 if (init->tailgate)
00271 {
00272 tmp |= ADC_CTRL_TAILGATE;
00273 }
00274
00275 adc->CTRL = tmp;
00276 }
00277
00278
00279
00299 void ADC_InitScan(ADC_TypeDef *adc, const ADC_InitScan_TypeDef *init)
00300 {
00301 uint32_t tmp;
00302
00303 EFM_ASSERT(ADC_REF_VALID(adc));
00304
00305
00306 adc->CMD = ADC_CMD_SCANSTOP;
00307
00308
00309 ADC_CalibrateLoadScan(adc, init->reference);
00310
00311 tmp = ((uint32_t)(init->prsSel) << _ADC_SCANCTRL_PRSSEL_SHIFT) |
00312 ((uint32_t)(init->acqTime) << _ADC_SCANCTRL_AT_SHIFT) |
00313 ((uint32_t)(init->reference) << _ADC_SCANCTRL_REF_SHIFT) |
00314 init->input |
00315 ((uint32_t)(init->resolution) << _ADC_SCANCTRL_RES_SHIFT);
00316
00317 if (init->prsEnable)
00318 {
00319 tmp |= ADC_SCANCTRL_PRSEN;
00320 }
00321
00322 if (init->leftAdjust)
00323 {
00324 tmp |= ADC_SCANCTRL_ADJ_LEFT;
00325 }
00326
00327 if (init->diff)
00328 {
00329 tmp |= ADC_SCANCTRL_DIFF;
00330 }
00331
00332 if (init->rep)
00333 {
00334 tmp |= ADC_SCANCTRL_REP;
00335 }
00336
00337 adc->SCANCTRL = tmp;
00338 }
00339
00340
00341
00361 void ADC_InitSingle(ADC_TypeDef *adc, const ADC_InitSingle_TypeDef *init)
00362 {
00363 uint32_t tmp;
00364
00365 EFM_ASSERT(ADC_REF_VALID(adc));
00366
00367
00368 adc->CMD = ADC_CMD_SINGLESTOP;
00369
00370
00371 ADC_CalibrateLoadSingle(adc, init->reference);
00372
00373 tmp = ((uint32_t)(init->prsSel) << _ADC_SINGLECTRL_PRSSEL_SHIFT) |
00374 ((uint32_t)(init->acqTime) << _ADC_SINGLECTRL_AT_SHIFT) |
00375 ((uint32_t)(init->reference) << _ADC_SINGLECTRL_REF_SHIFT) |
00376 ((uint32_t)(init->input) << _ADC_SINGLECTRL_INPUTSEL_SHIFT) |
00377 ((uint32_t)(init->resolution) << _ADC_SINGLECTRL_RES_SHIFT);
00378
00379 if (init->prsEnable)
00380 {
00381 tmp |= ADC_SINGLECTRL_PRSEN;
00382 }
00383
00384 if (init->leftAdjust)
00385 {
00386 tmp |= ADC_SINGLECTRL_ADJ_LEFT;
00387 }
00388
00389 if (init->diff)
00390 {
00391 tmp |= ADC_SINGLECTRL_DIFF;
00392 }
00393
00394 if (init->rep)
00395 {
00396 tmp |= ADC_SINGLECTRL_REP;
00397 }
00398
00399 adc->SINGLECTRL = tmp;
00400 }
00401
00402
00403
00420 uint8_t ADC_PrescaleCalc(uint32_t adcFreq, uint32_t hfperFreq)
00421 {
00422 uint32_t ret;
00423
00424
00425 if (adcFreq > ADC_MAX_CLOCK)
00426 {
00427 adcFreq = ADC_MAX_CLOCK;
00428 }
00429 else if (adcFreq < ADC_MIN_CLOCK)
00430 {
00431 adcFreq = ADC_MIN_CLOCK;
00432 }
00433
00434
00435 if (!hfperFreq)
00436 {
00437 hfperFreq = CMU_ClockFreqGet(cmuClock_HFPER);
00438 }
00439
00440 ret = (hfperFreq + adcFreq - 1) / adcFreq;
00441 if (ret)
00442 {
00443 ret--;
00444 }
00445
00446 return (uint8_t)ret;
00447 }
00448
00449
00450
00461 void ADC_Reset(ADC_TypeDef *adc)
00462 {
00463
00464 adc->CMD = ADC_CMD_SINGLESTOP | ADC_CMD_SCANSTOP;
00465 adc->SINGLECTRL = _ADC_SINGLECTRL_RESETVALUE;
00466 adc->SCANCTRL = _ADC_SCANCTRL_RESETVALUE;
00467 adc->CTRL = _ADC_CTRL_RESETVALUE;
00468 adc->IEN = _ADC_IEN_RESETVALUE;
00469 adc->IFC = _ADC_IFC_MASK;
00470 adc->BIASPROG = _ADC_BIASPROG_RESETVALUE;
00471
00472
00473 ADC_CalibrateLoadSingle(adc, adcRef1V25);
00474 ADC_CalibrateLoadScan(adc, adcRef1V25);
00475
00476
00477 }
00478
00479
00480
00490 uint8_t ADC_TimebaseCalc(uint32_t hfperFreq)
00491 {
00492 if (!hfperFreq)
00493 {
00494 hfperFreq = CMU_ClockFreqGet(cmuClock_HFPER);
00495
00496
00497 if (!hfperFreq)
00498 {
00499 hfperFreq = 1;
00500 }
00501 }
00502 #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_WONDER_FAMILY)
00503
00504
00505
00506
00507
00508 if( hfperFreq > 32000000 )
00509 {
00510 hfperFreq = 32000000;
00511 }
00512 #endif
00513
00514 hfperFreq += 999999;
00515 hfperFreq /= 1000000;
00516
00517
00518 return (uint8_t)(hfperFreq - 1);
00519 }
00520
00521
00524 #endif