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); //软件触发
}