以下是在STM32F103上配置PA0到PA4作为多路ADC输入并进行采集的完整指南。
硬件配置
- STM32F103系列MCU
- PA0-PA4引脚作为ADC输入通道(对应通道0-4)
- 确保模拟输入电压在0-3.3V范围内
使用STM32CubeMX配置
- 打开STM32CubeMX并选择您的STM32F103型号
- 在Pinout & Configuration标签页中:
- 启用ADC1
- 配置PA0-PA4为ADC1_IN0到ADC1_IN4
- 在Configuration标签页的ADC1设置中:
- 设置扫描模式(Scan Conversion Mode)为Enable
- 设置连续转换模式(Continuous Conversion Mode)为Enable
- 设置DMA Continuous Requests为Enable(如果使用DMA)
- 在Rank配置中添加通道0-4,设置采样时间(建议55.5或239.5周期)
不使用CubeMX的寄存器配置
#include "stm32f10x.h"
void ADC1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
// 1. 开启时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE);
// 2. 配置GPIO为模拟输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 3. 配置ADC
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // 独立模式
ADC_InitStructure.ADC_ScanConvMode = ENABLE; // 扫描模式
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // 连续转换
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 软件触发
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // 数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 5; // 5个通道
ADC_Init(ADC1, &ADC_InitStructure);
// 4. 配置通道和采样时间
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5); // PA0
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5); // PA1
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_55Cycles5); // PA2
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_55Cycles5); // PA3
ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 5, ADC_SampleTime_55Cycles5); // PA4
// 5. 使能ADC
ADC_Cmd(ADC1, ENABLE);
// 6. ADC校准
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
}
多路ADC采集程序
方法1:轮询方式采集
uint16_t ADC_Values[5]; // 存储5个通道的ADC值
void ADC_ReadAllChannels(void)
{
// 启动转换
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
// 等待转换完成
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
// 读取各通道值
for(int i = 0; i < 5; i++)
{
ADC_Values[i] = ADC_GetConversionValue(ADC1);
}
}
方法2:使用DMA方式采集(推荐)
#include "stm32f10x_dma.h"
uint16_t ADC_Values[5]; // DMA将把ADC值存储到这个数组
void ADC1_DMA_Init(void)
{
DMA_InitTypeDef DMA_InitStructure;
// 1. 开启DMA时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
// 2. 配置DMA
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_Values;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 5;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
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_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
// 3. 使能DMA
DMA_Cmd(DMA1_Channel1, ENABLE);
// 4. 配置ADC使用DMA
ADC_DMACmd(ADC1, ENABLE);
}
// 在主程序中初始化后,ADC会自动连续转换并将结果存入ADC_Values数组
主程序示例
int main(void)
{
// 初始化系统时钟等
SystemInit();
// 初始化ADC
ADC1_Init();
ADC1_DMA_Init(); // 如果使用DMA方式
// 启动ADC转换
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while(1)
{
// 如果使用轮询方式
// ADC_ReadAllChannels();
// 处理ADC值
// ADC_Values[0] 对应PA0
// ADC_Values[1] 对应PA1
// ...
// ADC_Values[4] 对应PA4
// 可以添加延时或其他处理
Delay_ms(100);
}
}
注意事项
- 确保输入电压不超过3.3V,否则可能损坏MCU
- 对于高精度应用,考虑添加参考电压电路
- 采样时间应根据信号源阻抗调整,高阻抗源需要更长的采样时间
- 在噪声环境中,考虑添加滤波电容和软件滤波算法
- DMA方式效率更高,适合需要连续采集的应用
以上代码提供了STM32F103上使用PA0-PA4进行多路ADC采集的基本框架,您可以根据具体应用需求进行调整和优化。