ADC模数转换(二)——独立模式多通道电压采集实验


 

接上篇文章ADC模数转换(一)——独立模式单通道电压采集实验,这篇讲了ADC的基础以及独立模式单通道采集实验。现在将介绍独立模式的多通道采集实验,还会有一篇文章介绍双重ADC模式的采集实验。

这个实验和上篇文章相比,只是通道多了,使用了DMA代替中断读取的方式,所以在上个实验的基础上,稍加修改即可。

现在我们需要先确定ADC和DMA的配置关系。

查阅参考手册DMA篇章可得,ADC1对应DMA1的通道1,ADC3对应DMA2的通道5,而ADC2则没有DMA功能。如图22-1,图22-2。所以,这里我们选择ADC1,其对应了DMA1的通道1。

图22-1

图22-2

接下来确定使用ADC1的哪些通道。查阅数据手册(Table 5. High-density STM32F103xx pin definitions)可知,PC0~PC3对应ADC1/2/3_IN10~ADC1/2/3_IN13,我们就选这4个引脚。然后可以开始配置了。

ADC的GPIO配置

PC0~PC3四个引脚都需要配置,引脚模式都是模拟输入。

/**  * @brief ADC的GPIO配置  * @param 无  * @retval 无  */ static void ADC1_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; // 模拟输入 GPIO_Init(GPIOC, &GPIO_InitStructure); } 

ADC配置

包括DMA和ADC1的配置说明,比较简单,有关DMA也在之前的文章有介绍,所以直接在下面的程序里通过注释简单说明了。

__IO uint16_t ADC_ConvertedValue[4] = {0, 0, 0, 0}; /**  * @brief ADC配置  * @param 无  * @retval 无  */ static void ADC1_Mode_Config(void) { /*------------------- DMA配置 -------------------*/ DMA_InitTypeDef DMA_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); DMA_DeInit(DMA1_Channel1); // 复位DMA DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(ADC1->DR)); // 外设基地址为ADC1_DR寄存器地址 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_ConvertedValue; // 内存存储地址,即ADC_ConvertedValue数组的首地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; // 数据来源于外设 DMA_InitStructure.DMA_BufferSize = 4; // 缓冲区大小,这里为ADC_ConvertedValue数组的长度 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 只有ADC1一个外设,所以地址不递增 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_InitStructure.DMA_Priority = DMA_Priority_High; // DMA通道优先级为高,当使用一个DMA通道时,优先级设置不受影响 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; // 外设到内存模式 DMA_Init(DMA1_Channel1, &DMA_InitStructure); DMA_Cmd(DMA1_Channel1, ENABLE); /*------------------- ADC配置 -------------------*/ ADC_InitTypeDef ADC_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); ADC_InitStruct.ADC_Mode = ADC_Mode_Independent; // 独立模式,只使用一个ADC ADC_InitStruct.ADC_ScanConvMode = ENABLE; // 扫描模式 ADC_InitStruct.ADC_ContinuousConvMode = ENABLE; // 连续转换 ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 不使用外部触发,用软件触发 ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right; // 转换结果右对齐 ADC_InitStruct.ADC_NbrOfChannel = 4; // 转换通道数量 ADC_Init(ADC1, &ADC_InitStruct); RCC_ADCCLKConfig(RCC_PCLK2_Div8); // 8分频,9MHz ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_55Cycles5); // ADC转换通道10,转换顺序1,采样周期55.5 ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_55Cycles5); // ADC转换通道11,转换顺序2,采样周期55.5 ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 3, ADC_SampleTime_55Cycles5); // ADC转换通道12,转换顺序3,采样周期55.5 ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_55Cycles5); // ADC转换通道13,转换顺序4,采样周期55.5 ADC_DMACmd(ADC1, ENABLE); // 使能ADC的DMA请求 ADC_Cmd(ADC1, ENABLE); ADC_ResetCalibration(ADC1); // 初始化ADC校准寄存器 while(ADC_GetResetCalibrationStatus(ADC1)); // 等待校准寄存器初始化完成 ADC_StartCalibration(ADC1); // ADC开始校准 while(ADC_GetCalibrationStatus(ADC1)); // 等待校准完成 ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 软件触发ADC转换 } 

配置程序就只是完成ADC和DMA的配置,配置项多了点,其实并不复杂。

由于采用了DMA的方式代替了中断读取的方式,所以直接main()函数里将读取到的值转换成可读的模拟电压值。

extern __IO uint16_t ADC_ConvertedValue[4]; float ADC_ConvertedValueLocal[4]; ADC_ConvertedValueLocal[0] = (float)ADC_ConvertedValue[0] / 4096 * 3.3; ADC_ConvertedValueLocal[1] = (float)ADC_ConvertedValue[1] / 4096 * 3.3; ADC_ConvertedValueLocal[2] = (float)ADC_ConvertedValue[2] / 4096 * 3.3; ADC_ConvertedValueLocal[3] = (float)ADC_ConvertedValue[3] / 4096 * 3.3; printf("\r\n CH10 value = %f V \r\n", ADC_ConvertedValueLocal[0]); printf("\r\n CH11 value = %f V \r\n", ADC_ConvertedValueLocal[1]); printf("\r\n CH12 value = %f V \r\n", ADC_ConvertedValueLocal[2]); printf("\r\n CH13 value = %f V \r\n", ADC_ConvertedValueLocal[3]); 

关于转换公式,可参考ADC模数转换(一)——独立模式单通道电压采集实验

有一点需要注意,每个转换的ADC通道引脚都需要为其提供电源输入,以作为待测电压进行转换。可以用杜邦线连接开发板上的3V3电源输入。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM