DMA+ADC单通道转换、多通道转换

在stm32中,使用ADC时往往采用DMA传输方式,由DMA把转换的数据传输到SRAM,再进行处理。
一、单通道转换
本章节选用ADC1进行配置实验:
ADC通道与GPIO对应表:
这里写图片描述
ADC结构体成员变量:
typedef struct
{
uint32_t ADC_Mode;
FunctionalState ADC_ScanConvMode;
FunctionalState ADC_ContinuousConvMode;
uint32_t ADC_ExternalTrigConv;
uint32_t ADC_DataAlign;
uint8_t ADC_NbrOfChannel;
}ADC_InitTypeDef;
1、 ADC_Mode 是用来设置ADC的模式的,
2、ADC_ScanConvMode;设置是否开启扫描模式(扫描模式用于多通道),实验一为单通道,故不需要开启扫描模式
3、ADC_ContinuousConvMode设置是否连续转换
4、ADC_ExternalTrigConv用来设置启动规则组转换的外部事件,如果不需要,选择ADC_ExternalTrigConv_None
5、ADC_DataAlign用来选择数据对齐方式,通常情况下选择右对齐
6、 ADC_NbrOfChannel设置规则序列的长度。
单通道转换初始化程序:
void ADC_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;

RCC_ADCCLKConfig(RCC_PCLK2_Div6);               //ADC转换的最大时钟为14M  
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);  //打开DMA时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1|GPIO_Pin_0; 
GPIO_Init(GPIOA,&GPIO_InitStructure);          //引脚做输入时 不用配置速率

DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;                    //DMA 外设地址
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedValue;               //DMA内存地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                                 //外设为源地址
DMA_InitStructure.DMA_BufferSize = 1;

//单通道的话值为1
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
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);
DMA_Cmd(DMA1_Channel1, ENABLE);

ADC_DeInit(ADC1);
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=1;
//单通道下直为1
ADC_Init(ADC1,&ADC_InitStructure);

ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5);
//ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_239Cycles5);
//单通道下注释掉本句

ADC_DMACmd(ADC1, ENABLE);

ADC_Cmd(ADC1, ENABLE);

ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
ADC_SoftwareStartConvCmd(ADC1, ENABLE);

}
实验二 多通道转换将以上初始化代码做一些相应改动即可。

### STM32F407 DMAADC多通道数据采集 对于STM32F407微控制器而言,其内部集成了多个高精度的模拟数字转换器(ADC),能够支持通过直接存储器访问(DMA)技术来高效处理多路输入信号的数据读取工作[^1]。 当涉及到六通道的同时采样时,可以配置ADC以连续模式运行,并启用扫描功能遍历各个选定的输入通道。为了确保不同通道间切换时不丢失任何样本点,在启动一次完整的轮询周期之前应当先准备好DMA传输请求,这样一旦当前序列结束就能立刻触发下一轮次的操作流程[^4]。 下面给出了一段简化版的例子程序用于展示如何设置并初始化这些外设: ```c #include "stm32f4xx_hal.h" // 定义使用的GPIO端口和引脚编号 #define CH1_PIN GPIO_PIN_0 #define CH2_PIN GPIO_PIN_1 #define CH3_PIN GPIO_PIN_2 #define CH4_PIN GPIO_PIN_3 #define CH5_PIN GPIO_PIN_4 #define CH6_PIN GPIO_PIN_5 #define ADC_CHANNEL_GPIO_PORT GPIOA static void SystemClock_Config(void); static void MX_GPIO_Init(void); int main(void){ HAL_Init(); SystemClock_Config(); /* 初始化所有已配置的外围设备 */ MX_ADC1_Init(); // 假定使用的是第一个ADC单元 uint16_t adcValue[6]; // 存储六个通道的结果缓冲区 // 开启DMA循环传送模式并将目标地址指向本地数组 if(HAL_OK != HAL_DMA_Start(&hadc1.DMA_Handle,(uint32_t)&(ADC1->DR),(uint32_t)adcValue,sizeof(uint16_t)*6)){ Error_Handler(); } // 启动带有DMA支持下的规则组自动注入转换过程 if(HAL_OK != HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adcValue, 6)){ Error_Handler(); } while (1){} } void MX_ADC1_Init(void){ __HAL_RCC_ADC1_CLK_ENABLE(); hadc1.Instance = ADC1; ADC_ChannelConfTypeDef sConfig = {0}; // 配置公共参数结构体 hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; hadc1.Init.Resolution = ADC_RESOLUTION_12B; hadc1.Init.ScanConvMode = ENABLE; // 扫描模式开启 hadc1.Init.ContinuousConvMode = DISABLE; // 单次转换模式关闭 hadc1.Init.DiscontinuousConvMode = DISABLE; hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc1.Init.NbrOfConversion = 6; // 总共需要转换的数量 hadc1.Init.DMAContinuousRequests = ENABLE; if (HAL_ADC_Init(&hadc1) != HAL_OK){ Error_Handler(); } // 对于每一个要用到的物理连接上的传感器/电阻网络等实际存在的元件所对应的引脚都要单独做相应的初始化操作。 for(int i=0;i<6;++i){ sConfig.Channel = i; // 设置为第几个通道 sConfig.Rank = i + 1 ; // 排列顺序也相应调整 sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES; if (HAL_ADC_ConfigChannel(&hadc1,&sConfig)!= HAL_OK){ Error_Handler(); } } } ``` 这段代码展示了基本框架以及一些重要的细节设定方法;然而具体应用场合可能还需要根据实际情况做出适当修改优化性能表现或是满足特定需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值