为什么现在比较喜欢写关于自己在工作中的博客,因为现在越来越觉得分享真的很重要,不仅仅是加深了自己的理解,也很大程度帮助了向我们这样的初学者解决一些在实际应用中的问题。就是这个驱使自己去写。
下面是我配置了内部温度传感器和一路外部ADC采集的范例,需要采集更多的通道则在配置ADC的时候在多配置几个就行。
好那我们来说说STM32的多通道ADC如何配置:
配置ADC:
void ADC_CONFIG(void)
{
Adc_Gpio_Init();//配置ADC相应管脚为模拟输入
Adc1_Dma_Config();//配置ADC1的DMA
Adc1_Config();//ADC1初始化/* Start ADC1 Software Conversion */
ADC_SoftwareStartConv(ADC1);//软件启动ADC采样
}
下面附上配置代码详解:
第一步:配置我们需要的外部采样ADC管教初始化,配置为模拟输入才可以给我们的ADC使用:
void Adc_Gpio_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;//配置GPIOA5为模拟输入,供ADC采样使用,当然这里根据你实际应用来配置
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;//配置为模拟输入
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;//悬空
GPIO_Init(GPIOA,&GPIO_InitStructure);
}
第二步:如果我们需要用DMA来取我们的采样值,就需要配置这一项,当然用中断或者是查询这不必配置DMA,但是在使用ADC,不用DMA那不是浪费CPU资源吗?所以我自己觉得这部是很重要的。
void Adc1_Dma_Config(void)
{
DMA_InitTypeDef DMA_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);//使能DMA2时钟,这个不知道是对应的是哪个,可以告诉大家可以使用stm的STM32CubeMX来生成相应工程模块确认,或者是翻手册
DMA_InitStructure.DMA_Channel=DMA_Channel_0;//选择DMA通道
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_ADDRESS;//ADC的数据寄存器地址,这里我用宏定义,如果不知道的话可以这样:(uint32_t)&ADC1->DR
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC1ConvertedValue[0];//这个是DMA把数据存入这个数组,一共定义了两个,一个用来存放PA5的ADC值,一个是温度传感器的ADC值,定义好了后DMA就会自动把数据存入其中。
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;//由外设存储到内存
DMA_InitStructure.DMA_BufferSize =2;//DMA存储数据区大小,我这里为2个单位
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址不累加,我们是从ADC固定的DR寄存器取数据的,所以不需要累加地址
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//内存地址累加
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//半字
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//DMA循环模式,就是送完了两个数据后又接着从新开始
DMA_InitStructure.DMA_Priority = DMA_Priority_High;//优先级高
DMA_InitStructure.DMA_FIFOMode= DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold= DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst= DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst= DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream0, &DMA_InitStructure);//配置DMA,这里与STM32F1xx有区别
/* Enable DMA1 channel1 */
DMA_Cmd(DMA2_Stream0, ENABLE);//使能DMA
}
void Adc1_Config(void)
{
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//使能ADC1时钟
ADC_TempSensorVrefintCmd(ENABLE);//使能内部温度传感器,这个范例是需要采集内部温度的,所以要使能这项
/* ADC1 configuration ------------------------------------------------------*/
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
/* ADCCLK = PCLK2/2 */
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div8;
/* Available only for multi ADC mode */
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
/* Delay between 2 sampling phases */
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 2;
ADC_Init(ADC1, &ADC_InitStructure);
//ADC_ContinuousModeCmd(ADC2,ENABLE);
/* ADC1 regular channel configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_480Cycles);//这个是配置外部输入为ADC1的通道5,ADC1采样序列为1。
ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 2, ADC_SampleTime_480Cycles);
//当然你也可以在这里多配置几路ADC通道,只要在后面追加就好:如:ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_480Cycles);但是要注意,如果是外部ADC采集的话,需要配置相应管脚为模拟输入,别忘了。
ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
/* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
}
ADC_SoftwareStartConv(ADC1);