STM32 AD单通道函数设计

news2024/12/30 2:18:35

单片机学习!

目录

文章目录

前言

一、ADC配置步骤

二、详细步骤

2.1 开启RCC时钟

2.2 配置GPIO

2.3 配置多路开关

2.4 配置ADC转换器

2.5 开启ADC电源

2.6 ADC进行校准

        2.6.1 复位校准

        2.6.2 等待复位校准完成

        2.6.3 开始校准

2.6.4 等待校准完成

三、启动AD转换函数设计

3.1 软件触发转换

3.2 等待转换完成

3.3 读取ADC数据寄存器

3.4 启动AD转换函数块总结

总结


前言

        本文介绍AD单通道函数设计的基础内容。


一、ADC配置步骤

        参照结构框图,在原理上将ADC外设运转起来。

第一步:开启RCC时钟,包括ADC和GPIO的时钟。另外ADCCLK的分频器也需要配置。

第二步:配置GPIO,把需要用到的GPIO配置成模拟输入的模式。

第三步:配置多路开关,把通道接入到规则组列表里。

第四步:配置ADC转换器,库函数中用结构体来配置电路参数,包括ADC是单次转换还是连续转换;扫描还是非扫描;有几个通道;触发源是什么;数据对齐是左对齐还是右对齐。

  • 如果需要模拟看门狗,可以用几个库函数来配置阈值和监测通道;
  • 如果需要开启中断,在中断输出控制里用 ITConfig 函数开启对应的中断输出,然后再在NVIC里配置一下优先级。这样就能触发中断了。

最后:开关控制,调用一下ADC_Cmd函数,开启ADC.

        在开启ADC之后,根据STM32手册的建议,还可以对ADC进行一下校准,这样可以减小误差。

        在ADC工作的时候,如果想要软件触发转换,有库函数可以触发;如果想读取转换结果,也会有函数可以读取结果。

二、详细步骤

2.1 开启RCC时钟

        第一步:开启RCC时钟。包括ADC和GPIO的时钟。另外ADCCLK的分频器也需要配置。

代码示例:

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//开启ADC1的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//还需要开启PA0口的时钟
    RCC_ADCCLKConfig(RCC_PCLK2_Div6);//配置ADCCLK

        RCC_APB2PeriphClockCmd函数开启ADC1的时钟,ADC都是APB2上的设备,所以这里用APB2开启时钟的函数。

        RCC_APB2PeriphClockCmd函数用于开启PA0口的时钟。

        以上时钟就配置好了,还需要配置ADCCLK,用RCC_ADCCLKConfig/函数来配置,函数有四个参数分别是2、4、6、8分频:

  • RCC_PCLK2_Div2: ADC clock = PCLK2/2
  • RCC_PCLK2_Div4: ADC clock = PCLK2/4
  • RCC_PCLK2_Div6: ADC clock = PCLK2/6
  • RCC_PCLK2_Div8: ADC clock = PCLK2/8

        函数参数配置好之后,ADC的CLOCK=PCLK2/2、PCLK2/4、PCLK2/6、PCLK2/8,参数的PCLK2就是APB2时钟的意思。

        代码示例中选择6分频,分频之后,ADCCLK=72MHz/6=12MHz

2.2 配置GPIO

        第二步:配置GPIO,把需要用到的GPIO配置成模拟输入的模式。

代码示例:

    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Mode= GPIO_Mode_AIN;//选择模拟输入
    GPIO_InitStruct.GPIO_Pin= GPIO_Pin_0;
    GPIO_InitStruct.GPIO_Speed= GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStruct);

        代码示例中选择GPIO_Mode_AIN模拟输入这个模式,在GPIO_Mode_AIN模式下,GPIO是无效的,断开GPIO口,防止GPIO口的输入输出对模拟电压造成干扰。GPIO_Mode_AIN模式就是ADC的专属模式。

2.3 配置多路开关

        第三步:配置多路开关,把通道接入到规则组列表里。

代码示例:

ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);

        用ADC_RegularChannelConfig函数可选择规则组的输入通道。

函数参数:

  • 第1个参数:选择ADC。
  • 第2个参数:指定通道,通道0~通道17.
  • 第3个参数:Rank,规则组序列器里的次序,在1~16之间。若只有PA0一个通道,使用的是非扫描模式,那指定的通道就放在第一个序列1的位置。
  • 第4个参数:指定通道的采样时间,采样时间参数根据需求调整,需要更快的转换,就选择小的参数;需要更稳定的转换,就选择大的参数。

        代码示例的配置是:再ADC1中,在规则组菜单列表的第一个位置,写入通道0这个通道,指定通道的采样时间参数选择的采样时间为55.5个ADCCLK的周期。

        如果想在序列2的位置写入其他通道,就可以复制一下这个代码,把序列数改成2,然后指定你想要的通道,若还需要继续填充序列,可以再复制这个函数,修改序列和通道,另外每个通道也可以设置不同的采样时间,在函数最后一个参数修改即可。

2.4 配置ADC转换器

        第四步、用结构体初始化ADC。

代码示例:

    ADC_InitTypeDef ADC_InitStructure;
    ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;//ADC的工作模式
    ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;//数据对齐
    ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//外部触发转换选择
    ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;//连续/单次转换模式
    ADC_InitStructure.ADC_ScanConvMode=DISABLE;//扫描/非扫描转换模式
    ADC_InitStructure.ADC_NbrOfChannel=1;//通道数目

    ADC_Init(ADC1,&ADC_InitStructure);

        ADC_Mode 是ADC的工作模式,这个参数是配置ADC是工作在独立模式还是双ADC模式,代码示例选择独立模式。

        ADC_DataAlign 数据对齐,这里介绍是指定ADC数据是左对齐还是右对齐。

  • ADC_DataAlign_Right右对齐;
  • ADC_DataAlign_Left左对齐 

        ADC_ExternalTrigConv 外部触发转换选择,就是触发控制的触发源,定义用于启动规则组转换的外部触发源。参数对应结构框图中的外部触发源选择。代码示例选择 ADC_ExternalTrigConv_None 参数,就是不使用外部触发,也就是使用内部软件触发的意思。

        ADC_ContinuousConvMode 连续/单次转换模式,这个参数可以选择是ENABLE连续转换模式还是DISABLE单次转换模式。

        ADC_ScanConvMode 扫描/非扫描转换模式,这个参数可以选择是ENABLE扫描模式(多通道)还是DISABLE非扫描模式(单通道)。

        ADC_NbrOfChannel 通道数目,这个是在指定扫描模式下,总共会有几个通道需要扫描,参数必须在1~16之间。这个参数仅在扫描模式下使用,因为非扫描模式整个列表就只有第一个序列有效,无论写多少数目,最终都只有序列1的位置有效。

        后三个参数设置可以对应四种模式:

  • 单次转换非扫描。
  • 连续转换非扫描。
  • 单次转换扫描。
  • 连续转换扫描。

2.5 开启ADC电源

        第五步、开关控制,调用一下ADC_Cmd函数,开启ADC.

代码示例:

ADC_Cmd(ADC1,ENABLE);

        以上配置完后ADC准备就绪。

2.6 ADC进行校准

        在开启ADC电源之后,根据手册的建议,还需要对ADC进行校准,校准分为以下四步。

  1. 复位校准
  2. 等待复位校准完成
  3. 开始校准
  4. 等待校准完成

        2.6.1 复位校准

代码示例:

ADC_ResetCalibration(ADC1);//复位校准

 

        2.6.2 等待复位校准完成

代码示例:

while(ADC_GetResetCalibrationStatus(ADC1)==SET);

        ADC_GetResetCalibrationStatus函数是返回复位校准的状态,要等待复位完成的话,还需要加一个while循环,若没校准完成的话,就在这个while空循环里一直等待。

        获取的标志位和是否校准完成的对应关系需参考函数定义寄存器说明

函数定义:

        ADC_GetResetCalibrationStatus函数定义中返回值的说明是,ADC复位校准寄存器的状态,SET或RESET。

函数代码:

/**
  * @brief  Gets the selected ADC reset calibration registers status.
  * @param  ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
  * @retval The new state of ADC reset calibration registers (SET or RESET).
  */
FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx)
{
  FlagStatus bitstatus = RESET;
  /* Check the parameters */
  assert_param(IS_ADC_ALL_PERIPH(ADCx));
  /* Check the status of RSTCAL bit */
  if ((ADCx->CR2 & CR2_RSTCAL_Set) != (uint32_t)RESET)
  {
    /* RSTCAL bit is set */
    bitstatus = SET;
  }
  else
  {
    /* RSTCAL bit is reset */
    bitstatus = RESET;
  }
  /* Return the RSTCAL bit status */
  return  bitstatus;
}

        在此函数代码中也可以看出来,它获取的就是CR2寄存器里的RSTCAL标志位。

寄存器说明:

        在ADC的CR2寄存器里RSTCAL复位校准位的说明是该位由软件设置并由硬件清除,在校准寄存器被初始化后该位将被清除。

        所以该标志位的用法就是软件置改位为1,那硬件就会开始复位校准,当复位校准完成后,该位就会由硬件自动清0.

        因为校准的第一条代码ADC_ResetCalibration(ADC1);开始复位校准,就是将RSTCAL标志位置1,然后获取复位校准状态,就是读取RSTCAL标志位这一位,所以在读取这一位的时候:

  • 如果它是1,那就需要一直空循环等待;
  • 如果它变为0了,那就说明复位校准完成,可以跳出等待了。

        所以校准第二条代码while(ADC_GetResetCalibrationStatus(ADC1)==SET);while的条件就是,获取标志位函数 ADC_GetResetCalibrationStatus 的返回值是不是==SET,如果等于SET,while条件为真,就会一直空循环。一旦标志位被硬件清0了,这个空循环就会自动跳出来。这样就实现了等待复位校准完成的效果。这里==SET也是可以省略的,因为返回值SET直接作为条件和是不是==SET作为条件效果是一样的。

        2.6.3 开始校准

代码示例:

ADC_StartCalibration(ADC1);

        调用ADC_StartCalibration函数就开始校准了,之后内部电路就会自动进行校准。

2.6.4 等待校准完成

    while(ADC_GetCalibrationStatus(ADC1)==SET);//调用函数获取校准状态

        调用ADC_GetCalibrationStatus函数获取校准状态,也需要将函数放于while循环内,和校准的第二步同理,循环条件是,校准标志位是不是==SET,这样就可以等待校准是否完成了。

三、启动AD转换函数设计

        上文描述的代码设置使ADC已处于准备就绪的状态,以下设计启动转换,获取转换结果的函数块。

        函数块里执行以下流程:

  • 第一步、软件触发转换。
  • 第二步、等待转换完成。
  • 第三步、读取ADC数据寄存器。

3.1 软件触发转换

        调用ADC_SoftwareStartConvCmd函数,实现软件触发。

代码示例:

ADC_SoftwareStartConvCmd(ADC1,ENABLE);

        调用ADC_SoftwareStartConvCmd函数之后就可以触发,ADC就已经开始进行转换了。转换需要一段时间。

3.2 等待转换完成

        等待转换完成,也就是等待EOC标志位置1.

代码示例:

    while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET);

        ADC_GetFlagStatus是获取标志位状态的函数,函数的第二个参数可选择以下参数:

  • ADC_FLAG_AWD: 模拟看门狗标志位
  • ADC_FLAG_EOC: 规则组转换完成标志位
  • ADC_FLAG_JEOC:注入组转换完成标志位
  • ADC_FLAG_JSTRT: 注入组开始转换标志位
  • ADC_FLAG_STRT: 规则组开始转换标志位

        这一步也需要套一个while空循环来实现一个等待的过程,返回标志位与转换是否完成的对应关系需参考函数定义和STM32手册的寄存器说明.

函数定义:

        ADC_GetFlagStatus函数定义中返回值的说明是,ADC状态寄存器的状态,SET或RESET。

函数代码:

/**
  * @brief  Checks whether the specified ADC flag is set or not.
  * @param  ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
  * @param  ADC_FLAG: specifies the flag to check. 
  *   This parameter can be one of the following values:
  *     @arg ADC_FLAG_AWD: Analog watchdog flag
  *     @arg ADC_FLAG_EOC: End of conversion flag
  *     @arg ADC_FLAG_JEOC: End of injected group conversion flag
  *     @arg ADC_FLAG_JSTRT: Start of injected group conversion flag
  *     @arg ADC_FLAG_STRT: Start of regular group conversion flag
  * @retval The new state of ADC_FLAG (SET or RESET).
  */
FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG)
{
  FlagStatus bitstatus = RESET;
  /* Check the parameters */
  assert_param(IS_ADC_ALL_PERIPH(ADCx));
  assert_param(IS_ADC_GET_FLAG(ADC_FLAG));
  /* Check the status of the specified ADC flag */
  if ((ADCx->SR & ADC_FLAG) != (uint8_t)RESET)
  {
    /* ADC_FLAG is set */
    bitstatus = SET;
  }
  else
  {
    /* ADC_FLAG is reset */
    bitstatus = RESET;
  }
  /* Return the ADC_FLAG status */
  return  bitstatus;
}

寄存器说明:

        在ADC状态寄存器里有EOC转换结束标志位,这里获取的就是EOC标志位,EOC标志位由硬件在(规则或注入)通道组转换结束时设置。

        意思是EOC标志位在规则组或注入组完成时都会置1,这一位由软件清除或由读取ADC_DR时清除。

        ADC_DR是数据寄存器,一般EOC标志位置1,程序就会来读取数据,所以EOC标志位就多设计了一个功能,这一位可以在读取数据寄存器之后自动清除,无需手动清除,可以省一条代码。

  • 当EOC标志位为0时,表示转换未完成;
  • 当EOC标志位为1时,表示转换完成。

        所以在代码中,当ADC_GetFlagStatus函数的返回值,也就是EOC标志位==RESET时,转换未完成,while条件为真,执行空循环。转换完成后,EOC由硬件自动置1,while循环自动跳出。这样等待转换完成的代码就OK了。

        具体等待的时间:ADC配置时,通道的采样周期是55.5,转换周期是固定的12.5,加在一起就是68个周期。ADCS时钟配置的ADCCLK是72MHz的6分频,就是12MHz,12MHz进行68个周期,转换才能完成。最终的时间1/12M再×68,结果大概是5.6us,可参考之前博文算转换时间的内容:STM32 ADC数模转换器-CSDN博客

3.3 读取ADC数据寄存器

        等待完成之后就可以取结果了,调用ADC_GetConversionValue函数可取得结果。

代码示例:

    return ADC_GetConversionValue(ADC1);

        ADC_GetConversionValue函数,也就是ADC获取转换值函数的返回值就是AD转换的结果。函数直接读取ADC的DR数据寄存器,因为读取DR寄存器会自动清除EOC标志位,所以在函数之后就不需要手动清除标志位了。

3.4 启动AD转换函数块总结

代码示例:

uint16_t AD_GetValue(void)
{
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);
	while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET);
	return ADC_GetConversionValue(ADC1);
}

        调用一次这个函数块就相当于执行了一次图单次转换,非扫描模式的流程。


总结

        以上就是今天要讲的内容,本文仅仅简单介绍了AD单通道函数设计的步骤和代码含义。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1537786.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构大合集06——树与二叉树的相关函数运算算法

函数运算算法合集06 1、树的基本运算1.1 树的存储结构1.1.1 双亲存储结构1.1.2 孩子链存储结构1.1.3 孩子兄弟链式存储结构 2、二叉树的顺序存储2.1 二叉树顺序存储的结构体2.2 顺序存储的基本思路 3、二叉树的链式存储3.1 二叉树的链式存储的结构体3.2 链式存储的基本算法3.2.…

docker镜像复制与常见命令

一、前言 最近通过阿里的镜像仓库远程拉取镜像,发现以前的版本不见了,拉取了最新的镜像,有发现版本不配问题。那么想使用老版本的镜像那就要从别的环境获取。于是就需要进行离线镜像复制,打包,上传,重新导入…

时序预测 | Matlab实现BiTCN-GRU双向时间卷积神经网络结合门控循环单元时间序列预测

时序预测 | Matlab实现BiTCN-GRU双向时间卷积神经网络结合门控循环单元时间序列预测 目录 时序预测 | Matlab实现BiTCN-GRU双向时间卷积神经网络结合门控循环单元时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现BiTCN-GRU双向时间卷积神经网络结…

Tkinter 一文读懂

Tkinter 简介 Tkinter(即 tk interface,简称“Tk”)本质上是对 Tcl/Tk 软件包的 Python 接口封装,它是 Python 官方推荐的 GUI 工具包,属于 Python 自带的标准库模块,当您安装好 Python 后,就可…

AI新工具(20240322) 免费试用Gemini Pro 1.5;先进的AI软件工程师Devika;人形机器人Apptronik给你打果汁

✨ 1: Gemini Pro 1.5 免费试用Gemini Pro 1.5 Gemini 1.5 Pro是Gemini系列模型的最新版本,是一种计算高效的多模态混合专家(MoE)模型。它能够从数百万个上下文Token中提取和推理细粒度信息,包括多个长文档和数小时的视频、音频…

R语言逻辑回归与lasso模型

一、数据描述 数据集heart_learning.csv与heart_test.csv是关于心脏病的数据集,heart_learning.csv是训练数据集,heart_test.csv是测试数据集。 变量名称变量说明age年龄sex性别,取值1代表男性,0代表女性pain 胸痛的类型&#x…

SQLiteC/C++接口详细介绍sqlite3_stmt类(十二)

返回:SQLite—系列文章目录 上一篇:SQLiteC/C接口详细介绍sqlite3_stmt类(十一) 下一篇: SQLiteC/C接口详细介绍sqlite3_stmt类(十三) 48、sqlite3_stmt_isexplain sqlite3_stmt_is…

Django日志(四)

一、Filters介绍 过滤器用于从logger传递给handler的哪些日志要做额外控制 默认情况下,满足日志级别的任何消息都将处理。只要级别匹配,任何日志消息都会被处理。不过,也可以通过添加 filter 来给日志处理的过程增加额外条件。例如,可以添加一个 filter 只允许某个特定来源…

手机网页关键词视频爬虫采集软件可导出视频分享链接|视频无水印批量下载工具

全新音视频批量下载工具,为您解放视频管理烦恼! 现如今,音上涌现出大量精彩的视频内容,但是要想高效地获取、管理和分享这些视频却是一件颇具挑战的事情。针对这一难题,我们自主研发了全新的音视频批量下载工具&#x…

什么是单点登录?

单点登录(Single Sign On,简称 SSO)简单来说就是用户只需在一处登录,不用在其他多系统环境下重复登录。用户的一次登录就能得到其他所有系统的信任。 为什么需要单点登录 单点登录在大型网站应用频繁,比如阿里旗下有淘…

B-tree - 深度解析+C语言实现+opencv绘图助解

B-tree - 深度解析C语言实现opencv绘图助解 1. 概述2. B-tree介绍3. Btree算法实现3.1 插入3.1.1 排序3.1.2 分裂1) 叶子节点的分裂2) 根节点的分裂(特殊的分裂)3) 内节点的分裂 3.2 删除3.2.1 再平衡(Rebalance)左旋右旋合并 3.2…

蓝桥杯 2022 省B 积木画

这是个典型的动态规划问题,重点在于找到他的递推方程。 可简单算出填满第0 1 2 3 4列个数为0 1 2 5 11; 运气好点,找到递推公式dp[i]2*dp[i-1]dp[i-3]; 直接解决了。 但我们还是按照动态规划一步一步来。 思路分析: 状态定义&a…

css3鼠标悬停图片特效,图片悬停效果源码

特效介绍 css3鼠标悬停图片特效,图片悬停效果源码,可以在网页上面作为自己的动态加载名片,放到侧边栏或者网站合适的位置即可 动态效果 代码下载 css3鼠标悬停图片特效,图片悬停效果源码

docker进阶篇,docker集群介绍

docker swarm 官网:https://docs.docker.com/engine/swarm/how-swarm-mode-works/nodes/ 什么是 docker swarm docker swarm 是 docker 官方提供的容器编排和集群管理工具。它允许用户将多个 docker 主机组成一个虚拟的 docker 集群,以便更高效地管理…

解决用POI库生成的word文件中的表格在python-docx无法解析的问题

问题背景 用apache-poi生成word文件中表格&#xff0c;在使用python-docx库解析时报错&#xff1a; 问题分析 1. word文档本质上是一个rar压缩包&#xff0c;用winrar解析后如下&#xff1a; 2. 查看document.xml&#xff0c;可以看到table元素下面是没有<w:tblGrid>这…

HTTP --- 上

目录 1. HTTP协议 2. 认识URL 2.1. URL中的四个主要字段 2.2. URL Encode && URL Decode 3. HTTP 协议格式 3.1. 快速构建 HTTP 请求和响应的报文格式 3.1.1. HTTP 请求格式 3.1.2. HTTP 响应格式 3.1.3. 关于 HTTP 请求 && 响应的宏观理解 3.2. 实现…

基于PID控制器的四旋翼无人机控制系统的simulink建模与仿真,并输出虚拟现实动画

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1四旋翼无人机的动力学模型 4.2 PID控制器设计 4.3 姿态控制实现 4.4 VR虚拟现实动画展示 5.完整工程文件 1.课题概述 基于PID控制器的四旋翼无人机控制系统的simulink建模与仿真,并输出vr虚拟现实…

CI/CD环境搭建

服务简介 Gitlab 官网&#xff1a;https://about.gitlab.com/ GitLab 是一个用于仓库管理系统的开源项目&#xff0c;使用Git作为代码管理工具&#xff0c;并在此基础上搭建起来的Web服务。安装方法是参考GitLab在GitHub上的Wiki页面。Gitlab是被广泛使用的基于git的开源代码管…

每日一题——LeetCode1720.解码异或后的数组

方法一 异或运算的性质 encoded[i−1]arr[i−1]⊕arr[i] 在等式两边同时异或arr[i−1] 由于&#xff1a; 一个数异或它自己&#xff0c;结果总是0。 0异或任何数&#xff0c;结果都是那个数本身。 所以等式可以转化为&#xff1a; arr[i]arr[i−1]⊕encoded[i−1] 由于 a…

智慧工业园区的物联网解决方案

智慧工业园区的物联网解决方案 智慧工业园区的物联网解决方案&#xff0c;是一种深度融合物联网、大数据、云计算及人工智能等前沿技术&#xff0c;以实现工业园区全方位、智能化管理与服务的综合体系。该方案旨在通过高效采集和分析园区内的各类实时数据&#xff0c;构建出一…