ARM嵌入式学习(十五)--- IMX6ULL的ADC接口使用

张开发
2026/4/3 17:17:58 15 分钟阅读
ARM嵌入式学习(十五)--- IMX6ULL的ADC接口使用
目录一、ADC介绍1.模拟信号和数字信号2.ADC工作原理1采样2保持:3量化ADC的核心量化过程具体怎么比4编码二、IMX6ULL的ADC配置1.ADC通道2.ADC时钟源3.ADC配置流程1ADC初始化2读取ADC数值3整体代码4.电压计算三、总结一、ADC介绍ADC是模拟到数字转换器Analog-to-Digital Converter的缩写。它是一种电子设备或模块2440内部拥有一个ADC外设。用于将连续变化的模拟信号转换为离散的数字信号以便数字系统如微处理器、微控制器等能够对其进行处理和分析。1.模拟信号和数字信号模拟信号:一般是指连续变化的电压信号其数值在一定范围内变化。数字信号:由一系列离散的数字表示只能取有限的值通常以二进制形式表示。2.ADC工作原理ADC的工作原理是将模拟信号分割成一系列离散的取样并将每个取样值转换为相应的数字表示。这个过程涉及到四个主要步骤采样、保持、量化、编码。1采样ADC将连续变化的模拟信号在一定时间间隔内进行取样。取样频率决定了每秒采集的样本数通常以赫兹Hz表示。采样过程通过保持并测量模拟信号在每个采样时间点的电压值来实现。采样频率必须满足奈奎斯特采样定理采样频率大于等于信号最高频率的两倍否则会失真2保持:采样后需要将电压值稳定一段时间让后续电路比较器、逐次逼近寄存器等有足够时间处理。采样保持电路通常用一个电容 开关实现3量化ADC的核心采样得到的连续模拟信号经过量化转换为数字形式。量化是将每个采样值映射到一个离散的数字值的过程。这通常通过比较采样值与参考电压之间的差异并将其转换为数字表示。量化原理ADC量化的过程是相对于一个基准值的这个基准值称之为基准电压。一般采用逐次逼近法的ADC会先拿采用电压Vadc跟基准电压Vref的1/2进行比较如果VadcVref则结果为1否则结果为0。之后继续拿Vadc和Vref的1/4或Vref的3/4继续比较。这个过程有点像二分法每次比较都会使量化的结果逼近真实值。很明显比较的次数决定了测量的精度这个精度被称之为ADC的分辨率。比如一个比较了8次的ADC外设它就称为8位ADC其结果是0~255之间的一个数值设该数值为n那么实际电压就是Vref* (n/255)。如果把比较次数增加到10次结果就是0~1023之间的一个数。常见的分辨率包括8位10位12位和16位。量化过程具体怎么比ADC 内部有一个比较器和电阻分压网络逐次比较输入电压与内置电阻产生的电压从 MSB 到 LSB 依次确定每一位。每次比较就是一次“量化决策”输入电压落在哪个电压区间就输出对应的二进制码。4编码将量化后的台阶序号十进制 0~4095转换为二进制或十六进制数字供单片机或 DSP 读取。例如 1024 → 0x400二进制 0100 0000 0000。二、IMX6ULL的ADC配置I.MX6ULL内部具有两个ADC控制器。都是采用逐次逼近法量化那里有介绍设计的。每路ADC的分辨率可选分别为8/10/12位。I.MX6ULL内部ADC具有自动校准功能因此能够保证更高的测量精度最大转换速率为1MHz即完成一次转换所需的时间最快只需要1us。I.MX6ULL的ADC还具有硬件平均功能和比较功能大大方便了软件设计。我们实验所使用的开发板将基准电压设置为3.3V参考《IMX6ULL_CORE_V2.0(核心板原理图).pdf 》1.ADC通道每个ADC拥有10个通道这里的通道就是指输入的电压信号是从哪个引脚输入进来的意思。10个引脚其实就是GPIO1_IO00~GPIO1_IO09这10个引脚。参考《IMX6ULL参考手册.pdf 》P394页。我们在配置引脚功能时只需将引脚配置为GPIO就行电器配置时可以保持默认配置下使能Keeper即可这里我们使用通道1。2.ADC时钟源I.MX6ULL的时钟源可以是igpclk、igpclk/2和ADACK其中ADACK是I.MX6ULL内部提供的时钟源只能提供给ADC外设使用这样做的目的是保证系统处于低功耗状态时ADC依旧能够运行。ADACK的时钟默认为20MHz。我们接下来的操作就把时钟配置为ADACK。3.ADC配置流程I.MX6ULL的ADC使用还是很简单的首先在初始化的时候配置好引脚例如GPIO1_IO01这个引脚之后配置ADCx_CFG和ADCx_GC寄存器(有关这两个寄存器的详细说明请参考手册)。然后启动一次自动校准系统校准完成后每次向ADCx_HC0寄存器中写入一次数据(其实就是切换到别的通道之后再切换回来)就会启动一次ADC转换。转换结束之后的数据就保存再ADCx_R0寄存器中。手册第412页有示例配置ADC的流程图1ADC初始化根据示例流程图配置即可2读取ADC数值选择ADC通道每次切换通道时会引发一次ADC转换。所以在采集数据函数中切换到别的通道再切换回来相当于启动一次ADC转换转换结束之后的数据就保存在ADCx_R0寄存器中。代码为3整体代码#include MCIMX6Y2.h #include epit.h #include fsl_iomuxc.h int adc_init(ADC_Type* base) { IOMUXC_SetPinMux(IOMUXC_GPIO1_IO01_GPIO1_IO01, 0); IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO01_GPIO1_IO01, 0x10b0); //配置时钟和模式 base-CFG | (0x3 0); base-CFG | (0x2 2); //打开ADACK时钟 base-GC | (1 0); base-GS | (1 1); //写1先清零校准标记位 //校准 base-GC | (1 7);//开始校准 while (base-GC (1 7)) ; //校准结束 //判断校准结果 if (base-GS (1 1)) //校准失败,返回 return -2; //校准成功继续 return 0; } unsigned short adc_read(ADC_Type* base) { unsigned short adc_value 0; base-HC[0] | (0x1f 0); //关闭通道 //切换通道启动转换 base-HC[0] 0x1; //设置为通道1 //等待转换 int time 50; while (!(base-HS (1 0)) time--) { delay_us(1); }; //为0则未完成 if (time 0) //超时保护 { return -1; } //转换完成,读取结果 adc_value (base-R[0] 0xfff); return adc_value; }4.电压计算写好adc后读出来的数值是一个二进制的我们需要把他转换成电压这里用3.3V和12位ADC做例子假如adc的读数为0x400那么实际电压为主函数代码为#include MCIMX6Y2.h #include adc.h #include beep.h #include clk.h #include core_ca7.h #include epit.h #include fsl_iomuxc.h #include gpt.h #include i2c.h #include irq.h #include key.h #include led.h #include stdio.h #include uart.h void gpio1_io18_handler(void) { GPIO1-DR ^ (1 3); GPIO5-DR ^ (1 1); } void epit1_irq_handler() { GPIO1-DR ^ (1 3); GPIO5-DR ^ (1 1); } int main(void) { unsigned short data 0; system_irq_init(); clk_init(); // led_init(); beep_init(); key_irq_init(gpio1_io18_handler); // epit1_init(epit1_irq_handler); gpt1_init(); uart_init(UART1); // printf(i2c 1 start init\r\n); // i2c_init(I2C1); // printf(i2c 1 init end\r\n); while (1) { int ret adc_init(ADC1); if (ret 0) { printf(adc init failed\r\n); delay_ms(3000); continue; } data adc_read(ADC1); unsigned int adc_value data * 300 / 4096 ; printf(data 0x%x value %d.%02d\r\n, data, adc_value / 100, adc_value % 100); delay_ms(3000); } return 0; }最后上板验证一下用一根线接这个IO引脚一根接电压或接地看数据是否正确三、总结要搞清楚ADC工作原理特别是量化的过程。

更多文章