Embedded System Design 2 - Project
adc.h File Reference

ADC functionality for reading the (battery) voltage and internal temperature. More...

#include <stdint.h>

Go to the source code of this file.

Typedefs

typedef enum adc_measurements ADC_Measurement_t
 

Enumerations

enum  adc_measurements { BATTERY_VOLTAGE, INTERNAL_TEMPERATURE }
 

Functions

void initADC (ADC_Measurement_t peripheral)
 Method to initialize the ADC to later check the battery voltage or internal temperature. More...
 
int32_t readADC (ADC_Measurement_t peripheral)
 Method to read the battery voltage or internal temperature. More...
 

Detailed Description

ADC functionality for reading the (battery) voltage and internal temperature.

Version
2.1
Author
Brecht Van Eeckhoudt

License

Copyright (C) 2019 - Brecht Van Eeckhoudt

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

A copy of the GNU General Public License can be found in the LICENSE file along with this source code.


Some methods use code obtained from examples from Silicon Labs' GitHub. These sections are licensed under the Silabs License Agreement. See the file "Silabs_License_Agreement.txt" for details. Before using this software for any purpose, you must agree to the terms of that agreement.

Definition in file adc.h.

Typedef Documentation

◆ ADC_Measurement_t

Enum type for the ADC

Enumeration Type Documentation

◆ adc_measurements

Enum type for the ADC

Enumerator
BATTERY_VOLTAGE 
INTERNAL_TEMPERATURE 

Definition at line 46 of file adc.h.

47 {
enum adc_measurements ADC_Measurement_t

Function Documentation

◆ initADC()

void initADC ( ADC_Measurement_t  peripheral)

Method to initialize the ADC to later check the battery voltage or internal temperature.

Parameters
[in]peripheralSelect the ADC peripheral to initialize.

Definition at line 86 of file adc.c.

87 {
88  /* Enable necessary clocks (just in case) */
89  CMU_ClockEnable(cmuClock_HFPER, true); /* ADC0 is a High Frequency Peripheral */
90  CMU_ClockEnable(cmuClock_ADC0, true);
91 
92  /* Set a timebase providing at least 1 us.
93  * If the argument is "0" the currently defined HFPER clock setting is used. */
94  init.timebase = ADC_TimebaseCalc(0);
95 
96  /* Set a prescale value according to the ADC frequency (400 000 Hz) wanted.
97  * If the last argument is "0" the currently defined HFPER clock setting is for the calculation used. */
98  init.prescale = ADC_PrescaleCalc(400000, 0);
99 
100  /* Initialize ADC peripheral */
101  ADC_Init(ADC0, &init);
102 
103  /* Setup single conversions */
104 
105  /* initSingle.acqTime = adcAcqTime16;
106  * The statement above was found in a SiLabs example but DRAMCO disabled it.
107  * After testing this seemed to have no real effect so it was disabled.
108  * This is probably not necessary since a prescale value other than 0 (default) has been defined. */
109  if (peripheral == INTERNAL_TEMPERATURE) initSingle.input = adcSingleInpTemp; /* Internal temperature */
110  else if (peripheral == BATTERY_VOLTAGE) initSingle.input = adcSingleInpVDDDiv3; /* Internal VDD/3 */
111  else
112  {
113 
114 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
115  dbcrit("Unknown ADC peripheral selected!");
116 #endif /* DEBUG_DBPRINT */
117 
118  /* Disable used clock */
119  CMU_ClockEnable(cmuClock_ADC0, false);
120 
121  error(11);
122 
123  /* Exit function */
124  return;
125  }
126 
127  ADC_InitSingle(ADC0, &initSingle);
128 
129  /* Manually set some calibration values
130  * ADC0->CAL = (0x7C << _ADC_CAL_SINGLEOFFSET_SHIFT) | (0x1F << _ADC_CAL_SINGLEGAIN_SHIFT);
131  * The statement above was found in a SiLabs example but DRAMCO disabled it.
132  * After testing this seemed to throw off the first measurement so it was disabled. */
133 
134  /* Enable interrupt on completed conversion */
135  ADC_IntEnable(ADC0, ADC_IEN_SINGLE);
136  NVIC_ClearPendingIRQ(ADC0_IRQn);
137  NVIC_EnableIRQ(ADC0_IRQn);
138 
139  /* Disable used clock */
140  CMU_ClockEnable(cmuClock_ADC0, false);
141 
142 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
143  if (peripheral == INTERNAL_TEMPERATURE) dbinfo("ADC0 initialized for internal temperature");
144  else if (peripheral == BATTERY_VOLTAGE) dbinfo("ADC0 initialized for VBAT");
145 #endif /* DEBUG_DBPRINT */
146 
147 }
ADC_InitSingle_TypeDef initSingle
Definition: adc.c:72
void dbinfo(char *message)
Print an info string (char array) to USARTx and go to the next line.
Definition: dbprint.c:503
ADC_Init_TypeDef init
Definition: adc.c:71
void error(uint8_t number)
Error method.
Definition: util.c:131
void dbcrit(char *message)
Print a critical error string (char array) in red to USARTx and go to the next line.
Definition: dbprint.c:539

◆ readADC()

int32_t readADC ( ADC_Measurement_t  peripheral)

Method to read the battery voltage or internal temperature.

This method re-initializes the ADC settings if necessary.
Negative internal temperatures work fine.

Parameters
[in]peripheralSelect the ADC peripheral to read from.
Returns
The measured battery voltage or internal temperature.

Definition at line 164 of file adc.c.

165 {
166  uint16_t counter = 0; /* Timeout counter */
167  int32_t value = 0; /* Value to eventually return */
168 
169  /* Enable necessary clock */
170  CMU_ClockEnable(cmuClock_ADC0, true);
171 
172  /* Change ADC settings if necessary */
173  if (peripheral == INTERNAL_TEMPERATURE)
174  {
175  if (initSingle.input != adcSingleInpTemp)
176  {
177  initSingle.input = adcSingleInpTemp; /* Internal temperature */
178  ADC_InitSingle(ADC0, &initSingle);
179  }
180  }
181  else if (peripheral == BATTERY_VOLTAGE)
182  {
183  if (initSingle.input != adcSingleInpVDDDiv3)
184  {
185  initSingle.input = adcSingleInpVDDDiv3; /* Internal VDD/3 */
186  ADC_InitSingle(ADC0, &initSingle);
187  }
188  }
189  else
190  {
191 
192 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
193  dbcrit("Unknown ADC peripheral selected!");
194 #endif /* DEBUG_DBPRINT */
195 
196  /* Disable used clock */
197  CMU_ClockEnable(cmuClock_ADC0, false);
198 
199  error(12);
200 
201  /* Exit function */
202  return (0);
203  }
204 
205  /* Set variable false just in case */
206  adcConversionComplete = false;
207 
208  /* Start single ADC conversion */
209  ADC_Start(ADC0, adcStartSingle);
210 
211  /* Wait until the conversion is completed */
212  while ((counter < TIMEOUT_CONVERSION) && !adcConversionComplete) counter++;
213 
214  /* Exit the function if the maximum waiting time was reached */
215  if (counter == TIMEOUT_CONVERSION)
216  {
217 
218 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
219  dbcrit("Waiting time for ADC conversion reached!");
220 #endif /* DEBUG_DBPRINT */
221 
222  /* Disable used clock */
223  CMU_ClockEnable(cmuClock_ADC0, false);
224 
225  error(13);
226 
227  /* Exit function */
228  return (0);
229  }
230 #if DBPRINT_TIMEOUT == 1 /* DBPRINT_TIMEOUT */
231  else
232  {
233 
234 #if DEBUG_DBPRINT == 1 /* DEBUG_DBPRINT */
235  dbwarnInt("ADC conversion (", counter, ")");
236 #endif /* DEBUG_DBPRINT */
237 
238  }
239 #endif /* DBPRINT_TIMEOUT */
240 
241  /* Get the ADC value */
242  value = ADC_DataSingleGet(ADC0);
243 
244  /* Disable used clock */
245  CMU_ClockEnable(cmuClock_ADC0, false);
246 
247  /* Calculate final value according to parameter */
248  if (peripheral == INTERNAL_TEMPERATURE)
249  {
250  float32_t ft = convertToCelsius(value)*1000;
251  value = (int32_t) ft;
252  }
253  else if (peripheral == BATTERY_VOLTAGE)
254  {
255  float32_t fv = value * 3.75 / 4.096;
256  value = (int32_t) fv;
257  }
258 
259  return (value);
260 }
ADC_InitSingle_TypeDef initSingle
Definition: adc.c:72
void dbwarnInt(char *message1, int32_t value, char *message2)
Print a warning value surrounded by two strings (char array) to USARTx.
Definition: dbprint.c:598
#define TIMEOUT_CONVERSION
Definition: adc.c:66
static float32_t convertToCelsius(int32_t adcSample)
Method to convert an ADC value to a temperature value.
Definition: adc.c:277
void error(uint8_t number)
Error method.
Definition: util.c:131
volatile bool adcConversionComplete
Definition: adc.c:70
void dbcrit(char *message)
Print a critical error string (char array) in red to USARTx and go to the next line.
Definition: dbprint.c:539