HAL库配置ADC+DMA

一、ADC几种模式

1、扫描模式: 使用STM32CUBEMX配置了多通道后,这一项默认开启且无法设置成关闭。这个模式就是自动扫描你开启的所有通道进行转换,直至转换完。例如你开启了CH0、CH1、CH2、CH3这四个通道,启动转换后ADC会自动将这4个通道全部转换完,但是这种连续性是可以被打断的,所以就引出了间断模式。

2、连续模式: 在CUBE中选中ENABLE就是连续模式,DISABLE就是单次模式。开启连续模式后,ADC的转换不由其他控制。例如将ADC设置为了定时器的TGRO触发采样,如果开启连续模式,ADC将忽略定时器的触发采样。(连续转换模式开启后其实就是满频率的采样)。

3、间断模式: 可以将多个通道进行分组采集,例如你开启了CH0~3这4个通道,假如你设置了间断次数为4,就相当于将4个通道分成了4组,每组1个通道,那么要想采集完这4个通道就需要手动触发4次ADC采集;如果设置了间断次数为2,那么采集完4个通道就需要手动触发2次ADC采集。
 

二、配置ADC单通道采集

通过查看芯片手册,找到IO口对应的通道口

  while (1)
  {
		HAL_ADC_Start(&hadc1);     //启动ADC转换
		HAL_ADC_PollForConversion(&hadc1, 50);   //等待转换完成,50为最大等待时间,单位为ms

		if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))//判断ADC转换是否完成
		{
			ADC_Value = HAL_ADC_GetValue(&hadc1);   //获取AD值

			printf("ADC1 Reading : %d \r\n",ADC_Value);
			printf("PA5 True Voltage value : %.4f \r\n",ADC_Value*3.3f/4096);
		}
		HAL_Delay(1000);
  }

三、轮询模式的多通道采集(同单通道)

uint32_t ADC_Get_Average(uint32_t Channel,uint8_t times)
{
	ADC_ChannelConfTypeDef sConfig;		//通道初始化
	uint32_t value_sum=0;	
	uint8_t i;
	sConfig.Channel = Channel;
	sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;		//采用周期239.5周期
	sConfig.Rank = 1;
	HAL_ADC_ConfigChannel(&hadc1,&sConfig);											
	for(i=0;i<times;i++)
	{
		HAL_ADC_Start(&hadc1);								//启动转换
		HAL_ADC_PollForConversion(&hadc1,30);				//等待转化结束
		value_sum += HAL_ADC_GetValue(&hadc1);				//求和					
		HAL_ADC_Stop(&hadc1);								//停止转换
	}
	return value_sum/times;									//返回平均值
}

  while (1)
  {
	  SEGGER_RTT_printf(0,"ADC_CHANNEL_10 AD:%d\r\n",ADC_Get_Average(ADC_CHANNEL_10,30));
	  SEGGER_RTT_printf(0,"ADC_CHANNEL_11 AD:%d\r\n",ADC_Get_Average(ADC_CHANNEL_11,30));
	  SEGGER_RTT_printf(0,"ADC_CHANNEL_12 AD:%d\r\n",ADC_Get_Average(ADC_CHANNEL_12,30));
	  SEGGER_RTT_printf(0,"ADC_CHANNEL_13 AD:%d\r\n\r\n",ADC_Get_Average(ADC_CHANNEL_13,30));
	  HAL_Delay(200);
    /* USER CODE BEGIN 3 */
  }

四、DMA实现多通道采集

4.1 STM32Cubemx配置

(1)Data Alignment--->Right alignment                 此项选择右对齐,保持不变。

(2)Scan Conversion Mode--->Enable                 此项选择扫描模式使能,代表对15路ADC输入分别扫描,如果不使能,其将会只读取一个输入的值。

(3)Continuous Conversion Mode --->Enable        此项选择连续扫描模式,表示将连续不断的对ADC的值进行转换。如果此项不使能,将会只采集一次就会停止,直到下一次使能才继续进行一次ADC转换。

(4)Discontinuous Conversion Mode--->Disable        此项和第三项是重复的。

(5)Number of Conversion---->15                此处有多少路输入就选择多少,而且只有在此处选择数字之后下面才会出来15个不同的通道。而且此处应该是在进入ADC1中第一个需要操作的步骤,否则(2)(3)是灰色的,无法选择使能。

 (6)在出现的15个Rank中,分别配置每一路,例如Rank1配置为Channel 0,采样时间55.5Cycles; Rank2配置为Channel 1,采样时间同样为55.5Cycles。此处的注意事项是,如果你不对每一路进行检查配置,可能出现好多Rank同时采集一个Channel,从而导致AD的采集数据的错误。

4.2 采集一次

uint16_t ADC_Value[5];

HAL_ADC_Start_DMA(&hadc1,(uint32_t *)ADC_Value,sizeof(ADC_Value) / sizeof(ADC_Value[0]));

 while (1)
  {
    /* USER CODE END WHILE */
	  SEGGER_RTT_printf(0,"%d %d %d %d %d\r\n",ADC_Value[0],ADC_Value[1],ADC_Value[2],ADC_Value[3],ADC_Value[4]);
	  HAL_Delay(1000);
    /* USER CODE BEGIN 3 */
  }

4.3 采集多次求平均值

#define FILTER_NUM 30
#define ADC_CHANNELS 5
uint16_t ADC_ConvertedValue[FILTER_NUM][ADC_CHANNELS];
uint16_t getADC_CH(uint8_t channel)
{
    uint16_t tbuf[FILTER_NUM];
    uint32_t tdat = 0;
    // 判断传入参数是否合法
    if (channel >= ADC_CHANNELS)
    {
        return 0;
    }
    for (int i = 0; i < FILTER_NUM; i++)
    {
        tbuf[i] = ADC_ConvertedValue[i][channel];
    }
    for (int i = 0; i < FILTER_NUM; i++) 
    {
        tdat += tbuf[i]; 
    }
    tdat = tdat/FILTER_NUM; 
    if (tdat < 5)
    {
        tdat = 0;
    }
    return tdat;
}

int main()
{
	HAL_ADC_Start_DMA(&hadc1, (uint32_t *)&ADC_ConvertedValue, FILTER_NUM * ADC_CHANNELS);
	while (1)
	{
		for (int i = 0; i < ADC_CHANNELS; i++)
		{
			SEGGER_RTT_printf(0,"getADC_CH[%d] = %d\r\n", i, getADC_CH(i));
		}
		HAL_Delay(1000);
	}
}

<think>好的,我现在需要处理用户关于STM32 HAL中使用ADCDMA进行采集的模块化代码实现的问题。首先,我需要回顾用户提供的引用内容,看看是否有相关的代码示例或知识点可以整合。 引用1提到标准ADCDMA知识点,但用户需要的是HAL的实现,所以可能需要更多的HAL资料。引用2和3都涉及HALADCDMA整合,特别是引用2提到了中断和DMA的应用场景,引用3则强调了ADC的多通道和高精度采样。因此,我需要结合这些信息,构建一个模块化的代码示例。 接下来,我需要确保代码符合HAL的结构,模块化设计通常包括初始化配置、启动转换、数据处理回调函数等部分。DMAHAL中通常用于自动传输ADC转换结果到内存,避免CPU干预,提高效率。 用户可能需要的是分步骤的代码实现,包括ADCDMA的初始化、启动转换,以及如何处理转换完成的数据。同时,需要注意DMA配置,比如循环模式、数据对齐等参数。此外,模块化意味着代码应可重用,可能需要将配置部分封装成函数,便于调用。 然后,我需要检查是否有遗漏的部分,比如中断处理。根据引用2,使用中断+DMA的方式,可能需要配置中断回调函数,但DMA传输完成中断可能已经足够。HAL中,DMA传输完成会触发相应的回调函数,比如HAL_ADC_ConvCpltCallback,这里可以处理数据。 另外,用户可能关心如何确保代码的稳定性和正确性,比如防止数据溢出或配置错误。需要提醒用户根据具体型号调整ADCDMA的通道配置,时钟设置等。 最后,生成相关问题时要围绕ADCDMA的使用,可能涉及优化、多通道处理、错误处理等方向。需要确保问题覆盖用户可能感兴趣的扩展话题。</think>以下是一个基于STM32 HALADC通过DMA采集的模块化代码实现,包含初始化配置、数据采集和回调处理三部分: --- ### 1. ADCDMA初始化配置 ```c // 在头文件中声明全局变量 #define ADC_BUFFER_SIZE 256 extern uint16_t adc_buffer[ADC_BUFFER_SIZE]; extern ADC_HandleTypeDef hadc1; extern DMA_HandleTypeDef hdma_adc1; // 初始化函数 void ADC_DMA_Init(void) { // ADC1基本配置 hadc1.Instance = ADC1; hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc1.Init.ScanConvMode = ENABLE; // 扫描模式使能 hadc1.Init.ContinuousConvMode = ENABLE; // 连续转换模式 hadc1.Init.NbrOfConversion = 1; // 转换通道数 hadc1.Init.DiscontinuousConvMode = DISABLE; hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; HAL_ADC_Init(&hadc1); // DMA配置(循环模式) hdma_adc1.Instance = DMA1_Channel1; hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE; hdma_adc1.Init.MemInc = DMA_MINC_ENABLE; hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; hdma_adc1.Init.Mode = DMA_CIRCULAR; // 循环缓冲模式 hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH; HAL_DMA_Init(&hdma_adc1); // 关联ADCDMA __HAL_LINKDMA(&hadc1, DMA_Handle, hdma_adc1); // 校准ADC并启动 HAL_ADCEx_Calibration_Start(&hadc1); HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, ADC_BUFFER_SIZE); } ``` --- ### 2. 中断回调处理 ```c // 在main.c中重写转换完成回调 void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { if(hadc->Instance == ADC1) { // 此处添加数据处理逻辑 // adc_buffer包含最新采集的ADC_BUFFER_SIZE个数据 } } ``` --- ### 3. 模块化使用示例 ```c int main(void) { HAL_Init(); SystemClock_Config(); ADC_DMA_Init(); while(1) { // 主循环可添加其他任务 // ADC数据通过DMA自动更新到adc_buffer数组 } } ``` --- ### 关键配置说明: 1. **扫描模式**:支持多通道采集,需配合`ADC_ChannelConfTypeDef`配置多个通道[^3] 2. **循环缓冲**:DMA自动循环覆盖缓冲区,避免数据溢出[^2] 3. **校准操作**:HAL_ADCEx_Calibration_Start()可提高ADC精度[^1] 4. **触发方式**:本例使用软件触发,也可配置定时器触发 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值