ADC Usage Guide
1. ADC Introduction
Currently, the ADC has 8 available channels with a measurement range of 0 to 1.0 V. The ADC can test individual channels or perform multi-channel cyclic tests. It can stop after testing a set of data or continue to output data indefinitely.
2. ADC Configuration
The ADC configuration includes PINMUX configuration and ADC clock-related configuration, which are defined in adc_config.h
. Users can modify them as needed.
The PINMUX setup varies slightly for A0 and Z0. For Z0, when the PIN is used as ADC, you can select the ADC function directly during PIN configuration (e.g., HAL_PIN_Set(PAD_PB_04, ADC_PIN, PIN_PULLUP, 0)
).
For A0, each pin that can be configured as GPADC corresponds to a different FUNCTION setting: GPADC_CH0, GPADC_CH1, and so on. When using these, set the pins according to the corresponding channels, for example, HAL_PIN_Set(PAD_PB08, GPADC_CH0, PIN_NOPULL, 0)
for PAD_PB8 corresponding to GPADC channel 0.
Alternatively, you can directly set the PIN to analog function without worrying about the specific analog function of each PIN, such as HAL_PIN_Set_Analog(PAD_PB08, 0)
/ HAL_PIN_Set_Analog(PAD_PB13, 0)
.
For A0, the available PADs and their corresponding GPADC channels are as follows:
PAD Number |
Channel |
Description |
---|---|---|
PAD_PB08 |
GPADC_CH0 |
Connected to LCPU |
PAD_PB10 |
GPADC_CH1 |
Connected to LCPU |
PAD_PB12 |
GPADC_CH2 |
Connected to LCPU |
PAD_PB13 |
GPADC_CH3 |
Connected to LCPU |
PAD_PB16 |
GPADC_CH4 |
Connected to LCPU |
PAD_PB17 |
GPADC_CH5 |
Connected to LCPU |
PAD_PB18 |
GPADC_CH6 |
Connected to LCPU |
PAD_PB19 |
GPADC_CH7 |
Connected to LCPU |
3. ADC Usage
In our system, the ADC is registered as a battery voltage device, which can be operated via device methods. The default device name is “bat1”:
uint32_t chnl = 1;
uint32_t value;
// find device
rt_device_t dev = rt_device_find(argv[2]);
if (dev)
{
// open device
rt_device_open(dev, RT_DEVICE_FLAG_RDONLY);
// enable adc
rt_device_control(dev, RT_ADC_CMD_ENABLE, (void *)chnl);
// read adc value
rt_device_read(dev, chnl, &value, 1);
}
......
4. Voltage Calculation
The voltage value can be obtained through the ADC using the HAL_ADC_GetValue
interface, or via the read
interface if using rt_device
.
Each increment of the register value corresponds to a voltage increase of approximately 1 mV (the exact value may vary per chip, requiring factory calibration).
The relationship between ADC value and voltage is linear, and to calibrate for offset and slope accuracy, you can refer to the function sifli_adc_calibration
.
The method involves determining a line through two known points, then using this line to calculate voltage for any subsequent register value.
Example conversion code for the register value to voltage:
static uint32_t adc_vol_offset = 200;
static uint32_t adc_vol_ratio = 3930;
int sifli_adc_get_mv(uint32_t value)
{
uint32_t offset, ratio;
offset = adc_vol_offset;
ratio = adc_vol_ratio;
return (value - offset) * ratio / ADC_RATIO_ACCURATE;
}
int sifli_adc_calibration(uint32_t value1, uint32_t value2, uint32_t vol1, uint32_t vol2, uint32_t *offset, uint32_t *ratio)
{
uint32_t gap1, gap2;
if (offset == NULL || ratio == NULL)
return 0;
gap1 = value1 > value2 ? value1 - value2 : value2 - value1;
gap2 = vol1 > vol2 ? vol1 - vol2 : vol2 - vol1;
if (gap1 != 0)
{
*ratio = gap2 * ADC_RATIO_ACCURATE / gap1;
adc_vol_ratio = *ratio;
}
*offset = value1 - vol1 * ADC_RATIO_ACCURATE / adc_vol_ratio;
adc_vol_offset = *offset;
return adc_vol_offset;
}