使用HAL库开发STM32的ADC功能

配置ADC转换通道。

Data Alignment(数据对齐)一般默认右对齐

因为只对一个引脚测量ADC因此不用使能扫描模式。

ADC的扫描模式是一种工作模式,用于在单个转换序列中连续地转换多个输入通道的模拟信号。

在扫描模式下,ADC会按照预先配置的顺序对多个输入通道上的模拟信号进行连续转换。每次转换完成后,ADC会自动切换到下一个输入通道并开始新的转换,直到转换序列结束。

扫描模式对于需要同时监测多个模拟信号的应用非常有用。例如,在多通道传感器、数据采集系统以及需要对不同传感器进行周期性采样的系统中,扫描模式可以提高转换效率和减少软件开销。

在配置ADC的扫描模式时,您需要指定转换的输入通道顺序以及相应通道的采样时间和转换触发方式。这些设置可根据具体的应用需求进行调整。

值得注意的是,扫描模式与单次转换模式不同。在单次转换模式下,ADC只进行一次转换并输出结果;而在扫描模式下,ADC会按照顺序进行多次转换。

 打开串口,用于接收显示测量的AD值。

检测AD的两种方法:

1.使用阻塞式A/D转换

①启动AD转换,即调用阻塞式AD转换启动函数:HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef* hadc)

②确保AD转换完成,即调用AD转换完成函数:HAL_ADC_PollForConversion()

③使用AD值获取值函数获取转换的AD值:HAL_ADC_GetValue(ADC_HandleTypeDef* hadc)

2.使用中断式A/D转换

①使用中断式A/D转换函数开启A/D转换:HAL_StatusTypeDefHAL_ADC_Start_IT(ADC_HandleTypeDef* hadc)

②调用A/D转换完成回调函数:void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)

③回调函数里面调用A/D值获取函数:HAL_ADC_GetValue(ADC_HandleTypeDef* hadc)

1.使用阻塞式A/D转换

HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef* hadc)

该函数的参数为hadc,是一个指向ADC_HandleTypeDef结构体的指针,用于指定要操作的ADC设备。

当调用HAL_ADC_Start函数时,它会激活ADC设备开始进行转换。在转换过程中,ADC将按照事先配置好的通道、采样时间等参数进行转换,并将转换结果保存在相关寄存器中。

启动转换后,可以通过其他函数如HAL_ADC_GetValue()获取转换结果,也可以使用中断或DMA方式进行处理。

HAL_ADC_GetValue(ADC_HandleTypeDef* hadc)

该函数的参数为hadc,是一个指向ADC_HandleTypeDef结构体的指针,用于指定要操作的ADC设备。

调用HAL_ADC_GetValue函数时,它会读取ADC设备中的转换结果,并返回该结果。转换结果一般是一个数字,表示对应通道的模拟电压的离散值。

需要注意的是,在使用HAL_ADC_GetValue函数之前,必须先调用HAL_ADC_Start函数来启动ADC转换,并确保转换已经完成。

HAL_ADC_PollForConversion()是一个函数,属于STM32的HAL库(Hardware Abstraction Layer硬件抽象层),用于在ADC转换完成后轮询检查转换状态。

函数的作用是等待ADC转换完成,并在转换完成后返回。它接受两个参数:

  • hadc:指向ADC_HandleTypeDef结构体的指针,用于指定要操作的ADC设备。
  • Timeout:等待转换完成的超时时间,以毫秒为单位。
  • 当调用HAL_ADC_PollForConversion()函数时,它会阻塞程序执行,直到检测到ADC转换完成或达到超时时间。一旦转换完成,函数将返回,允许您获取转换结果或执行其他操作。

    此函数常用于单次转换的场景,适用于需要实时获取ADC转换结果的应用。注意,在使用此函数之前,需要先配置好ADC的通道、采样时间等参数,并启动转换。

    "PollForConversion"是一个在编程中常见的术语,指的是通过轮询(polling)的方式检查某个操作是否完成或条件是否满足。

    启动开始转换,确保转换完成,获取采样值。12位的AD采样,最大值是4096。因此,求电压时3.3V乘以采样值再除4096即可得到电压值。

    定义ad用于存储采样值,voltage用于存储电压值。一个缓存数组ad_buff用于存储需要发送并打印的数据

    sprintf是stdio的文件,所以使用它之前需要加入stdio头文件。

     

    2.使用中断式A/D转换

    HAL_StatusTypeDef HAL_ADC_Start_IT(ADC_HandleTypeDef* hadc)

    该函数的参数为hadc,是一个指向ADC_HandleTypeDef结构体的指针,用于指定要操作的ADC设备。

    调用HAL_ADC_Start_IT函数时,它会激活ADC设备开始进行转换,并配置相应的中断使能。在转换过程中,当转换完成时,会触发中断,用户可以在中断处理函数中处理转换结果。

    使用中断方式进行ADC转换可以提高系统的并发性和响应速度,适用于需要实时获取转换结果或多任务处理的场景。

    void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)

    当使用中断方式启动ADC转换,并且转换完成时,系统会自动调用HAL_ADC_ConvCpltCallback函数,以通知用户转换已经完成。

    该回调函数的参数hadc是指向完成转换的ADC设备的指针。

    "buff" 可以是 "buffer" 的简写,表示缓冲区。在计算机科学中,缓冲区是一种临时存储数据的区域,用于暂时保存数据,或者用作输入/输出操作之间传递数据的容器。

    重写回调函数,每次中断只调用一次回调函数,需要持续响应中断时需要将启动中断放在回调函数里。

     

     将开启AD转换开启函数放在while外面,在大型项目的时候可以提升程序执行速度,减少扫描到不必要的启动函数次数。

    /* USER CODE BEGIN Header */
    /**
      ******************************************************************************
      * @file           : main.c
      * @brief          : Main program body
      ******************************************************************************
      * @attention
      *
      * Copyright (c) 2023 STMicroelectronics.
      * All rights reserved.
      *
      * This software is licensed under terms that can be found in the LICENSE file
      * in the root directory of this software component.
      * If no LICENSE file comes with this software, it is provided AS-IS.
      *
      ******************************************************************************
      */
    /* USER CODE END Header */
    /* Includes ------------------------------------------------------------------*/
    #include "main.h"
    #include "adc.h"
    #include "usart.h"
    #include "gpio.h"
    
    /* Private includes ----------------------------------------------------------*/
    /* USER CODE BEGIN Includes */
    #include "stdio.h"
    /* USER CODE END Includes */
    
    /* Private typedef -----------------------------------------------------------*/
    /* USER CODE BEGIN PTD */
    
    /* USER CODE END PTD */
    
    /* Private define ------------------------------------------------------------*/
    /* USER CODE BEGIN PD */
    /* USER CODE END PD */
    
    /* Private macro -------------------------------------------------------------*/
    /* USER CODE BEGIN PM */
    
    /* USER CODE END PM */
    
    /* Private variables ---------------------------------------------------------*/
    
    /* USER CODE BEGIN PV */
    uint16_t ad=0;
    uint8_t ad_buff[64];
    float voltage=0;
    /* USER CODE END PV */
    
    /* Private function prototypes -----------------------------------------------*/
    void SystemClock_Config(void);
    /* USER CODE BEGIN PFP */
    
    /* USER CODE END PFP */
    
    /* Private user code ---------------------------------------------------------*/
    /* USER CODE BEGIN 0 */
    void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
    {
      if(hadc->Instance==ADC1)
    	{
    	ad=HAL_ADC_GetValue(&hadc1);
    	voltage=3.3*ad/4096;
    	HAL_ADC_Start_IT(&hadc1);
    	}
    }
    /* USER CODE END 0 */
    
    /**
      * @brief  The application entry point.
      * @retval int
      */
    int main(void)
    {
      /* USER CODE BEGIN 1 */
    
      /* 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_ADC1_Init();
      MX_USART1_UART_Init();
      /* USER CODE BEGIN 2 */
    HAL_ADC_Start_IT(&hadc1);
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
    		sprintf((char *)ad_buff,"采样值是%d\r\n电压值是%f\r\n",ad,voltage);
    		HAL_UART_Transmit(&huart1,ad_buff,sizeof(ad_buff),1000);
    		HAL_Delay(1000);
        /* USER CODE END WHILE */
    
        /* USER CODE BEGIN 3 */
      }
      /* USER CODE END 3 */
    }
    
    /**
      * @brief System Clock Configuration
      * @retval None
      */
    void SystemClock_Config(void)
    {
      RCC_OscInitTypeDef RCC_OscInitStruct = {0};
      RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
      RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
    
      /** Initializes the RCC Oscillators according to the specified parameters
      * in the RCC_OscInitTypeDef structure.
      */
      RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
      RCC_OscInitStruct.HSEState = RCC_HSE_ON;
      RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
      RCC_OscInitStruct.HSIState = RCC_HSI_ON;
      RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
      RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
      RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
      if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
      {
        Error_Handler();
      }
    
      /** Initializes the CPU, AHB and APB buses clocks
      */
      RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                                  |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
      RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
      RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
      RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
      RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    
      if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
      {
        Error_Handler();
      }
      PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
      PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
      if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
      {
        Error_Handler();
      }
    }
    
    /* USER CODE BEGIN 4 */
    
    /* USER CODE END 4 */
    
    /**
      * @brief  This function is executed in case of error occurrence.
      * @retval None
      */
    void Error_Handler(void)
    {
      /* USER CODE BEGIN Error_Handler_Debug */
      /* User can add his own implementation to report the HAL error return state */
      __disable_irq();
      while (1)
      {
      }
      /* USER CODE END Error_Handler_Debug */
    }
    
    #ifdef  USE_FULL_ASSERT
    /**
      * @brief  Reports the name of the source file and the source line number
      *         where the assert_param error has occurred.
      * @param  file: pointer to the source file name
      * @param  line: assert_param error line source number
      * @retval None
      */
    void assert_failed(uint8_t *file, uint32_t line)
    {
      /* USER CODE BEGIN 6 */
      /* User can add his own implementation to report the file name and line number,
         ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
      /* USER CODE END 6 */
    }
    #endif /* USE_FULL_ASSERT */
    

    物联沃分享整理
    物联沃-IOTWORD物联网 » 使用HAL库开发STM32的ADC功能

    发表评论