目录
ADC介绍
ADC特性
ADC通道
ADC转换顺序
ADC触发方式
ADC转化时间
ADC转化模式
实验:使用ADC读取烟雾传感器的值
代码实现
ADC介绍
ADC
是什么?
全称:
Analog-to-Digital Converter
,指模拟
/
数字转换器
ADC的性能指标
- 量程:能测量的电压范围
- 分辨率:ADC能辨别的最小模拟量,通常以输出二进制数的位数表示,比如:8、10、12、 16位等;位数越多,分辨率越高,一般来说分辨率越高,转化时间越长
- 转化时间:从转换开始到获得稳定的数字量输出所需要的时间称为转换时间
ADC特性
- 12位精度下转换速度可高达1MHZ
- 供电电压:V SSA :0V,V DDA :2.4V~3.6V
- ADC输入范围:VREF- ≤ VIN ≤ VREF+
- 采样时间可配置,采样时间越长, 转换结果相对越准确, 但是转换速度就越慢
- ADC 的结果可以左对齐或右对齐方式存储在 16 位数据寄存器中
ADC通道
总共
2
个
ADC
(
ADC1
,
ADC2
),每个
ADC
有
18
个转换通道
: 16
个外部通道、
2
个内部通道(温度
传感器、内部参考电压)。
外部的
16
个通道在转换时又分为规则通道和注入通道,其中规则通道最多有
16
路,注入通道最多
有
4
路。
规则组:正常排队的人;
注入组:有特权的人(军人、孕妇)
ADC转换顺序
每个
ADC
只有一个数据寄存器,
16
个通道一起共用这个寄存器,所以需要指定规则转换通道的转
换顺序。
规则通道中的转换顺序由三个寄存器控制:
SQR1
、
SQR2
、
SQR3
,它们都是
32
位寄存器。
SQR
寄
存器控制着转换通道的数目和转换顺序,只要在对应的寄存器位
SQx
中写入相应的通道,这个通
道就是第
x
个转换。
和规则通道转换顺序的控制一样,注入通道的转换也是通过注入寄存器来控制,只不过只有一个
JSQR
寄存器来控制,控制关系如下:
注入序列的转换顺序是从
JSQx[ 4 : 0 ]
(
x=4-JL[1:0]
)开始。只有当
JL=4
的时候,注入通道的转换
顺序才会按照
JSQ1
、
JSQ2
、
JSQ3
、
JSQ4
的顺序执行。
ADC触发方式
1.通过向控制寄存器
ADC-CR2
的
ADON
位写
1
来开启转换,写
0
停止转换。
2.
也可以通过外部事件(如定时器)进行转换。
ADC转化时间
ADC是挂载在APB2总线(PCLK2)上的,经过分频器得到ADC时钟(ADCCLK),最高 14 MHz。
转换时间=采样时间+12.5个周期
12.5
个周期是固定的,一般我们设置
PCLK2=72M
,经过
ADC
预分频器能分频到最大的时钟只能
是
12M
,采样周期设置为
1.5
个周期,算出最短的转换时间为
1.17us
。
ADC转化模式
扫描模式
关闭扫描模式:只转换
ADC_SQRx
或
ADC_JSQR
选中的第一个通道
打开扫描模式:扫描所有被
ADC_SQRx
或
ADC_JSQR
选中的所有通道
单次转换
/
连续转换
单次转换:只转换一次
连续转换:转换一次之后,立马进行下一次转换
实验:使用ADC读取烟雾传感器的值
CubeMX
配置
代码实现
/* 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 */
/* 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 */
int fputc(int ch, FILE *f)
{
unsigned char temp[1]={ch};
HAL_UART_Transmit(&huart1,temp,1,0xffff);
return ch;
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
uint32_t smoke_value=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_ADC1_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
HAL_ADC_Start(&hadc1); //启动ADC单次转换
HAL_ADC_PollForConversion(&hadc1, 50); //等待ADC转换完成
smoke_value = HAL_ADC_GetValue(&hadc1); //读取ADC转换数据
printf("smoke_value = %f\r\n", 3.3/4096 * smoke_value);
//printf("smoke_value = %d \r\n", smoke_value);
HAL_Delay(500);
/* 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 */