ADC与DMA(江科大笔记)

本文详细介绍了如何在嵌入式系统中使用ADC进行模拟信号的数字化,包括单次、连续和扫描转换模式的配置,以及如何配合DMA进行高效数据传输。特别关注了GPIO设置、ADC初始化、DMA参数配置和校准过程。
摘要由CSDN通过智能技术生成

ADC简介

ADC(Analog-Digital Converter)模拟-数字转换器

GPIO需要为模拟模式

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;  

主要的配置

	ADC_InitTypeDef ADC_InitStructure;
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;          	    //持续转换
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;              //数据对齐
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //外部触发方式
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;    			    //单独使用ADC
	ADC_InitStructure.ADC_NbrOfChannel = 4;                			    //通道数
	ADC_InitStructure.ADC_ScanConvMode = ENABLE;        			    //扫描模式
	ADC_Init(ADC1, &ADC_InitStructure);

针对其中的转换和扫描配置进一步说明:

EOC:End of conversion)

转换模式:

单次转换,在一次获得完数据后,EOC将会自动置1,每次获得数据都要重新开启

uint16_t AD_GetValue(void)
{
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);                  //软件触发
	while (ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET);  //转换完成置1,退出循环,且会自动清除EOC标志位,无需手动
	return ADC_GetConversionValue(ADC1);
}

连续转换,在开启后,将不会自动关闭。

扫描模式:

有读取多个通道的需求。

对于触发方式的说明:

1.单次转换:

软\硬件触发 -> 判断转换是否结束(EOC标志转成1,结束后会自动重置回0)-> 读取值(地址在ADC1->DR ,通过上函数)

且每次都要执行上述流程

2.连续转换:

在初始化Init中直接 \硬件触发,无需判断EOC,读取值(同上)

3.扫描模式(多通道同时进行,配合DMA):

在DMA配置中填入数据来\去的地址。

最后,连续转换和扫描模式都要在短时间获取、存储较多的数据,

因此,要配合使用到DMA

DMA

DMA(Direct Memory Access)直接存储器存取

相当于将获得的数据存在了指定的地方

主要的配置

	DMA_InitTypeDef DMA_InitStructure;
	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &ADC1->DR;
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

	DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) AD_Value;
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

分别为

发出地与发送地的地址

单次转运数据的大小(ADC一次转运uint16_t,HalfWord)

地址是否自增(Increase)

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;          //传输方向

传输方向(Direction)

DMA_InitStructure.DMA_BufferSize = 4;            //缓存区大小,传输计数器
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;  //传输模式,是否自动重装

 传输计数器: 每次传输多少个数据(写传输计数器时,需要先关闭DMA)

自动重装器: 传输结束后,是否开启下一轮(多次获取数据,AD多通道+DMA )

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;          //Memory to memory

开启则为软件触发,存储器到存储器转运,不能与DMA循环模式同时使用

DMA配置总:

	DMA_InitTypeDef DMA_InitStructure;
	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &ADC1->DR;
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) AD_Value;
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
	DMA_InitStructure.DMA_BufferSize = 4;            //缓存区大小,传输计数器
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;          //传输方向
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;          //Memory to memory
	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;  //传输模式,是否自动重装
	DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_Init(DMA1_Channel11, &DMA_InitStructure);

额外细节:

1.一般存储器到存储器之间的转运用软件触发,外设到存储器用硬件触发

2.DMA1时钟在AHB上

AD多通道 + DMA 总代码

uint16_t AD_Value[4];

void AD_Init(void)
{
	//ADC和GPIOA开启时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
	//开起ADC的校准时钟
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //ADCLK在rcc中,12MHz
	//初始化Pin_0
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;  
	//模拟输入模式,ADC专属
	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);

	ADC_RegularChannelConfig( ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig( ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig( ADC1, ADC_Channel_2, 3, ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig( ADC1, ADC_Channel_3, 4, ADC_SampleTime_55Cycles5);

	//ADC初始化,连续转换扫描
	ADC_InitTypeDef ADC_InitStructure;
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;          	    //持续转换
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;              //数据对齐
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //外部触发方式
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;    			    //单独使用ADC
	ADC_InitStructure.ADC_NbrOfChannel = 4;                			    //通道数
	ADC_InitStructure.ADC_ScanConvMode = ENABLE;        			    //扫描模式
	ADC_Init(ADC1, &ADC_InitStructure);
	
	DMA_InitTypeDef DMA_InitStructure;
	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &ADC1->DR;
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) AD_Value;
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
	DMA_InitStructure.DMA_BufferSize = 4;            //缓存区大小,传输计数器
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;          //传输方向
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;          //Memory to memory
	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;  //传输模式,是否自动重装
	DMA_InitStructure.DMA_Priority = DMA_Priority_High;
	DMA_Init(DMA1_Channel11, &DMA_InitStructure);
	
	ADC_DMACmd(ADC1,ENABLE);
	DMA_Cmd(DMA1_Channel11,ENABLE);
	//开启ADC
	ADC_Cmd(ADC1,ENABLE);
	//AD校准
	ADC_ResetCalibration(ADC1);
	while (ADC_GetResetCalibrationStatus(ADC1) == SET);
	ADC_StartCalibration(ADC1);
	while (ADC_GetCalibrationStatus(ADC1) == SET);
	
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);  //软件触发
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值