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架构几天就能达到更好的效果;那些让程序员们头疼的梯度消失问题,突然变得不再重要。这一切的魔法钥匙,都藏在一个叫做&…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...

练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...

基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...
LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用
中达瑞和自2005年成立以来,一直在光谱成像领域深度钻研和发展,始终致力于研发高性能、高可靠性的光谱成像相机,为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...
WEB3全栈开发——面试专业技能点P7前端与链上集成
一、Next.js技术栈 ✅ 概念介绍 Next.js 是一个基于 React 的 服务端渲染(SSR)与静态网站生成(SSG) 框架,由 Vercel 开发。它简化了构建生产级 React 应用的过程,并内置了很多特性: ✅ 文件系…...
书籍“之“字形打印矩阵(8)0609
题目 给定一个矩阵matrix,按照"之"字形的方式打印这个矩阵,例如: 1 2 3 4 5 6 7 8 9 10 11 12 ”之“字形打印的结果为:1,…...