目录
一.背景
二.寄存器
HC0
HS
R0
CFG
GC
GS
三.实现
复用功能
电气属性
完整初始化
校准函数
读取传感器
一.背景
- ➢模拟信号一般是指连续变化的电压信号,其数值在一定范围内变化。而数字信号是由一系列离散的数字表示,只能取有限的值,通常以二进制形式表示。
- ➢ADC的工作原理是将模拟信号分割成一系列离散的取样,并将每个取样值转换为相应的数字表示。这个过程涉及到两个主要步骤:采样和量化。
- ➢采样:ADC将连续变化的模拟信号在一定时间间隔内进行取样。取样频率决定了每秒采集的样本数,通常以赫兹(Hz)表示。采样过程通过保持并测量模拟信号在每个采样时间点的电压值来实现。
- ➢量化:采样得到的连续模拟信号经过量化转换为数字形式。量化是将每个采样值映射到一个离散的数字值的过程。这通常通过比较采样值与参考电压之间的差异,并将其转换为数字表示。
- ➢ADC量化的过程是相对于一个基准值的,这个基准值称之为基准电压。一般采用逐次逼近法,ADC会先拿采用电压Vadc跟基准电压Vref的1/2进行比较,如果Vadc>Vref,则结果为1,否则结果为0。之后继续拿Vadc和Vref的1/4或Vref的3/4继续比较。这个过程有点像二分法,每次比较都会使量化的结果逼近真实值。
二.寄存器
HC0
HS
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; }