1.什么是ADC?
ADC,即模数转换器,(DAC是数模转换),ADC是一种将模拟信号转换为数字信号的设备。它在现代电子系统中广泛应用,尤其是在需要将现实世界的模拟信号(如温度、电压、声音等)转换为可以由数字设备(如微控制器、计算机等)处理的数字信号的场景中
2.ADC是如何转换的呢?
其主要步骤为:采样-量化-编码。采样:首先将连续的模拟信号在固定的时间间隔内进行取样,得到一系列离散的采样点。量化:然后将每个采样点的模拟值映射到一个离散的数字值。编码:最后将量化后的离散值转换为二进制码,以便数字设备可以处理。
3.ADC相关参数
- 分辨率(位数)(Resolution):ADC输出的数字值的位数。分辨率越高,ADC可以表示的电压范围越大。例如,(2^8)8位ADC可以表示256个不同的电压值,(2^10)10位ADC可以表示1024个不同的电压值。
- 采样率(Sampling Rate):每秒钟对模拟信号进行采样的次数,通常用每秒采样次数(Samples Per Second,SPS)表示。采样率越高,ADC可以更精确地捕捉到快速变化的信号。
- 输入范围(Input Range):ADC能够转换的输入模拟信号的电压范围。
- 转换时间(Conversion Time):ADC完成一次模数转换所需的时间。
stm32ADC转换时间
ADC的采样率
一个在不断变化信号如何采集?
比如采集1hz正弦信号。我们可以每1s采集一次,那么完全看不出这个信号的变化和波形;但如果我们每100ms采集一次呢,一个信号周期内就采集了10个点,可以大致看出这个信号的波形,果我们每1ms,每1us采集一次呢?那么这个信号的波形就完全被我们知道了。
上面的1s,100ms,1us分别对应的是1 sps、10 sps、1M sps采样率。采样率表示的是ADC的采样速度。对于不同ADC,有自己的采样率上限的。比如STM32F103的单个ADC采样率支持1hz-1Mhz。
拿1M采样率去采集1K信号,一个周期有1000个点,效果非常好;但是如果1M去采集1M信号,这和每1s去采集一个1hz信号一样,一个周期1个点,根本看不出波形
采样位数(分辨率)
如果测量一个3.3V电压。设为10位ADC,那么就是将3.3V分为2^10=1024个电压值,那么最小的电压为位为3.3/1024=0.032V,那么假设电压为0.01V,那么其就采样不到了,则会显示0V
采样精度
拿0-3.3V的12位ADC为例子。如果我们去测量80mv的信号,理论值应该是0.08/3.3*4096=100
可是实际我们测量出来的是95-105波动的,这是因为实际上的ADC不是理想器件,他会有误差。一个12位的ADC虽说能分辨0.0008V的电压,但是他的波动电压有10mv,那么这个分辨能力也就失去了他测得准的意义。
因为测得的电压的波动。通常一个12位的ADC只能当作8-9位的理想ADC来用,8-9位就是ADC的采样精度。
4.其他
不同单片机的通道不同,以stm32fc8t6,其通道分配为:
引用江科大程序:ad多通道中adc初始化流程为
void AD_Init(void)
{
/*开启时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //开启ADC1的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟
/*设置ADC时钟*/
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //选择时钟6分频,ADCCLK = 72MHz / 6 = 12MHz
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); //将PA0、PA1、PA2和PA3引脚初始化为模拟输入
/*不在此处配置规则组序列,而是在每次AD转换前配置,这样可以灵活更改AD转换的通道*/
/*ADC初始化*/
ADC_InitTypeDef ADC_InitStructure; //定义结构体变量
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //模式,选择独立模式,即单独使用ADC1
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //数据对齐,选择右对齐
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //外部触发,使用软件触发,不需要外部触发
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //连续转换,失能,每转换一次规则组序列后停止
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //扫描模式,失能,只转换规则组的序列1这一个位置
ADC_InitStructure.ADC_NbrOfChannel = 1; //通道数,为1,仅在扫描模式下,才需要指定大于1的数,在非扫描模式下,只能是1
ADC_Init(ADC1, &ADC_InitStructure); //将结构体变量交给ADC_Init,配置ADC1
/*ADC使能*/
ADC_Cmd(ADC1, ENABLE); //使能ADC1,ADC开始运行
/*ADC校准*/
ADC_ResetCalibration(ADC1); //固定流程,内部有电路会自动执行校准
while (ADC_GetResetCalibrationStatus(ADC1) == SET);
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1) == SET);
}
/**
* 函 数:获取AD转换的值
* 参 数:ADC_Channel 指定AD转换的通道,范围:ADC_Channel_x,其中x可以是0/1/2/3
* 返 回 值:AD转换的值,范围:0~4095
*/
uint16_t AD_GetValue(uint8_t ADC_Channel)
{
ADC_RegularChannelConfig(ADC1, ADC_Channel, 1, ADC_SampleTime_55Cycles5); //在每次转换前,根据函数形参灵活更改规则组的通道1
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //软件触发AD转换一次
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); //等待EOC标志位,即等待AD转换结束
return ADC_GetConversionValue(ADC1); //读数据寄存器,得到AD转换的结果
}