IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32--ADC简介—独立模式ADC 采样 -> 正文阅读

[嵌入式]STM32--ADC简介—独立模式ADC 采样

目录

单个ADC框图(F4)

ADC的电源要求

ADC时钟

ADC通道

内部通道与外部通道

规则通道与注入通道

转换顺序

规则序列

注入序列

触发源

直接写寄存器

外部事件触发

转换时间

输入时钟

采样周期

转换时间

数据寄存器

电压转换

函数讲解

轮询模式

中断模式

DMA模式

其他函数


单个ADC框图(F4)

Analog-to-Digital Converter的缩写。指模/数转换器或者模拟/数字转换器。是指将连续变量的模拟信号转换为离散的数字信号的器件。

典型的模拟数字转换器将模拟信号转换为表示一定比例电压值的数字信号。

简单地说就是将模拟电压值,转换成对应的肉眼可读数值

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

(本文将不介绍看门狗的用法)

ADC的电源要求

● ADC 电源要求:全速运行时为 2.4 V 到 3.6 V,慢速运行时为 1.8 V

● ADC 输入范围:Vref- <= Vin <= Vref+

ADC时钟

ADC 具有两个时钟方案:

● 用于模拟电路的时钟:ADCCLK,所有 ADC 共用 此时钟来自于经可编程预分频器分频的 APB2 时钟,该预分频器允许 ADC 在 fPCLK2/2、 /4、/6 或 /8 下工作。有关 ADCCLK 的最大值,请参见数据手册。(每一种芯片的最大值不同)

?(芯片中给出的电压与其他例子均是工作在典型值的条件下)

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

ADC通道

关于ADC的通道,规则手册中已经明确的给出了标注

按照不同的分类方式,STM32的ADC通道可以有一下两种分类方式:

● 内部通道+外部通道

● 规则通道+注入通道

内部通道与外部通道

?图:野火《库开发实战指南》

规则通道与注入通道

规则通道:顾名思意,规则通道就是很规矩的意思,我们平时一般使用的就是这个通 道,或者应该说我们用到的都是这个通道,没有什么特别要注意的可讲。

注入,可以理解为插入,插队的意思,是一种不安分的通道。它是一种在规则通道转 换的时候强行插入要转换的一种。如果在规则通道转换过程中,有注入通道插队,那么就 要先转换完注入通道,等注入通道转换完成后,再回到规则通道的转换流程。这点跟中断 程序很像,都是不安分的主。所以,注入通道只有在规则通道存在时才会出现。

转换顺序

从数据手册中我们可以看到,STM32的ADC采集可以分为单通道模式和多通道模式。其中,如果我们采用的是单通道的模式,则不需要管理通道间的转换顺序。但是当我们设计多通道采集ADC电压时,便会涉及到ADC通道的转换顺序问题。那么,由上面的介绍,我们知道,这种情况下的转换顺序就有两种,即“规则序列”与“注入序列”。

规则序列

规则序列,说白了就像排队一样,在寄存器中依次填入要参与转换的通道的名字。

● 规则组由多达16个转换组成。规则通道和它们的转换顺序在ADC_SQRx寄存器中选择。规 则组中转换的总数应写入ADC_SQR1寄存器的L[3:0]位中。

注入序列

● 注入组由多达4个转换组成。注入通道和它们的转换顺序在ADC_JSQR寄存器中选择。注入 组里的转换总数目应写入ADC_JSQR寄存器的L[1:0]位中

?需要注意的是,只有当JL=4的时候,注入通道的转换顺序才会按照JSQ1、JSQ2、JSQ3、JSQ4的顺序执行。当JL<4时,注入通道的转换顺序恰恰相反,也就是执行顺序为:JSQ4、JSQ3、JSQ2、JSQ1。

触发源

ADC有两种触发方式:直接控制寄存器的方式和外部事件触发的方式

直接写寄存器

ADC 转换可以由 ADC 控制寄存器 2: ADC_CR2 的 ADON 这个位来控制,写 1 的时候开始转换。写0的时候停止转换。

外部事件触发

ADC 还支持外部事件触发转换,这个触发包括内部定时 器触发和外部 IO 触发。

触发源有很多,具体选择哪一种触发源,由 ADC 控制寄存器 2:ADC_CR2 的 EXTSEL[2:0]和 JEXTSEL[2:0]位来控制。EXTSEL[2:0]用于选择规则通道的 触发源,JEXTSEL[2:0]用于选择注入通道的触发源。选定好触发源之后,触发源是否要激 活,则由 ADC 控制寄存器 2:ADC_CR2 的 EXTTRIG 和 JEXTTRIG 这两位来激活。

如果使能了外部触发事件,我们还可以通过设置 ADC 控制寄存器 2:ADC_CR2 的 EXTEN[1:0]和 JEXTEN[1:0]来控制触发极性,可以有 4 种状态,分别是:禁止触发检测、 上升沿检测、下降沿检测以及上升沿和下降沿均检测。

转换时间

对于转换时间的问题,ADC的每一次信号转换都要时间,这个时间就是转换时间,转换时间由输入时钟和采样周期来决定。

输入时钟

由于ADC在STM32中是挂载在APB2总线上的,所以ADC得时钟是由PCLK2(72MHz)经过分频得到的,分频因子由 RCC 时钟配置寄存器RCC_CFGR 的位 15:14 ADCPRE[1:0]设置,可以是 2/4/6/8 分频。

采样周期

采样周期是确立在输入时钟上的,配置采样周期可以确定使用多少个ADC时钟周期来对电压进行采样,采样的周期数可通过 ADC采样时间寄存器 ADC_SMPR1 和 ADC_SMPR2 中的 SMP[2:0]位设置,ADC_SMPR2 控制的是通道 0~9, ADC_SMPR1 控制的是通道 10~17。每个通道可以配置不同的采样周期,但最小的采样周期是1.5个周期,也就是说如果想最快时间采样就设置采样周期为1.5。

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 时)

转换时间

转换时间=采样时间+12.5个周期
12.5个周期是固定的,一般我们设置 PCLK2=72M,经过 ADC 预分频器能分频到最大的时钟只能是 12M,采样周期设置为 1.5 个周期,算出最短的转换时间为 1.17us。

ADC的最高转换频率可以从数据受从中查到。

数据寄存器

电压转换

模拟电压经过 ADC 转换后,是一个相对精度的数字值,如果通过串口以 16 进制打印 出来的话,可读性比较差,那么有时候我们就需要把数字电压转换成模拟电压,也可以跟 实际的模拟电压(用万用表测)对比,看看转换是否准确。

我们一般在设计原理图的时候会把 ADC 的输入电压范围设定在:0~3.3v,如果设置 ADC 为 12 位的,那么 12 位满量程对应的就是 3.3V,12 位满量程对应的数字值是:2^12。

数值 0 对应的就是 0V。如果转换后的数值为 X ,X 对应的模拟电压为 Y,那么会有这么 一个等式成立:

2^{12} / 3.3 = X / Y\Rightarrow Y = (3.3 * X ) / 2^{12}

函数讲解

轮询模式

HAL_StatusTypeDef HAL_ADC_Start (ADC_HandleTypeDef * hadc) // 开启
HAL_StatusTypeDef HAL_ADC_Stop (ADC_HandleTypeDef * hadc) // 关闭

中断模式

HAL_StatusTypeDef HAL_ADC_PollForConversion (ADC_HandleTypeDef * hadc, uint32_t Timeout) // 循环等待转换结束
HAL_StatusTypeDef HAL_ADC_PollForEvent (ADC_HandleTypeDef * hadc, uint32_t EventType, uint32_t Timeout) // 中断回调函数
HAL_StatusTypeDef HAL_ADC_Start_IT (ADC_HandleTypeDef * hadc) // 开启中断
HAL_StatusTypeDef HAL_ADC_Stop_IT (ADC_HandleTypeDef * hadc) // 结束中断
void HAL_ADC_IRQHandler (ADC_HandleTypeDef * hadc) // 中断请求处理(调用中断回调函数)

DMA模式

HAL_StatusTypeDef HAL_ADC_Start_DMA (ADC_HandleTypeDef * hadc, uint32_t * pData, uint32_t Length) // 开启DMA
HAL_StatusTypeDef HAL_ADC_Stop_DMA (ADC_HandleTypeDef * hadc) // 结束DMA
void HAL_ADC_ConvCpltCallback (ADC_HandleTypeDef * hadc) // DMA模式下传输完成后的回调函数
void HAL_ADC_ConvHalfCpltCallback (ADC_HandleTypeDef * hadc) // DMA模式下传输一半时的回调函数

其他函数

uint32_t HAL_ADC_GetValue (ADC_HandleTypeDef * hadc) // 获得该通道的ADC的结果
HAL_ADC_StateTypeDef HAL_ADC_GetState (ADC_HandleTypeDef * hadc) // 返回通道的状态
void HAL_ADC_ErrorCallback (ADC_HandleTypeDef * hadc) // 错误回调函数

初始化结构体

typedef struct {
     uint32_t             ADC_Mode;                 // ADC 工作模式选择
     FunctionalState      ADC_ScanConvMode;         // ADC 扫描(多通道)或者单次(单通道)模式选择 
     FunctionalState      ADC_ContinuousConvMode;   // ADC 单次转换或者连续转换选择
     uint32_t             ADC_ExternalTrigConv;     // ADC 转换触发信号选择
     uint32_t             ADC_DataAlign;            // ADC 数据寄存器对齐格式
     uint8_t              ADC_NbrOfChannel;         // ADC 采集通道数
 } ADC_InitTypeDef;
typedef struct {
    ADC_TypeDef                   *Instance;                   /*寄存器基地址指针*/
    ADC_InitTypeDef               Init;                        /*ADC 初始化参数结构体*/
    __IO uint32_t                 NbrOfCurrentConversionRank;  /*正在转换序列的 ADC 数目 */
    DMA_HandleTypeDef             *DMA_Handle;                 /* DMA 处理程序指针 */
    HAL_LockTypeDef               Lock;                        /*ADC 锁定对象 */
    __IO uint32_t                 State;                       /*ADC 通信状态*/
    __IO uint32_t                 ErrorCode;                   /*ADC 错误码 */
} ADC_HandleTypeDef;

单通道电压采集实验

轮询方式获取并打印ADC值

第一步,在usart.c中对printf和scanf进行重定向

第二步,首先在main.c文件中的/* USER CODE BEGIN PD */与/* USER CODE END PD */之间生命两个变量:

uint32_t ADC_ConvertedValue = 0;
float value = 0.0;

?其中ADC_ConvertedValue为uint32_t类型,因为ADC的采样值为uint32_t。将value值声明为浮点类型

然后再while(1)循环中对ADC的值进行轮询

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		printf("ADC测试\n");
		HAL_ADC_Start(&hadc1);
		HAL_ADC_PollForConversion(&hadc1, 1000);
		ADC_ConvertedValue = HAL_ADC_GetValue(&hadc1);
		value = (ADC_ConvertedValue * 3.3 / 4096);
		printf("%.5f\n", value);
		HAL_Delay(1000);
  }
  /* USER CODE END 3 */

DMA方式获取并打印ADC值

用 HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc),因此只需重写该函数进行数据处理即可。


?

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章           查看所有文章
加:2021-07-15 23:50:11  更:2021-07-15 23:50:17 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 19:47:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码