【STM32】7_0 ADC

发布时间 2023-08-28 23:26:37作者: 山愈海

概述

12 位 ADC 是逐次趋近型模数转换器。它具有多达 19 个复用通道,可测量来自 16 个外部 源、两个内部源和 VBAT 通道的信号。这些通道的 A/D 转换可在单次、连续、扫描或不连续 采样模式下进行。ADC 的结果存储在一个左对齐或右对齐的 16 位数据寄存器中。 ADC 具有模拟看门狗特性,允许应用检测输入电压是否超过了用户自定义的阈值上限或下限。

ADC基本结构

ADC供电

时钟

用于模拟电路的时钟:ADCCLK,所有 ADC 共用 此时钟来自于经可编程预分频器分频的 APB2 时钟,该预分频器允许 ADC 在 fPCLK2/2、 /4、/6 或 /8 下工作

用于数字接口的时钟(用于寄存器读/写访问) 此时钟等效于 APB2 时钟。可以通过 RCC APB2 外设时钟使能寄存器 (RCC_APB2ENR) 分别为每个 ADC 使能/禁止数字接口时钟。

ADC通道

外部输入通道

有 16 条复用通道。可以将转换分为两组:规则转换和注入转换。每个组包含一个转换序列,该序列可按任意顺序在任意通道上完成。

内部通道

对于 STM32F40x 和 STM32F41x 器件,温度传感器内部连接到通道 ADC1_IN16。内部参考电压 VREFINT 连接到 ADC1_IN17。

对于 STM23F42x 和 STM32F43x 器件,温度传感器内部连接到与 VBAT 共用的通道 ADC1_IN18。一次只能选择一个转换(温度传感器或 VBAT)。同时设置了温度传感器和 VBAT 转换时,将只进行 VBAT 转换。

VBAT 通道连接到通道 ADC1_IN18。该通道也可转换为注入通道或规则通道

注:温度传感器、VREFINT 和 VBAT 通道只在主 ADC1 外设上可用。

规则通道和注入通道

规则通道最多有16个转换构成、一个规则转换组规定了多路复用转换的顺序。

注入通道就是可以在规则通道转换过程中插入进行转换的通道。数量最多为4个。

ADC触发模式

软件启动:直接控制寄存器,启动ADC外设,一般为轮询方式进行ADC转换

内部定时器触发:

外部IO触发:

ADC转换时序

ADC开始精确转换之前,需要一定的稳定时间 tstab。稳定时间以后,才可以启动ADC进行转换。ADC 开始转换并经过 15 个

时钟周期后,EOC 标志置 1,转换结果存放在 16 位 ADC 数据寄存器中。

ADC 会在数个 ADCCLK 周期内对输入电压进行采样,可使用 ADC_SMPR1 和 ADC_SMPR2

寄存器中的 SMP[2:0] 位修改周期数。每个通道均可以使用不同的采样时间进行采样。

总转换时间的计算公式如下:

Tconv = 采样时间 + 12 个周期

示例:

ADCCLK = 30 MHz 且采样时间 = 3 个周期时:

Tconv = 3 + 12 = 15 个周期 = 0.5 μs(APB2 为 60 MHz 时)

由于规则通道组只有一个数据寄存器,因此,对于多个规则通道的转换,使用 DMA 非常有帮助。这样可以避免丢失在下一次写入之前还未被读出的 ADC_DR 寄存器中的数据。如果数据没有被读出,之后的ADC数据会覆盖前面的ADC数据。

例1:规则通道

  • 规则通道
  • 时钟配置 略
  • ADC配置

使用软件方式触发,开启单个ADC检测通道 生成代码

HAL_ADC_Start() 采用软件方式启动ADC。

在软件方式启动ADC以后,需要使用函数HAL_ADC_PollForConversion()判断转换是否完成。

然后使用HAL_ADC_GetValue()将32位寄存器中保存的数据读取出来

uint32_t ADC_Value=0;

HAL_ADC_Start(&hadc1);

if(HAL_ADC_PollForConversion(&hadc1, 100)==HAL_OK)

{

ADC_Value=HAL_ADC_GetValue(&hadc1);

}

 

可以使用串口或者LCD显示,将数据进行显示。

例2 使用定时器触发ADC转换

ADC触发方式有3种:软件触发,内部定时器触发和外部IO触发

内部定时器触发,通过定时器的TRGO事件来激活ADC进行电压采集

注:单个ADC使用多个通道时候使用中断时,扫描模式会被强制打开。如果在使用扫描模式的情况下使用中断,会在最后一个通道转换完毕后才会产生中断。因此只能使用DMA进行多通道数据搬运。

  • 时钟设定略
  • 定时器设定

配置定时器时钟

配置触发事件选择(trigger event selection) 定时器的全局中断可以不打开 不影响事件发生

  • ADC设置

在配置ADC通道时,需要将定时器时钟映射到ADC的触发条件上

单通道的情况下 模式似乎不影响定时器触发ADC

打开ADC的中断,在中断回调函数中可以进行数据处理等操作

生成代码

  • 代码补充

在主函数中,启动定时器和ADC中断

HAL_TIM_Base_Start_IT(&htim2);

HAL_ADC_Start_IT(&hadc1);

 

在adc.c中添加通道结束后的中断回调函数,来获得ADC转换后中寄存器的值

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)

{

if(hadc->Instance==ADC1)

{

uint32_t val=HAL_ADC_GetValue(hadc);

}

}

 

DMA 多通道 定时器

在使用多通道时,必须使用扫描模式,cubemx 会强制开启(scan conversion mode)ADC完成转换换后会立刻转换下一个通道,知道整个组里面的通道序列转换完成,如果中断被允许,此时才会发生中断。

因此,使用DMA来对数据进行自动存储到缓存区中,在一个通道组完成转换后,触发中断,再对数据进行处理。

  • 时钟配置 略
  • 定时器配置

根据触发需求进行定时器配置,配置触发事件选择(trigger event selection) 定时器的全局中断可以不打开 不影响事件发生

  • ADC配置

选择多个通道进行扫描模式scan conversion mode

修改需要采集的通道数量(Number of Conversion)将通道(channel)对应到Rank中

开启DMA连续触发请求,关闭后 DMA只触发一次

将ADC的触发方式映射到TRGO上

打开DMA传输 将ADC映射到DMA上 修改DMA的模式为循环模式(正常模式只触发一次)

修改传输数据的长度

注:TIM和ADC的中断都可以不开。在外设使用DMA是,建议尽量不要开启外设中断,若必须开,也要禁止外设主要事件源产生硬件中断。因为HAL中DMA的中断回调函数会映射到外设的回调函数中,这样可能导致多次进入中断回调函数中。

  • 补充代码

在主函数中开启定时器和ADC的DMA

HAL_TIM_Base_Start(&htim2);

HAL_ADC_Start_DMA(&hadc1, dmaDataBuffer, DATA_LEN);

 

在adc.c中添加回调函数处理

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)

{

}