ADC

注:本文学习朱有鹏老师课程和自己整理而成。方便今后查阅,感谢朱老师~

ADC的引入

1、什么是ADC
(1)ADC:analog digital converter,AD转换,模数转换(也就是模拟转数字)
(2)CPU本身是数字的,而外部世界变量(如电压、温度、高度、压力···)都是模拟的,所以需要用CPU来处理这些外部的模拟变量的时候就需要做AD转换。


2、为什么需要ADC
为了用数字技术来处理外部的模拟物理量。

3、关于模拟量和数字量
(1)模拟的就是连续的,现实生活当中的时间、电压、高度等都是模拟的(连续分布的,划分的话可以无限的更小划分)。模拟量反映在数学里面就是无限小数位(从0到1之间有无数个数)
(2)数字的就是离散的,离线的就是不连续的。这种离散处理实际上是从数学上对现实中的模拟量的一种有限精度的描述。数字化就是离散化,就是把连续分布的模拟量按照一定精度进行取点(采样)变成有限多个不连续分布的数字值,就叫数字量。
(3)数字化的意义就在于可以用(离散)数学来简化描述模拟量,这东西是计算机技术的基础。
(4)计算机处理参量的时候都是数字化的,计算机需要数字化的值来参与运算。如果系统输入参数中有模拟量,就需要外加AD转换器将模拟量转成数字量再给计算机。


4、有AD自然就有DA
(1)AD是analog to digital,DA自然就是digital to analog,数字转模拟。
(2)纯粹用cpu是不可能实现数字转模拟,因为cpu本身就是数字的。使用一些(具有一些积分或微分效果的)物理器件就可实现数字转模拟。
(3)数字转模拟的作用。譬如可以用来做波形发生器




ADC的主要相关概念

1、量程(模拟量输入范围)
(1)AD转换器是一个电子器件,所以他只能输入电压信号。其他种类的模拟信号要先经过传感器(Sensor)的转换变成模拟的电压信号然后才能给AD。
(2)AD输入端的模拟电压要求有一个范围,一般是0~3.3V或0~5V或者是0~12V等等。模拟电压的范围是AD芯片本身的一个参数。实际工作时给AD的电压信号不能超过这个电压范围。


2、精度(分辨率resolution)
(1)AD转换输出的数字值是有一定的位数的(譬如说10位,意思就是输出的数字值是用10个二进制位来表示的,这种就叫10位AD)。这个位数就表示了转换精度。
(2)10位AD就相当于把整个范围分成了1024个格子,每个格子之间的间隔就是电压的表示精度。加入AD芯片的量程是0~3.3V,则每个格子代表的电压值是3.3V/1024=0.0032265V。如果此时AD转换后得到的数字量是447,则这个数字量代表的模拟值是:447×0.0032265V=1.44V。
(3)AD的位数越多,则每个格子表示的电压值越小,将来算出来的模拟电压值就越精确。
(4)AD的模拟量程一样的情况下,AD精度位数越多精度越高,测出来的值越准。但是如果AD的量程不一样。譬如2个AD,A的量程是0~50V,B的量程是0~0.5V,A是12位的,B是10位的,可能B的精度比A的还要高。(A的精度:50/1024=0.04883,B的精度:0.5/4096=0.000122)


3、转换速率(MSPS与conventor clock的不同)
(1)首先要明白:AD芯片进行AD转换是要耗费时间的。这个时间需要多久,不同的芯片是不一样的,同一颗芯片在配置不一样(譬如说精度配置为10位时时间比精度配置为12位时要小,譬如说有些AD可以配转换时钟,时钟频率高则转换时间短)时转换时间也不一样。
(2)详细的需要时间可以参考数据手册。一般数据手册中描述转换速率用的单位是MSPS(第一个M是兆,S是sample,就是采样;PS就是per second,总的意思就是兆样本每秒,每秒种转出来多少M个数字值)
(3)AD工作都需要一个时钟,这个时钟有一个范围,我们实际给他配置时不要超出这个范围就可以了。AD转换是在这个时钟下进行的,时钟的频率控制着AD转换的速率。注意:时钟频率和MSPS不是一回事,只是成正比不是完全相等。譬如S5PV210中的AD转换器,MSPS = 时钟频率/5


4、通道数
AD芯片有多少路analog input通道,代表了将来可以同时进行多少路模拟信号的输入。


S5PV210的ADC控制器

1、ADC和(电阻式)触摸屏的关系
(1)ADC在210的数据手册的Section10.7
(2)电阻式触摸屏本身工作时依赖于AD转换,所以在210的SoC中电阻触摸屏接口本身和ADC接口是合二为一的。或者说电阻触摸屏接口使用了(复用了)ADC的接口。


2、ADC的工作时钟框图
(1)ADCCLK是ADC控制器工作的时钟,也就是1.13.2.3节中讲到的conventor clock。从时钟框图可以看出,它是PCLK(当然是PCLK_PSYS)经过了一次分频后得到的。所以将来初始化ADC控制器时一定有一个步骤是初始化这里的分频器。


3、210的10个ADC通道(注意ADC引脚和GPIO的区别)
(1)210一共支持10个ADC通道,分别叫AIN[0]~AIN[9]。理论上可以同时做10路AD转换。
(2)SoC的引脚至少分2种:digit数字引脚和analog模拟引脚。我们以前接触的GPIO都属于数字引脚,ADC channel通道引脚属于模拟引脚。数字引脚和模拟引脚一般是不能混用的。


4、ADC控制器的主要寄存器
TSADCCON0
TSDATX0  TSDATY0 转出来的AD值存在这里,我们读也是读这里
CLRINTADC0 清中断
ADCMUX 选择当前正在操作的AD通道
(1)等待触摸屏转换完毕的方法有2种:一种是检查标志位,第二种是中断。第一种方式下我们先开启一次转换然后循环不停检查标志位直到标志位为1表明已经转换完可以去读了;第二种方式下就是设置好中断,写好中断isr来读取AD转换数据。然后开启中断后CPU就不用管了,等AD转换完成后会生成一个中断信号给CPU,就会进入中断处理流程。第一种方法是同步的,第二种方式是异步的。
(2)AD转换都是需要反复进行的,那么转完一次一般要立即开启下一次转换,所以需要有一种机制能够在一次转完时自动开启下一次。这个机制就叫start by read,这个机制的工作方法是:当我们读取本次AD转换的AD值后,硬件自动开启下一次AD转换。




AD转换的编程实践

注意:start by read模式
应用方法:开启start by read模式,第一次先读一次丢掉,这次读就能开启下一次AD转换,然后以后就可以不停的读取AD值了。



<think>我们正在讨论ADC检测的相关问题。用户提供了多个引用,这些引用涉及ADC的初始化、校准、硬件配置以及电路设计注意事项。用户的问题聚焦在“如何检测ADC”上,因此我们需要整合这些信息,提供一个关于ADC检测的全面指南。 ### 步骤1:理解ADC检测的关键步骤 根据引用内容,ADC检测通常包括以下步骤: 1. **初始化配置**:设置ADC的时钟、通道、引脚等(引用[2][3])。 2. **校准**:复位校准和启动校准,确保ADC精度(引用[1])。 3. **数值获取**:读取转换结果(引用[1][2])。 4. **硬件电路设计**:注意保护电路,防止过压损坏(引用[4])。 5. **多通道支持**:如何配置多个ADC通道(引用[5])。 ### 步骤2:详细解释每个步骤 #### 1. 初始化配置 - **使能时钟**:ADC和GPIO的时钟必须使能(引用[3])。 - 例如:`RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);` - **配置GPIO**:将引脚设置为模拟输入模式(无复用,引用[3])。 - **配置ADC参数**:包括采样时间、分辨率、扫描模式等(引用[3])。 - 示例代码片段(STM32标准库): ```c ADC_InitTypeDef ADC_InitStructure; ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 单通道 ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // 单次转换 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 1; ADC_Init(ADC1, &ADC_InitStructure); ``` - **通道配置**:指定ADC通道对应的引脚(引用[3][5])。 - 例如:`ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);` #### 2. 校准 校准是提高ADC精度的关键步骤(引用[1]): ```c ADC_ResetCalibration(ADC1); // 复位校准寄存器 while(ADC_GetResetCalibrationStatus(ADC1)); // 等待复位完成 ADC_StartCalibration(ADC1); // 启动校准 while(ADC_GetCalibrationStatus(ADC1)); // 等待校准完成 ``` > **注意**:校准只需在上电后执行一次。 #### 3. 数值获取 - **启动转换并读取**(引用[1][2]): ```c ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 软件触发转换 while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); // 等待转换结束 uint16_t value = ADC_GetConversionValue(ADC1); // 读取值 ``` - **多通道处理**:若使用扫描模式,需配置DMA或中断读取数据(引用[5]未直接说明,但常见实践)。 #### 4. 硬件电路设计注意事项 - **过压保护**:如引用[4]所述,外部电压可能超过ADC允许范围(如3.3V),需设计保护电路: - 使用分压电阻降低输入电压。 - 添加钳位二极管(如1N4148)限制电压,防止损坏ADC引脚。 - 示例:若输入最大10V,通过电阻分压(如10kΩ串联)降至3.3V以内,并加二极管接地(钳位至3.3V+0.7V≈4.0V)。 #### 5. 多通道配置 - 引用[5]展示了多通道的引脚定义(如`Board_ADC0~Board_ADC8`)。 - 配置方法: - 启用扫描模式:`ADC_InitStructure.ADC_ScanConvMode = ENABLE;` - 设置通道数量和顺序: ```c ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5); // 通道0为第1个 ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5); // 通道1为第2个 ``` - 使用DMA传输转换结果数组。 ### 步骤3:完整代码框架(STM32示例) 结合引用[1][2][3],给出一个完整的单通道ADC检测代码: ```c // bsp_adc.h(参考引用[3]) #ifndef __ADC_H__ #define __ADC_H__ #include "stm32f10x.h" void ADCx_Init(void); uint16_t ADC_GetValue(void); #endif // bsp_adc.c #include "bsp_adc.h" void ADCx_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; ADC_InitTypeDef ADC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE); // 配置PA0为模拟输入 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOA, &GPIO_InitStructure); ADC_DeInit(ADC1); ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 1; ADC_Init(ADC1, &ADC_InitStructure); ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5); ADC_Cmd(ADC1, ENABLE); // 校准 ADC_ResetCalibration(ADC1); while(ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while(ADC_GetCalibrationStatus(ADC1)); } uint16_t ADC_GetValue(void) { ADC_SoftwareStartConvCmd(ADC1, ENABLE); while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); return ADC_GetConversionValue(ADC1); } // main.c #include "bsp_adc.h" int main() { ADCx_Init(); while(1) { uint16_t adc_value = ADC_GetValue(); float voltage = (adc_value * 3.3) / 4095; // 12位ADC,参考电压3.3V // 使用voltage... } } ``` ### 关键问题与解决方案 1. **精度问题**: - 校准可减少误差(引用[1])。 - 硬件上,确保模拟电源稳定,添加滤波电容。 2. **过压保护**: - 如引用[4]案例,设计分压电路和钳位二极管。 3. **多通道扩展**: - 参考引用[5]的引脚定义,配置扫描模式和DMA。 ### 相关问题 基于上述内容,生成以下相关问题供深入探讨: 1. ADC校准为什么能提高精度?校准的具体原理是什么? 2. 如何设计ADC输入端的过压保护电路? 3. 多通道ADC扫描模式下,如何避免通道间串扰? 4. ADC采样时间如何影响转换精度?如何优化?</think>### ADC检测详解 ADC(模数转换器)是将模拟信号(如电压、电流)转换为数字值的核心硬件模块。以下是基于引用内容的完整检测流程和关键注意事项: --- #### 1. **ADC初始化配置** **硬件配置**(引用[3][5]): - 使能ADC时钟和GPIO时钟(如APB2总线)。 - 配置ADC引脚为模拟输入模式(无复用功能): ```c // 示例:STM32F10x配置(引用[3]) #define ADC_PORT GPIOC #define ADC_PIN GPIO_Pin_0 // 连接可调电阻 #define ADC_CHANNEL ADC_Channel_10 ``` - 多通道支持需定义多个引脚(引用[5]): ```c #define Board_DIO23_ANALOG CC2640R2_LAUNCHXL_DIO23_ANALOG // 通道0 #define Board_DIO24_ANALOG CC2640R2_LAUNCHXL_DIO24_ANALOG // 通道1 ``` **软件初始化**(引用[2][3]): ```c // ADC头文件定义(引用[2]) #ifndef __AD_H #define __AD_H void AD_Init(void); uint16_t AD_GetValue(uint8_t ADC_Channel); #endif // 初始化函数核心步骤(引用[1][3]) void ADCx_Init(void) { ADC_InitTypeDef ADC_InitStructure; ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // 独立模式 ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 单通道扫描 ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // 单次转换 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // 数据右对齐 ADC_Init(ADC1, &ADC_InitStructure); ADC_Cmd(ADC1, ENABLE); // 使能ADC } ``` --- #### 2. **校准与复位**(关键步骤!引用[1][4]) 校准消除ADC内部误差,必须在初始化后执行: ```c ADC_ResetCalibration(ADC1); // 复位校准寄存器 while(ADC_GetResetCalibrationStatus(ADC1)); // 等待复位完成 ADC_StartCalibration(ADC1); // 启动校准 while(ADC_GetCalibrationStatus(ADC1)); // 等待校准完成 ``` > **为何校准?** > ADC内部电容存在偏差,校准通过测量内部参考电压修正误差,精度可提升至±1 LSB(引用[4])。 --- #### 3. **数值获取与转换** - **启动转换并读取**(引用[1][2]): ```c uint16_t AD_GetValue(uint8_t ADC_Channel) { ADC_RegularChannelConfig(ADC1, ADC_Channel, 1, ADC_SampleTime_55Cycles5); ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 软件触发转换 while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); // 等待转换结束 return ADC_GetConversionValue(ADC1); // 返回12位数字值 } ``` - **电压计算**: 若参考电压 $V_{ref} = 3.3V$,ADC分辨率12位($2^{12}=4096$): $$ V_{in} = \frac{\text{ADC\_Value} \times 3.3}{4095} $$ --- #### 4. **硬件电路设计注意事项**(引用[4]) - **过压保护**: - 输入电压超过 $V_{ref}$ 可能烧毁ADC!需添加钳位二极管和分压电阻: ```plaintext 例如:10Vmax输入 → 串联10kΩ电阻 → 二极管D4接地(钳位至3.3V+0.7V=4.0V) ``` > 若不设计保护,10V输入经10kΩ电阻会导致ADC引脚电压升至4.02V,超出3.3V极限(引用[4])。 - **抗干扰设计**: - 模拟输入引脚并联0.1μF电容滤波。 - 独立模拟/数字电源,避免数字噪声耦合。 --- #### 5. **调试与故障排查** - **常见问题**: 1. **读数跳动**: - 检查电源稳定性(纹波需<10mV)。 - 增加采样时间(如 `ADC_SampleTime_239Cycles5`)。 2. **校准失败**: - 确保时钟使能(`RCC_APB2Periph_ADCx`)。 - 检查复位状态函数返回值(引用[1])。 3. **通道干扰**: - 未使用的通道接地,避免悬空引入噪声。 --- ### 相关问题 1. ADC校准失败的可能原因及解决方法? 2. 如何设计多通道ADC扫描模式(如温度+光敏同步采集)? 3. 高精度ADC(如16位)的硬件设计有哪些特殊要求? 4. ADC采样时间如何影响信号带宽和精度? > 引用说明: > - 校准流程和数值获取参考[1][2] > - 硬件配置参考[3][5] > - 过压保护设计参考[4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

种瓜大爷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值