Skip to content

概述

ADC(Analog-to-Digital Converter,模数转换器)将模拟电压转换为数字值,是读取传感器(温度、光敏、电位器等)的基础。本教程通过 ADC 通道 10(IO11) 采集分压网络的电压,换算成实际电压后通过串口打印。

用大白话讲:开发板只能理解数字(0 和 1),看不懂「3.3 伏」这种连续变化的电压。ADC 就像一台「电压翻译机」:把引脚上的电压高低翻译成一串数字告诉程序。本教程还用一个分压网络(像水位计的刻度)把大电压按比例缩小,让翻译机量得下、量得准。

本教程基于安信可官方 SDKAi-Thinker-Open/Ai-Thinker-WB2,版本 release_bl_iot_sdk_1.6.40)的官方示例 applications/peripherals/demo_adc 编写,代码可在本地 SDK 中直接找到。

🎯本页目标通过 ADC 通道 10(IO11)采集电压,利用分压网络换算实际电压并在串口打印,掌握 ADC 初始化、通道添加与采样 API。
🧰前置条件① Ai-WB2 开发板、4.7kΩ 电阻、1kΩ 电阻、杜邦线 ② 已按 [SDK 安装](../sdk/sdk_intro) 完成环境搭建。
🔗相关章节电压测量常用于传感器采集,见 [最佳实践-传感器](../best/);串口日志输出见 [UART(串口)](./uart)。

硬件接线

按官方示例接线(见 SDK applications/peripherals/demo_adc/README.md),通过 4.7kΩ + 1kΩ 分压网络将待测电压降到 ADC 量程内:

Ai-WB2 引脚 连接到
IO11(ADC 通道 10) 分压点(4.7kΩ 与 1kΩ 之间)
待测电压(如 3V3) 4.7kΩ 上端
GND 1kΩ 下端
VCC ── 4.7kΩ ──┬── IO11
               │
              1kΩ
               │
              GND

💡 示例中 ADC 输出的原始值按 实际电压 = ADC值 × (4700 + 1000) ÷ 1000(单位 mV)换算,即考虑 4.7kΩ 与 1kΩ 分压的还原公式。BL602 的 ADC 参考电压为 1.0V,量程(能测量的电压范围)为 0~1.8V(需分压采样),接线务必按分压网络。

进入示例工程

打开终端,进入官方 demo_adc 示例工程目录:

cd ~/Ai-Thinker-WB2/applications/peripherals/demo_adc

说明:cd 是「进入目录」命令,这里进入 demo_adc 示例工程目录;后续的 make 编译、make flash 烧录命令都必须先在这个目录里执行。

编写代码

打开 demo_adc/main.c,本步完整代码已移至文末,见:

📜 完整代码 — 位于本页「完整代码」章节,默认折叠,点击展开,与官方示例(applications/peripherals/demo_adc/demo_adc/main.c)完全一致。

代码要点:

代码 作用
.mode = HOSAL_ADC_ONE_SHOT 单次采样模式(采样一次返回一个值),模式选错采不到预期结果
.pin = GPIO_ADC_PIN / ADC_CHANNEL 采样引脚 IO11 对应 ADC 通道 10,引脚与通道必须配套,否则读数恒为 0
hosal_adc_init(&adc0) 初始化 ADC 设备,不初始化后面所有采样函数都无效
hosal_adc_add_channel(&adc0, ADC_CHANNEL) 把通道 10 加进采样列表,不加则这个通道永远不会被采样
hosal_adc_value_get(&adc0, ADC_CHANNEL, 100) 读取一次采样值(超时 100ms),调用成功才能拿到 adc->data 里的数值
ret * (4700 + 1000) / 1000 按分压比例还原实际电压(mV),不算这步打印的是缩水后的错误数值

📌 官方注释中的通道映射表表明:通道 10 对应 GPIO11。BL602 共 12 个 ADC 通道(通道 6、8 保留),换引脚时先查映射表。

编译工程

在工程目录执行编译:

make -j8

说明:make 是「编译工程」命令,把代码变成开发板能运行的固件(程序文件);-j8 表示用 8 个核并行编译,速度更快。

编译成功后生成固件 build_out/demo_adc.bin

烧录固件

开发板保持 USB 连接,确认串口设备号后执行烧录:

make flash p=/dev/ttyUSB0 b=921600

说明:make flash 是「烧录」命令,把编译好的固件写进开发板芯片。p= 后面是串口设备号(改成你电脑上实际的串口,可用 ls /dev/ttyUSB* 查看),b= 是烧录波特率(传输速度)。

⏳ 烧录过程中按提示长按开发板 EN 键进入下载模式,等待进度条完成即烧录成功。

运行验证

烧录完成后开发板自动重启运行,打开串口助手(波特率 921600),每 2 秒打印一次换算后的电压值:

ADC = 3300 mV
ADC = 3300 mV
...

待测电压接 3V3 时打印约 3300mV;用可调电源缓慢调节电压,串口打印值随之线性变化,即 ADC 采样正常。

看到串口每 2 秒打印一个电压值、数值随输入电压变化即为成功;如果一直打印 0 或数值不变,说明还没成功,对照文末「常见问题与踩坑提示」排查。

💡 尝试改动分压网络中的电阻值,观察打印电压变化;也可将 4.7kΩ 换成 光敏电阻(LDR),即可做成简易光线检测。

代码执行流程

例程从启动到运行的完整流程如下(图中的循环箭头表示反复执行):


本文 API 汇总

hosal_adc_init(adc)

dev 结构体中的模式、引脚、采样频率等配置 ADC(本教程初始化单次采样模式)。

参数

  • adchosal_adc_dev_t 结构体指针,必填。关键字段:config.mode(采样模式,可选值:HOSAL_ADC_ONE_SHOT 单次采样 / HOSAL_ADC_CONTINUOUS 连续采样)、config.pin(ADC 引脚号,本教程 IO11)、config.sampling_freq(采样频率 Hz)

返回值:成功返回 0;失败返回负值错误码

hosal_adc_add_channel(adc, channel)

将指定 ADC 通道加入采样列表(本教程添加通道 10)。

参数

  • adchosal_adc_dev_t 结构体指针
  • channel:通道号,可选值:0~11(其中 6、8 保留不可用),本教程 10(对应 IO11)

返回值:成功返回 0;失败返回负值错误码

hosal_adc_remove_channel(adc, channel)

将指定通道从采样列表中移除。

参数

  • adchosal_adc_dev_t 结构体指针
  • channel:通道号,可选值:0~11(需与添加时一致)

返回值:成功返回 0;失败返回负值错误码

hosal_adc_value_get(adc, channel, timeout)

单次模式下触发一次采样并等待结果,采样值存回 adc->data(本教程换算为分压前的实际电压)。

参数

  • adchosal_adc_dev_t 结构体指针
  • channel:通道号,可选值:0~11(6、8 保留)
  • timeout:等待超时时间(单位 ms),可选值:如 100(超时未出结果返回失败)

返回值:成功返回 0(原始采样值在 adc->data);超时或失败返回负值错误码

hosal_adc_start(adc, data, size)

连续模式下启动持续采样,数据通过中断回调逐个给出。

参数

  • adchosal_adc_dev_t 结构体指针
  • data:采样数据输出缓冲区指针
  • size:缓冲区大小

返回值:成功返回 0;失败返回负值错误码

hosal_adc_stop(adc)

停止连续采样。

参数

  • adchosal_adc_dev_t 结构体指针

返回值:成功返回 0;失败返回负值错误码

blog_info(fmt, ...)

输出一条 INFO 级日志(UART0,受级别过滤)。

参数

  • fmt:格式化字符串,同 printf 用法,必填
  • ...:变参,与 fmt 占位符对应,可省略

返回值:无


完整代码

以下为 demo_adc/main.c 完整源码,与官方示例(applications/peripherals/demo_adc/demo_adc/main.c)完全一致:

📜 点击展开 demo_adc/main.c 完整代码
c
#include <stdio.h>
#include <string.h>
#include <FreeRTOS.h>
#include <task.h>
#include <hosal_adc.h>
#include <blog.h>

/**********   BL602  ************
*    channel0   ----->     gpio12 
*    channel1   ----->     gpio4
*    channel2   ----->     gpio14
*    channel3   ----->     gpio13
*    channel4   ----->     gpio5
*    channel5   ----->     gpio6
*    channel7   ----->     gpio9
*    channel9   ----->     gpio10
*    channel10  ----->     gpio11
*    channel11  ----->     gpio15
*/

#define GPIO_ADC_PIN 11
#define ADC_CHANNEL 10

void main(void)
{
    static hosal_adc_dev_t adc0 = {
        .cb = NULL,
        .config = {
            .mode = HOSAL_ADC_ONE_SHOT,
            .pin = GPIO_ADC_PIN,
            .sampling_freq = 340,
        },
        .dma_chan = 0,
        .p_arg = NULL,
        .port = 0,
    };

    hosal_adc_init(&adc0);

    hosal_adc_add_channel(&adc0, ADC_CHANNEL);

    for (;;) {
        int ret = hosal_adc_value_get(&adc0, ADC_CHANNEL, 100);

        /// ADC
        ///  |
        /// ┌┴┐
        /// | | 4.7 kΩ
        /// └┬┘
        ///  |
        ///  ├-----IO11
        ///  |
        /// ┌┴┐
        /// | | 1 kΩ
        /// └┬┘
        ///  |
        ///  ┴
        /// GND
        /// Actual Voltage = ADC output * 1000 / (4700 + 1000)  (Unit: mV)
        
        ret = ret * (4700 + 1000) / 1000;

        blog_info("ADC = %ld mV\r\n", ret);

        vTaskDelay(pdMS_TO_TICKS(2000));
    }
}

常见问题与踩坑提示

⚠️ 串口打印的电压值异常(过大或过小)
原因:分压电阻值换过但公式未同步,或待测电压超过 ADC 量程
解决:确认换算公式与分压电阻匹配;BL602 ADC 参考电压 1.0V,量程有限,待测电压必须经过分压后再采样

⚠️ 采样值恒为 0 或固定值不变
原因:引脚与通道号不匹配(如把通道 10 用在 IO15 上)
解决:对照官方通道映射表选择引脚与通道(通道 10 → IO11),换引脚时同时改 GPIO_ADC_PINADC_CHANNEL

⚠️ 采样值跳变、噪声大
原因:杜邦线过长、未共地,或采样点悬空
解决:缩短杜邦线并确认与开发板共地;采样点并联 100nF 电容滤波;软件上可多次采样取平均

⚠️ 烧录一直卡住等待,进度条不动
原因:未进入下载模式,或数据线只能充电不能传数据
解决:烧录时按提示长按 EN 键进入下载模式;换一根能传数据的 Type-C 数据线后重试

⚠️ 找不到串口设备或提示无权限
原因:Linux 下 /dev/ttyUSB0 不存在或权限不足,Windows 下未安装 USB 转串口驱动
解决:Linux 用 ls /dev/ttyUSB* 确认设备号,权限不足执行 sudo usermod -aG dialout $USER 后重新登录;Windows 在设备管理器安装驱动并确认 COM 口号

⚠️ 执行 make 报找不到 Makefile
原因:在错误的目录执行了编译命令(必须在示例工程目录内)
解决:先执行 cd ~/Ai-Thinker-WB2/applications/peripherals/demo_adc 进入工程目录,再执行 make -j8

运行自检

串口每 2 秒打印一次电压值,且调节输入电压时打印值线性跟随,即 ADC 功能验证通过。

遇到问题?

如有其他问题,请到统一的提问与讨论区:Ai-Thinker Discussions

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