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电压采集-LMLPHP

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,其通道分配为:

ADC电压采集-LMLPHP

引用江科大程序: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转换的结果
}
07-20 04:06