9.DMA
目录
DMA —为 CPU 减负
DMA 的简介和使用场景
DMA 的例子讲解
STM32 的 DMA 框图和主要特性
编辑 DMA 的通道的对应通道外设 – DMA 和哪些外设使用
编辑编辑ADC_DR 寄存器地址的计算
常见的数据滤波方法
ADC+DMA 的编程
DMA —为 CPU 减负
DMA 的简介和使用场景
外设--UART SPI ADC
存储器--RAM ROM(FLASH)
使用场景:外设和存储器之间或者存储器和存储器之间
DMA 的例子讲解
无 DMA:任何指令都需要 CPU 去处理
搬砖:需要自己亲手去搬运
有 DMA:安排一个人,告诉他,把砖搬走
STM32 的 DMA 框图和主要特性
DMA 的通道的对应通道外设 – DMA 和哪些外设使用

ADC_DR 寄存器地址的计算
光照硬件电路-->PA5-->ADC1_IN5-->DMA1_CH1
1. 找外设基地址
通过查看数据手册存储器图
2.找寄存器的偏移地址
通过参考手册 11.12.14 确定 ADC1_DR 寄存器的偏移
3.计算寄存器的地址
ADC1_DR=0x40012400+0x4C=0x4001244C
常见的数据滤波方法
1. 均值滤波
2. 限幅滤波 -- 10%的变化幅度
目前检测的温度,都是 10℃,突然检测到 30℃,限制 1 个变化的幅度,比如说 10%,那么再 10℃ ±10%都认为是正常的,超过认为不正常。
3. 中值滤波、高斯滤波、算术平均滤波
ADC+DMA 的编程
#include "ADC.h"
#include "stdio.h"
#include "DMA.h"#if(USE_ADC_DMA_BUFF==0)
uint16_t ADC_DMA_LIGHT_Value = 0;
uint16_t ADC_DMA_SMOKE_Value = 0;
#elif(USE_ADC_DMA_BUFF==1)
uint16_t ADC_DMA_LIGHT_Value = 0;
uint16_t ADC_DMA_SMOKE_Value = 0;
uint16_t ADC_DMA_Value[2];
#endif#define SAMPLE_COUNT 10 // 滤波所用样本数量
uint16_t light_sample[SAMPLE_COUNT];//存储光照采样值
uint16_t smoke_sample[SAMPLE_COUNT];//存储烟雾采样值
uint8_t light;//光照循环变量
uint8_t smoke;//烟雾循环变量#define ADC1_DR 0x4001244Cvoid DMA_Config(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC, ENABLE);GPIO_InitTypeDef GPIO_InitStruct = {0};//给结构体赋值GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;//代配置引脚GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;//模拟输入GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;//引脚速率GPIO_Init(GPIOA, &GPIO_InitStruct);GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1;//代配置引脚GPIO_Init(GPIOC, &GPIO_InitStruct);RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //使用ADC1时钟RCC_ADCCLKConfig(RCC_PCLK2_Div6);//分频,RCC_CFGR寄存器位15:14RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);ADC_InitTypeDef ADC_InitStruct;/*启动1次,获取1次转换结果,再次启动,再获取*/ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;// 是否开启连续模式 ADC_CR2的位1ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;//数据对齐方式 ADC_CR2的位11 16的寄存器存放12位转换结果 右对齐方便取数据ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;// 是否使用外部触发,ADC_CR2的位19:17 通过SWSTART位软件启动ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;// 独立模式 ADC1 ADC2独立工作 参考手册 11.9 ADC_CR1的位19:16ADC_InitStruct.ADC_NbrOfChannel = 2;// 待转换的通道的数量 ADC_SQR1位23:20 参考手册 11.3.3ADC_InitStruct.ADC_ScanConvMode = ENABLE;是否开启扫描 多通道必须扫描,单通道无所谓 参考手册 11.3.8 ADC_CR1的位8ADC_Init(ADC1, &ADC_InitStruct);DMA_InitTypeDef DMA_InitStruct = {0};
#if(USE_ADC_DMA_BUFF==0)DMA_InitStruct.DMA_BufferSize = 1; //目标地址可以存放几次搬运的数据 DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)&ADC_DMA_LIGHT_Value;//内存基地址 DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Disable;//内存基地址是否递增
#elif(USE_ADC_DMA_BUFF==1)DMA_InitStruct.DMA_BufferSize = sizeof(ADC_DMA_Value)/sizeof(ADC_DMA_Value[0]); //目标地址可以存放几次搬运的数据 DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)ADC_DMA_Value;//内存基地址 DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;//内存基地址是否递增
#endifDMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;//设置DMA数据传输方向为从外设(ADC)到内存。外设是源地址DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;//不使用内存到内存,使用外设-->寄存器DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;//设置DMA模式为循环模式,在数据传输完成后会重新从内存开始,适用于需要持续获取数据的场景。DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//内存数据宽度,半字,ADC转换结果是12位的DMA_InitStruct.DMA_PeripheralBaseAddr = ADC1_DR;//ADC1的数据寄存器的地址。DMA将从该地址读取数据。DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//外设数据宽度,半字,ADC转换结果是12位的DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设基地址不递增 始终是ADC_DR寄存器DMA_InitStruct.DMA_Priority = DMA_Priority_High;//设置DMA的优先级为高,表示DMA请求优先级较高。DMA_Init(DMA1_Channel1, &DMA_InitStruct);ADC_DMACmd(ADC1, ENABLE);//使能ADC的DMA功能 ADC_CR2的位8ADC_Cmd(ADC1, ENABLE);//使能ADCADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_55Cycles5);//配置转换的ADC通道ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_55Cycles5);//配置转换的ADC通道DMA_Cmd(DMA1_Channel1, ENABLE);//开机至少初始化1次ADC_ResetCalibration(ADC1);//将ADC_CR2的位3 RSTCAL位置1,初始化校准寄存器while(ADC_GetResetCalibrationStatus(ADC1));//等待校准寄存器初始化完成 ADC_CR2的位3是0 初始化完成 1未完成等待ADC_StartCalibration(ADC1);//将ADC_CR2的位2 CAL位置1,开始校准while(ADC_GetCalibrationStatus(ADC1));//等待A/D校准完成 ADC_CR2的位2是0 校准完成完成 1正在校准,未完成等待ADC_SoftwareStartConvCmd(ADC1,ENABLE);//启动ADC转换 ADC_CR2的位22}void ADC_DMA_Handle(void)
{
#if(USE_ADC_DMA_BUFF==0)while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET)//未转换完成死等ADC_DMA_LIGHT_Value = ADC_GetConversionValue(ADC1);printf("光照ADC采样值=%d\r\n",ADC_DMA_LIGHT_Value);printf("光照ADC采样口=%.2f\r\n",(3.3/4096)*ADC_DMA_LIGHT_Value);while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET)ADC_SMK_Value = ADC_GetConversionValue(ADC1);printf("烟雾采样值=%d\r\n",ADC_SMK_Value);printf("烟雾浓度采样口=%.2f\r\n",(3.3/4096)*ADC_SMK_Value);printf("\r\n");
#elif(USE_ADC_DMA_BUFF==1)ADC_DMA_LIGHT_Value = ADC_DMA_Value[0];//光照采样值light_sample[light++] = ADC_DMA_LIGHT_Value;if(light >= SAMPLE_COUNT){//保存关照,10个一组light = 0;}uint32_t light_sum = 0;//光照10个数据总和for (int i = 0; i < SAMPLE_COUNT; i++){light_sum += light_sample[i];}//算平均值uint16_t light_avg = light_sum / SAMPLE_COUNT;printf("光照采样平均值=%d\r\n",light_avg);printf("光照ADC采样口平均值=%.2f\r\n",(3.3/4096)*light_avg);printf("\r\n");ADC_DMA_SMOKE_Value = ADC_DMA_Value[1];//烟雾采样值smoke_sample[smoke++] = ADC_DMA_SMOKE_Value;if(smoke >= SAMPLE_COUNT){//保存烟雾,10个一组smoke = 0;}uint32_t smoke_sum = 0;//烟雾10个数据总和for (int i = 0; i < SAMPLE_COUNT; i++){smoke_sum += smoke_sample[i];}float smoke_avg = (float)smoke_sum / SAMPLE_COUNT;printf("烟雾采样平均值=%.1f\r\n",smoke_avg);printf("烟雾浓度采样口平均值=%.2f\r\n",(3.3/4096)*smoke_avg);printf("\r\n");#endif}
//void ADC_DMA_Handle(void)
//{
// uint64_t temp1=0;
// uint64_t temp2=0;
// for(uint8_t i=0;i<ADC_DMA_Count;i+=2)
// {
// temp1+=ADC_DMA_Value[i];
// temp2+=ADC_DMA_Value[i+1];
// }
// ADC_DMA_LIGHT_Value=temp1/5;
// ADC_DMA_SMOKE_Value=temp2/5;
// printf("光照ADC采样值=%d\r\n",ADC_DMA_LIGHT_Value);
// printf("光照ADC采样口电压=%.2f\r\n",(3.3/4096)*ADC_DMA_LIGHT_Value);
// printf("烟雾ADC采样值=%d\r\n",ADC_DMA_SMOKE_Value);
// printf("烟雾ADC采样口电压=%.2f\r\n",(3.3/4096)*ADC_DMA_SMOKE_Value);
//}
相关文章:

9.DMA
目录 DMA —为 CPU 减负 DMA 的简介和使用场景 DMA 的例子讲解 STM32 的 DMA 框图和主要特性 编辑 DMA 的通道的对应通道外设 – DMA 和哪些外设使用 编辑编辑ADC_DR 寄存器地址的计算 常见的数据滤波方法 ADCDMA 的编程 DMA —为 CPU 减负 DMA 的简介和使用场…...

大语言模型 10 - 从0开始训练GPT 0.25B参数量 补充知识之模型架构 MoE、ReLU、FFN、MixFFN
写在前面 GPT(Generative Pre-trained Transformer)是目前最广泛应用的大语言模型架构之一,其强大的自然语言理解与生成能力背后,是一个庞大而精细的训练流程。本文将从宏观到微观,系统讲解GPT的训练过程,…...

python基础语法(三-中)
基础语法3: 2.列表与元组: <1>.列表、元组是什么? 都用来存储数据,但是两者有区别,列表可变,元组不可变。 <2>.创建列表: 创建列表有两种方式: [1].a 【】&#x…...
【gitee 初学者矿建仓库】
简易的命令行入门教程: Git 全局设置: git config --global user.name "你的名字"触摸 git config --global user.email "你的邮箱"创建 git 仓库: mkdir codestore cd codestore git init -b "main" touch README.md # 选择运行 git add REA…...
思路收集文档
降低工作量思路 nodejsjava混合网站开发...
OpenCV 光流估计:从原理到实战
在计算机视觉领域,光流估计(Optical Flow Estimation)是一项至关重要的技术,它能够通过分析视频序列中图像像素的运动信息,捕捉物体和相机的运动情况。OpenCV 作为强大的计算机视觉库,为我们提供了高效实现…...
使用HtmlAgilityPack采集墨迹天气中的天气数据
需要解析对应的HTML源码: <div class"left"><div class"wea_alert clearfix"><ul><li><a href "https://tianqi.moji.com/aqi/china/jiangxi/hukou-county" >< span class"level level_2&qu…...

ZTE 7551N 中兴小鲜60 远航60 努比亚小牛 解锁BL 刷机包 刷root 展讯 T760 bl
ZTE 7551N 中兴小鲜60 远航60 努比亚小牛 解锁BL 刷机包 刷root 3款机型是一个型号,包通用, ro.product.system.modelZTE 7551N ro.product.system.nameCN_P720S15 #################################### # from generate-common-build-props # Th…...
SearxNG本地搜索引擎
SearxNG 是一个强大、开源的 元搜索引擎(meta search engine),它不会存储用户信息,注重隐私保护,并支持从多个搜索引擎聚合结果,用户可以自建部署,打造一个无广告、可定制的搜索平台。 🔍 什么是 SearxNG? SearxNG 是 Searx 的一个积极维护的分支(fork),意在改进…...
MyBatis 核心组件源码分析
MyBatis 作为 Java 领域最受欢迎的持久层框架之一,以灵活的 SQL 映射和强大的扩展性著称。要真正驾驭 MyBatis,深入理解其核心组件的源码实现是关键。本文将通过源码分析,结合图文并茂的方式,带大家揭开 MyBatis 核心组件的神秘面纱。 1.SqlSessionFactory:会话工厂的核心…...

信息系统项目管理师高级-软考高项案例分析备考指南(2023年案例分析)
个人笔记整理---仅供参考 计算题 案例分析里的计算题就是进度、挣值分析、预测技术。主要考査的知识点有:找关键路径、求总工期、自由时差、总时差、进度压缩资源平滑、挣值计算、预测计算。计算题是一定要拿下的,做计算题要保持头脑清晰,认真读题把PV、…...
stack和queue简单模拟实现
stackreverse_iteratorqueuepriority_queue仿函数具体代码 stack Stacks are a type of container adaptor, specifically designed to operate in a LIFO context (last-in first-out), where elements are inserted and extracted only from one end of the container. 上述描…...
如何安装双系统?即windows已经安装,如何安装ubuntu 22.04LTS
在已安装 Windows 的电脑上安装 Ubuntu 22.04 LTS 双系统,需通过 分区调整、UEFI/BIOS 设置 和 引导管理 实现。以下是详细步骤: 一、准备工作 备份数据 • 备份 Windows 中的重要文件(防止分区操作失误导致数据丢失)。 下载 Ubu…...

产品经理入门(2)产品体验报告
产品体验报告大纲:重点在产品体验——优点。 1.产品概括 可以从各大平台搜产品介绍。 2.市场分析 按照产品方向分析各个指标——包括有效使用时间,市场规模等。 3. 用户分析——对用户通过各项指标画像。 4.产品体验——对各项功能与设计的体验。 5.报告总结...

C43-指针与数组
一 定义一个指针变量指向数组 1.途径一:指向数组首元素的地址 代码示例: #include <stdio.h> int main() {int arr[3]{2,4,5};int *p;p&arr[0];printf("该数组的首元素是:%d",*p);return 0; }成果展示: 报错与总结: 给指针变量赋值时,未在数组首元素前输…...

UDP--DDR--SFP,FPGA实现之ddr读写控制模块
DDR读写控制模块实现介绍 由于该模块接口数量较多,为了详细说明模块实现,采用文字流程进行介绍 上级模块传输数据到来捕捉数据有效上升沿传输写指令,写有效,写指令成功被下一级模块缓存,进行写地址一次读写长度&…...

云计算与大数据进阶 | 26、解锁云架构核心:深度解析可扩展数据库的5大策略与挑战(上)
在云应用/服务的 5 层架构里,数据库服务层稳坐第 4 把交椅,堪称其中的 “硬核担当”。它的复杂程度常常让人望而生畏,不少人都将它视为整个架构中的 “终极挑战”。 不过,也有人觉得可扩展存储系统才是最难啃的 “硬骨头”&#…...

AI Agent | Coze 插件使用指南:从功能解析到实操步骤
一、前言 在人工智能技术飞速发展的今天,低代码开发模式正成为构建智能应用的主流趋势。对于希望快速搭建 AI Bot 的开发者和业务人员而言,coze作为一款强大的低代码 AI 开发平台,凭借其高度模块化的插件体系脱颖而出。这些插件就像搭建智能…...
06、基础入门-SpringBoot-依赖管理特性
06、基础入门-SpringBoot-依赖管理特性 Spring Boot 的依赖管理特性是其核心优势之一,极大地简化了项目的构建和维护过程。以下是其主要特点: ## 1. 父项目依赖管理 ### 1.1 继承 spring-boot-starter-parent 在 pom.xml 文件中,通过继承 spr…...

MK米客方德SD NAND:无人机存储的高效解决方案
在无人机技术迅猛发展的当下,飞控系统的数据记录对于飞行性能剖析、故障排查以及飞行安全保障极为关键。以往,SD 卡是飞控 LOG 记录常见的存储介质,但随着技术的革新,新的存储方案不断涌现。本文聚焦于以 ESP32 芯片为主控制器的无…...

【vscode】解决vscode无法安装远程服务器插件问题,显示正在安装
文章目录 现状分析采用VSIX离线安装第一步:离线下载插件包第二步:把下载好的插件文件上传到远程服务器上第三步:在windows下打开vscode,并链接远端,进行安装 现状分析 vscode无法远程安装扩展插件,显示正在…...
1688 数据接口调用秘籍:高效获取商品实时信息的开发指南
在电商行业竞争白热化的当下,企业想要抢占市场先机,实时掌握商品信息至关重要。作为国内 B2B 电商巨头,1688 平台汇聚海量商品资源,通过高效调用其数据接口获取商品实时信息,能为企业价格策略制定、库存管理、竞品分析…...

【Spring】Spring的请求处理
欢迎来到啾啾的博客🐱。 记录学习点滴。分享工作思考和实用技巧,偶尔也分享一些杂谈💬。 欢迎评论交流,感谢您的阅读😄。 目录 引言HTTP/HTTPS协议Spring Web与Spring Web MVCSpring WebFlux 自定义的TPC/IP协议FTP、S…...

粒子群算法(PSO算法)
粒子群算法概述 1.粒子群优化算法(Particle Swarm Optimization,简称PSO)。粒子群优化算法是在1995年由Kennedy博士和Eberhart博士一起提出的,它源于对鸟群捕食行为的研究。 2.基本核心是利用群体中的个体对信息的共享从而使得整…...
git提交库常用词
新功能 feat修改BUG fix文档修改 docs格式修改 style重构 refactor性能提升 perf测试 test构建系统 build对CI配置文件修改 ci修改构建流程、或增加依赖库、工具 chore回滚版本 revert...

LLM智能体新纪元:深入解析MCP与A2A协议,赋能智能自动化协作
LLM智能体(LLM agents)是能够自主行动以实现特定目标的AI系统。在实际应用中,智能体能够将用户请求拆解为多个步骤,利用知识库或API获取数据,最终整合出答案。这让智能体相比于传统独立聊天机器人拥有更强大的能力——…...

SAP学习笔记 - 开发豆知识01 - CDS SDK命令出乱码 (cds init CAP-Test03 --add java)
1,现象 安装完VSCode以及各种需要的插件(比如SAP CDS Language Support),就可以做CAP开发。 用这个命令创建Project:cds init CAP-Test03 --add java 然后出来一个乱码错误 adding java The derived package name c…...

(C语言)超市管理系统 (正式版)(指针)(数据结构)(清屏操作)(文件读写)(网页版预告)(html)(js)(json)
目录 前言: 源代码: product.h product.c fileio.h fileio.c main.c json_export.h json_export.c tasks.json idex.html script.js 相关步骤: 第一步: 第二步: 第三步: 第四步: 第五步…...

进阶-数据结构部分:2、常用排序算法
飞书文档https://x509p6c8to.feishu.cn/wiki/FfpIwIPtviMMb4kAn3Sc40ABnUh 常用排序算法 这几种算法都是常见的排序算法,它们的优劣和适用场景如下: 冒泡排序(Bubble Sort):简单易懂,时间复杂度较高&…...
解决 Three.js Raycaster 点击位置与实际交点偏差问题
当使用 Three.js 的 Raycaster 时,如果发现点击位置与显示的碰撞点之间存在较大偏差,这通常是由于坐标系统不匹配或参数设置不正确导致的。以下是系统性的排查和解决方案: 1. 检查鼠标坐标转换 最常见的偏差原因是鼠标坐标到标准化设备坐标…...