STM32 HAL库 ADC采集(查询,中断,DMA)

一、ADC的三种工作方式及优缺点

1.查询模式:查询模式下,占用CUP时间较多,cup效率较低。
2.中断模式:相比查询模式大大释放了cup,提高了cup的利用率。
3.DMA模式:该模式下基本不占用cup,能直接将ADC采集的数据存储到存储器。

二、ADC的转换方式

转换方式需要根据情况搭配使用,分为扫描模式(Scan Conversion mode)、连续转换模式(Continuous Conversion Mode)和间断模式(Discontinuous Conversion Mode)。

ADC单通道转换:

“单次转换模式,扫描模式关闭”:只进行一次转换,不过可以持续使能ADC达到不断采集的的。
“连续转换模式,扫描模式关闭”:使能一次ADC后,能够连续转换。

ADC多通道转换:

“单次转换模式”,扫描模式开启”:每个通道转换完一次后结束转换,但可以通过持续使能ADC不断进行多通道连续采集。
“连续转换模式”,扫描模式开启”:每个通道转换完之后还能继续循环转换,不需要反复使能ADC。

多通道必须开启扫描模式。

三、ADC之查询模式(阻塞模式)

1、流程:

①开启ADC:调用HAL_ADC_Start(),开启ADC。
②等待EOC标志位:调用查询函数HAL_ADC_PollForConversion(),等待ADC转化结束,CUP在这段时间内不能干其他事,所以查询方式降低了CUP的使用率。
③读取寄存器数据:调用HAL_ADC_GetValue()。

2、STM32CUBEMX配置(ADC部分)**

在这里插入图片描述
在这里插入图片描述
Data Alignment : 可选左对齐或右对齐。
Conversion Mode:由于只使用了一个通道,关闭就行。
Continuous Conversion Mode:这里关闭,我们使用软件开启ADC。
Discontinuous Conversion Mode:单通道模式间断模式自动关闭,不可选。
Enable Regular Conversions:是否使能转换,开启规则转换。
Number Of Conversion:转换的通道数,单通道当然只能是1。
External Trigger Conversion Source:选择由软件触发采集。
Rank :每个通道的编号,
每个Rank有如下参数配置:
Channel:所选择的通道
Sampling Time:每次采集ADC所需要的时间(采样周期),T = 采样周期 + 12.5个周期,(其中1周期为1/ADCCLK,设置的ADC时钟频率为12M),这里我设置的ADC的采样周期 为1.5Cycles,所以转化一次总的时间T=(1.5+12.5)/12=1.167us。补充:采样周期越长,越准确,这里存在一个竞争冒险的关系。

3、软件配置

在adc.h文件添加代码:

/* USER CODE BEGIN 1 */
获取ADC的值
uint16_t Get_adc(uint16_t ch)
{
	HAL_ADC_Start(&hadc1);  //先开启ADC
	HAL_ADC_PollForConversion(&hadc1,1);//查询函数,查询EOC标志位。每次采样,CUP在这里都要 
                                       //等待采样完成才能进行下一步,这段时间CUP没有干其他 
                                       //事,所以降低了CUP使用率
 
	return HAL_ADC_GetValue(&hadc1);    //得到ADC的值
} 
 
/获取times次采样值的平均值///
uint16_t Get_ADC_Average(uint16_t ch,uint8_t times)
{
   uint32_t ADC_Sum=0;
	 uint8_t i;
   for(i=0;i<times;i++)
	 {
		 ADC_Sum+=Get_adc(ch);
		 HAL_Delay(5);
	 }
	 return ADC_Sum/times;                //对times次样品值取平均,使采样值更加准确
}
/* USER CODE END 1 */

在main…c的初始化代码段定义一个uint16_t ADC_Value1;在while中添加一下代码

  /* USER CODE BEGIN 1 */
    uint16_t ADC_Value1;    //
  /* USER CODE END 1 */
 
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_ADC1_Init();
  /* USER CODE BEGIN 2 */
    HAL_ADCEx_Calibration_Start(&hadc1);//开启ADC之前校准一下
  /* USER CODE END 2 */
  while (1)
  {
		ADC_Value1=Get_ADC_Average(ADC_CHANNEL_1,10);//得到10次采样值的均值
		printf("ADC:%d\n",ADC_Value1);
		HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);
		HAL_Delay(1);
  }

ADC查询模式小总结:在关闭间断模式的情况下,多通道采集尽量不使用ADC查询模式进行,不然采样值容易出错,如果要用一定要开启间断采样模式。

四、多通道查询模式

1.STM32CUBEMX配置

开启ADC1的四个通道**
在这里插入图片描述
在这里插入图片描述

2.软件配置

在main.c中添加:

int main(void)
{
  /* USER CODE BEGIN 1 */
    uint16_t ADC_Value1,i; 
	uint16_t adcbuf[4];    //四个通道采样数据存储的数组
  /* USER CODE END 1 */
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_ADC1_Init();
  /* USER CODE BEGIN 2 */
  HAL_ADCEx_Calibration_Start(&hadc1);   //开启adc前校准一下ADC
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		
		for(i=1;i<5;i++)
		{
			HAL_ADC_Start(&hadc1);   //由于没有开启连续转换,每次转换前需要软件开启adc
			HAL_ADC_PollForConversion(&hadc1,10);//轮询等待ADC转换完成
			adcbuf[i]=HAL_ADC_GetValue(&hadc1);     //将四个通道的采样值存在数组里
			printf("adc_ch%d:  %d  \n\r",i,adcbuf[i]);
		}
		
     HAL_ADC_Stop(&hadc1);//关闭ADC
		  HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);
			HAL_Delay(100);
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

五、ADC之中断模式(单通道)

1、流程

①启动ADC,使能中断
②等待中断触发
③在中断中读取寄存器数据

2、STM32CUBEMX配置(ADC部分)

ADC的中断模式和单通道采样一样,只是多使能了一下adc中断。
在这里插入图片描述

3、软件配置

只需在while()的上面校准adc和开启ADC。

HAL_ADCEx_Calibration_Start(&hadc1);
HAL_ADC_Start_IT(&hadc1);
在ADC的回调函数里面添加:

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)//回调函数
{
	uint16_t Adc_Value;
	Adc_Value=HAL_ADC_GetValue(&hadc1);
  printf("adc_value:%d\n",Adc_Value);
}

六、ADC之DMA(多通道)

1、流程

① 启动ADC
②配置DMA缓冲区
③读取缓冲区数据

2、STM32CUBEMX配置(ADC部分)

开启ADC1的通道1和2。
在这里插入图片描述
在这里插入图片描述

3、软件配置

main.c

int main(void)
{
  /* USER CODE BEGIN 1 */
   uint16_t ADC_Value1,i;
	uint16_t AD_Buf[2]={0};//两个通道采集数据存在这个数组里面
  /* USER CODE END 1 */
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_DMA_Init();
  MX_ADC1_Init();
  /* USER CODE BEGIN 2 */
	 HAL_ADCEx_Calibration_Start(&hadc1);
	HAL_ADC_Start_DMA(&hadc1,(uint32_t *)&AD_Buf,2);//开启ADC的DMA,采集的数据直接放入 
                                                     AD_Buf这个数组里,操作简单。
  /* USER CODE END 2 */
  while (1)
  {
		printf("AD1=%d\n\r",AD_Buf[0]);
        printf("AD2=%d\n\r",AD_Buf[1]);
		HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);
		HAL_Delay(20);
  }
}

ADC的DMA模式小总结:DMA模式最简单,并且采样过程基本不会影响CPU,一般使用ADC的DMA模式进行采样。
————————————————

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好!对于STM32HAL库中的ADC采集DMA,您可以使用以下步骤进行设置: 1. 首先,需要初始化ADCDMA。您可以使用`HAL_ADC_Init()`函数初始化ADC,并使用`HAL_DMA_Init()`函数初始化DMA。 2. 配置ADC通道和采样时间。使用`HAL_ADC_ConfigChannel()`函数配置ADC通道,并使用`HAL_ADCEx_InjectedConfigChannel()`函数配置注入通道(如果需要)。 3. 配置DMA传输参数。使用`HAL_DMA_ConfigChannel()`函数配置DMA通道参数,如传输方向、数据宽度、内存地址等。 4. 启用ADCDMA。使用`HAL_ADC_Start_DMA()`函数启动ADC转换和DMA传输。 5. 在DMA传输完成后,可以在回调函数中处理接收到的数据。可以使用`HAL_ADC_ConvCpltCallback()`函数作为转换完成的回调函数。 以下是一个示例代码片段,展示了如何使用STM32HAL库进行ADCDMA采集: ```c #define ADC_BUFFER_SIZE 10 uint16_t adc_buffer[ADC_BUFFER_SIZE]; void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { // 处理接收到的数据 // 示例中仅打印接收到的数据 for(int i = 0; i < ADC_BUFFER_SIZE; i++) { printf("ADC value: %u\r\n", adc_buffer[i]); } } void ADC_DMA_Init(void) { // ADC初始化 ADC_HandleTypeDef hadc; hadc.Instance = ADC1; hadc.Init.Resolution = ADC_RESOLUTION_12B; hadc.Init.ScanConvMode = DISABLE; hadc.Init.ContinuousConvMode = ENABLE; hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc.Init.NbrOfConversion = 1; HAL_ADC_Init(&hadc); // 配置ADC通道 ADC_ChannelConfTypeDef sConfig; sConfig.Channel = ADC_CHANNEL_0; sConfig.Rank = 1; sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES; HAL_ADC_ConfigChannel(&hadc, &sConfig); // DMA初始化 DMA_HandleTypeDef hdma_adc; hdma_adc.Instance = DMA1_Channel1; hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE; hdma_adc.Init.MemInc = DMA_MINC_ENABLE; hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; hdma_adc.Init.Mode = DMA_CIRCULAR; hdma_adc.Init.Priority = DMA_PRIORITY_HIGH; HAL_DMA_Init(&hdma_adc); // 配置DMA通道 __HAL_LINKDMA(&hadc, DMA_Handle, hdma_adc); // 启动ADCDMA HAL_ADC_Start_DMA(&hadc, (uint32_t*)adc_buffer, ADC_BUFFER_SIZE); } ``` 这段代码演示了如何使用DMA进行连续的ADC转换,并在DMA传输完成后处理接收到的数据。您可以根据自己的需求进行修改和扩展。 希望对您有所帮助!如果您有任何其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值