(STM32)ADC驱动配置

news2024/11/24 5:40:16

1.ADC驱动(STM32)

ADC模块中,**常规模式(Regular Mode)和注入模式(Injected Mode)**是两种不同的ADC工作模式

常规模式:用于普通的ADC转换,是默认的ADC工作模式。

注入模式:用于对特定通道进行高优先级的ADC采样。

特性

常规模式(Regular Mode)

注入模式(Injected Mode)

优先级

采样通道

支持多通道,按顺序扫描

支持多通道,但专用优先处理

DMA的兼容性

支持,适合连续采样传输

通常不使用 DMA

场景

采集温度、湿度等非关键的环境传感器数据

采集电流、电压等高优先级的实时数据

1.1 常规模式

  1. 转换触发方式:软件启动或者外部硬件触发(比如使用函数开启读取数据这种)

  2. 数据转换完存储在ADC的数据寄存器(ADC_DR)中(这个知道就行,平常也用不到)

  3. 支持、适合使用DMA进行连续数据传输

  4. 可配置扫描模式,对多个通道依次采样

  5. 转换通道数可以通过 NbrOfConversion 配置

1.1.1 初始化代码

下面的代码按照:配置ADC参数、初始化ADC、启动校准、配置常规模式的参数、写入常规通道顺序写的

int32_t stm32_adc_init(void)
{
    // 定义ADC配置结构体(常规模式)
    ADC_ChannelConfTypeDef sConfig = {0};

    // 初始化ADC3的实例
    hadc3.Instance = ADC3;

    // 配置ADC的初始化参数
    hadc3.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV4;          // 异步时钟分频因子设为4
    hadc3.Init.Resolution = ADC_RESOLUTION_12B;               // 分辨率为12位
    hadc3.Init.DataAlign = ADC3_DATAALIGN_RIGHT;              // 数据右对齐
    hadc3.Init.ScanConvMode = ADC_SCAN_ENABLE;                // 启用扫描模式
    hadc3.Init.EOCSelection = ADC_EOC_SINGLE_CONV;            // 每次单次转换结束触发EOC
    hadc3.Init.LowPowerAutoWait = DISABLE;                    // 禁用低功耗模式
    hadc3.Init.ContinuousConvMode = DISABLE;                  // 禁用连续转换模式(单次模式)
    hadc3.Init.NbrOfConversion = 2;                           // 常规模式中转换2个通道
    hadc3.Init.DiscontinuousConvMode = DISABLE;               // 禁用不连续模式
    hadc3.Init.DMAContinuousRequests = ENABLE;                // 启用DMA连续请求
    hadc3.Init.SamplingMode = ADC_SAMPLING_MODE_NORMAL;        // 使用普通采样模式
    hadc3.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR; // 数据直接存储到数据寄存器
    hadc3.Init.Overrun = ADC_OVR_DATA_PRESERVED;              // 数据溢出时保持旧数据
    hadc3.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;          // 禁用左移位操作
    hadc3.Init.OversamplingMode = DISABLE;                    // 禁用过采样

    // 初始化ADC,检查初始化是否成功
    if (HAL_ADC_Init(&hadc3) != HAL_OK)
    {
        Error_Handler();  // 如果失败,调用错误处理函数
    }

    // 启动ADC校准
    HAL_ADCEx_Calibration_Start(&hadc3, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED);

    // 配置第1个通道:通道0
    sConfig.Channel = ADC_CHANNEL_0;                          // 通道0
    sConfig.Rank = ADC_REGULAR_RANK_1;                        // 常规序列中的第1个通道
    sConfig.SamplingTime = ADC_SAMPLETIME_810CYCLES_5;         // 采样时间为810.5周期
    sConfig.SingleDiff = ADC_SINGLE_ENDED;                    // 单端输入模式
    sConfig.OffsetNumber = ADC_OFFSET_NONE;                   // 不使用偏移校正
    sConfig.Offset = 0;                                       // 偏移量为0
    if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
    {
        Error_Handler();  // 如果配置失败,调用错误处理函数
    }

    // 配置第2个通道:通道1
    sConfig.Channel = ADC_CHANNEL_1;                          // 通道1
    sConfig.Rank = ADC_REGULAR_RANK_2;                        // 常规序列中的第2个通道
    if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
    {
        Error_Handler();  // 如果配置失败,调用错误处理函数
    }
    
    // 开启ADC转换,通常在主程序中启动
    HAL_ADC_Start(&hadc3);

    return 0;  // 返回0表示初始化成功
}

1.2 注入模式

  1. 转换触发方式:常规一样,但是独立于常规模式的触发,可以在任意时间插入采样

  2. 注入模式启动,会中断常规模式转换,优先完成注入模式的采样

  3. 通常不使用 DMA

  4. 转换结果存储在专用的注入数据寄存器(ADC_JDRx)中

  5. 每次触发可以采样一个或多个通道(InjectedNbrOfConversion 用于配置注入通道数)。

1.2.1 CUBEMX中的配置(参考)

可以通过配置CUBEMX中的配置进行参考,这里也使用的是注入模式的三个通道,IN0 1 和Temperature,这个当作参考,代码我删了一个通道。

其中IN1的single-ended表示的是:ADC 只采集输入信号相对于地的电压值(单端输入),比如VCC是3.3V,GND是0V,那么输入信号0V--->ADC读取0,输入信号3.3V--->ADC读取4095(分辨率12位)。看配置模块的要求,信号直接连接。

还有一个是differential模式(差分模式):采取差分信号进行读取数据,抗干扰能力强。这个除非使用的是差分信号接口才选择这个

 

1.2.2 初始化代码

下面的代码按照:配置ADC参数、初始化ADC、启动校准、配置注入模式的参数、写入注入通道顺序写的

int32_t stm32_adc_init(void)
{
    // 定义并初始化一个注入模式配置结构体变量
    ADC_InjectionConfTypeDef sConfigInjected = {0};

    // 初始化ADC3的实例
    hadc3.Instance = ADC3;

    // 配置ADC的初始化参数
    hadc3.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV4;          // 异步时钟分频因子设为4
    hadc3.Init.Resolution = ADC_RESOLUTION_12B;               // 分辨率为12位
    hadc3.Init.DataAlign = ADC3_DATAALIGN_RIGHT;              // 数据右对齐
    hadc3.Init.ScanConvMode = ADC_SCAN_ENABLE;                // 启用扫描模式
    hadc3.Init.EOCSelection = ADC_EOC_SINGLE_CONV;            // 每次单次转换结束触发EOC
    hadc3.Init.LowPowerAutoWait = DISABLE;                    // 禁用低功耗模式
    hadc3.Init.ContinuousConvMode = DISABLE;                  // 禁用连续转换模式
    hadc3.Init.NbrOfConversion = 1;                           // 常规模式中转换数量为1
    hadc3.Init.DiscontinuousConvMode = DISABLE;               // 禁用不连续模式
    hadc3.Init.DMAContinuousRequests = DISABLE;               // 禁用DMA连续请求
    hadc3.Init.SamplingMode = ADC_SAMPLING_MODE_NORMAL;        // 使用普通采样模式
    hadc3.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR; // 数据直接存储到数据寄存器
    hadc3.Init.Overrun = ADC_OVR_DATA_PRESERVED;              // 数据溢出时保持旧数据
    hadc3.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;          // 禁用左移位操作
    hadc3.Init.OversamplingMode = DISABLE;                    // 禁用过采样

    // 初始化ADC,检查初始化是否成功
    if (HAL_ADC_Init(&hadc3) != HAL_OK)
    {
        Error_Handler();  // 如果失败,调用错误处理函数
    }

    // 启动ADC校准,使用偏移校准和单端模式
    HAL_ADCEx_Calibration_Start(&hadc3, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED);

    // 配置注入通道的第一个通道:通道0
    sConfigInjected.InjectedChannel = ADC_CHANNEL_0;                  // 注入通道为0
    sConfigInjected.InjectedRank = ADC_REGULAR_RANK_1;                // 注入序列中的第1个通道
    sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_810CYCLES_5; // 采样时间为810.5周期
    sConfigInjected.InjectedSingleDiff = ADC_SINGLE_ENDED;            // 单端输入模式
    sConfigInjected.InjectedOffsetNumber = ADC_OFFSET_NONE;           // 不使用偏移校正
    sConfigInjected.InjectedOffset = 0;                               // 偏移量为0
    sConfigInjected.InjectedNbrOfConversion = 2;                      // 注入模式中有2个通道
    sConfigInjected.InjectedDiscontinuousConvMode = DISABLE;          // 禁用注入的不连续模式
    sConfigInjected.AutoInjectedConv = DISABLE;                       // 禁用自动注入
    sConfigInjected.QueueInjectedContext = DISABLE;                   // 禁用注入上下文队列
    sConfigInjected.ExternalTrigInjecConv = ADC_INJECTED_SOFTWARE_START; // 使用软件触发注入模式
    sConfigInjected.ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONV_EDGE_NONE; // 无触发边沿
    sConfigInjected.InjecOversamplingMode = DISABLE;                  // 禁用注入模式的过采样

    // 配置第一个注入通道
    if (HAL_ADCEx_InjectedConfigChannel(&hadc3, &sConfigInjected) != HAL_OK)
    {
        Error_Handler();  // 如果配置失败,调用错误处理函数
    }

    // 配置第二个注入通道:通道1
    sConfigInjected.InjectedChannel = ADC_CHANNEL_1;          // 注入通道为1
    sConfigInjected.InjectedRank = ADC_INJECTED_RANK_2;       // 注入序列中的第2个通道
    if (HAL_ADCEx_InjectedConfigChannel(&hadc3, &sConfigInjected) != HAL_OK)
    {
        Error_Handler();  // 如果配置失败,调用错误处理函数
    }

    // 开始注入模式的转换
    HAL_ADCEx_InjectedStart(&hadc3);

    return 0;  // 返回0表示初始化成功
}

1.3 使用

配置完初始化之后,可以通过以下方式调用读取:这里用的是轮询模式,即阻塞模式读取;还可以用DMA(配置有一点区别,函数中调用不同的函数开启,适合连续采样)、和中断方式(实时处理采样数据,转换完成时触发中断,将采集的函数放在中断回调函数里面,通常用这个)。

#include "main.h"

int main(void)
{
    HAL_Init();                  // 初始化HAL库
    SystemClock_Config();        // 配置系统时钟
    stm32_adc_init();           // 初始化ADC注入模式

    uint32_t values[3]; // 用于存储3个注入通道的ADC值

    while (1)
    {
    /*注入模式:
        // 触发注入模式转换(软件触发)
        HAL_ADCEx_InjectedStart(&hadc3);
        // 等待转换完成(注入模式支持轮询方式)
        if (HAL_ADCEx_PollForInjectedConversion(&hadc3, HAL_MAX_DELAY) == HAL_OK)
        {
            // 从注入数据寄存器中读取结果
            values[0] = HAL_ADCEx_InjectedGetValue(&hadc3, ADC_INJECTED_RANK_1);
            values[1] = HAL_ADCEx_InjectedGetValue(&hadc3, ADC_INJECTED_RANK_2);
        }
     */
     /*常规模式:
        // 启动ADC
        HAL_ADC_Start(&hadc3);
        // 等待转换完成(轮询模式)
        for (uint32_t i = 0; i < 2; i++)
        {
            // 等待当前通道转换完成
            if (HAL_ADC_PollForConversion(&hadc3, HAL_MAX_DELAY) == HAL_OK)
            {
                // 读取当前通道的转换值
                adc_values[i] = HAL_ADC_GetValue(&hadc3);
            }
        }
        HAL_ADC_Stop(&hadc3); // 停止ADC转换
     */
    }
}

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

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

相关文章

flume-将日志采集到hdfs

看到hdfs大家应该做什么&#xff1f; 是的你应该去把集群打开&#xff0c; cd /export/servers/hadoop/sbin 启动集群 ./start-all.sh 在虚拟机hadoop02和hadoop03上的conf目录下配置相同的日志采集方案&#xff0c;‘ cd /export/servers/flume/conf 切换完成之后&#…

机器人SLAM建图与自主导航:从基础到实践

前言 这篇文章我开始和大家一起探讨机器人SLAM建图与自主导航 &#xff0c;在前面的内容中&#xff0c;我们介绍了差速轮式机器人的概念及应用&#xff0c;谈到了使用Gazebo平台搭建仿真环境的教程&#xff0c;主要是利用gmapping slam算法&#xff0c;生成一张二维的仿真环境…

在线解析工具链接

在线字数统计工具-统计字符字节汉字数字标点符号-计算word文章字数字数统计,字符统计,字节统计,字数计算,统计字数,统计字节数,统计字符数,统计word字数,在线字数统计,在线查字数,计算字数,字数统计工具,支持手机移动端查询多少字数,英文:Calculate the number of words,Count …

学习Servlet(含义,作用)

目录 前言 Servlet 的含义 Servlet 的作用 前言 一个完整的前后端项目&#xff0c;是需要前端和后端&#xff08;Java实现&#xff09;共同完成的。那应该如何实现前后端进行交互呢&#xff1f;答案&#xff1a;使用Servlet实现前后端交互 我会从了解Servlet的含义&…

从源码到应用:在线教育系统与教培网校APP开发实战指南

时下&#xff0c;各类教培网校APP逐渐成为教育机构的核心工具。那么&#xff0c;如何从源码出发&#xff0c;开发一套符合需求的在线教育系统与教培网校APP&#xff1f;本文将从架构设计、功能实现到部署上线&#xff0c;提供一份全面的开发实战指南。 一、在线教育系统的核心架…

Pyqt5的簡單教程

簡介 pyqt5是qt的Python版本&#xff0c;因為最近需要做一個有界面的程式&#xff0c;所以想到這個庫&#xff0c;這裡就稍微介紹它的安裝和使用教程 1.安裝qt5 可能需要安裝vs的c編譯組件 pip install pyQt52.使用拖拽組件編寫頁面 使用此工具打開組件 ctrls 生成.ui文件 …

---Arrays类

一 java 1.Arrays类 1.1 toString&#xff08;&#xff09; 1.2 arrays.sort( )-----sort排序 1&#xff09;直接调用sort&#xff08;&#xff09; Arrays.sort() 方法的默认排序顺序是 从小到大&#xff08;升序&#xff09;。 2&#xff09;定制排序【具体使用时 调整正负…

STM32F4----ADC模拟量转换成数字量

STM32F4----ADC模拟量转换成数字量 基本原理 当需要测量和记录外部电压的变化&#xff0c;或者根据外部电压的变化量来决定是否触发某个动作时&#xff0c;我们可以使用ADC&#xff08;模拟—数字转换器&#xff09;功能。这个功能可以将模拟的电压信号转换为数字信号&#x…

《Python 股票交易分析:开启智能投资新时代》(二)

Python 进行股票交易分析的优势 简洁易读&#xff1a;Python 的语法简洁明了&#xff0c;即使是编程新手也能较快上手&#xff0c;降低了股票交易分析的门槛。 Python 的简洁易读是其在股票交易分析中受欢迎的重要原因之一。Python 的语法简洁明了&#xff0c;与其他编程语言相…

python程序的编写以及发布(形象类比)

最近重新接触python&#xff0c;本人之前对于python的虚拟环境&#xff0c;安装包比较比较迷惑&#xff0c;这里给出一个具象的理解。可以将 Python 程序运行的过程类比成一次 做菜的过程&#xff0c;从准备食材到最后出锅。以下是具体的类比步骤&#xff1a; 1. 安装 Python 环…

ThinkPad t61p 作SMB服务器,打印服务器,pc ,android ,ipad利用此服务器互传文件

1.在t61p上安装win7 2,配置好smb 服务 3.再安装好打印驱动程序 4.pc与win7利用系统的网络互相发现,映射为硬盘使用。 5.android&#xff0c;ipad安装ES文件浏览器访问win7 共享文件夹&#xff0c;互传文件。 6.android手机安装FE文件浏览器&#xff0c;可以利用花生壳外网…

C# 属性 学习理解记录

字段和属性 左边字段&#xff0c;右边属性 拓展&#xff0c;属性安全&#xff1a; 1、设置public private 和protected 等&#xff0c;只读&#xff0c;只写&#xff0c; 2、在get set 方法时&#xff0c;验证&#xff0c;异常时抛出错误

决策树分类算法【sklearn/决策树分裂指标/鸢尾花分类实战】

决策树分类算法 1. 什么是决策树&#xff1f;2. DecisionTreeClassifier的使用&#xff08;sklearn&#xff09;2.1 算例介绍2.2 构建决策树并实现可视化 3. 决策树分裂指标3.1 信息熵&#xff08;ID3&#xff09;3.2 信息增益3.3 基尼指数&#xff08;CART&#xff09; 4. 代码…

CentOS使用中遇到的问题及解决方法

一、CentOS 7网络配置&#xff08;安装后无法联网问题&#xff09; 现象说明 在安装CentOS系统后&#xff0c;有可能出现无法联网的问题&#xff0c;虚拟机中的网络配置并没有问题&#xff0c;而系统却无法联网,也ping不通。 原因描述 CentOS默认开机不启动网络&#xff0c;因…

硬件知识 cadence16.6 原理图输出为pdf 网络名下划线偏移 (ORCAD)

1. cadence原理图输出为PDF网络名下划线偏移 生这种情况的原因 1. 设计的原理图图纸大小比正常的 A4图纸大。 2. 打印为PDF 的时候&#xff0c;打印机的设置有问题。 2.cadence原理图输出为 PDF网络名下划线偏移的情况 可以看到上图&#xff0c;网络名往上漂移。 3. 解决办法 …

Hash table类算法【leetcode】

哈希表中关键码就是数组的索引下标&#xff0c;然后通过下标直接访问数组中的元素 那么哈希表能解决什么问题呢&#xff0c;一般哈希表都是用来快速判断一个元素是否出现集合里。 例如要查询一个名字是否在这所学校里。 要枚举的话时间复杂度是O(n)&#xff0c;但如果使用哈希…

利用c语言详细介绍下希尔排序

希尔排序是针对插入排序的优化算法。它是缩少增量的算法&#xff0c;一开始增量从元素个数len/2的增量开始&#xff0c;然后缩小增量gapgap/2&#xff0c;直到gap为1&#xff0c;最终完成序列排序。 一、图文介绍 我们还是使用数组【10&#xff0c;5&#xff0c;3&#xff0c;2…

Flutter踩坑记录(三)-- 更改入口执行文件

我们在flutter 中可能不习惯默认的lib/main.dart 作为入口文件&#xff0c;会修改成index.dart 或者修改main.dart的位置, 用Andorid studio开发 如果我们用Andorid studio开发&#xff0c;默认修改一下配置地址 运行项目即可。 用VSCode开发 如果我们使用VSCode开发&…

C#桌面应用制作计算器进阶版01

基于C#桌面应用制作计算器做出了少量改动&#xff0c;其主要改动为新增加了一个label控件&#xff0c;使其每一步运算结果由label2展示出来&#xff0c;而当点击“”时&#xff0c;最终运算结果将由label1展示出来&#xff0c;此时label清空。 修改后运行效果 修改后全篇代码 …

应用商店双弹窗“APP在向用户申请权限时未同步告知用户申请此权限的理由”驳回uni-app应用上线的解决方法

目录 问题分析 解决方法 下载插件包&#xff1a;x-perm-apply-instr 将插件包导入进你项目中的uni_modules文件夹 在项目中的main.js文件中添加以下代码 完成 其它注意事项 addPermisionInterceptor 添加 uniApi 调用拦截 removePermisionInterceptor 移除 uniApi 调用…