STM32DMA

文章目录

  • 前言
  • 一、介绍部分
    • DMA简介
    • 存储器映像
    • DMA框图
      • 仲裁器
    • DMA基本结构
    • 请求映像
    • 数据对齐方式
    • 数据转运
    • ADC扫描模式配合DMA
  • 二、代码部分
    • DMA数据转运
    • 连接电路
    • 代码实现
    • ADC扫描+DMA
    • 实现思路
    • 连接电路
    • 代码实现
  • 总结
    • 函数相关


前言

介绍STM32DMA的原理以及功能,使用DMA配合ADC实现自动化AD转换。


一、介绍部分

DMA简介

在这里插入图片描述

存储器映像

在这里插入图片描述

DMA框图

这里APB1、APB2位置互换。

在这里插入图片描述

仲裁器

在这里插入图片描述

DMA基本结构

自动重装不能与存储器到存储器模式同时设置,会使DMA 永远执行

在这里插入图片描述

请求映像

每个硬件触发对应特定的DMA通道。

在这里插入图片描述

数据对齐方式

发送的数据于接收数据的大小设置不对等时,大转小:高位补0,小转大:高位舍弃。

在这里插入图片描述

数据转运

在这里插入图片描述

ADC扫描模式配合DMA

在这里插入图片描述

二、代码部分

DMA数据转运

连接电路

连接一个OLED即可
在这里插入图片描述

代码实现

封装ThisDMA.c

#include "stm32f10x.h"                  // Device headeruint16_t DMA_Size;void ThisDMA_Init(uint32_t ArrA,uint32_t ArrB,uint16_t BufSize){RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);DMA_Size = BufSize;DMA_InitTypeDef DMA_InitStructure;DMA_InitStructure.DMA_BufferSize = BufSize;	// 传输计数器的值DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;	// 外设作为发送方DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;		// 软件触发还是硬件触发DMA_InitStructure.DMA_MemoryBaseAddr = ArrA;	// 存储器初始地址DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;	// 存储器数据大小DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;				// 转运时是否自增DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;	// 传输计数器是否重装DMA_InitStructure.DMA_PeripheralBaseAddr = ArrB;	// 外设初始地址DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;	// 外设数据大小DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;				// 转运时是否自增DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;		// 优先级DMA_Init(DMA1_Channel1,&DMA_InitStructure);// 初始化后先不开始转运DMA_Cmd(DMA1_Channel1,DISABLE);
}void ThisDMA_Transfer(void){// DMA失能,先关闭,再修改数据DMA_Cmd(DMA1_Channel1,DISABLE);// 重新赋值传输计数器,使其再次工作DMA_SetCurrDataCounter(DMA1_Channel1,DMA_Size);// DMA使能DMA_Cmd(DMA1_Channel1,ENABLE);// 等待转运完成while(DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);// 清除标志位DMA_ClearFlag(DMA1_FLAG_TC1);
}

主函数main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "ThisDMA.h"// 需要转运的数据
uint8_t DataA[] = {0x01,0x02,0x03,0x04};
// 用于接收数据
uint8_t DataB[] = {0,0,0,0};
uint8_t i;
// 显示数据函数
void ShowData(void){OLED_ShowHexNum(1,4,(uint32_t)&DataA,8);OLED_ShowHexNum(3,4,(uint32_t)&DataB,8);OLED_ShowHexNum(2,1,DataA[0],2);OLED_ShowHexNum(2,4,DataA[1],2);OLED_ShowHexNum(2,7,DataA[2],2);OLED_ShowHexNum(2,10,DataA[3],2);OLED_ShowHexNum(4,1,DataB[0],2);OLED_ShowHexNum(4,4,DataB[1],2);OLED_ShowHexNum(4,7,DataB[2],2);OLED_ShowHexNum(4,10,DataB[3],2);
}int main(void)
{OLED_Init();ThisDMA_Init((uint32_t)DataB,(uint32_t)DataA,4);OLED_ShowString(1,1,"A");OLED_ShowString(3,1,"B");ShowData();while (1){for(i=0;i<4;i++)DataA[i]++;ShowData();Delay_ms(1000);ThisDMA_Transfer();ShowData();Delay_ms(1000);}
}

ADC扫描+DMA

实现思路

使用AD 的连续转换扫描模式,通过DMA帮助在数据寄存器及时的取走数据来实现自动化的AD转换

在这里插入图片描述

连接电路

在这里插入图片描述

代码实现

改写AD.c

#include "stm32f10x.h"                  // Device headeruint16_t ADBufArr[4];	// 在头文件声明为外部变量void AD_Init(void){RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);// 设置ADC时钟 72/6=12MHzRCC_ADCCLKConfig(RCC_PCLK2_Div6);// 初始化GPIOGPIO_InitTypeDef GPIO_Structure;GPIO_Structure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;GPIO_Structure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Structure.GPIO_Mode = GPIO_Mode_AIN;		// 模拟输入模式(ADC专用)GPIO_Init(GPIOA,&GPIO_Structure);// 使用规则组// 配置规则组通道(ADC、此ADC的通道、序号、采样时间)ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);ADC_RegularChannelConfig(ADC1,ADC_Channel_1,2,ADC_SampleTime_55Cycles5);ADC_RegularChannelConfig(ADC1,ADC_Channel_2,3,ADC_SampleTime_55Cycles5);ADC_RegularChannelConfig(ADC1,ADC_Channel_3,4,ADC_SampleTime_55Cycles5);// 初始化ADCADC_InitTypeDef ADC_InitStructure;ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;										// 连续模式还是单次模式ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;								// 数据对齐,右对齐ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;		// 触发转换的触发源,不使用外部触发使用软件触发ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;										// 独立模式or双ADC模式ADC_InitStructure.ADC_NbrOfChannel = 4;																// 指定要使用多少个通道ADC_InitStructure.ADC_ScanConvMode = ENABLE;													// 扫描模式还是非扫描模式ADC_Init(ADC1,&ADC_InitStructure);// 初始化DMADMA_InitTypeDef DMA_InitStructure;DMA_InitStructure.DMA_BufferSize = 4;	// 传输计数器的值DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;	// 外设作为发送方DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;		// 软件触发还是硬件触发DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADBufArr;	// 存储器初始地址DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;	// 存储器数据大小DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;				// 转运时是否自增DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;	// 传输计数器是否重装DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;	// 外设初始地址DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;	// 外设数据大小DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;				// 转运时是否自增DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;		// 优先级DMA_Init(DMA1_Channel1,&DMA_InitStructure);// 开启DMADMA_Cmd(DMA1_Channel1,ENABLE);// 开启ADC1触发DMA的通道ADC_DMACmd(ADC1,ENABLE);// 开启ADCADC_Cmd(ADC1,ENABLE);// 校准ADC_ResetCalibration(ADC1);													// 复位校准while(ADC_GetResetCalibrationStatus(ADC1) == SET);	// 获取复位校准的状态,等待复位完成ADC_StartCalibration(ADC1);													// 开始校准while(ADC_GetCalibrationStatus(ADC1) == SET);				// 获取校准状态,等待校准完成// ADC开始运转ADC_SoftwareStartConvCmd(ADC1,ENABLE);
}

主函数main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "AD.h"int main(void)
{OLED_Init();AD_Init();OLED_ShowString(1,1,"AD0");OLED_ShowString(2,1,"AD1");OLED_ShowString(3,1,"AD2");OLED_ShowString(4,1,"AD3");while (1){OLED_ShowNum(1,5,ADBufArr[0],4);OLED_ShowNum(2,5,ADBufArr[1],4);OLED_ShowNum(3,5,ADBufArr[2],4);OLED_ShowNum(4,5,ADBufArr[3],4);Delay_ms(100);}
}

总结

函数相关

// 打开此ADC的DMA触发通道
void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);
// DMA初始化
void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct);
// DMA结构体负初值
void DMA_StructInit(DMA_InitTypeDef* DMA_InitStruct);
// DMA使能
void DMA_Cmd(DMA_Channel_TypeDef* DMAy_Channelx, FunctionalState NewState);
// DMA中断使能
void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, uint32_t DMA_IT, FunctionalState NewState);
// 设置传输计数器的值
void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t DataNumber); 
// 获取传输计数器的值
uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx);
// 获取标志位状态
FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG);
// 清除标志位
void DMA_ClearFlag(uint32_t DMAy_FLAG);
// 获取标志位状态(中断函数中)
ITStatus DMA_GetITStatus(uint32_t DMAy_IT);
// 清除标志位(中断函数中)
void DMA_ClearITPendingBit(uint32_t DMAy_IT);

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

目标检测 | 卷积神经网络(CNN)详细介绍及其原理详解

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。卷积神经网络&#xff08;Convolutional Neural Network&#xff0c;CNN&#xff09;是一种深度学习模型&#xff0c;主要用于图像识别和计算机视觉任务。它的设计灵感来自于生物学中视觉皮层的工作原理。CNN的核心思想是通…

车载自动化项目:Python

1. 自动化测试用的什么框架&#xff1f; 第一种&#xff1a;PythonSeleniumuittest框架 首先是拿到需求文档&#xff0c;基于这个需求去进行搭建。 用pytestrequestallure 这些第三方库进行编写自动化脚本。 举个例子一般的话整个的一个自动化的搭建是分为6层嘛&#xff1a…

redis集群配置

redis集群配置.pdf 跳转/opt/redis → cd /opt/redis 1、下载redis wget http://download.redis.io/releases/redis-6.2.1.tar.gz 2、解压 tar -xzvf redis-6.2.1.tar.gz 3、编译 cd /opt/redis/redis-6.2.1 make MALLOClibc 4、安装 make PREFIX/opt/redis/ install ⽣成…

Talk|香港中文大学(深圳)张雪遥:音频生成开源工具包Amphion的歌声转换指南

本期为TechBeat人工智能社区第570期线上Talk。 北京时间2月7日(周三)20:00&#xff0c;香港中文大学(深圳)博士生—张雪遥的Talk已准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “音频生成开源工具包Amphion的歌声转换指南”&#xff0c;系统地介绍他的团…

mysql 对于null字段排序处理

最近遇到一个需求 &#xff0c;需要对一个报表的多个字段进行多字段复杂条件排序 排序字段为NULL时 Mysql对于排序字段为NULL时&#xff0c;有自身默认的排序规则&#xff0c;默认是认为null 值 是无穷小 ELECT id,script_id,last_modified,live_count,next_show FROM virtua…

红队打靶练习:PHOTOGRAPHER: 1

目录 信息收集 1、arp 2、nmap 3、nikto 目录扫描 1、gobuster 2、dirsearch WEB 信息收集 enum4linux smbclient 8000端口 CMS利用 信息收集 文件上传漏洞利用 提权 信息收集 get user.txt get flag 信息收集 1、arp ┌──(root㉿ru)-[~/kali] └─# a…

AI专题:2023年AI和标准化网络安全报告

今天分享的是AI系列深度研究报告&#xff1a;《AI专题&#xff1a;2023年AI和标准化网络安全报告》。 &#xff08;报告出品方&#xff1a;enisa&#xff09; 报告共计&#xff1a;37页 文件目的和目标 本文件的总体目标是概述与人工智能(AI)网络安全有关的标准(现有的、正在…

ChatGPT 3.5与4.0:深入解析技术进步与性能提升的关键数据

大家好&#xff0c;欢迎来到我的博客&#xff01;今天我们将详细比较两个引人注目的ChatGPT版本——3.5和4.0&#xff0c;通过一些关键数据来深入解析它们之间的差异以及4.0版本的技术进步。 1. 模型规模与参数 ChatGPT 3.5&#xff1a; 参数数量&#xff1a;约1.7亿个模型层数…

格子表单GRID-FORM | 文档网站搭建(VitePress)与部署(Github Pages)

格子表单/GRID-FORM已在Github 开源&#xff0c;如能帮到您麻烦给个星&#x1f91d; GRID-FORM 系列文章 基于 VUE3 可视化低代码表单设计器嵌套表单与自定义脚本交互文档网站搭建&#xff08;VitePress&#xff09;与部署&#xff08;Github Pages&#xff09; 效果预览 格…

FPGA高端项目:解码索尼IMX327 MIPI相机转USB3.0 UVC 输出,提供FPGA开发板+2套工程源码+技术支持

目录 1、前言免责声明 2、相关方案推荐我这里已有的 MIPI 编解码方案 3、本 MIPI CSI-RX IP 介绍4、个人 FPGA高端图像处理开发板简介5、详细设计方案设计原理框图IMX327 及其配置MIPI CSI RX图像 ISP 处理图像缓存UVC 时序USB3.0输出架构FPGA逻辑设计工程源码架构SDK软件工程源…

CentOS镜像如何下载?在VMware中如何安装?

一、问题 CentOS镜像如何下载&#xff1f;在VMware中如何安装&#xff1f; 二、解决 1、CentOS镜像的下载 &#xff08;1&#xff09;官方网站 The CentOS Project &#xff08;2&#xff09;官方中文官网 CentOS 中文 官网 &#xff08;3&#xff09;选择CentOS Linux…

yarn/npm certificate has expired

目录 报错 原因&#xff1a;HTTPS 证书验证失败 方法 a.检查网络安全软件&#xff1a;可能会拦截或修改 HTTPS 流量 b.strict-ssl:false关闭验证【临时方法】 报错 info No lockfile found. [1/4] Resolving packages... error Error: certificate has expired at TLS…