当前位置: 首页 > news >正文

STM32 DMA+AD多通道

接线图

代码配置

ADC单次扫描+DMA单次转运模式

uint16_t AD_Value[4];
//DMA+AD多通道
void DMA_Config(void)
{//定义结构体变量
GPIO_InitTypeDef GPIO_InitStructure;//定义GPIO结构体变量
ADC_InitTypeDef ADC_InitStructure;  //定义ADC结构体变量
DMA_InitTypeDef DMA_InitStructure;//定义DMA结构体变量//开启RCC时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//开启ADC1的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//开启GPIO A族时钟
RCC_ADCCLKConfig(RCC_PCLK2_Div6);                   //配置分频器 选择6分频 分频之后ADCCLK = 72MHz/6 = 12MHz
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);//开启DMA1的时钟
//配置GPIO
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);   //GPIO初始化//配置多路开关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);//配置ADC转换器
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//选择连续转换模式还是单次转换 本次单次转换
ADC_InitStructure.ADC_DataAlign =ADC_DataAlign_Right; //指定ADC数据是左对齐还是右对齐 这次选择右对齐
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//触发控制的触发源 本次使用软件触发
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//配置独立模式还是双ADC模式 这里选独立模式
ADC_InitStructure.ADC_NbrOfChannel = 4;//在扫描模式下,总共会用到几个通道 
ADC_InitStructure.ADC_ScanConvMode = ENABLE;//选择扫描模式还是非扫描模式 本次扫描模式
ADC_Init(ADC1, &ADC_InitStructure);//配置DMA
//外设站点
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;//外设站点的基地址,这里要写一个32位的地址
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//数据宽度 半字16位来转运
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//地址是否自增
//存储器站点
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)AD_Value;//存储器站点的及地址
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//数据宽度
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器站点地址自增
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//传输方向 选择外设站点到存储器站点
DMA_InitStructure.DMA_BufferSize = 4;//传输次数
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//传输计数器是否自动重装 这里选择正常模式不自动重装
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//选择触发源,这里选择软件触发
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//通道优先级DMA_Init(DMA1_Channel1, &DMA_InitStructure);//使能
DMA_Cmd(DMA1_Channel1,ENABLE);//使能DMA//开启ADC到DMA的输出
ADC_DMACmd(ADC1, ENABLE);//开关控制 开启ADC
ADC_Cmd(ADC1,ENABLE);//开启ADC电源//校准
ADC_ResetCalibration(ADC1);//复位校准
while(ADC_GetResetCalibrationStatus(ADC1) == SET);//返回复位校准状态
ADC_StartCalibration(ADC1);//开始校准
while(ADC_GetCalibrationStatus(ADC1) == SET);//获取校准状态}

功能函数

void DMA_GetValue(void)
{DMA_Cmd(DMA1_Channel1,DISABLE);//失能DMADMA_SetCurrDataCounter(DMA1_Channel1, 4);//转运数据DMA_Cmd(DMA1_Channel1,ENABLE);//使能DMAADC_SoftwareStartConvCmd(ADC1, ENABLE);//软件触发//等待转运完成while(DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);DMA_ClearFlag(DMA1_FLAG_TC1);//清除标志位}

主函数

需要在头函数将AD_Value extern引用一下才能在主函数里使用

#include "MyDMA.h"
int main(void)
{OLED_Init();DMA_Config();OLED_ShowString(1, 1, "AD0:");OLED_ShowString(2, 1, "AD1:");OLED_ShowString(3, 1, "AD2:");OLED_ShowString(4, 1, "AD3:");while(1){DMA_GetValue();OLED_ShowNum(1, 6, AD_Value[0], 4);OLED_ShowNum(2, 6, AD_Value[1], 4);OLED_ShowNum(3, 6, AD_Value[2], 4);OLED_ShowNum(4, 6, AD_Value[3], 4);}}

ADC连续扫描+DMA循环模式

在上一个函数的基础上修改几个参数,将ADC单次扫描改为连续扫描,DMA模式选择位循环模式,这种模式就不需要写功能函数了,主函数里直接可以用

将ADC触发放到最后

//DMA+AD多通道
void DMA_Config(void)
{//定义结构体变量GPIO_InitTypeDef GPIO_InitStructure;//定义GPIO结构体变量ADC_InitTypeDef ADC_InitStructure;  //定义ADC结构体变量DMA_InitTypeDef DMA_InitStructure;//定义DMA结构体变量//开启RCC时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//开启ADC1的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//开启GPIO A族时钟RCC_ADCCLKConfig(RCC_PCLK2_Div6);                   //配置分频器 选择6分频 分频之后ADCCLK = 72MHz/6 = 12MHzRCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);//开启DMA1的时钟//配置GPIOGPIO_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);   //GPIO初始化//配置多路开关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);//配置ADC转换器ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//选择连续转换模式还是单次转换 本次连续转换ADC_InitStructure.ADC_DataAlign =ADC_DataAlign_Right; //指定ADC数据是左对齐还是右对齐 这次选择右对齐ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//触发控制的触发源 本次使用软件触发ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//配置独立模式还是双ADC模式 这里选独立模式ADC_InitStructure.ADC_NbrOfChannel = 4;//在扫描模式下,总共会用到几个通道 ADC_InitStructure.ADC_ScanConvMode = ENABLE;//选择扫描模式还是非扫描模式 本次扫描模式ADC_Init(ADC1, &ADC_InitStructure);//配置DMA//外设站点DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;//外设站点的基地址,这里要写一个32位的地址DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//数据宽度 半字16位来转运DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//地址是否自增//存储器站点DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)AD_Value;//存储器站点的及地址DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//数据宽度DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器站点地址自增DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//传输方向 选择外设站点到存储器站点DMA_InitStructure.DMA_BufferSize = 4;//传输次数DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//传输计数器是否自动重装 这里选择循环模式DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//选择触发源,这里选择软件触发DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//通道优先级DMA_Init(DMA1_Channel1, &DMA_InitStructure);//使能DMA_Cmd(DMA1_Channel1,ENABLE);//使能DMA//开启ADC到DMA的输出ADC_DMACmd(ADC1, ENABLE);//开关控制 开启ADCADC_Cmd(ADC1,ENABLE);//开启ADC电源//校准ADC_ResetCalibration(ADC1);//复位校准while(ADC_GetResetCalibrationStatus(ADC1) == SET);//返回复位校准状态ADC_StartCalibration(ADC1);//开始校准while(ADC_GetCalibrationStatus(ADC1) == SET);//获取校准状态ADC_SoftwareStartConvCmd(ADC1, ENABLE);//软件触发}

主函数

#include "MyDMA.h"
int main(void)
{OLED_Init();DMA_Config();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, 6, AD_Value[0], 4);OLED_ShowNum(2, 6, AD_Value[1], 4);OLED_ShowNum(3, 6, AD_Value[2], 4);OLED_ShowNum(4, 6, AD_Value[3], 4);}}

相关文章:

STM32 DMA+AD多通道

接线图 代码配置 ADC单次扫描DMA单次转运模式 uint16_t AD_Value[4]; //DMAAD多通道 void DMA_Config(void) {//定义结构体变量 GPIO_InitTypeDef GPIO_InitStructure;//定义GPIO结构体变量 ADC_InitTypeDef ADC_InitStructure; //定义ADC结构体变量 DMA_InitTypeDef DMA_In…...

如何构建ObjC语言编译环境?构建无比简洁的clang编译ObjC环境?Windows搭建Swift语言编译环境?

如何构建ObjC语言编译环境? 除了在线ObjC编译器,本地环境Windows/Mac/Linux均可以搭建ObjC编译环境。 Mac自然不用多说,ObjC是亲儿子。(WSL Ubuntu 22.04) Ubuntu可以安装gobjc/gnustep和gnustep-devel构建编译环境。 sudo apt-get install gobjc gnus…...

【C语言】指针详解:概念、类型与解引用

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C语言 文章目录 💯前言💯指针的基本概念1. 什么是指针2. 指针的基本操作 💯指针的类型1. 指针的大小2. 指针类型与所指向的数据类型3. 指针类型与数据访问的关系4. 指针类型的实际意…...

VoIP中常见术语

在 VoIP(Voice over Internet Protocol,基于互联网协议的语音传输)技术中,涉及许多专业术语。以下是常见术语及其含义: 1. 核心协议相关 SIP(Session Initiation Protocol,会话发起协议&#xf…...

360嵌入式开发面试题及参考答案

解释一下 802.11ax 和 802.11ac/n 有什么区别 速度与带宽 802.11n 支持的最高理论速率为 600Mbps,802.11ac 进一步提升,单流最高可达 866.7Mbps,多流情况下能达到更高,如 1.3Gbps 等。而 802.11ax(Wi-Fi 6)引入了更多先进技术,理论最高速率可达 9.6Gbps,相比前两者有大…...

物理群晖SA6400核显直通win10虚拟机(VMM)

写在前面:请先确保你的核显驱动支持开启SR-IOV 确保你的BIOS开启了以下选项: VT-D VMX IOMMU Above 4G ResizeBAR 自行通过以下命令确认支持情况: dmesg | grep -i iommudmesg | grep DMAR分配1个虚拟vGPU:echo 1 | sudo tee /sy…...

【NLP 20、Encoding编码 和 Embedding嵌入】

目录 一、核心定义与区别 二、常见Encoding编码 (1) 独热编码(One-Hot Encoding) (2) 位置编码(Positional Encoding) (3) 标签编码(Label Encoding) (4) 注意事项 三、常见Embedding词嵌入 (1) 基础词嵌入…...

雷赛LC2000

【一,概述】 这个是中型PLC 【二,外观】 网口编号: 【2】【3】 //默认ip:192.168.1.xxx 【0】【1】 可视化授权不如禾川Q系。 【三,总线轴】 因为本次带的轴是台达A2系列伺服 A2最快总线是【1ms】的倍数…...

ESP32开发工具介绍:Thonny——初学者的MicroPython利器

文章目录 引言什么是 Thonny?为什么选择 Thonny 开发 ESP32?1. **MicroPython 的天然支持**2. **极简的配置流程**3. **适合快速原型开发**如何用 Thonny 开发 ESP32?步骤 1:准备工作步骤 2:烧录 MicroPython 固件步骤 3:在 Thonny 中连接 ESP32步骤 4:编写并运行代码Th…...

【Go语言圣经】第六节:方法

第六章:方法 6.1 方法声明 在函数声明时,在其名字之前放上一个变量,这就是声明了变量对应类型的一个方法,相当于为这种类型定义了一个独占的方法。 下例为 Point 类型声明了计算两个点之间距离的方法: package mai…...

【Leetcode刷题记录】45. 跳跃游戏 II--贪心算法

45. 跳跃游戏 II 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 每个元素 nums[i] 表示从索引 i 向后跳转的最大长度。换句话说&#xff0c;如果你在 nums[i] 处&#xff0c;你可以跳转到任意 nums[i j] 处: 0 < j < nums[i]i j < n 返回到达 num…...

mysql_init和mysql_real_connect的形象化认识

解析总结 1. mysql_init 的作用 mysql_init 用于初始化一个 MYSQL 结构体&#xff0c;为后续数据库连接和操作做准备。该结构体存储连接配置及状态信息&#xff0c;是 MySQL C API 的核心句柄。 示例&#xff1a; MYSQL *conn mysql_init(NULL); // 初始化连接句柄2. mysql_…...

Qt网络相关

“ 所有生而孤独的人&#xff0c;葆有的天真 ” 为了⽀持跨平台, QT对⽹络编程的 API 也进⾏了重新封装。本章会上手一套基于QT的网络通信编写。 UDP Socket 在使用Qt进行网络编程前&#xff0c;需要在Qt项目中的.pro文件里添加对应的网络模块( network ). QT core gui net…...

deepseek接入pycharm 进行AI编程

要将DeepSeek接入PyCharm进行AI编程,可以按照以下步骤操作: ### 1. 获取DeepSeek API访问权限 DeepSeek通常以API的形式对外提供服务,你需要在其官方网站注册账号,申请API访问权限。在申请通过后,会获得API密钥(API Key),这是后续调用API的关键凭证。 ### 2. 安装必要…...

Verilog基础(三):过程

过程(Procedures) - Always块 – 组合逻辑 (Always blocks – Combinational) 由于数字电路是由电线相连的逻辑门组成的&#xff0c;所以任何电路都可以表示为模块和赋值语句的某种组合. 然而&#xff0c;有时这不是描述电路最方便的方法. 两种always block是十分有用的&am…...

生成式AI安全最佳实践 - 抵御OWASP Top 10攻击 (上)

今天小李哥将开启全新的技术分享系列&#xff0c;为大家介绍生成式AI的安全解决方案设计方法和最佳实践。近年来&#xff0c;生成式 AI 安全市场正迅速发展。据 IDC 预测&#xff0c;到 2025 年全球 AI 安全解决方案市场规模将突破 200 亿美元&#xff0c;年复合增长率超过 30%…...

.Net WebAPI -[HttpPut(“{fileServiceId:int}“)]

[HttpPut("{fileServiceId:int}")] 这个写法是 ASP.NET Core 中的一个路由特性&#xff0c;用于定义一个 HTTP PUT 请求的路由&#xff0c;并指定路由参数的类型。 解析 HttpPut [HttpPut]&#xff1a; 这是一个 ASP.NET Core 的路由特性&#xff0c;用于标记一个方…...

[EAI-027] RDT-1B,目前最大的用于机器人双臂操作的机器人基础模型

Paper Card 论文标题&#xff1a;RDT-1B: a Diffusion Foundation Model for Bimanual Manipulation 论文作者&#xff1a;Songming Liu, Lingxuan Wu, Bangguo Li, Hengkai Tan, Huayu Chen, Zhengyi Wang, Ke Xu, Hang Su, Jun Zhu 论文链接&#xff1a;https://arxiv.org/ab…...

C基础寒假练习(7)

一、有 1、2、3、4个数字&#xff0c;能组成多少互不相同且无重复的三位&#xff1f; 都是多少&#xff1f; #include <stdio.h> int main() {// 定义数字数组int digits[] {1, 2, 3, 4};int n sizeof(digits) / sizeof(digits[0]);// 嵌套循环遍历所有排列for (int …...

Ajax:重塑Web交互体验的人性化探索

在数字化时代&#xff0c;网页的交互性和响应速度已成为衡量用户体验的关键指标。Ajax&#xff08;Asynchronous JavaScript and XML&#xff09;&#xff0c;作为前端与后端沟通的桥梁&#xff0c;凭借其异步通信的能力&#xff0c;极大地提升了网页的动态性和用户友好度&…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

第25节 Node.js 断言测试

Node.js的assert模块主要用于编写程序的单元测试时使用&#xff0c;通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试&#xff0c;通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

【Linux】Linux 系统默认的目录及作用说明

博主介绍&#xff1a;✌全网粉丝23W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...

CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝

目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为&#xff1a;一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...

数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !

我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...

【Ftrace 专栏】Ftrace 参考博文

ftrace、perf、bcc、bpftrace、ply、simple_perf的使用Ftrace 基本用法Linux 利用 ftrace 分析内核调用如何利用ftrace精确跟踪特定进程调度信息使用 ftrace 进行追踪延迟Linux-培训笔记-ftracehttps://www.kernel.org/doc/html/v4.18/trace/events.htmlhttps://blog.csdn.net/…...

Axure零基础跟我学:展开与收回

亲爱的小伙伴,如有帮助请订阅专栏!跟着老师每课一练,系统学习Axure交互设计课程! Axure产品经理精品视频课https://edu.csdn.net/course/detail/40420 课程主题:Axure菜单展开与收回 课程视频:...

C#最佳实践:为何优先使用as或is而非强制转换

C#最佳实践&#xff1a;为何优先使用as或is而非强制转换 在 C# 的编程世界里&#xff0c;类型转换是我们经常会遇到的操作。就像在现实生活中&#xff0c;我们可能需要把不同形状的物品重新整理归类一样&#xff0c;在代码里&#xff0c;我们也常常需要将一个数据类型转换为另…...