Skip to content

Contributed by 爱笑, organized by Ai-Thinker

[Ai-WB2 Intermediate] ADC Analog-to-Digital Conversion

An analog-to-digital converter (ADC) is a device that converts analog signals to digital signals. It supports 12 external analog inputs and a number of internal analog signal selections. The Ai-WB2 ADC supports the following four modes: single-shot single-channel conversion, continuous single-channel conversion, single-shot multi-channel conversion, and continuous multi-channel conversion. The conversion result is 12/14/16-bit left-aligned. The ADC has a FIFO depth of 32 and supports multiple interrupts and DMA operations. In addition to ordinary analog signal measurement, the ADC can also measure the supply voltage, and it can be used for temperature detection by measuring the internal/external diode voltage.

This article will detail how to sample the voltage of a potentiometer using the Ai-WB2 ADC module. 1. ADC Introduction The BL602 chip has a built-in 12-bit successive-approximation ADC that supports 12 external analog inputs and a number of internal analog signal selections. The ADC can work in two modes: single-shot conversion and multi-channel scan, with 12/14/16-bit left-aligned conversion results. The ADC has a FIFO depth of 32, supports multiple interrupts, and supports DMA operations. In addition to ordinary analog signal measurement, the ADC can also measure the supply voltage, and it can be used for temperature detection by measuring the internal/external diode voltage. The Ai-WB2 ADC has the following features:

Click to expand full code
c
**高性能**
**·** 可以选择12-bit,14-bit,16-bit 转换结果输出
**·** ADC 转换时间最快0.5us(12-bit 转换结果)
**·** 支持1.8V3.3V 可选参考电压
**·** 支持DMA 将转换结果搬运到内存
**·** 支持单通道转换和多通道扫描两种模式
**·** 支持单端与差分两种输入模式
**·** 支持抖动补偿
**·** 支持用户自行设定转换结果偏移值
**·** 扫描模式时钟最大支持1M,非扫描模式支持2M
**模拟通道数**
**·** 12 路外部模拟通道
**·** 2 路DAC 内部通道
**·** 1路VBAT/2 通道
**·** 1路TSEN 通道

The functional block diagram of the ADC is as follows:

The ADC module consists of five major parts: the front-end input channel selector, the programmable gain amplifier, the ADC sampling module, the data processing module, and the FIFO. The input channel selector is used to select the channel to be sampled, covering both external analog signals and internal analog signals. The programmable gain amplifier further processes the input signal, and can be configured according to the characteristics of the input signal, such as DC or AC, to obtain a more accurate conversion value. The ADC sampling module is the most important functional module, which performs the conversion from analog signals to digital signals through successive comparison. The conversion result is 12-bit. The data processing module is responsible for further processing the conversion result, including adding channel information, etc. The final data is pushed to the FIFO at the end.

In the BL602, the mapping between ADC channels and GPIOs is as follows:

2. ADC Driver API In the bl_iot_sdk, the high-level HOSAL-layer API of the ADC is defined in components/platform/hosal/include/hosal_adc.h. The commonly used driver API functions are as follows: · int hosal_adc_init(hosal_adc_dev_t *adc): Initialize the ADC. Parameter description: · adc: ADC device. It is defined as follows:

Click to expand full code
c
/**
* @brief Define ADC dev hosal handle
*/
typedef struct {
uint8_t port;                    /**< @brief adc 端口 */
hosal_adc_config_t config;        /**< @brief adc 配置 */
hosal_dma_chan_t dma_chan;        /**< @brief adc dma 通道 */
hosal_adc_irq_t cb;               /**< @brief adc 回调函数 */
void *p_arg;                      /**< @brief p_arg 回调函数参数 */
void *priv;                       /**< @brief priv 用户自定义数据 */
} hosal_adc_dev_t;

Among them, hosal_adc_config_t is the ADC configuration, defined as follows:

Click to expand full code
c
/**
* @brief Define ADC config args
*/
typedef struct {
uint32_t sampling_freq;             /**< @brief 采样频率(以Hz为单位) */
uint32_t pin;                        /**< @brief adc 引脚 */
hosal_adc_sample_mode_t mode;       /**< @brief adc 采样模式 */
uint8_t sample_resolution;          /**< @brief adc 采样精度 */
} hosal_adc_config_t;

The definition of hosal_adc_sample_mode_t is as follows:

Click to expand full code
c
/**
* @brief ADC MODE type
*/
typedef enum {
HOSAL_ADC_ONE_SHOT,       /**< @brief 单次采样 */
HOSAL_ADC_CONTINUE        /**< @brief 持续采样 */
} hosal_adc_sample_mode_t;
Click to expand full code
c
**·** 返回值:成功时返回0,否则返回EIO或其他值
**·** int hosal_adc_add_channel(hosal_adc_dev_t *adc,uint32_t channel):添加向ADC设备添加ADC通道。参数说明如下:
**·** adc:ADC端口设备
**·** ochannel:需要添加的ADC通道
**·** 返回值:成功时返回0,否则返回EIO或其他值
**·** int hosal_adc_remove_channel(hosal_adc_dev_t *adc, uint32_t channel):移除ADC诵道。参数说明如下:
**·** adc:ADC端囗设备
**·** ochannel:需要移除的ADC通道
**·** 返回值:成功时返回0,否则返回EIO或其他值
**·** int hosal_adc_value_get(hosal_adc_dev_t *adc, uint32_t channel,uint32_t timeout):读取单个ADC采样结果。参数说明如下:
**·** adc:ADC端口设备
**·** channel:ADC通道
**·** otimeout:超时时长
**·** 返回值:如果读取失败,则返回-1:否则返回ADC值
**·** int hosal_adc_tsen_value_get(hosal_adc_dev_t*adc):获取ADC端囗的TSEN值。参数说明如下:
**·** adc:ADC端口设备
**·** 返回值:如果读取失败,则返回-1:否则返回ADC值
**·** int hosal_adc_sample_cb_reg(hosal_adc_dev_t *adc,hosal_adc_cb_t cb):注册ADC回调函数(该函数未具体实现)
**·** adc:ADC端口设备
**·** cb:回调函数,当cb不为NULL时,表示注册;当cb为NULL时,表示注销。其定义如下:
  1. typedef void (*hosal_adc_irq_t)(void *parg);

     Please note: the adc pointer in cb must be the same as the adc pointer passed to hosal_adc_sample_cb_reg. The driver must notify the upper layer by calling cb whether the ADC data is ready in hardware or in memory (DMA).
    
Click to expand full code
c
**·** 返回值:成功时返回0,否则返回EIO或其他值
**·** int hosal_adc_start(hosal_adc_dev_t *adc,void *data,uint32_t size):启动ADC采样(该函数未具体实现)。参数说明如下:
**·** adc:ADC端口设备
**·** data:用于储存采样结果
**·** size:储存ADC采样结果长度
**·** 返回值:成功时返回0,否则返回EIO或其他值
**·** int hosal adc_stop(hosal_adc_dev_t *adc):ADC停止采样(该函数未具体实现)。参数说明如下:
**·** adc:ADC端口设备
**·** 返回值:成功时返回0,否则返回EIO或其他值
**·** hosal_adc_finalize(hosal_adc_dev_t *adc):释放ADC。参数说明如下:
**·** adc:ADC端囗设备
**·** 返回值:成功时返回0,否则返回EIO或其他值
**三:ADC使用示例**

The following demonstrates sampling the potentiometer voltage through ADC channel 4 (GPIO5). The example code is as follows:

Click to expand full code
c
#include <stdio.h>
#include <string.h>
#include <FreeRTOS.h>
#include <task.h>
#include <stdio.h>
#include <stdbool.h>
#include <hosal_dma.h>
#include <hosal_adc.h>
#include <blog.h>
#define TAG "adc_demo"
/**********   BL602  ************
*    channel0   ----->     gpio12
*    channel1   ----->     gpio4
*    channel2   ----->     gpio14
*    channel3   ----->     gpio13
*    channel4   ----->     gpio5
*    channel5   ----->     gpio6
*    channel7   ----->     gpio9
*    channel9   ----->     gpio10
*    channel10  ----->     gpio11
*    channel11  ----->     gpio15
*/
static hosal_adc_dev_t adc0;
static void adc_init(void){
adc0.port = 0;
adc0.config.sampling_freq = 340;
adc0.config.pin = 5;
adc0.config.mode = HOSAL_ADC_ONE_SHOT; // 配置为单次采样
int ret = hosal_adc_init(&adc0);
if (ret != 0) {
blog_error("init adc failed. \r\n");
return;
}
hosal_adc_add_channel(&adc0, 4);
printf("adc init done\r\n");
}
void adc_task(void* params){
adc_init();
printf("adc task start...\r\n");
vTaskDelay(500);
while(true){
//hosal_adc_start(&adc0);
int ret = hosal_adc_value_get(&adc0, 4, 20);
if(ret < 0){
printf("adc sample failed:%d\r\n",ret);
continue;
}
printf("adc value = %d\r\n",ret);
vTaskDelay(10);
}
hosal_adc_finalize(&adc0);
}
void main(void) {
hosal_dma_init();
printf("adc demo inited\r\n");
xTaskCreate(adc_task, "adc_task", 1024, NULL, 15, NULL);
}
   Note: the HOSAL layer samples using DMA, so you need to call the hosal_dma_init function to initialize the DMA module.

Released under the MIT License. Build Time 2026-09-11 14:52:23