一、简介:
什么是ADC?
Analog-to-Digital Converter的缩写。指模/数转换器或者模拟/数字转换器。是指将连续变量的模拟信号转换为离散的数字信号的器件。
典型的模拟数字转换器将模拟信号转换为表示一定比例电压值的数字信号。也就是模数转换,即将模拟量转换为数字量。
简单地说就是将模拟电压值,转换成对应的肉眼可读数值。
STM32F10x ADC特点
- 12位逐次逼近型的模拟数字转换器。
- 最多带3个ADC控制器
- 最多支持18个通道,可最多测量16个外部和2个内部信号源。
- 支持单次和连续转换模式
- 转换结束,注入转换结束,和发生模拟看门狗事件时产生中断。
- 通道0到通道n的自动扫描模式 自动校准
- 采样间隔可以按通道编程
- 规则通道和注入通道均有外部触发选项
- 转换结果支持左对齐或右对齐方式存储在16位数据寄存器
- ADC转换时间:最大转换速率 1us。(最大转换速度为1MHz,在ADCCLK=14M,采样周期为1.5个ADC时钟下得到。)
- ADC供电要求:2.4V-3.6V
- ADC输入范围:VREF- ≤ VIN ≤ VREF+
STM32F4x ADC特点
F1与F4区别
F4的ADC支持12位,10位,8位和6位精度,F1只支持12位
F1和F4都具有3个ADC,F1可提供21个输入通道,F4可以提供24个输入通道。
F1的ADC最大采样频率为1Msps,2路交替采样可到2Msps(F1不支持3路交替采样)。F4的ADC最大采样频率为2.4Msps,3路交替采样可到7.2Msps。
1.工作框图:
2.ADC时钟
图中的ADC预分频器的ADCCLK是ADC模块的时钟来源。通常,由时钟控制器提供的ADCCLK时钟和PCLK2(APB2时钟)同步。RCC控制器为ADC时钟提供一个专用的可编程预分频器。 分频因子由RCC_CFGR的ADCPRE[1:0]配置,可配置2/4/6/8分频
STM32的ADC最大的转换速率为1MHz,也就是说最快转换时间为1us,为了保证ADC转换结果的准确性,ADC的时钟最好不超过14M。
3.分辨率:
读出的数据的长度,如8位就是最大值为255的意思,即范围[0,255],12位就是最大值为4096,即范围[0,4096]。STM32的ADC通常最大精度是12位,使用时也可以配置成10位、8位或6位等。精度会影响转换速度和数据计算。
12位ADC是一种逐次逼近型模拟数字转换器。如STM32f103它有3个ADC控制器,多达18个通道,可测量16个外部和2个内部信号源。各通道的A/D转换可以单次、连续、扫描或间断模式执行。ADC的结果可以左对齐或右对齐方式存储在16位数据寄存器中。
12位ADC, 即2^12 = 4096, 也就是说你希望采集到的量被分成了4096份,根据测出的ADC值即可推出实际的值
例:一节电池的最大电压为3V,现在用了一些电,我不知道还剩多少电,我用12位ADC测一下,测得的ADC值为2048。3V被分成了4096份,现在还剩2048份,也就是现在还剩1.5V
4.通道:
ADC输入引脚,通常一个ADC控制器控制多个通道,如果需要多通道的话,就得进行每个通道扫描了。
5.ADC DMA功能:
DMA是内存到内存或内存到存储的直接映射,数据不用经过单片机处理器而直接由硬件进行数据的传递。方便直接将读取的ADC值放到内存变量中。
6.ADC输入电压范围:
ADC一般用于采集小电压,其输入值不能超过VDDA,即ADC输入范围:VREF- ≤ VIN ≤ VREF+。具体的定义见上图。
一般把VSSA和VREF- 接地, VREF+ 和 VDDA接3V3,那么ADC的输入范围是0~3.3V。在STM32中ADC还可以用于采集芯片的温度、RTC供电电压.
一般来说,采样时间越长,结果越准确,采样时间要更具ADC的时钟周期和ADC通道设置的采样周期计算,如STM32F103C8T6配置的ADC时钟周期为12MHZ,采样周期配置的是239.5 Cycles。
7.左/右对齐:
ADC数据是12位精度的,但是数据是存储在 16 位数据寄存器中,所以ADC的存储结果可以分为左对齐或右对齐两种方式
8.ADC的转换方式:
l 单次转换,一次只转换一个通道
l 连续转换,转换完成一个通道后立即自动执行下一个通道的转换
l 扫描模式,开启一次后,自动的连续读取多个通道
总结:
只有一个ADC通道,并且这个通道只转换一次,选择单次转换模式
只有一个ADC通道,需要连续转换,选择连续转换模式
ADC通道多于一个,并且所有的通道只转换一次,选择单次转换模式,同时使能扫描模式
ADC通道多于一个,需要连续转换,选择连续转换模式,同时使能扫描模式
假如有4个通道需要转换,设定扫描模式+连续转换,那么顺序是ch0->ch1->ch2->ch3->ch0->ch1…这个过程无法被打断。如果我希望通道之间转换有可调的时间间隔,那么就引入间断模式(有点类似中断的意思)
9.ADC的三种工作方式:
触发转换:
外部触发:ADC_CR2 的ADON控制 ;定时器捕获;EXIT
中断触发:规则 / 注入通道转换结束(转换完一次即进入中断);模拟看门狗状态位被设置(当转换的模拟电压值低于低阈值或高于高阈值时,便会产生中断。阈值的高低值由ADC_LTR和ADC_HTR配置)
DMA触发:规则 / 注入通道转换结束后会产生DMA请求(只有ADC1和ADC3可以)
二、工程创建
1.RCC设置
2.开启ADC
3.时钟树设置
ADC频率不高于14M不然转换结果容易出错。
4.ADC设置
- ADCs_Common_Settings ADC模式设置
- Mode ADC_Mode_Independent 这里设置为独立模式
独立模式模式下,双ADC不能同步,每个ADC接口独立工作。所以如果不需要ADC同步或者只是用了一个ADC的时候,应该设成独立模式,多个ADC同时使用时会有其他模式,如双重ADC同步模式,两个ADC同时采集一个或多个通道,可以提高采样率
- Data Alignment (数据对齐方式): 右对齐/左对齐
- Scan Conversion Mode( 扫描模式 ) : DISABLE
- Continuous Conversion Mode(连续转换模式) ENABLE
- Discontinuous Conversion Mode(间断模式) DISABLE
- Enable Regular Conversions (启用常规转换模式) ENABLE
设定ADC的触发方式
- Regular Conversion launched by software 规则的软件触发 调用函数触发即可
- Timer X Capture Compare X event 外部引脚触发,
- Timer X Trigger Out event 定时器通道输出触发 需要设置相应的定时器设置
Rank 转换顺序
这个只修改通道采样时间即可 默认为1.5个周期
多个通道时会有多个Rank,可以设定每个通道的转换顺序
ADC总转换时间如下计算:
TCONV = 采样时间+ 12.5个周期
当ADCCLK=14MHz(最大),采样时间为1.5周期(最快)时,TCONV =1.5+12.5=14周期=1μs。
因此,ADC的最小采样时间1us(ADC时钟=14MHz,采样周期为1.5周期下得到)
ADC转换结束中断
ADC的DMA传输
GPIO的模式为模拟模式
5.串口设置
6.项目设置
三、代码讲解。
1.重定向串口:
#include "stdio.h"
//重定向c库函数printf到串口DEBUG_USART,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
/* 发送一个字节数据到串口DEBUG_USART */
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000);
return (ch);
}
//重定向c库函数scanf到串口DEBUG_USART,重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{
int ch;
HAL_UART_Receive(&huart1, (uint8_t *)&ch, 1, 1000);
return (ch);
}
在main.c中加上
/* USER CODE BEGIN 0 */
uint16_t ADC_Value;
/* USER CODE END 0 */
在ADC初始化之后加上AD校准函数
MX_ADC1_Init();
HAL_ADCEx_Calibration_Start(&hadc1); //AD校准
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
while中加上:
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_Value = HAL_ADC_GetValue(&hadc1); //获取AD值
printf("ADC1 Reading : %d \r\n",ADC_Value);
printf("PA1 True Voltage value : %.4f \r\n",ADC_Value*3.3f/4096);
printf("测试\r\n");
}
HAL_Delay(1000);
中断读取:
如果使能了ADC转换结束中断,并且使能了定时器中断,可以这样写:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) //定时器中断回调
{
HAL_ADC_Start_IT(&hadc1); //定时器中断里面开启ADC中断转换,1ms开启一次采集
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) //ADC转换完成回调
{
HAL_ADC_Stop_IT(&hadc1); //关闭ADC
HAL_TIM_Base_Stop_IT(&htim3); //关闭定时器
AD_Value=HAL_ADC_GetValue(&hadc1); //获取ADC转换的值
printf("ADC1 Reading : %d \r\n",AD_Value);
printf("%.4f V\r\n",(AD_Value*3.3/4096)); //串口打印电压信息
HAL_TIM_Base_Start_IT(&htim3); //开启定时器
}
函数讲解:
开启ADC 3种模式 ( 轮询模式 中断模式 DMA模式 )
• HAL_ADC_Start(&hadcx); //轮询模式开启ADC
• HAL_ADC_Start_IT(&hadcx); //中断轮询模式开启ADC
• HAL_ADC_Start_DMA(&hadcx); //DMA模式开启ADC
关闭ADC 3种模式 ( 轮询模式 中断模式 DMA模式 )
• HAL_ADC_Stop()
• HAL_ADC_Stop_IT()• HAL_ADC_ConvCpltCallback()
• HAL_ADC_Stop_DMA()
ADC校准函数 :
• HAL_ADCEx_Calibration_Start(&hadcx);
读取ADC转换值(F4系列不支持)
• HAL_ADC_GetValue()
等待转换结束函数
• HAL_ADC_PollForConversion(&hadc1, 50);
第一个参数为那个ADC,第二个参数为最大等待时间
ADC中断回调函数
• HAL_ADC_ConvCpltCallback()
转换完成后回调,DMA模式下DMA传输完成后调用
规则通道及看门狗配置文章来源:https://www.toymoban.com/news/detail-451183.html
• HAL_ADC_ConfigChannel() 配置规则组通道
• HAL_ADC_AnalogWDGConfig()文章来源地址https://www.toymoban.com/news/detail-451183.html
到了这里,关于STM32 (九)ADC的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!