拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

ARM裸机开发-ADC

ARM裸机开发-ADC

目录

一.背景

二.寄存器

HC0

HS

R0

CFG

GC

GS

三.实现

复用功能

电气属性

完整初始化

校准函数

读取传感器


一.背景

ADC是模拟到数字转换器(Analog-to-Digital Converter)的缩写。它是一种电子设备或模块,2440内部拥有一个ADC外设。用于将连续变化的模拟信号转换为离散的数字信号,以便数字系统(如微处理器、微控制器等)能够对其进行处理和分析。
  • ➢模拟信号一般是指连续变化的电压信号,其数值在一定范围内变化。而数字信号是由一系列离散的数字表示,只能取有限的值,通常以二进制形式表示。
  • ➢ADC的工作原理是将模拟信号分割成一系列离散的取样,并将每个取样值转换为相应的数字表示。这个过程涉及到两个主要步骤:采样和量化。
  • ➢采样:ADC将连续变化的模拟信号在一定时间间隔内进行取样。取样频率决定了每秒采集的样本数,通常以赫兹(Hz)表示。采样过程通过保持并测量模拟信号在每个采样时间点的电压值来实现。
  • ➢量化:采样得到的连续模拟信号经过量化转换为数字形式。量化是将每个采样值映射到一个离散的数字值的过程。这通常通过比较采样值与参考电压之间的差异,并将其转换为数字表示。
  • ➢ADC量化的过程是相对于一个基准值的,这个基准值称之为基准电压。一般采用逐次逼近法,ADC会先拿采用电压Vadc跟基准电压Vref的1/2进行比较,如果Vadc>Vref,则结果为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设备,喇叭是DAC
ADC最高频率限制20MHZ,ADACK为ADC内部时钟,imx6ull专门为ADC配置的时钟,默认20MHZ,所以经过分频器选择一分频即可将运行速度拉满

二.寄存器

HC0

AIEN:转换完成中断使能或禁止控制位,转换完成会引发中断,置0表示禁止,采用轮询方式检测是否转换完成。
ADCH:输入通道选择,如下有通道0到9

HS

转换完成标记位,在R0寄存器中存储

R0

CFG

OVWREN:数据覆写使能位,置0表示不覆盖上一次转换的结果,置1则表示覆盖,置0置1都可,因为本次转换一次读一次,所以无影响。

AVGS:硬件平均滤波选择位,选择在几次采样后进行滤波,默认即可,后续自己写一个滤波函数

ADTRG:转换触发选择位,清零软件触发ADC转换,开始干活。

REFSEL:选择基准电压,VREFH-VREFL得到基准电压

ADC_VREFH接了3.3V电压(3P3),所以VREFL理论接地,为0V电压。

ADHSC:高速配置,设置转换速度。

ADSTS:采样周期,00表示一次采样消耗2个时钟周期,越久越精准

ADLPC:低功耗模式,置0表示不在低功耗。

ADIV:时钟分频位,00表示输入时钟不分频。

ADLSMP:长采样或者短采样,默认即可。

MODE:设置ADC分辨率,设置最高12位

ADICLK:选择输入时钟,11为上述提及的专用时钟20MHZ。

GC

CAL:使用ADC之前校准,将CAL置1

ADCO:持续转换使能位,0表示单次转换,1表示持续转换,本次采用单次转换。

而要开启ADC转换要先切换一次通道,比如从ADC1通道0切换到ADC1通道1,开启转换。

AVGE:硬件平均功能使能位,清零表示硬件平均滤波失能,因为要自己写滤波,所以置零。

ACFE:设置中断阈值,根据结果触发中断,本次不用中断,置0

ACFGT:对中断比较结果的判断,大于,小于,置0

ACREN:开启ACFE位

DMA:DMA位,本次不用。

对ADACK的使能配置,置1表示时钟输出使能。

GS

0表示校准成功,1失败,失败清零

三.实现

复用功能

// 配置引脚复用功能 IOMUXC_SetPinMux(IOMUXC_GPIO1_IO01_GPIO1_IO01, 0);

电气属性

PUE位配0为保持电压,若置1则为拉,可能改变传感器输入的电压

PKE置1为保持功能使能

// 配置电气属性 IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO01_GPIO1_IO01, IOMUXC_SW_PAD_CTL_PAD_PKE(1)); IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO01_GPIO1_IO01, IOMUXC_SW_PAD_CTL_PAD_PUE(0));

完整初始化

void adc1_channel1_init(void) { // 配置引脚复用功能 IOMUXC_SetPinMux(IOMUXC_GPIO1_IO01_GPIO1_IO01, 0); // 配置电气属性 IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO01_GPIO1_IO01, IOMUXC_SW_PAD_CTL_PAD_PKE(1)); IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO01_GPIO1_IO01, IOMUXC_SW_PAD_CTL_PAD_PUE(0)); ADC1->HC[0] &= ~(1 << 7);//置0表示禁止,采用轮询方式检测是否转换完成。 ADC1->CFG = 0; ADC1->CFG |= (1 << 3) | (3 << 0); //2,3位MODE:设置ADC分辨率,设置最高12位 //0,1位ADICLK:选择输入时钟,11为上述提及的专用时钟20MHZ。 ADC1->GC = 0; ADC1->GC |= (1 << 0);//对ADACK的使能配置,置1表示时钟输出使能。 // 校准 printf(adc1_calibration() ? "calibration completed normally!\n" : "calibration completed failed!\n"); }

校准函数

内部对电压校准,校准之后产生误差,下次调用会自动减去误差

int adc1_calibration(void) { // 校准 ADC1->GC |= (1 << 7); while ((ADC1->GC & (1 << 7)) != 0);//校准需要过一段时间,校准完成后此位会自动清零,所以卡住等校准成功 if ((ADC1->GS & (1 << 1)) == 0) //GSbit1位清零说明校准通过 { return 1; } else { return 0; } }

读取传感器

unsigned short adc1_get_origin_value(void)//数字信号 { ADC1->HC[0] = 0; ADC1->HC[0] = 1;//切换通道,开启转换 while ((ADC1->HS & (1 << 0)) == 0); return ADC1->R[0] & 0xFFF; //读取ADC转换完成后的数据 } float adc1_get_value(void) //转换为模拟信号 { return adc1_get_origin_value() / 4095.0 * 3.3; }
返回列表