【STM32】进阶(二):DMA+ADC实现模拟量检测
1、简述
DMA:Direct Memory Access,直接内存访问
ADC:Analog to Digital Converter,模数转换器,模拟信号转换成数字信号的电路(采样-量化-编码)
参考博客:
STM32DMA功能详解
STM32F4之ADC介绍
DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。这里的存储器可以是片内的SRAM(默认存放变量)或者是FLASH(默认存放常量,被const修饰的全局变量可以看成是常量类型),而外设指的其实是外设的数据寄存器。但它们本质上是一样的,都是从内存的某一区域传输到内存的另一区域(外设的数据寄存器本质上就是内存的一个存储单元)。
我们知道CPU有转移数据、计算、控制程序转移等很多功能,系统运作的核心就是CPU,CPU无时不刻的在处理着大量的事务,但有些事情却没有那么重要,比方说数据的复制和存储数据,DMA的主要功能是用来搬数据,在传输数据的时候,CPU就可以不被占用用来干其他事情,对于实时性要求比较高的场合,我们可以利用DMA来减小CPU的负担。
因此:转移数据(尤其是转移大量数据)是可以不需要CPU参与。比如希望外设A的数据拷贝到外设B,只要给两种外设提供一条数据通路,直接让数据由A拷贝到B不经过CPU的处理,通过DMA解决大量数据转移过度消耗CPU资源的问题。
2、模拟量检测
2.1 初始化步骤
模拟量检测,需要将GPIO引脚设置为模拟输入模式、设置模数转换ADC、设置DMA等,完整初始化步骤如下
初始化时钟
初始化GPIO
初始化ADC
初始化DMA
使能ADC
使能DMA
2.2 初始化时钟
void RCC_Configuration(void)
{# a) DMA1 的时钟RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); # b) 使能GPIO 和 ADC1 的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1, ENABLE );# c) 因为ADC时钟不要超过14M,否则精度会下降,因此设置ADC分频因子=6,即72M/6=12MRCC_ADCCLKConfig(RCC_PCLK2_Div6);
}
2.3 初始化GPIO
void GPIO_Configuration(void)
{GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; # a)将引脚设置为模拟输入引脚GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);
}
2.4 初始化ADC
void ADC1_Configuration(void)
{ADC_InitTypeDef ADC_InitStructure;# a)将外设ADC1的全部寄存器重设为缺省值ADC_DeInit(ADC1); # b)设置为独立工作模式(ADC1和ADC2工作在独立模式)ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; # c)使能扫描模式ADC_InitStructure.ADC_ScanConvMode =ENABLE; # d)连续转换模式ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; # e)关闭外部触发转换ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; # f)ADC数据右对齐ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; # g)按顺序规划转换的 ADC 通道的数目ADC_InitStructure.ADC_NbrOfChannel = M; ADC_Init(ADC1, &ADC_InitStructure); # h)设置转换顺序和时间ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5 );# i)使能 ADC 的 DMA功能ADC_DMACmd(ADC1, ENABLE);# j)使能指定ADC,这里是ADC1ADC_Cmd(ADC1, ENABLE);# k)复位指定 ADC1 的校准寄存器ADC_ResetCalibration(ADC1); # l)等待完成复位校准寄存器while(ADC_GetResetCalibrationStatus(ADC1)); # m)开始指定 ADC1 的校准状态ADC_StartCalibration(ADC1); /# n)等待获取 ADC1 的校准状态while(ADC_GetCalibrationStatus(ADC1));
}
2.5 初始化DMA
void DMA_Configuration(void)
{DMA_InitTypeDef DMA_InitStructure;# a)将 DMA 的通道1寄存器重置为缺省值DMA_DeInit(DMA1_Channel1); # b)DMA 外设基地址指向 ADC1DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->DR; # c)设置内存基地址DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&AD_Value;# d)将内存作为数据传输的目的地 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; # e)DMA 的缓存大小DMA_InitStructure.DMA_BufferSize = N*M; # f)外设地址寄存器不变DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;# g)内存地址寄存器递增DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;# h)外设数据宽度为16位DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;# i)内存数据宽度为16位DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; # j)循环缓存模式DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;# k)高优先级DMA_InitStructure.DMA_Priority = DMA_Priority_High;# l)这里是外设到内存直接传输,因此关闭内存到内存模式DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;DMA_Init(DMA1_Channel1, &DMA_InitStructure);
}
2.6 使能ADC 和 DMA
ADC_SoftwareStartConvCmd(ADC1, ENABLE);DMA_Cmd(DMA1_Channel1, ENABLE);
2.7 使用数据
使能后,从ADC1采集的模数转换后的值将循环存储在数组AD_Value中,对AD_Value中数据求平均值即可
#define N 50
#define M 1
vu16 AD_Value[N][M];
vu16 After_filter[M];
int i;void filter(void)
{int sum = 0;u8 count;for ( count=0;count<N;count++){sum += AD_Value[count][0];}After_filter[0]=sum/N;sum=0;
}
3、时钟设置小结
3.1 GPIO作为输出时
如:点亮LED灯实验时,开启GPIOB的时钟:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIO,ENABLE);
3.2 GPIO作为输入时(轮询方式)
如:按键实验,将PA0作为按键
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
3.3 GPIO作为输入时(中断方式)
如:按键实验,将PC13作为按键,以中断方式打开,需要打开复用时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO,ENABLE);
3.4 配置串口UASRT
需要先设置引脚的时钟,然后设置串口的时钟。
如:配置UASRT1时,用到了PA9和PA10,所有要开启GPIOA的时钟,另外还有开启USART1的时钟。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
3.5 配置DMA
DMA挂载在AHB总线上
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
3.6 配置基本定时器
基本定时器挂载在APB1总线上
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE);
3.7 配置通用定时器
通用定时器挂载在APB1总线上。
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
3.8 其它注意事项
1)配置按键中断时,只需要开启相应的GPIO的时钟。初始化EXTI结构体时,不需要开启EXTI时钟。
2)配置NVIC中断向量控制器时,不需要开启时钟。
3)使用SysTick系统定时器时,不需要开启时钟。
相关文章:
【STM32】进阶(二):DMA+ADC实现模拟量检测
1、简述 DMA:Direct Memory Access,直接内存访问 ADC:Analog to Digital Converter,模数转换器,模拟信号转换成数字信号的电路(采样-量化-编码) 参考博客: STM32DMA功能详解 STM32…...
Lab2_Simple Shell_2020
Lab2: 实验目的:给xv6添加新的系统调用 并理解系统调用是如何工作的,并理解xv6内核的一些内部特征 实验准备: 阅读xv6的第2章以及第4章的4.3,4.3小节熟悉下面的源码 用户态相关的代码:user/user.h和user/usys.pl内核态相关的代…...
2023最全电商API接口 高并发请求 实时数据 支持定制 电商数据 买家卖家数据
电商日常运营很容易理解,就是店铺商品维护,上下架,评价维护,库存数量,协助美工完成制作详情页。店铺DSR,好评率,提升客服服务等等,这些基础而且每天都必须做循环做的工作。借助电商A…...
MySQL 的索引类型
1. 按照功能划分 按照功能来划分,索引主要有四种: 普通索引唯一性索引主键索引全文索引 普通索引就是最最基础的索引,这种索引没有任何的约束作用,它存在的主要意义就是提高查询效率。 普通索引创建方式如下: CREATE…...
< Linux > 进程信号
目录 1、信号入门 生活角度的信号 技术应用角度的信号 前台进程 && 后台进程 信号概念 用kill -l命令察看系统定义的信号列表 信号处理的方式 2、信号产生前 用户层产生信号的方式 3、产生信号 3.1、通过终端按键产生信号 3.2、核心转储core dump 3.3、调用系统函数…...
Pyspark基础入门7_RDD的内核调度
Pyspark 注:大家觉得博客好的话,别忘了点赞收藏呀,本人每周都会更新关于人工智能和大数据相关的内容,内容多为原创,Python Java Scala SQL 代码,CV NLP 推荐系统等,Spark Flink Kafka Hbase Hi…...
C/C++每日一练(20230307)
目录 1. 国名排序 ★★ 2. 重复的DNA序列 ★★★ 3. 买卖股票的最佳时机 III ★★★ 🌟 每日一练刷题专栏 C/C 每日一练 专栏 Python 每日一练 专栏 1. 国名排序 小李在准备明天的广交会,明天有来自世界各国的客房跟他们谈生意,…...
一条SQL查询语句是如何执行的?
平时我们使用数据库,看到的通常都是一个整体。比如,你有个最简单的表,表里只有一个ID字段,在执行下面这个查询语句时: mysql> select * from T where ID10; 我们看到的只是输入一条语句,返…...
tcsh常用配置
查看当前的shell类型 在 Linux 的世界中,有着许多 shell 程序。常见的有: Bourne shell (sh) C shell (csh) TC shell (tcsh) Korn shell (ksh) Bourne Again shell (bash) 其中,最常用的就是bash和tcsh,本次文章介绍tcsh的…...
YOLOv5源码逐行超详细注释与解读(2)——推理部分detect.py
前言 前面简单介绍了YOLOv5的项目目录结构(直通车:YOLOv5源码逐行超详细注释与解读(1)——项目目录结构解析),对项目整体有了大致了解。 今天要学习的是detect.py。通常这个文件是用来预测一张图片或者一…...
什么叫个非对称加密?中间人攻击?数字签名?
非对称加密也称为公钥密码。就是用公钥来进行加密,撒子意思? 非对称加密 在对称加密中,我们只需要一个密钥,通信双方同时持有。而非对称加密需要4个密钥,来完成完整的双方通信。通信双方各自准备一对公钥和私钥。其中…...
2023.03.07 小记与展望
碎碎念系列全新改版! 以后就叫小记和展望系列 最近事情比较多,写篇博客梳理一下自己3月到5月下旬的一个规划 一、关于毕设 毕设马上开题答辩了,准备再重新修改一下开题报告,梳理各阶段目标。 毕设是在去年的大学生创新训练项目…...
MyBatis源码分析(七)MyBatis与Spring的整合原理与源码分析
文章目录写在前面一、SqlSessionFactoryBean配置SqlSessionFactory1、初识SqlSessionFactoryBean2、实现ApplicationListener3、实现InitializingBean接口4、实现FactoryBean接口5、构建SqlSessionFactory二、SqlSessionTemplate1、初始SqlSessionTemplate2、SqlSessionTemplat…...
基于声网 Flutter SDK 实现多人视频通话
前言 本文是由声网社区的开发者“小猿”撰写的Flutter基础教程系列中的第一篇。本文除了讲述实现多人视频通话的过程,还有一些 Flutter 开发方面的知识点。该系列将基于声网 Fluttter SDK 实现视频通话、互动直播,并尝试虚拟背景等更多功能的实现。 如果…...
IT服务管理(ITSM) 中的大数据
当我们谈论IT服务管理(ITSM)领域的大数据时,我们谈论的是关于两件不同的事情: IT 为业务提供的大数据工具/服务 - 对业务运营数据进行数字处理。IT 运营中的大数据 – 处理和利用复杂的 IT 运营数据。 面向业务运营的大数据服务…...
Validator校验之ValidatorUtils
注意:hibernate-validator 与 持久层框架 hibernate 没有什么关系,hibernate-validator 是 hibernate 组织下的一个开源项目 。 hibernate-validator 是 JSR 380(Bean Validation 2.0)、JSR 303(Bean Validation 1.0&…...
C++---背包模型---采药(每日一道算法2023.3.7)
注意事项: 本题是"动态规划—01背包"的扩展题,dp和优化思路不多赘述。 题目: 辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。 为此,他想拜附近最有威望的医师为师。 医师为了判断他的资质&…...
Java各种锁
目录 一、读写锁(ReentrantReadWriteLock) 二、非公平锁(synchronized/ReentrantLock) 三、可重入锁/递归锁(synchronized/ReentrantLock) 四、自旋锁(spinlock) 五、乐观锁/悲观锁 六、死锁 1、死锁代码 2、死锁的检测(jps -l 与 jstack 进程号) 七、sychronized-wait…...
TryHackMe-Tardigrade(应急响应)
Tardigrade 您能否在此 Linux 端点中找到所有基本的持久性机制? 服务器已遭到入侵,安全团队已决定隔离计算机,直到对其进行彻底清理。事件响应团队的初步检查显示,有五个不同的后门。你的工作是在发出信号以使服务器恢复生产之前…...
导出GIS | 将EXCEL表格中坐标导出成GIS格式文件
一 前言 EXCEL是我们日常工作学习数据处理的办公软件,操作易上手,几乎人人都会用。EXCEL表格能够处理各种数据,包括经纬度坐标数据,地址数据等等。 有时因工作需要需将表格中地址数据处理为GIS格式的文件,以便能够将数…...
测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...
逻辑回归暴力训练预测金融欺诈
简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...
c++第七天 继承与派生2
这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分:派生类构造函数与析构函数 当创建一个派生类对象时,基类成员是如何初始化的? 1.当派生类对象创建的时候,基类成员的初始化顺序 …...
[USACO23FEB] Bakery S
题目描述 Bessie 开了一家面包店! 在她的面包店里,Bessie 有一个烤箱,可以在 t C t_C tC 的时间内生产一块饼干或在 t M t_M tM 单位时间内生产一块松糕。 ( 1 ≤ t C , t M ≤ 10 9 ) (1 \le t_C,t_M \le 10^9) (1≤tC,tM≤109)。由于空间…...
