STM32F407寄存器操作(多通道单ADC+DMA)

news2025/6/4 13:05:52

1.前言

又是半年没更新了,趁着端午放假有点时间,并且最近项目要用这块知识,我就顺带研究一下ADC吧。

一般来说ADC主要用法包含了1.单通道软件触发(这是最简单和最常用的用法)2.单通道多次采集(需要快速采集数据,常见应用场景就是示波器)3.多通道采集(多个传感器数据)。

其中1、2我在前面的文章里也都介绍过了,这次我就说一说多通道采集。若是不能使用多通道采集,那么407里面两个ADC只能用两个通道,非常浪费。而407内一个ADC包涵16个通道,如此多的通道量基本能覆盖大部分应用场景了。

OK,那么废话不多说,下面我们正式开始介绍。

2.理论介绍

首先我们看看手册上关于这块的描述

这次我就以规则通道为例了,我们所有数据应该都是存放在DR寄存器里,这就会导致一个问题——数据覆盖。因此我们使用扫描模式时必须要用DMA配合使用。理论上来说如果全部使用注入通道,配置会比较简单,因为每个注入通道ADC都有保存的寄存器。不过这次教程我还是以较难的规则通道为例,一次性解决这个问题。

我们看到手册上对于扫描模式的开启只需要关注ADC->CR1里的SCAN,还是比较简单的。

我们看到CR1寄存器里,SCAN是第八位

给第八位置1即可

3.ADC配置

3.1ADC初始化

我首先把程序放出来,这里我用的是通道0和通道3

void init_adc1()
{
 	init_adc12_chinal(0);	//初始化通道0
	init_adc12_chinal(3);	//初始化通道3

	ADC1->CR1&=~(3<<24);	//15 ADCCLK 周期
	ADC1->CR1|=(1<<8);		//扫描模式
			
	ADC1->CR2&=~(1<<1);		//单次转换
	ADC1->CR2&=~(1<<11);	//数据右对齐
	ADC1->CR2&=~(3<<28);	//禁止触发检测
			
	ADC1->SQR1&=~(0XF<<20);	//重置规则通道序重置列长度
	ADC1->SQR1|=1<<20;     	//2个转换在规则序列中
			
	//设置通道0的采样时间
	ADC1->SMPR2&=~(7<<(3*0));		//通道0	采样时间清空	  
	ADC1->SMPR2|=(7<<(3*0)); 		//通道0  480个周期,提高采样时间可以提高精确度
	//设置通道3的采样时间
	ADC1->SMPR2&=~(7<<(3*3));		//通道3	采样时间清空	  
	ADC1->SMPR2|=(7<<(3*3)); 		//通道3  480个周期,提高采样时间可以提高精确度
			
	//ADC1->CR2|=1<<8;			//使能DMA模式
	ADC1->CR2|=1<<0;	   	//开启AD转换器	  
}

基本上没有什么特殊的,按照手册上描述的,给第8位置1

记得把要使用的ADC通道初始化好,配置好采样时间,通道数量正确即可

然后是触发的程序

void adc1_scanf(void)
{
	ADC1->SQR3=0;	//重置规则通道转换配置
	ADC1->SQR3|=0<<0;	//设置第一次规则转换通道0
	ADC1->SQR3|=3<<5;	//设置第二次规则转换通道3
	ADC1->CR2|=1<<30;	//开始转换
}

与软件触发类似,就是要多配置一个通道

3.2主程序

主程序里我们依次初始化DMA,ADC然后触发一次ADC即可

int main(void)
{
	Stm32_Clock_Init(336,25,2,7);//设置时钟,168Mhz
	NVIC_SetGroup(1);//设置中断分组,分组1
	init_PinClock();//初始化所有时钟
	delay_init(168);//初始化延时
	
	init_DMAClock();//初始化DMA时钟
    init_DMA2_S0C0(2);//DMA2 ADC1转换

	init_adc1(0);//初始化ADC
	adc1_scanf();//触发ADC
}

3.3测试

我们首先要看一下ADC程序是否正确

那么改如何测试呢?我们外部通道是PA0和PA3,我们的转换顺序是PA0-PA3。那么我们首先将PA3接地,那么程序运行结束后ADC的DR寄存器里应该是最后一次转换的数据,即PA3管脚的电压,但是因为PA3接地的,那么DR寄存器里首先应该是PA0的浮空值,之后应该被PA0覆盖为0。之后我们再把PA0接地,同理DR寄存器里应首先是PA0管脚的0,之后被覆盖为PA3的浮空值。

OK,我们来测试一下,首先把PA3接地。

可以看到DR寄存器内的数据为0

之后我们再把PA0接地

数据也是正常的浮空数据了

4.DMA配置

下面我来说说加上DMA后该怎么写,配合上DMA后ADC读取到的数据就不会丢失了,所有的数据都可以正常读取进RAM里,而且没有什么标志位,比较简单。

4.1DMA初始化

程序如下,与上一次篇配置是一样的,这里不做过多的介绍了

unsigned short adc_scanf[5];

//初始化DMA2 组0 通道0
//ADC1
void init_DMA2_S0C0(unsigned int ADCDMAWei)
{
	DMA2_Stream0 ->CR   = 0;//禁止数据流 ,才能写寄存器 
	
	//外设地址寄存器
	//将所需寄存器的地址放入PAR寄存器
	DMA2_Stream0 ->PAR  = (unsigned int)(&ADC1->DR);
	
	//数据流地址寄存器
	//M1AR仅在双通道模式下有用
	//将数据所在地址给M0AR寄存器
	DMA2_Stream0 ->M0AR = (unsigned int)(&adc_scanf);
	
	DMA2_Stream0 ->NDTR = ADCDMAWei;			// 一次传输数量      
	DMA2_Stream0 ->FCR  = 0x21;		//FIFO所有配置失效
	DMA2_Stream0 ->CR |= 0<< 6;		//外设到储存器模式
	
	//循环模式
	//当NDTR寄存器减到0时自动重装
	//单次模式(普通模式)
	//NDTR减到0后停止DMA
	DMA2_Stream0 ->CR |= 0<< 8;   //非循环模式
	DMA2_Stream0 ->CR |= 0<< 9;   //外设非增量模式
	DMA2_Stream0 ->CR |= 1<<10;   //存储器增量模式,指针增加,可用于传输数组
	DMA2_Stream0 ->CR |= 1<<11;		//外设数据长度:16位
	DMA2_Stream0 ->CR |= 1<<13;		//存储器数据长度:16位
	DMA2_Stream0 ->CR |= 2<<16;   //高等优先级
	
	//突发传输
	//DMA占用CPU总线时间,此时CPU无法工作
	//一个节拍:传输多少次32位变量
	//应用场景:从ram里读出字节
	DMA2_Stream0 ->CR |= 0<<21;   //外设突发单次传输
	DMA2_Stream0 ->CR |= 0<<23;   //存储器突发单次传输
	
	DMA2_Stream0 ->CR |= 0<<25;   //通道0
	DMA2_Stream0 ->CR |= 1<<0;    //使能数据流
}

4.2ADC初始化修改

ADC这里我们需要把CR2里DMA置1

程序如下

void init_adc1()
{
 	init_adc12_chinal(0);	//初始化通道0
	init_adc12_chinal(3);	//初始化通道3

	ADC1->CR1&=~(3<<24);	//15 ADCCLK 周期
	ADC1->CR1|=(1<<8);		//扫描模式
			
	ADC1->CR2&=~(1<<1);		//单次转换
	ADC1->CR2&=~(1<<11);	//数据右对齐
	ADC1->CR2&=~(3<<28);	//禁止触发检测
			
	ADC1->SQR1&=~(0XF<<20);	//重置规则通道序重置列长度
	ADC1->SQR1|=1<<20;     	//2个转换在规则序列中
			
	//设置通道0的采样时间
	ADC1->SMPR2&=~(7<<(3*0));		//通道0	采样时间清空	  
	ADC1->SMPR2|=(7<<(3*0)); 		//通道0  480个周期,提高采样时间可以提高精确度
	//设置通道3的采样时间
	ADC1->SMPR2&=~(7<<(3*3));		//通道3	采样时间清空	  
	ADC1->SMPR2|=(7<<(3*3)); 		//通道3  480个周期,提高采样时间可以提高精确度
			
	ADC1->CR2|=1<<8;			//使能DMA模式
	ADC1->CR2|=1<<0;	   	//开启AD转换器	  
}

主函数里面使用方法也是一样的

4.3测试 

首先把PA0接地

可以看到第0位数据为0了

然后再把PA3接地

可以看到第1为是0了

5.结语

STM32F407多通道扫描模式至此就结束了,整个过程还是比较简单的。这样一来ADC的使用范围也比较大了。在此之外ADC还有一个非连续扫描模式,那么我们下一篇文章去看。那么好的,还是老样子,有什么问题评论区见,我们下一篇文章见。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于React和TypeScript的金融市场模拟器开发与模式分析

基于React和TypeScript的金融市场模拟器开发与模式分析 项目概述 本项目开发了一个基于React和TypeScript的金融市场模拟器&#xff0c;通过模拟订单流和价格发现机制&#xff0c;重现了真实市场的动态特性。该模拟器不仅提供了实时价格图表、订单簿和交易功能&#xff0c;还…

reverse_ssh 建立反向 SSH 连接指南 混淆AV [好东西哟]

目录 &#x1f310; 工具简介 ⚙️ 前提条件 攻击主机 (Linux) 目标主机 (Windows) &#x1f4cb; 详细步骤 步骤 1&#xff1a;安装 Go 环境 步骤 2&#xff1a;安装必要依赖 步骤 3&#xff1a;下载并编译 reverse_ssh 步骤 4&#xff1a;配置密钥 步骤 5&#xff…

lvs-keepalived高可用群集

目录 1.Keepalived 概述及安装 1.1 Keepalived 的热备方式 1.2 keepalived的安装与服务控制 &#xff08;1&#xff09;安装keep alived (2)控制 Keepalived 服务DNF 安装 keepalived 后,执行以下命令将keepalived 服务设置为开机启动。 2.使用 Keepalived 实现双机热备 …

高速收发器

一、高速收发器 1.FPGA高速收发器&#xff1a;GTP,GTX,GTH,GTZ 2.每个Quad有4对高速收发器GT(4个TX和4个RX)和一个COmmon 3.走差分&#xff0c;提高抗干扰性 4.CPLL是每个lane私有的&#xff0c;QPLL是整个Quad的所有通道共享的 5.每个MGT的bank有两对差分参考时钟 6.CPLL的时钟…

webpack的安装及其后序部分

npm install原理 这个其实就是npm从registry下载项目到本地&#xff0c;没有什么好说的 值得一提的是npm的缓存机制&#xff0c;如果多个项目都需要同一个版本的axios&#xff0c;每一次重新从registry中拉取的成本过大&#xff0c;所以会有缓存&#xff0c;如果缓存里有这个…

如何利用自动生成文档工具打造出色的技术文档

文章目录 每日一句正能量前言一、自动生成文档工具的优势&#xff08;一&#xff09;提高效率&#xff08;二&#xff09;保持一致性&#xff08;三&#xff09;实时更新 二、常见的自动生成文档工具&#xff08;一&#xff09;Sphinx&#xff08;二&#xff09;Javadoc&#x…

实验设计与分析(第6版,Montgomery)第5章析因设计引导5.7节思考题5.7 R语言解题

本文是实验设计与分析&#xff08;第6版&#xff0c;Montgomery著&#xff0c;傅珏生译) 第5章析因设计引导5.7节思考题5.7 R语言解题。主要涉及方差分析&#xff0c;正态假设检验&#xff0c;残差分析&#xff0c;交互作用图&#xff0c;等值线图。 dataframe <-data.frame…

OpenCv高阶(二十)——dlib脸部轮廓绘制

文章目录 一、人脸面部轮廓绘制代码实现1、定义绘制直线段的函数2、定义绘制凸包轮廓的函数3、读取输入图像4、初始化dlib的人脸检测器5、使用检测器在图像中检测人脸&#xff08;参数0表示不进行图像缩放&#xff09;6、加载dlib的68点人脸关键点预测模型7、遍历检测到的每个人…

pikachu靶场通关笔记08 XSS关卡04-DOM型XSS

目录 一、XSS原理 二、DOM型XSS 三、源码分析 1、进入靶场 2、XSS探测 3、源码分析 四、渗透实战 1、Payload1 2、Payload2 3、Payload3 本系列为通过《pikachu靶场通关笔记》的XSS关卡(共10关&#xff09;渗透集合&#xff0c;通过对XSS关卡源码的代码审计找到XSS风…

Spring AI 系列之使用 Spring AI 开发模型上下文协议(MCP)

1. 概述 现代网页应用越来越多地集成大型语言模型&#xff08;LLMs&#xff09;来构建解决方案&#xff0c;这些解决方案不仅限于基于常识的问答。 为了增强 AI 模型的响应能力&#xff0c;使其更具上下文感知&#xff0c;我们可以将其连接到外部资源&#xff0c;比如搜索引擎…

[Python] Python运维:系统性能信息模块psutil和系统批量运维管理器paramiko

初次学习&#xff0c;如有错误还请指正 目录 系统性能信息模块psutil 获取系统性能信息 CPU信息 内存信息 磁盘信息 网络信息 其他信息 进程信息 实用的IP地址处理模块IPy IP地址、网段的基本处理 多网络计算方法 系统批量运维管理器paramiko paramiko 的安装 Li…

Linux 简单模拟实现C语言文件流

&#x1f307;前言 在 C语言 的文件流中&#xff0c;存在一个 FILE 结构体类型&#xff0c;其中包含了文件的诸多读写信息以及重要的文件描述符 fd&#xff0c;在此类型之上&#xff0c;诞生了 C语言 文件相关操作&#xff0c;如 fopen、fclose、fwrite 等&#xff0c;这些函数…

小程序使用npm包的方法

有用的链接 npm init -y 这个命令很重要, 会初始化 package.json 再重新打开微信小程序开发工具 选择工具中npm构建 在程序中引用时在main.js中直接使用包名的方式引用即可 如安装的是generator包&#xff0c;npm构建后就会生成 const myPackage require(***-generato…

Rust 学习笔记:发布一个 crate 到 crates.io

Rust 学习笔记&#xff1a;发布一个 crate 到 crates.io Rust 学习笔记&#xff1a;发布一个 crate 到 crates.io提供有用的文档注释常用标题文档注释作为测试注释所包含的项目 使用 pub use 导出一个方便的公共 API设置 crates.io 账户添加 metadata 到一个新的 crate发布到 c…

Vert.x学习笔记-EventLoop与Context的关系

Vert.x学习笔记 1. EventLoop 的核心作用2. Context 的核心作用3. EventLoop 与 Context 的关系1. 事件循环&#xff08;EventLoop&#xff09;的核心职责2. 上下文&#xff08;Context&#xff09;的核心职责3. 事件循环与上下文的关系&#xff08;1&#xff09;一对一绑定&am…

2025030给荣品PRO-RK3566开发板单独升级Android13的boot.img

./build.sh init ./build.sh -K ./build.sh kernel 【导入配置文件】 Z:\Android13.0\rockdev\Image-rk3566_t\config.cfg 【更新的内核】 Z:\Android13.0\rockdev\Image-rk3566_t\boot.img 【导入分区表&#xff0c;使用原始的config.cfg会出错的^_】 Z:\Android13.0\rockdev\…

由enctype-引出post与get的关系,最后深究至请求/响应报文

本篇载自我的笔记&#xff0c;本次为第二次复习。我觉得我有能力理一下思路了。 --- 笔记截图。 enctype HTML 表单的 enctype&#xff08;Encode Type&#xff0c;编码类型&#xff09;属性用于控制表单数据在提交到服务器时的编码方式&#xff0c;不同取值的详细解析如下&a…

搭建基于VsCode的ESP32的开发环境教程

一、VsCode搜索ESP-IDF插件 根据插件处搜索找到ESP-IDF并安装 安装完成 二、配置安装ESP-IDF 配置IDF 按照如下配置&#xff0c;点击安装 安装完成 三、使用案例程序 创建一个闪光灯的例子程序&#xff0c;演示程序编译下载。 选择blink例子&#xff0c;闪烁LED的程序 选…

【MFC】初识MFC

目录 01 模态和非模态对话框 02 静态文本 static text 01 模态和非模态对话框 首先我们需要知道模态对话框和非模态对话框的区别&#xff1a; 模态对话框是一种阻塞时对话框&#xff0c;它会阻止用户与应用程序的其他部分进行交互&#xff0c;直到用户与该对话框进行交互并关…

如何通过数据分析优化项目决策

通过数据分析优化项目决策需从明确数据分析目标、选择适当的数据分析工具、确保数据质量、建立数据驱动文化等方面入手&#xff0c;其中&#xff0c;明确数据分析目标是优化决策过程的基础&#xff0c;只有清晰明确的数据分析目标才能指导有效的数据采集与分析&#xff0c;避免…