(STM32)ADC驱动配置

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转换
     */
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

初级数据结构——二叉搜索树

目录 前言一、定义二、基本操作三、时间复杂度分析四、变体五、动态图解六、代码模版七、经典例题[1.——700. 二叉搜索树中的搜索](https://leetcode.cn/problems/search-in-a-binary-search-tree/)代码题解 [2.——938. 二叉搜索树的范围和](https://leetcode.cn/problems/ra…

48-基于单片机的LCD12864时间调控和串口抱站

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于51单片机的公交报站系统&#xff0c;可以手动报站&#xff0c;站名十个。 在lcd12864上显示时间&#xff08;年月日时分秒&#xff09;和站名&#xff0c;时间可以设置&#xff0c; 仿真中可以…

云计算的计算包括哪些内容

‌云计算的计算主要包括以下几种类型‌&#xff1a; ‌分布式计算‌&#xff1a;分布式计算是一种计算方法&#xff0c;它将大型问题分解成多个小任务&#xff0c;然后分配给多个计算机进行处理。这种方法可以提高计算效率和可靠性‌1。‌并行计算‌&#xff1a;并行计算是同时…

PICO 获取设备号 SN码

Unity版本 2020.3.42f1c1PICO SDK版本PICO Unity Integration SDK-3.0.5-20241105Pico设备pico 4ultra 注意 此api暂时只测试企业版本 pico 4ultra 代码 using Unity.XR.PICO.TOBSupport;private void Awake() {bool result PXR_Enterprise.InitEnterpriseService();Debug.L…

如何制作项目网页

一、背景 许多论文里经常会有这样一句话Supplementary material can be found at https://hri-eu.github.io/Lami/&#xff0c;这个就是将论文中的内容或者补充视频放到一个网页上&#xff0c;以更好的展示他们的工作。因此&#xff0c;这里介绍下如何使用前人提供的模板制作我…

圆域函数的傅里叶变换和傅里叶逆变换

空域圆域函数的傅里叶变换 空域圆域函数&#xff08;也称为空间中的圆形区域函数&#xff09;通常指的是在二维空间中&#xff0c;以原点为中心、半径为 a a a的圆内取值为1&#xff0c;圆外取值为0的函数。这种函数可以表示为&#xff1a; f ( x , y ) { 1 if x 2 y 2 ≤ …

云技术-docker

声明&#xff01; 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团…

win10中使用ffmpeg的filter滤镜

1 给视频加文字水印 1.1 添加播放时间 ffmpeg -i input.mp4 -vf "drawtextfontfileC\\:/Windows/fonts/consola.ttf:fontsize30:fontcolorwhite:timecode00\:00\:00\:00:rate25:textTCR\::boxcolor0x000000AA:box1:x20:y20" -y output.mp4 在视频的x20:y20位置添加t…

MyBatis事务管理-附案例代码

一、MyBatis事务管理 SqlSession对象 getMapper(DAO.class)&#xff1a;获取Mapper&#xff08;DAO接口的实体类&#xff09;事务管理 1.1 手动提交事务 手动事务管理 当我们获取sqlSession对象时&#xff0c;就默认开启了事务; 当一系列业务操作完成之后&#xff0c;我们需要…

QChart数据可视化

目录 一、QChart基本介绍 1.1 QChart基本概念与用途 1.2 主要类的介绍 1.2.1 QChartView类 1.2.2 QChart类 1.2.3QAbstractSeries类 1.2.4 QAbstractAxis类 1.2.5 QLegendMarker 二、与图表交互 1. 动态绘制数据 2. 深入数据 3. 缩放和滚动 4. 鼠标悬停 三、主题 …

互联网视频推拉流EasyDSS视频直播点播平台视频转码有哪些技术特点和应用?

视频转码本质上是一个先解码再编码的过程。在转码过程中&#xff0c;原始视频码流首先被解码成原始图像数据&#xff0c;然后再根据目标编码标准、分辨率、帧率、码率等参数重新进行编码。这样&#xff0c;转换前后的码流可能遵循相同的视频编码标准&#xff0c;也可能不遵循。…

黑马程序员Java项目实战《苍穹外卖》Day01

苍穹外卖-day01 课程内容 软件开发整体介绍苍穹外卖项目介绍开发环境搭建导入接口文档Swagger 项目整体效果展示&#xff1a; ​ 管理端-外卖商家使用 ​ 用户端-点餐用户使用 当我们完成该项目的学习&#xff0c;可以培养以下能力&#xff1a; 1. 软件开发整体介绍 作为一…

使用phpStudy小皮面板模拟后端服务器,搭建H5网站运行生产环境

一.下载安装小皮 小皮面板官网下载网址&#xff1a;小皮面板(phpstudy) - 让天下没有难配的服务器环境&#xff01; 安装说明&#xff08;特别注意&#xff09; 1. 安装路径不能包含“中文”或者“空格”&#xff0c;否则会报错&#xff08;例如错误提示&#xff1a;Cant cha…

No.1 杀戮尖塔Godot复刻|项目概述|场景设置

项目概述 含有47个脚本文件&#xff0c;包括1185行代码&#xff0c;最长的脚本有111行 Battle Node——战斗节点 start_battle()——开始战斗turn management——管理回合win/lose conditions——识别输赢条件 EnemyHandler——敌人处理程序 enemy turn management——管理…

化工专业如何转软工

在当今数字化时代&#xff0c;跨考软件工程已经成为许多理工科学子的一个重要选择。化工专业的同学有着扎实的理工科基础&#xff0c;尤其是数学功底&#xff0c;这对于转向计算机领域是一个天然的优势。让我们详细探讨如何规划这段跨考之路。 编程语言的选择是入门的第一步。…

《Opencv》基础操作<1>

目录 一、Opencv简介 主要特点&#xff1a; 应用领域&#xff1a; 二、基础操作 1、模块导入 2、图片的读取和显示 &#xff08;1&#xff09;、读取 &#xff08;2&#xff09;、显示 3、 图片的保存 4、获取图像的基本属性 5、图像转灰度图 6、图像的截取 7、图…

论文阅读:A Software Platform for Manipulating theCamera Imaging Pipeline

论文代码开源链接&#xff1a; A Software Platform for Manipulating the Camera Imaging Pipelinehttps://karaimer.github.io/camera-pipeline/摘要&#xff1a;论文提出了一个Pipline软件平台&#xff0c;可以方便地访问相机成像Pipline的每个阶段。该软件允许修改单个模块…

ChatGPT的应用场景:开启无限可能的大门

ChatGPT的应用场景:开启无限可能的大门 随着人工智能技术的快速发展,自然语言处理领域迎来了前所未有的突破。其中,ChatGPT作为一款基于Transformer架构的语言模型,凭借其强大的语言理解和生成能力,在多个行业和场景中展现出了广泛的应用潜力。以下是ChatGPT八个最具代表…

音视频-什么是帧,视频为什么要编码

帧就是动画中的一张图片&#xff0c;这相当于电影胶片上的一个镜头&#xff0c;一帧就是一幅静止的画面&#xff0c;连续的帧就形成了我们看到的动画和视频。 但是直接采集后没经过处理的视频&#xff0c;其实是没有办法真正在互联网上进行传输的。以一张1920乘1080的图片为例&…

“蜀道山”高校联合公益赛 Web (部分)

文章目录 奶龙牌WAF海关警察训练平台恶意代码检测器 奶龙牌WAF <?php if ($_SERVER[REQUEST_METHOD] POST && isset($_FILES[upload_file])) {$file $_FILES[upload_file];if ($file[error] UPLOAD_ERR_OK) {$name isset($_GET[name]) ? $_GET[name] : basen…