配置stm32cubemx采集stm32H743IIT6,通过DMA实现多通道和多模块ADC的采集,亲测有效!

news2024/11/15 8:46:50

 之前写到stm32cubemx通过阻塞实现单通道和多通道的ADC的采集。

本文分享通过DMA实现单模块多通道和多模块多通道的ADC采集。

stm32cubemx的版本6.10.0。

一、DMA采集多通道ADC数据

阻塞采集是每次采集adc数据,cpu死等,直到采集完或者在设定时间超时没能采集,返回到cpu。

DMA采集是每次采集adc数据,不占用cpu资源。

配置sm32cubemx:

1、配置时钟源

使用的是25M无源晶振。

这里power regulator voltage scale 选择“Power Regulator Voltage Scale 0”,系统时钟能达到480MHz。查看数据手册

2、时基选择系统滴答定时器

3、配置时钟

配置时钟为480MHz,系统自动生成时钟树。

ADC的时钟是64MHz。

4、配置ADC

选择通道18和19

DMA settings 里添加,Mode 选择“Circular”,Data Width选择“Half Word”,半字16位。

Continuous Conversion Mode(连续转换模式)

在连续转换模式下,如果发生软件或者硬件触发,ADC会执行所有常规通道的转换,随后会自动重启并继续执行每一个通道的转换

Conversion Data Managerment Mode(转换数据管理模式)

选择存放转换完成的模拟量数据的地方。

时钟设置为32MHz,

采样时间为32.5 时钟周期

转换时间=采样时间+7.5ADC时钟周期

=32.5+7.5 =40个时钟周期=1.25us

5、配置串口

6、调试模式

配置成SW模式

7、项目管理

配置完成后,生成初始化代码。

代码部分

(1)添加头文件

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

#include "stdio.h" //添加头文件
/* USER CODE END Includes */

(2)添加打印函数

/* USER CODE BEGIN 0 */

int fputc(int c, FILE *stream)    //重写fputc函数
{
 /*
    huart1是工具生成代码定义的UART1结构体,
    如果以后要使用其他串口打印,只需要把这个结构体改成其他UART结构体。
*/
    HAL_UART_Transmit(&huart1, (unsigned char *)&c, 1, 1000);   
    return 1;
}

/* USER CODE END 0 */

(3)添加变量

int main(void)
{
  /* USER CODE BEGIN 1 */
uint16_t ADC_Value[100];//定义16位的100个数据的数组,存储adc的数据
	uint8_t i;
	uint32_t ad1,ad2;//采集数据平均值
	float ad1x,ad2x;//电压值
	float ADCx;//转换后的电压值

  /* USER CODE END 1 */

(4)启动ADC的DMA转换

  /* USER CODE BEGIN 2 */
  MX_ADC1_Init();//初始化ADC1,

HAL_ADC_Start_DMA(&hadc1,(uint32_t *)&ADC_Value,100); //直接采集到50组,通道4和通道5的数据,ADC_Value[i],偶数存的是通道4的数据,奇数存的是通道5的数据
printf("<<<<<<<ADC many channel DMA test\r\n");
HAL_Delay(2000);
  /* USER CODE END 2 */

DMA每次使能,会把选择的通道都采集一次。

(5)while添加采集

 while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		
		
		ad1=0,ad2=0;//清零

		for(i=0;i<50;i++) 
		{
			ad1+=ADC_Value[2*i]; //通道4数据累加
			ad2+=ADC_Value[2*i+1];//通道5数据累加
		}
		ad1/=50;//求平均值
		ad2/=50;//求平均值
		ad1x =ad1 *3.3/65536; //转化为电压值
		ad2x =ad2 *3.3/65536;  //转化为电压值
		printf("\r\n ****ADC DMA Example****\r\n\r\n");
    printf("AD1 value = %d, AD1电压是%.2fV\r\n",ad1,ad1x);
		printf("AD2 value = %d, AD2电压是%.2fV\r\n",ad2,ad2x);
		HAL_Delay(1000);
				
  }
  /* USER CODE END 3 */

(6)添加adc校准函数

这里很关键!stm32cubemx初始化不包含校准函数,需要自己手动添加。

在adc.c的初始化函数void MX_ADC1_Init(void)内添加

  /* USER CODE BEGIN ADC1_Init 2 */
  HAL_ADCEx_Calibration_Start(&hadc1, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED); /* ADC校准 */
  /* USER CODE END ADC1_Init 2 */

(7)编译

stm32H7系列编译起来时间超级长

花了十分钟多。有两个解决办法:

①、不勾选“Browse information”

②编译器选择“version 6“

两个方法都能编译速度极大的提升!

Debug一次。

能看到直接采集100个数据,保存到数组里。

运行

二、DMA多模块多通道ADC数据

和单模块多通道ADC数据一样的配置就不贴图了。

(1)ADC配置

增加ADC模块ADC3的芯片温度和内部基准电压采集,采集时间设置为850.5个周期

时钟设置为32MHz,

采样时间为810.5时钟周期

转换时间=采样时间+7.5ADC时钟周期

=810.5+7.5 =812个时钟周期=25.375us

配置完成后,生成初始化代码。

代码部分

(1)添加头文件

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

#include "stdio.h" //添加头文件
/* USER CODE END Includes */

(2)添加打印函数

/* USER CODE BEGIN 0 */

int fputc(int c, FILE *stream)    //重写fputc函数
{
 /*
    huart1是工具生成代码定义的UART1结构体,
    如果以后要使用其他串口打印,只需要把这个结构体改成其他UART结构体。
*/
    HAL_UART_Transmit(&huart1, (unsigned char *)&c, 1, 1000);   
    return 1;
}

/* USER CODE END 0 */

(3)添加变量

int main(void)
{
   /* USER CODE BEGIN 1 */

uint16_t ADC1_Value[100];//定义16位的100个数据的数组,存储adc的数据
uint16_t ADC3_Value[100];//定义16位的100个数据的数组,存储adc的数据
	
	uint8_t i;
	uint32_t ad1,ad2;//平均值
	uint32_t ad3,ad4;//平均值
	float ad1x,ad2x;//转换后的电压值
	float ad3x,ad4x;//转换后的电压值
	float temp; //芯片内部温度
  
	
  /* USER CODE END 1 */

(4)启动ADC的DMA转换

 /* USER CODE BEGIN 2 */
HAL_ADC_Start_DMA(&hadc1,(uint32_t *)&ADC1_Value,100); //直接采集到50组,通道4和通道5的数据,ADC_Value[i],偶数存的是通道4的数据,奇数存的是通道5的数据
HAL_ADC_Start_DMA(&hadc3,(uint32_t *)&ADC3_Value,100); //直接采集到50组,通道4和通道5的数据,ADC_Value[i],偶数存的是通道4的数据,奇数存的是通道5的数据

printf("<<<<<<<ADC + many module+channel DMA test\r\n");
HAL_Delay(2000);
  /* USER CODE END 2 */

(5)while添加采集

  while (1)
  {
		
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		ad1=0,ad2=0;
		ad3=0,ad4=0;
		
			for(i=0;i<50;i++) 
		{
			ad1+=ADC1_Value[2*i]; //通道4数据累加
			ad2+=ADC1_Value[2*i+1];//通道5数据累加
			ad3+=ADC3_Value[2*i]; //通道4数据累加
			ad4+=ADC3_Value[2*i+1];//通道5数据累加
		}
     ad1/=50;//求平均值
		 ad2/=50;//求平均值
		ad3/=50;//求平均值
		 ad4/=50;//求平均值
			ad1x =ad1 *3.3/65536;
		ad2x =ad2 *3.3/65536;
		ad3x =ad3 *3.3/65536;
		ad4x = (110.0-30.0)/(*(unsigned short*)(0x1FF1E840) - *(unsigned short*)(0x1FF1E820));//芯片内部温度计算公式
		temp = ad4x*(ad4 - *(unsigned short*)(0x1FF1E820))+30;//芯片内部温度计算公式
		//temp为最终的温度值

		
		printf("\r\n ****ADC DMA  Example****\r\n\r\n");
    printf("AD1 value = %d, AD1电压是%.2fV\r\n",ad1,ad1x);
		printf("AD2 value = %d, AD2电压是%.2fV\r\n",ad2,ad2x);
		 printf("AD3 value = %d, AD3内部参考电压是%.2fV\r\n",ad3,ad3x);
		printf("AD4 value = %d, AD4温度是%.2f℃\r\n",ad4,temp);
		HAL_Delay(1000);
  }
  /* USER CODE END 3 */
}

(6)添加adc校准函数

这里很关键!stm32cubemx初始化不包含校准函数,需要自己手动添加。

在adc.c的初始化函数void MX_ADC1_Init(void)内添加

  /* USER CODE BEGIN ADC1_Init 2 */
  HAL_ADCEx_Calibration_Start(&hadc1, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED); /* ADC校准 */
  HAL_ADCEx_Calibration_Start(&hadc3, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED); /* ADC校准 */
  /* USER CODE END ADC1_Init 2 */

运行

验证准确性

(1)我们查看芯片数据手册,

内部参考电压是1.216V

采集的电压是1.21V,能够对的起来。

(2)内部温度

我们运行正点原子的例程

采集的温度在41.5到42摄氏度之间。

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

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

相关文章

不能使用乘除法、for、while、if、else、switch、case求1+2+3+...+n

求123...n_牛客题霸_牛客网 (nowcoder.com) 描述 求123...n&#xff0c;要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句&#xff08;A?B:C&#xff09;。 数据范围&#xff1a; 0<n≤2000<n≤200 进阶&#xff1a; 空间复杂度 O(1)O(…

PCRNet: Point Cloud Registration Network using PointNet Encoding 论文解读

目录 一、导言 二、先导知识 1、Frobenius范数 三、相关工作 1、点云配准工作 2、PointNet 3、基于深度学习的点云配准 四、PCRNet 1、PCRNet 2、Iterative PCRNet 3、损失函数 五、实验 一、导言 本论文收录于CVPR2019&#xff0c;本论文提出了一种依赖PointNet网…

快排补充(挖坑法,lomuto前后指针,非递归法)

挖坑法 挖坑法动态示意图 挖坑法方法分析 创建左右指针。⾸先从右向左找出⽐基准⼩的数据&#xff0c;找到后⽴即放⼊左边坑中&#xff0c;当前位置变为新 的"坑"&#xff0c;然后从左向右找出⽐基准⼤的数据&#xff0c;找到后⽴即放⼊右边坑中&#xff0c;当前位置…

STM32——CAN通讯基础知识

CAN 协议简介 CAN 是控制器局域网络 (Controller Area Network) 的简称&#xff0c;它是由研发和生产汽车电子产品著称的德国 BOSCH 公司开发的&#xff0c;并最终成为国际标准(ISO11519以及ISO11898),是国际上应用最广泛的现场总线之一。差异点如下&#xff1a; 高速CAN可以达…

关于shortlink项目重构增加了del_time字段自己出现的问题

最近刚做完shortlink项目的重构问题,其中增加del_time作为t_link表的唯一索引要注意几点问题. 1.数据库表中的del_time字段类型为什么,一定要和DO中的类型统一. 2.del_time作为唯一索引不要写死了,不然就无法创建短连接了,这里我是将del_time修改成date类型,然后通过new date…

Python数分实战

学习视频&#xff1a;【课程3.0】Python基础与分析实战_哔哩哔哩_bilibili 由于学习过python进行数据分析&#xff0c;所以就简单记录一下&#xff0c;最主要学习的还是视频最后的两个项目&#xff0c;进行实战 之前想不明白明明有很智能的软件做数据分析&#xff0c;为什么还要…

XXX【5】观察者模式

文件分割案例&#xff1a; 用户输入文件路径filePath和分割数量number&#xff0c;初始化出一个FileSplitter实例对象&#xff0c;然后调用split方法文件分割。 假如&#xff1a;我要加一个进度条的设计 抽象不能依赖于实现细节&#xff1a;在第6行的m_progressBar是一个进度通…

【深度解析】WRF-LES与PALM微尺度气象大涡模拟

查看原文>>>【深度解析】WRF-LES与PALM微尺度气象大涡模拟 针对微尺度气象的复杂性&#xff0c;大涡模拟&#xff08;LES&#xff09;提供了一种无可比拟的解决方案。微尺度气象学涉及对小范围内的大气过程进行精确模拟&#xff0c;这些过程往往与天气模式、地形影响和…

vimplus出现的错误,如何解决??

&#x1f3c6;本文收录于《CSDN问答解惑-专业版》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收…

C++面向对象编程(上)

类与对象属于面向对象的程序设计思想(Object Oriented Programming)&#xff0c;简称OOP。 面向对象基础理论 面向对象是一种对现实世界理解和抽象的方法&#xff0c;是计算机编程技术发展到一定阶段后的产物&#xff0c;是一种软件开发的方法 面向对象四大特性 1.抽象 忽…

数据库(五):多表设计和多表查询

项目开发中&#xff0c;在进行数据库表结构设计时&#xff0c;会根据业务需求及业务模块之间的关系&#xff0c;分析并设计表结构&#xff0c;由于业务之间相互关联&#xff0c;所以各个表结构之间也存在各种联系&#xff0c;基本上分为三种&#xff1a;一对一、多对一、一对多…

如何在寂静中用电脑找回失踪的手机?远程控制了解一下

经过一番努力&#xff0c;我终于成功地将孩子哄睡了。夜深人静&#xff0c;好不容易有了一点自己的时间&#xff0c;就想刷手机放松放松&#xff0c;顺便看看有没有重要信息。但刚才专心哄孩子去了&#xff0c;一时就忘记哄孩子之前&#xff0c;顺手把手机放哪里去了。 但找过手…

进程相关知识

进程和程序的区别 程序 程序是静态的&#xff0c;是存储在硬盘、SSD等存储介质中的一个文件&#xff0c;通常由源代码&#xff08;如 .c 文件&#xff09;编译生成的二进制可执行文件&#xff08;如 a.out&#xff09;。程序包含了指令和数据&#xff0c;但在未被执行时&#…

【计算机操作系统】基本分页存储管理

文章目录 基本分页存储管理分页存储的概念重要的数据结构——页表页表项大小计算地址转换实现 基本地址变换机构具有快表的地址变换机构快表&#xff08;TLB&#xff09;的概念引入快表后的地址变换局部性原理 两级页表单级页表 vs 两级页表 基本分页存储管理 非连续分配&#…

使用Python编写AI程序,让机器变得更智能

人工智能&#xff08;AI&#xff09;是当今科技领域最热门的话题之一。随着Python编程语言的逐渐流行&#xff0c;它已经成为许多人工智能编程的首选语言。本文将介绍如何使用Python编写AI程序&#xff0c;让机器变得更智能。 首先&#xff0c;Python提供了大量的AI库和工具&a…

Easysearch 性能测试方法概要

&#xff08;公众号用的是QQ音乐&#xff0c;可以随时听&#xff09; INFINI Easysearch INFINI Easysearch 是一个分布式的近实时搜索与分析引擎&#xff0c;核心引擎基于开源的 Apache Lucene。Easysearch 衍生自基于开源协议Apache 2.0 的Elasticsearch 7.10 版本&#xff0…

4-1-2 直流电机(电机专项教程)

4-1-2 直流电机&#xff08;电机专项教程&#xff09; 4-1-2 直流电机主要参数尺寸参数额定电压额定电流空载转速 如何控制直流电机有刷直流电机转向控制H桥电路控制转向 如何控制电机转速PWM控制电机转速 4-1-2 直流电机 之前学习了有刷直流电机的基本结构个工作原理&#xff…

[数据集][图像分类]电力场景电力线固定处连接处腐蚀有鸟巢分类数据集1279张3类别

数据集类型&#xff1a;图像分类用&#xff0c;不可用于目标检测无标注文件 数据集格式&#xff1a;仅仅包含jpg图片&#xff0c;每个类别文件夹下面存放着对应图片 图片数量(jpg文件个数)&#xff1a;1279 分类类别数&#xff1a;3 类别名称:["corrosion","nes…

SparkSQL遵循ANSI标准

ANSI简介 ANSI Compliance通常指的是遵循美国国家标准学会&#xff08;American National Standards Institute, ANSI&#xff09;制定的标准。在计算机科学和技术领域&#xff0c;这通常涉及到数据库管理系统&#xff08;DBMS&#xff09;对于SQL语言的支持程度。 ANSI为SQL…

FreeRTOS 快速入门(二)之内存管理

目录 一、概述二、FreeRTOS 中管理内存的 5 种方法1、Heap_12、Heap_23、Heap_34、Heap_44.1 内存申请4.2 内存释放 5、Heap_5 三、Heap 相关的函数1、pvPortMalloc/vPortFree2、xPortGetFreeHeapSize3、xPortGetMinimumEverFreeHeapSize4、malloc 失败的钩子函数 一、概述 在…