stm32单片机开发三、DMA

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

DMA其实就是一种将ADC的数据寄存器、串口的数据寄存器等等一些数据放到sram中特定位置,方便CPU去读取
比如ADC转换,DMA直接转换的ADC的值放在内存中的特定位置,CPU可以直接去读取

uint16_t AD_Value[4];					//定义用于存放AD转换结果的全局数组

/**
  * 函    数:AD初始化
  * 参    数:无
  * 返 回 值:无
  */
void AD_Init(void)
{
	/*开启时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);	//开启ADC1的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	//开启GPIOA的时钟
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);		//开启DMA1的时钟
	
	/*设置ADC时钟*/
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);						//选择时钟6分频,ADCCLK = 72MHz / 6 = 12MHz
	
	/*GPIO初始化*/
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);					//将PA0、PA1、PA2和PA3引脚初始化为模拟输入
	
	/*规则组通道配置*/
	ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);	//规则组序列1的位置,配置为通道0
	ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5);	//规则组序列2的位置,配置为通道1
	ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_55Cycles5);	//规则组序列3的位置,配置为通道2
	ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_55Cycles5);	//规则组序列4的位置,配置为通道3
	
	/*ADC初始化*/
	ADC_InitTypeDef ADC_InitStructure;											//定义结构体变量
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;							//模式,选择独立模式,即单独使用ADC1
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;						//数据对齐,选择右对齐
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;			//外部触发,使用软件触发,不需要外部触发
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;							//连续转换,使能,每转换一次规则组序列后立刻开始下一次转换
	ADC_InitStructure.ADC_ScanConvMode = ENABLE;								//扫描模式,使能,扫描规则组的序列,扫描数量由ADC_NbrOfChannel确定
	ADC_InitStructure.ADC_NbrOfChannel = 4;										//通道数,为4,扫描规则组的前4个通道
	ADC_Init(ADC1, &ADC_InitStructure);											//将结构体变量交给ADC_Init,配置ADC1
	
	/*DMA初始化*/
	DMA_InitTypeDef DMA_InitStructure;											//定义结构体变量
	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;				//外设基地址,给定形参AddrA
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;	//外设数据宽度,选择半字,对应16为的ADC数据寄存器
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;			//外设地址自增,选择失能,始终以ADC数据寄存器为源
	DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)AD_Value;					//存储器基地址,给定存放AD转换结果的全局数组AD_Value
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;			//存储器数据宽度,选择半字,与源数据宽度对应
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;						//存储器地址自增,选择使能,每次转运后,数组移到下一个位置
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;							//数据传输方向,选择由外设到存储器,ADC数据寄存器转到数组
	DMA_InitStructure.DMA_BufferSize = 4;										//转运的数据大小(转运次数),与ADC通道数一致
	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;								//模式,选择循环模式,与ADC的连续转换一致
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;								//存储器到存储器,选择失能,数据由ADC外设触发转运到存储器
	DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;						//优先级,选择中等
	DMA_Init(DMA1_Channel1, &DMA_InitStructure);								//将结构体变量交给DMA_Init,配置DMA1的通道1
	
	/*DMA和ADC使能*/
	DMA_Cmd(DMA1_Channel1, ENABLE);							//DMA1的通道1使能
	ADC_DMACmd(ADC1, ENABLE);								//ADC1触发DMA1的信号使能
	ADC_Cmd(ADC1, ENABLE);									//ADC1使能
	
	/*ADC校准*/
	ADC_ResetCalibration(ADC1);								//固定流程,内部有电路会自动执行校准
	while (ADC_GetResetCalibrationStatus(ADC1) == SET);
	ADC_StartCalibration(ADC1);
	while (ADC_GetCalibrationStatus(ADC1) == SET);
	
	/*ADC触发*/
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);	//软件触发ADC开始工作,由于ADC处于连续转换模式,故触发一次后ADC就可以一直连续不断地工作
}

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "AD.h"

int main(void)
{
	/*模块初始化*/
	OLED_Init();				//OLED初始化
	AD_Init();					//AD初始化
	
	/*显示静态字符串*/
	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, AD_Value[0], 4);		//显示转换结果第0个数据
		OLED_ShowNum(2, 5, AD_Value[1], 4);		//显示转换结果第1个数据
		OLED_ShowNum(3, 5, AD_Value[2], 4);		//显示转换结果第2个数据
		OLED_ShowNum(4, 5, AD_Value[3], 4);		//显示转换结果第3个数据
		
		Delay_ms(100);							//延时100ms,手动增加一些转换的间隔时间
	}
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

告别繁琐!小浪助手助你轻松下载学浪视频

小浪助手,一站式学浪视频下载工具,能让你轻松下载学浪视频 工具我已经打包好了,有需要的自己取一下 学浪下载器链接:https://pan.baidu.com/s/1djUmmnsfLEt_oD2V7loO-g?pwd1234 提取码:1234 --来自百度网盘超级会…

Pycharm配深度学习环境所遇到的部分问题

问题1:Anaconda prompt界面安装CUDA出现的问题: 不管是:conda install pytorch torchvision torchaudio cudatoolkit11.3 -c pytorch 还是:pip ****什么的 问题描述:EnvironmentNotWritableError: The current user does not have write p…

python应用-socket网络编程(1)

目录 1 先简单回顾下客户端和服务端通信的知识 2 服务端常用函数 3 客户端常用函数 4 服务端和客户端都用的函数 5 示例介绍客户端和服务端通信过程 6 建立服务端套接制 7 创建服务端函数socket.create_server() 8 创建客户端套接字 9 客户端连接函数socket.create_co…

用socat验证multicase(组播)和broadcast(广播) with k8s容器环境

安装socat 网络允许的话,可以使用yum install -y socat进行安装。 如果是在容器里面运行,建议使用静态链接的socat: 可以从此处下载: Release socat-v1.7.4.4 ernw/static-toolbox GitHub 确定网络接口地址和组播地址 #kubectl exec -i…

请编写函数fun,该函数的功能是:实现B=A+A‘,即把矩阵A加上A的转置,存放在矩阵B中。计算结果在main函数中输出。

本文收录于专栏:算法之翼 https://blog.csdn.net/weixin_52908342/category_10943144.html 订阅后本专栏全部文章可见。 本文含有题目的题干、解题思路、解题思路、解题代码、代码解析。本文分别包含C语言、C++、Java、Python四种语言的解法完整代码和详细的解析。 题干 请编…

ASP.NET汽车销售管理系统的设计与开发

摘 要 随着人们生活水平的不断提高,人们对汽车的消费和需求也越来越旺盛。很多汽车销售公司的业务环节仍然运用人工记账的传统方法,既容易出错又会导致账目混乱,查询和统计起来也非常不方便,费时又费力,严重时会给公…

Python | Leetcode Python题解之第58题最后一个单词的长度

题目: 题解: class Solution:def lengthOfLastWord(self, s: str) -> int:ls[]for i in s.split():ls.append(i)return len(ls[-1])

CLI举例:基于用户接入方式和终端设备类型的安全策略

组网需求 如图1所示,某企业在网络边界处部署了FW作为安全网关,连接内部网络与Internet。具体情况如下: 内部网络中已经部署了Agile Controller身份验证机制,Agile Controller服务器上存储了用户信息。内部网络中的用户可以使用不…

畅信达呼叫中心通过麒麟软件适配认证,引领行业新标准

在数字化浪潮汹涌的时代,软件兼容性已成为衡量一个企业技术实力和市场竞争力的重要标准。近日,畅信达呼叫中心产品成功通过麒麟软件适配认证,标志着产品在通用兼容性、性能及可靠性方面均达到了行业领先水平,将为用户的关键性应用…

Spring Boot整合Camunda实现工作流

文章目录 1. 环境准备2. 添加Camunda配置3. 创建并部署工作流程4. 启动Spring Boot应用程序5. 部署工作流程6. 访问Camunda Tasklist7. 执行工作流程8. 总结 🎉欢迎来到SpringBoot框架学习专栏~ ☆* o(≧▽≦)o *☆嗨~我是IT陈寒🍹✨博客主页&#xff1a…

deepflow grafana plugin 编译问题解决

修改tsconfig.js 增加"noImplicitAny": false,解决代码类型没有指定,显示Any 错误 To solve the error, explicitly set the parameters type to any, use a more specific type or set noImplicitAny to false in tsconfig.json. https://b…

vue处理查询框清除后无法查询问题,举例为日期选择

例如 在对应的查询方法添加 //我这里获取的是date,如果是其他参数改为其他的即可 if (query.date && query.date.length > 2) {conditions.noedate query.date[0] || conditions.noedate;//获取开始时间conditions.twodate query.date[1] || conditi…

CVE-2023-48795修复方法

CVE-2023-48795修复方法 1、修复原理2、检测漏洞3、修复漏洞4、成功修复 近期nessus扫描经常出现一个中危漏洞CVE-2023-48795,但网上的修复方法清一色的将openSSH升级到9.6p1版本 而我在升级当中处处碰壁,甚至于差点给服务器都干崩溃,特意研究…

基于python-flask技术的社区信息交流平台【数据库+15000文档】

预览 介绍 系统只需使用者通过电脑浏览器即可实现系统的访问和操作的WEB模式的信息化系统。为了保证系统数据的准确性、安全性的数据存储,系统应用MySQL数据库进行系统数据存储服务。根据对社区工作的深入调研和对社区居民的走访调查,详细分析整体系统的…

智慧公厕:高速服务区公厕智慧技术改造

近年来,随着科技的迅速发展,高速服务区的公共卫生设施也在不断创新。深圳光明源智能科技在这一领域做出了积极的探索和实践,通过引入智能科技,提升了高速服务区公厕的管理水平和服务质量。以下是其中一些具体的创新技术和功能&…

Power BI:如何将文件夹批量Excel(多sheet页)文件导入?

故事背景: 业务同事想用Power BI分析近两年市场费用。 数据源全部是Excel文件,并且以每月一个Excel文件的方式,统一存放到同一文件夹下面。 重点,每张Excel文件会有多张sheet页,用区分每家分公司的费用信息。 目前…

Web前端开发之CSS_2

关系选择器CSS盒子模型弹性盒子模型文档流浮动清除浮动定位 1. 关系选择器 1.1 后代选择器 E F{} 选择所有被 E 元素包含的 F 元素&#xff0c;中间用空格隔开 <ul> <li>后代列表1</li> <div> <ol> <li>后代列表2</li> </ol>…

VULHUB复现fastjson1.2.24反序列化漏洞

蚌埠住了&#xff0c;遇到了很多奇奇怪怪的问题。 如果你问我为啥不用kali&#xff0c;我会告诉你&#xff0c;我电脑上的kali装不成docker-compose!我急用了ubuntu如果你问我为啥用ubuntu克隆&#xff0c;我会告诉你&#xff0c;我电脑上的kali不能安装成功java8这个版本如果你…

秋招后端开发面试题 - Java语言基础(下)

目录 Java基础下前言面试题toString() 、String.valueof()、(String)&#xff1f;hashCode() 方法&#xff1f;hashCode 和 equals 方法判断两个对象是否相等&#xff1f;为什么重写 equals 时必须重写 hashCode 方法&#xff1f;String、StringBuffer、StringBuilder?String …

《ESP8266通信指南》9-TCP通信(Arudino开发)

往期 《ESP8266通信指南》8-连接WIFI&#xff08;Arduino开发&#xff09;&#xff08;非常简单&#xff09;-CSDN博客 《ESP8266通信指南》7-Arduino 开发8266的环境配置与示例代码烧录-CSDN博客 《ESP8266通信指南》6-创建TCP服务器&#xff08;AT指令&#xff09;-CSDN博…