ADC模数转换——DMA方式(其中有对CPU指令获取内存(变量)的比较)

一、ADC简介
1、ADC是神马?
ADC模数转换——DMA方式(其中有对CPU指令获取内存(变量)的比较)_第1张图片

2、STM32的ADC主要技术指标涉及:分辨率、转换速度、参考电压范围
(1)分辨率
12位精度(分辨率)。不能直接测量负电压,所以没有符号位,即其==最小化量程(LSB)==为Vref+/4096=0.00008
计算电压值
float型变量ADC_ConvertedValueLocal保存了由转换值计算出来的电压值,其计算公式是ADC通用的。
实际电压值 = ADC转换值*LSB(最低有效位)

STM32的ADC精度上面说了为12位,而板子中的Vref+接的参考电压值为3.3V,所以LSB=3.3/4096

(2)转换时间(周期/时钟)
TCONV = 采样时间+12.5个周期
采样一次至少要用14个ADC时钟周期,而ADC的时钟频率最高为14MHz,即采样时间最短为1us

(3)参考电压范围
当需要测量负电压或测量的电压信号超出范围时(3.6V),要先经过运算电路进行电阻分压
②串联电阻分压公式
该电阻占总电阻的百分比就是分压的百分比。U=(R/R总)*U原

二、ADC工作过程分析

ADC模数转换——DMA方式(其中有对CPU指令获取内存(变量)的比较)_第2张图片
我们以ADC的规则通道转换进行过程分析。
所有的器件都是围绕中间的ADC模拟至数字转换器展开的。
它的左端为VREF+ 、VREF-等ADC参考电压, ADCx_IN0—ADCx_IN15为ADC的输入信号通道(GPIO的引脚)。
模拟输入信号经过这些通道被送到ADC模拟至数字转换器!
而ADC模拟至数字转换器需要受到触发信号才开始进行转换(如;EXTI外部触发、TIM触发、软件触发)!
ADC模拟至数字转换器接收到触发信号后,在ADCCLK时钟的驱动下对输入信号进行采样并模数转换,(其中ADCCLK是来自ADC预分频器的)
需注意的是:无论是CPU指令获取数字信号还是DMA读取到内存,ADC模拟至数字转换器转换后的12位数值都先被保存到一个16位的ADC_DR里
①DMA请求
因为规则通道转换的值储存在一个仅有的数据寄存器里,所以当转换多个规则通道时需要使用DMA,这样可以避免丢失已经存储在ADC_DR中的数据。
需注意的是:只有在规则通道的转换结束时才产生DMA请求,并将转换的数据从ADC_DR实时传输到用户指定的目的地址。
(只有ADC1和ADC3才有DMA功能,由ADC2转换的数据可以通过中断或双ADC模式,利用ADC1的DMA功能)
②ADC中断
ADC1和ADC2的中断都在同一个中断映射向量上,而ADC3有自己的中断向量。

三、DMA简介 (了解DMA进一步便了解数据从哪里来到哪里去)
1、DMA(直接存储器存取) ,是单片机的一个外设,它的主要功能用于搬运数据,但不需要占用CPU(即在传输数据的时候,CPU可以干其他的事情)。其数据传输方向有三个:
1、从外设寄存器到内部SRAM/FLASH存储器
2、从内部存储器到外设寄存器
3、从内部FLASH存储器到内部SRAM存储器

插入:1、 微控制器由CPU,存储器,外设三部分构成,各部分之间的协调与交互由CPU完成 (大脑,脚与手的关系) (CPU每次都是从A外设拿到一个数据送到B外设使用,中间通过一个”桥”) 而 DMA可实现存储器和存储器之间,外设和存储器之间,存储器和外设之间的传输(跳过CPU)!!
2、寄存器主要功能是操作数据、存储器是保存数据

外设寄存器到存储器
当我们使用从外设寄存器到存储器传输时,以ADC电压采集为例。

           // DMA外设寄存器的地址对应的就是串口数据寄存器的地址;
       //ADC_DR寄存器保存了ADC转换后的12位数值,方向我们设置外设寄存器为源地址
	 DMA_InitStructure.DMA_PeripheralBaseAddr = ( uint32_t ) ( & ( ADCx->DR ) );
	     
	     //DMA存储器的地址就是我们自定义的变量(用来接收AD采集的数据)的地址
         DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_ConvertedValue;

存储器到外设
待更新…

存储器到存储器
待更新…

下面我们通过实例分析CPU指令和DMA获取内存变量的不同吧!

DMA单通道采集电压

// ADC1转换的电压值通过DMA方式传到SRAM(静态随机存取存储器)
extern __IO uint16_t ADC_ConvrtedValue; (main.c)

// 配置 DMA 初始化结构体
// 外设基址为:ADC 数据寄存器地址                 //ADC_DR数据寄存器保存了ADC转换后的数值,                                                                                                                                  以它作为DMA的传输源地址!!!
DMA_InitStructure.DMA_PeripheralBaseAddr = ( uint32_t ) ( & ( ADCx->DR ) );

// 存储器地址,实际上就是一个内部SRAM的变量     //数据从ADC的外设寄存器转移到内存SRAM变量!!!
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_ConvertedValue; (adc.c)

CPU中断方式

extern __IO uint16_t ADC_ConvertedValue;//定义一个存储变量(main.c)

void ADC_IRQHandler(void) //ADC转换完成后(转换后的数值此时已经存储在ADC_DR里)会进入中断服务函数,
{ //在中断函数内,通过CPU指令把它读取到内存变量。
if (ADC_GetITStatus(ADCx,ADC_IT_EOC)==SET)
{
// 读取ADC的转换值
ADC_ConvertedValue = ADC_GetConversionValue(ADCx); // 获取ADC转换结果值的库函数
}
ADC_ClearITPendingBit(ADCx,ADC_IT_EOC);
}

由此可以得出,DMA将ADC_DR的数字信号从外设直接传递至变量(跳过CPU)
而CPU方式则需要外设到CPU再到变量。

可能有人会问,电位器并没有旋转,但采集到的电压却一直在变化是个啥情况?
原因如下:
测量的器件所在的板子供电(比如5V)不稳
比如板子上接的5V电是usb充电线接的
你把他接到电脑的端口和劣质的手机充电器端口
都会导致电压不稳,一些精密器件工作不正常。



上述读完如有不尽之处,烦请诸位将自己更好的见解发在评论区指点一二!晚辈万分感谢!!

你可能感兴趣的:(C)