一、ADC 基础概念
ADC(Analog to Digital Converter):模数转换器,把连续的模拟电压信号转换成离散的数字值。
I.MX6U 内部集成了 12位 ADC,最大分辨率 4096 个刻度(0~4095),参考电压一般为 3.3V。
精度计算:

二、ADC 相关寄存器
2.1 ADC_CFG --- 配置寄存器
| 位 | 名称 | 说明 |
|---|---|---|
| bit1:0 | MODE | 转换精度:00=8位,01=10位,10=12位,11=16位 |
| bit3:2 | ADIV | 时钟分频:00=1分频,01=2分频,10=4分频,11=8分频 |
| bit4 | ADLSMP | 采样时间:0=短采样,1=长采样 |
| bit6:5 | ADSTS | 长采样时间选择 |
| bit7 | ADHSC | 高速转换:0=正常,1=高速 |
| bit9:8 | REFSEL | 参考电压选择:00=内部VREFH/VREFL |
| bit10 | ADTRG | 触发方式:0=软件触发,1=硬件触发 |
| bit11 | AVGE | 硬件均值使能 |
| bit13:12 | AVGS | 均值采样数:00=4次,01=8次,10=16次,11=32次 |
| bit15 | OVRD | 覆盖使能 |
代码中的配置:
base->CFG = (0x2 << 2) | (0x3 << 0);
// ↑ ADIV=2 → 4分频
// ↑ MODE=3 → 12位精度(实际12位用0x2,这里0x3在某些型号为16位)
注意 :I.MX6ULL 的 ADC 最高支持 12 位,MODE 设为
0x2才是 12 位,0x3在部分芯片为无效值或 16 位模式,读数需用 0xFFF 掩码取低 12 位。
2.2 ADC_GC --- 通用控制寄存器
| 位 | 名称 | 说明 |
|---|---|---|
| bit0 | ADACKEN | 异步时钟输出使能 |
| bit1 | DMAEN | DMA 使能 |
| bit2 | ACREN | 比较范围使能 |
| bit3 | ACFGT | 比较功能大于使能 |
| bit4 | ACFE | 比较功能使能 |
| bit5 | AVGE | 硬件均值使能 |
| bit6 | ADCO | 连续转换使能:0=单次,1=连续 |
| bit7 | CAL | 校准启动位:写1启动校准,校准完成后硬件自动清0 |
代码中的配置:
base->GC = (0x01 << 0); // 使能异步时钟
base->GC |= (0x01 << 7); // 启动校准
while(base->GC & (1 << 7)); // 等待校准完成(CAL自动清0)
2.3 ADC_GS --- 通用状态寄存器
| 位 | 名称 | 说明 |
|---|---|---|
| bit0 | ADACT | 转换状态:1=正在转换 |
| bit1 | CALF | 校准失败标志:1=校准失败,需软件清零 |
| bit2 | AWKST | 异步唤醒状态 |
代码中的使用:
base->GS |= (0x01 << 1); // 先清除上次可能残留的 CALF 标志
// ... 校准 ...
if(base->GS & (1 << 1)) // 校准后检查 CALF
return -1; // 校准失败
2.4 ADC_HC[n] --- 转换控制寄存器(每个通道一个)
| 位 | 名称 | 说明 |
|---|---|---|
| bit4:0 | ADCH | 通道选择:0~15=对应输入通道,11111(0x1F)=禁用转换 |
| bit7 | AIEN | 转换完成中断使能:0=关闭,1=使能 |
代码中的使用:
base->HC[0] &= ~(1 << 0); // 初始化时先清通道位
// ...
base->HC[0] |= (0x1f << 0); // 先写 0x1F 禁用
base->HC[0] = (0x1 << 0); // 再选通道1(GPIO1_IO01对应ADC通道1)
触发机制:软件触发模式下,向 HC[n] 写入通道号就会立刻启动一次转换,这就是"写通道号 = 触发转换"。
2.5 ADC_HS --- 状态寄存器
| 位 | 名称 | 说明 |
|---|---|---|
| bit0 | COCO0 | 通道0转换完成标志:1=转换完成,读 R[0] 后自动清零 |
代码中的使用:
while(!(base->HS & (1 << 0))); // 等待 COCO0=1 转换完成
2.6 ADC_R[n] --- 转换结果寄存器
| 位 | 名称 | 说明 |
|---|---|---|
| bit11:0 | D | 转换结果(12位模式下低12位有效) |
代码中的使用:
adc_value = base->R[0] & 0xfff; // 取低12位
重要:读取 R[0] 这个动作会自动清除 HS 中的 COCO0 标志,为下次转换做准备。
三、初始化流程(对应手册图 Figure 13-5)

bash
Reset
↓
Initialize ADC
├─ ADC_CFG:设置精度、分频、触发方式
├─ ADC_GC:使能时钟,启动校准(CAL=1)
└─ ADC_HCn:配置通道(先写0x1F禁用)
↓
Check COCOn=1? ──No──→ 等待(轮询 GC.CAL 位变0)
│ Yes
↓
Read ADC_Rn to Clear COCOn Bit
↓
Continue(初始化完成)
对应代码:
cs
int adc_init(ADC_Type *base)
{
// 1. 配置引脚为模拟输入(GPIO1_IO01)
IOMUXC_SetPinMux(IOMUXC_GPIO1_IO01_GPIO1_IO01, 0);
IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO01_GPIO1_IO01, 0x10b0);
// 2. 配置通道0:先禁用(写0x1F),等初始化完再配置
base->HC[0] &= ~(1 << 0);
// 3. 配置 ADC:4分频 + 12位精度
base->CFG = (0x2 << 2) | (0x3 << 0);
// 4. 使能异步时钟
base->GC = (0x01 << 0);
// 5. 清除上次残留的校准失败标志
base->GS |= (0x01 << 1);
// 6. 启动硬件校准
base->GC |= (0x01 << 7);
// 7. 等待校准完成(CAL位自动清0)
while(base->GC & (1 << 7));
// 8. 检查校准结果
if(base->GS & (1 << 1))
return -1; // 校准失败
return 0; // 校准成功
}
四、读取 ADC 值
cs
unsigned short adc_read(ADC_Type *base)
{
unsigned short adc_value = 0;
// 1. 先写 0x1F 禁用当前通道(清空通道选择)
base->HC[0] |= (0x1f << 0);
// 2. 写入目标通道号(通道1),同时触发一次软件转换
base->HC[0] = (0x1 << 0);
// 3. 等待转换完成(COCO0=1)
while(!(base->HS & (1 << 0)));
// 4. 读取结果,取低12位(读操作同时清除 COCO0)
adc_value = base->R[0] & 0xfff;
return adc_value;
}
五、main.c 中的电压换算
cs
data = adc_read(ADC1);
// 换算为电压(单位:mV,参考电压3.00V)
unsigned int adc_value = data * 300 / (4096 - 1);
// 打印:整数部分 / 小数部分(保留两位)
printf("data = 0x%x value = %d.%02d\r\n",
data,
adc_value / 100, // 整数部分(单位:V的百分位)
adc_value % 100); // 小数部分
换算逻辑:
cs
电压(mV) = ADC值 × 参考电压(mV) / (2^12 - 1)
= data × 3000 / 4095
代码里用 data × 300 / 4095,结果单位是"0.01V"
打印时 /100 得整数部分,%100 得小数后两位
例:data=2048 → 2048×300/4095 ≈ 150 → 打印 1.50 V
六、引脚配置说明
ADC 输入引脚必须配置为模拟输入模式,不能配置为普通 GPIO。
bash
IOMUXC_SetPinMux(IOMUXC_GPIO1_IO01_GPIO1_IO01, 0);
// 第二个参数 0 = SION不使能(模拟输入不需要输入通路回读)
IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO01_GPIO1_IO01, 0x10b0);
// 0x10b0 = 关闭上下拉、关闭施密特触发,适合模拟信号输入
GPIO1_IO01 对应 ADC1 的通道 1(ADCH=0x01)。
七、关键寄存器速查表
| 寄存器 | 关键位 | 功能 |
|---|---|---|
| ADC_CFG | bit1:0 MODE | 转换精度(10=12位) |
| ADC_CFG | bit3:2 ADIV | 时钟分频 |
| ADC_CFG | bit10 ADTRG | 触发方式(0=软件) |
| ADC_GC | bit7 CAL | 启动校准,完成后自动清0 |
| ADC_GC | bit6 ADCO | 连续转换使能 |
| ADC_GS | bit1 CALF | 校准失败标志(写1清零) |
| ADC_HC[n] | bit4:0 ADCH | 通道选择(写通道号=触发转换) |
| ADC_HC[n] | bit7 AIEN | 转换完成中断使能 |
| ADC_HS | bit0 COCO0 | 转换完成标志(读R[0]后自动清零) |
| ADC_R[n] | bit11:0 D | 转换结果(取低12位) |