STM32 如何使用DMA和获取ADC
目录
背景
摇杆的原理
程序
端口配置
ADC 配置
DMA配置
背景
DMA是一种计算机技术,允许某些硬件子系统直接访问系统内存,而不需要中央处理器(CPU)的介入,从而减轻CPU的负担。我们可以通过DMA来从外设(ADC、UART等)读取数据之后,搬运到指定的内存。
ADC是根据用户动作或者环境变化会造成传感器等设备的电压值发生变化,再通过STM32的ADC块实现采样、保持、量化、编码将模拟量转换成数据量。
本篇文章会介绍目前无人机常用的摇杆操作(左右、上下、按下等),变为电压值变化,以及STM32 如何实现DMA定期读取遥感ADC值。
摇杆的原理


JS_X:作为X轴方向的模拟信号输入口
JS_Y:作为Y轴方向的模拟信号输入口
JS_D:挥动开关的状态的检测端口
通过原理图可以通过X轴方向滑动可以改变接触点在电阻的位置,从而影响读取到的电压值。Y轴方向亦是同理。因此只需将JS_X和JS_Y的端口设置位模拟量输入端,然后由STM32单片机的ADC块处理。
而按下的操作显然是普通的Port Key, 因此只用将JS_D设置位上拉输入,然后通过读取该端口的状态,来判断是否摇杆被按下。
STM32的DMA通道:STM32系列最多有12个独立可配置的通道,包括DMA1(7个通道)和DMA2(5个通道)。每个通道可以分别设置源地址与目的地址,实现独立工作
程序
端口配置
#define ADC1_DR_Address ((uint32_t)0x4001244C) //ADC1这个外设的地址(查参考手册得出)#define ADCPORT GPIOA //定义ADC接口
#define ADC_CH4 GPIO_Pin_4 //定义ADC接口 电压电位器
#define ADC_CH5 GPIO_Pin_5 //定义ADC接口 光敏电阻
#define ADC_CH6 GPIO_Pin_6 //定义ADC接口 摇杆X轴
#define ADC_CH7 GPIO_Pin_7 //定义ADC接口 摇杆Y轴#define JoyStickPORT GPIOB //定义IO接口组
#define JoyStick_KEY GPIO_Pin_2 //定义IO接口void ADC_GPIO_Init(void){ //GPIO初始化设置GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//使能DMA时钟(用于ADC的数据传送)RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);//使能ADC1时钟GPIO_InitStructure.GPIO_Pin = ADC_CH6 | ADC_CH7; //!!!选择端口 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //选择IO接口工作方式 GPIO_Init(ADCPORT, &GPIO_InitStructure);
}void JoyStick_Init(void){ //摇杆的挥动开关的接口初始化GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO的初始化枚举结构 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE); GPIO_InitStructure.GPIO_Pin = JoyStick_KEY; //选择端口号(0~15或all) GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //选择IO接口工作方式 //上拉电阻 GPIO_Init(JoyStickPORT,&GPIO_InitStructure);
}
1)GPIOA组、GPIOB组、DMA1的外设时钟使能起来(GPIOC组功能用于其他,我们可以忽略它)
2) X轴和Y轴的输入端要设置为模拟量输入端口
3)Port Key 要设置位上拉电阻输入口,因为在没有被按下时,要能读入高电平!
3)初始化端口
ADC 配置
void ADC_Configuration(void){ //初始化设置ADC_InitTypeDef ADC_InitStructure;//定义ADC初始化结构体变量ADC_GPIO_Init();//GPIO初始化设置ADC_DMA_Init();//DMA初始化设置ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//ADC1和ADC2工作在独立模式ADC_InitStructure.ADC_ScanConvMode = ENABLE; //使能扫描ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//ADC转换工作在连续模式ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//有软件控制转换ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//转换数据右对齐ADC_InitStructure.ADC_NbrOfChannel = 2;//!!!顺序进行规则转换的ADC输入口的数目(根据ADC采集通道数量修改)ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器//设置指定ADC的规则组通道,设置它们的转化顺序和采样时间//ADC1,ADC通道x,规则采样顺序值为y,采样时间为28周期 ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 1, ADC_SampleTime_28Cycles5);//!!! ADC1选择信道x,采样顺序y,采样时间n个周期ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 2, ADC_SampleTime_28Cycles5);//!!! ADC1选择信道x,采样顺序y,采样时间n个周期ADC_DMACmd(ADC1, ENABLE);// 开启ADC的DMA支持(要实现DMA功能,还需独立配置DMA通道等参数)ADC_Cmd(ADC1, ENABLE);//使能ADC1ADC_ResetCalibration(ADC1); //重置ADC1校准寄存器while(ADC_GetResetCalibrationStatus(ADC1));//等待ADC1校准重置完成ADC_StartCalibration(ADC1);//开始ADC1校准while(ADC_GetCalibrationStatus(ADC1));//等待ADC1校准完成ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能ADC1软件开始转换
}
常见的ADC数据对齐方式
右对齐(默认情况):这是大多数STM32 ADC寄存器的默认行为。例如,如果你使用12位分辨率的ADC,那么只有最低的12位将被用来存储转换结果,而最高的4位(在16位寄存器中)将会是0。
左对齐:在某些情况下,你可能需要将数据左对齐,这意味着将最高有效位(MSB)放在寄存器的最高位。这通常通过特定的硬件配置或软件操作来实现,比如在某些STM32系列中,可以通过配置ADC寄存器来实现数据的左对齐。
![]()
输入通道数配置,X轴通道和Y轴通道总共两个。
![]()
注册规则组


注册包含通道信息、采样顺序、采样时间。ADC通道通过查阅端口定义可知。
STM32F103C8T6



C8:48pin 64K Flash 属于中容量 SRAM 20K.
查看引脚定义可以知道PA6的ADC通道是6,PA7的通道是7.

使能ADC1的DMA请求
![]()
使能ADC1
![]()
ADC1自校准

软件触发开始ADC1转换
![]()
DMA配置
vu16 ADC_DMA_IN[2]; //ADC数值存放的变量void ADC_DMA_Init(void){ //DMA初始化设置DMA_InitTypeDef DMA_InitStructure;//定义DMA初始化结构体DMA_DeInit(DMA1_Channel1);//复位DMA通道1DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; //定义 DMA通道外设基地址=ADC1_DR_AddressDMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_DMA_IN; //!!!定义DMA通道ADC数据存储器(其他函数可直接读此变量即是ADC值)DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//指定外设为源地址DMA_InitStructure.DMA_BufferSize = 2;//!!!定义DMA缓冲区大小(根据ADC采集通道数量修改)DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//当前外设寄存器地址不变DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//!!! 当前存储器地址:Disable不变,Enable递增(用于多通道采集)DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//定义外设数据宽度16位DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //定义存储器数据宽度16位DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//DMA通道操作模式位环形缓冲模式DMA_InitStructure.DMA_Priority = DMA_Priority_High;//DMA通道优先级高DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//禁止DMA通道存储器到存储器传输DMA_Init(DMA1_Channel1, &DMA_InitStructure);//初始化DMA通道1DMA_Cmd(DMA1_Channel1, ENABLE); //使能DMA通道1
}


由于是从ADC1外设(ADC1的数据寄存器DR)到内存,因此方向配置如下
![]()
DMA设置为循环模式,可以连续多次的从ADC1外设搬运数据到指定内存。
![]()
因为ADC1外设(DR)是16位(ADC分辨率是12位),所以
![]()
DMA1的每个channel用于设置数据源外设和目的地内存地址。因为我们的外设是ADC1。所以我们选择Channel1.
![]()


ADC1的外设的地址



DMA优先级设置为HIGH


![]()
优先级相同情况下,由内部硬件优先级决定!

由于不是内存搬运到内存,故DMA_M2M要设置为Disable
![]()
相关文章:
STM32 如何使用DMA和获取ADC
目录 背景 摇杆的原理 程序 端口配置 ADC 配置 DMA配置 背景 DMA是一种计算机技术,允许某些硬件子系统直接访问系统内存,而不需要中央处理器(CPU)的介入,从而减轻CPU的负担。我们可以通过DMA来从外设…...
【JAVA实战】JAVA实现Excel模板下载并填充模板下拉选项数据
背景 有这样一个场景:前端下载Excel模板,进行数据导入,这个下载模板过程需要经过后端接口去数据库查询数据进行某些列的下拉数据填充,下拉填充的数据过程中会出现错误String literals in formulas can’t be bigger than 255 cha…...
java面试笔记(一)
1. 一万个string类型的数据,设计一个算法如何按照String长度来排序 以使用 Arrays.sort() 方法,并结合一个自定义的比较器。以下是实现的示例代码: public class StringLengthSort {public static void main(String[] args) {// 定义一万个字符串的示例…...
【C++】36.C++IO流
文章目录 1. C语言的输入与输出2. 流是什么3. CIO流3.1 C标准IO流3.2 C文件IO流 4. stringstream的简单介绍 1. C语言的输入与输出 C语言中我们用到的最频繁的输入输出方式就是scanf ()与printf()。 scanf(): 从标准输入设备(键盘)读取数据,并将值存放在变量中。pri…...
Qt5开发入门指南:从零开始掌握跨平台开发
目录 Qt框架概述 开发环境搭建 基础语法与核心机制 第一个Qt窗口程序 常见问题解答 一、Qt框架概述 1.1 什么是Qt? Qt是一个1995年由挪威Trolltech公司开发的跨平台C图形用户界面应用程序框架。最新Qt5版本主要包含: GUI模块:支持Wind…...
Rook-ceph(1.92最新版)
安装前准备 #确认安装lvm2 yum install lvm2 -y #启用rbd模块 modprobe rbd cat > /etc/rc.sysinit << EOF #!/bin/bash for file in /etc/sysconfig/modules/*.modules do[ -x \$file ] && \$file done EOF cat > /etc/sysconfig/modules/rbd.modules &l…...
深度学习在蛋白质-蛋白质相互作用(PPI)领域的研究进展(2022-2025)
一、蛋白质-蛋白质相互作用(PPI)的定义与生物学意义 蛋白质-蛋白质相互作用(Protein-Protein Interaction, PPI)是指两个或多个蛋白质通过物理结合形成复合物,进而调控细胞信号传导、代谢、免疫应答等生命活动的过程。PPI是生物体内复杂功能网络的核心,例如酶与底物的结…...
网络安全学习架构 网络安全架构内容
网上买的《信息安全原理及应用》的书还没到,就找了一本《密码编码学与网络安全》的电子书,写的也不错,计划今天和明天把第一章绪论和第二章的数论给看完 1. 计算机网络安全概念 计算机安全的三个核心是:完整性(只要特…...
硕成C语言24
不管风吹浪打,胜似闲庭信步! 1.选择排序: 不管风吹浪打,胜似闲庭信步!1.选择排序: // 这个宏定义用于忽略 Visual Studio 中一些安全相关的警告,使得可以使用像 scanf 这样的函数而不产生警告…...
《Stable Diffusion绘画完全指南:从入门到精通的Prompt设计艺术》-配套代码示例
第一章:模型加载与基础生成 1.1 基础模型加载 from diffusers import StableDiffusionPipeline import torch# 加载SD 1.5基础模型(FP32精度) pipe StableDiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5",…...
Linux下为Intel核显安装OpenCL
实验环境 CPU:N5105运行内存:32G系统:almalinux 8 (类似CentOS系统) 安装过程 检查i915驱动 输入命令dmesg | grep i915查看驱动的加载信息。 我这里没接显示器,输出正确的驱动加载信息如下图所示&…...
用deepseek学大模型04-机器学习建模过程
https://metaso.cn/s/7tEmBHr 目前已经学完深度学习的数学基础,给出机器学习建模的基本过程 好的,我现在需要回答用户的问题:已经学完深度学习的数学基础,现在要给出机器学习建模的基本过程。我需要结合我搜索到的资料来构建一个详…...
【ClickHouse】Ubuntu下离线安装ClickHouse数据库并使用DBeaver连接
目录 0. 安装前准备1 安装ClickHouse1.1 下载安装包1.2 离线安装1.3 配置密码1.4 启动ClickHouse服务 2 DBeaver连接配置2.1 下载ClickHouse驱动2.2 DBeaver配置2.2.1 配置主要参数2.2.2 配置驱动 2.3 常见问题处理2.3.1 修改远程登录配置2.3.2 更新驱动配置 0. 安装前准备 有…...
Unity3D实现接入DeepSeek对话
系列文章目录 unity知识点 文章目录 系列文章目录👉前言👉一、使用第一步👉1-1、登录注册DeepSeek👉1-2、创建API-key👉二、使用第二步👉三、使用第三步👉壁纸分享👉总结👉前言 随着人工智能和机器学习技术的不断进步,DeepSeek的未来发展趋势充满了无限可能…...
【ISO 14229-1:2023 UDS诊断(会话控制0x10服务)测试用例CAPL代码全解析②】
ISO 14229-1:2023 UDS诊断【会话控制0x10服务】_TestCase02 作者:车端域控测试工程师 更新日期:2025年02月15日 关键词:UDS诊断、0x10服务、诊断会话控制、ECU测试、ISO 14229-1:2023 TC10-002测试用例 用例ID测试场景验证要点参考条款预期…...
前端新手必看:10 大 UI 组件库全面解析,快速搭建高质量 Web 应用」 「从零开始:Vue 和 React 最受欢迎的 UI 组件库入门指南」 「超实用!PC 端和移动端 UI 组件库推荐与实战
前端新手必看:10 大 UI 组件库全面解析,快速搭建高质量 Web 应用 目录 什么是 UI 组件库?为什么需要 UI 组件库?PC 端 UI 组件库推荐 Ant DesignElement UIVuetifyBootstrapVueiView (View UI)Quasar FrameworkMaterial-UI (MUI…...
【MySQL高级】17 - MySQL中常用工具
1. mysql 该mysql不是指mysql服务,而是指mysql的客户端工具。语法: mysql [options] [database]1.1 连接选项 参数 : -u, --username 指定用户名-p, --password[name] 指定密码-h, --hostname 指定服务器IP或域名-P, --por…...
【Linux】Linux 文件系统——有关 inode 不足的案例
ℹ️大家好,我是练小杰,今天周二了,明天星期三,还有三天就是星期五了,坚持住啊各位!!!😆 本文是对之前Linux文件权限中的inode号进行实例讨论,看到博客有错误…...
计算机视觉:卷积神经网络(CNN)基本概念(二)
第一章:计算机视觉中图像的基础认知 第二章:计算机视觉:卷积神经网络(CNN)基本概念(一) 第三章:计算机视觉:卷积神经网络(CNN)基本概念(二) 第四章:搭建一个经典的LeNet5神经网络(附代码) 第五章࿱…...
【第7章:注意力机制与Transformer模型—7.4 NLP领域的BERT、GPT系列模型】
当你在2017年第一次听说Transformer时,可能不会想到这个模型会在短短三年内彻底改变NLP领域。想象一下,原本需要数周训练的翻译模型,现在用Transformer架构几天就能达到更好的效果;那些让程序员们头疼的梯度消失问题,突然变得不再重要。这一切的魔法钥匙,都藏在一个叫做&…...
超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...


