【stm32HAL库】ADC多通道DMA采集

一、介绍一下HAL库函数

1.ADC

 

2.DMA

 

二、实验思路

1.根据数据手册直到PC1,PA2,PA3分别为ADC123的通道11,2,3,我们就用这三个通道来采集,每一个通道采集 50 次,即一共需要DMA传输150个数据

2.由于我们是DMA直接得到的ADC的原始数据,若是我们不进行处理就继续下一次传输,那么数据就会被覆盖,所以我们还打开DMA传输中断,在里面用标志位,用来判断是否传输完成,然后在main里面进行数据的处理

 三、HAL具体操作

1.初始化ADC和DMA结构体,然后用__HAL_LINKDMA();函数连接DMA和ADC的句柄

2.初始化ADC通道结构体,配置转换顺序

3.开启DMA的中断,开启ADC的DMA请求

4.编写MSP函数,配置GPIO,ADC和DMA的时钟,记得配置ADC的采样时钟

5.编写ADC_DMA传输启动函数

#define ADC_DMA_REC_NumOf_3_BUFFSIZE     	50*3
uint16_t adc_dma_rec_NumOf_3_buf[ADC_DMA_REC_NumOf_3_BUFFSIZE];
uint8_t g_adc_dma_sta=0;
DMA_HandleTypeDef g_dma_adc_handle;
ADC_HandleTypeDef g_adc_dma_handle;



void ADC_DMA_NumOf_3_Init(uint32_t rec_buf)
{
	__HAL_RCC_DMA1_CLK_ENABLE();
	
	ADC_ChannelConfTypeDef ADC_sConfig;
	
	g_adc_dma_handle.Instance = ADC1;
	g_adc_dma_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;//右对齐
	g_adc_dma_handle.Init.ScanConvMode = ADC_SCAN_ENABLE;//由于我们是多通道,所以用扫描模式
	g_adc_dma_handle.Init.ContinuousConvMode = ENABLE;//开启连续转换
	g_adc_dma_handle.Init.NbrOfConversion = 3;//转换通道个数
	g_adc_dma_handle.Init.DiscontinuousConvMode = DISABLE;//不用(不连续采用模式,只适用于扫描模式)间断模式
	g_adc_dma_handle.Init.NbrOfDiscConversion = 0;
	g_adc_dma_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;//软件触发
	HAL_ADC_Init(&g_adc_dma_handle);
	
	HAL_ADCEx_Calibration_Start(&g_adc_dma_handle);//开启校准
	
	ADC_sConfig.Channel = ADC_CHANNEL_11;//PC1
	ADC_sConfig.Rank	  = ADC_REGULAR_RANK_1;
	ADC_sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
	HAL_ADC_ConfigChannel(&g_adc_dma_handle, &ADC_sConfig);
	
	ADC_sConfig.Channel = ADC_CHANNEL_2;//PA2
	ADC_sConfig.Rank	  = ADC_REGULAR_RANK_2;
	HAL_ADC_ConfigChannel(&g_adc_dma_handle, &ADC_sConfig);
	
	ADC_sConfig.Channel = ADC_CHANNEL_3;//PA3
	ADC_sConfig.Rank	  = ADC_REGULAR_RANK_3;
	HAL_ADC_ConfigChannel(&g_adc_dma_handle, &ADC_sConfig);
	

	
	g_dma_adc_handle.Instance = DMA1_Channel1;
	g_dma_adc_handle.Init.Direction = DMA_PERIPH_TO_MEMORY;//P->M
	g_dma_adc_handle.Init.PeriphInc = DMA_PINC_DISABLE;//地址不自增
	g_dma_adc_handle.Init.MemInc = DMA_MINC_ENABLE;//地址自增
	g_dma_adc_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
	g_dma_adc_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
	g_dma_adc_handle.Init.Mode = DMA_NORMAL;//不循环转换,即开启一次DMA,转换一次
	g_dma_adc_handle.Init.Priority = DMA_PRIORITY_MEDIUM;
	HAL_DMA_Init(&g_dma_adc_handle);
	
	/*连接ADC和DMA句柄*/
	__HAL_LINKDMA(&g_adc_dma_handle,DMA_Handle,g_dma_adc_handle);
	

	//我们这里开启DMA的中断,在里面用标志位来表示数据传输完成
	HAL_NVIC_SetPriority(DMA1_Channel1_IRQn,3,3);
	HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
	

	HAL_DMA_Start_IT(&g_dma_adc_handle, (uint32_t)&ADC1->DR, rec_buf, 0);//传输0个,即先不传输
	HAL_ADC_Start_DMA(&g_adc_dma_handle,&rec_buf,0);//传输0个,即先不传输
	
}

void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
	if(hadc->Instance == ADC1)
	{
		RCC_PeriphCLKInitTypeDef  ADC_PeriphClkInit={0};

		__HAL_RCC_GPIOC_CLK_ENABLE();//PC1
		__HAL_RCC_ADC1_CLK_ENABLE();//开时钟
		GPIO_InitTypeDef GPIO_Init;
	
		GPIO_Init.Pin = GPIO_PIN_1;
		GPIO_Init.Mode = GPIO_MODE_ANALOG;
		HAL_GPIO_Init(GPIOC,&GPIO_Init);
	
		/*多通道配置*/
		__HAL_RCC_GPIOA_CLK_ENABLE();//PA2,PA3
		GPIO_Init.Pin = GPIO_PIN_2 | GPIO_PIN_3;
		GPIO_Init.Mode = GPIO_MODE_ANALOG;
		HAL_GPIO_Init(GPIOA,&GPIO_Init);
	
		ADC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;//选择配置ADC时钟
		ADC_PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;//6分频,即72/6=12M
		HAL_RCCEx_PeriphCLKConfig(&ADC_PeriphClkInit);
	}
}


/*转换开始函数*/
// 参数:cndtr,传输的个数,寄存器是低16位有效,所以设置16位
/*数据传输数量为0至65535。这个寄存器只能在通道不工作(DMA_CCRx的EN=0)时写入。通
道开启后该寄存器变为只读,指示剩余的待传输字节数目。*/
void ADC_DMA_Transfer(uint16_t cndtr)
{
	__HAL_ADC_DISABLE(&g_adc_dma_handle);
	__HAL_DMA_DISABLE(&g_dma_adc_handle);//先关闭ADC和DMA,以写入CNDTR要传输的数据个数
	while (DMA1_Channel1->CCR & (1 << 0));//检测是否DMA关闭了		
	DMA1_Channel1->CNDTR = cndtr;//设置传输数目
	__HAL_ADC_ENABLE(&g_adc_dma_handle);
	__HAL_DMA_ENABLE(&g_dma_adc_handle);//使能ADC和DMA
	
	HAL_ADC_Start(&g_adc_dma_handle);//软件触发ADC,开始ADC转换和DMA传输
}


/*DMA中断处理函数*/
void DMA1_Channel1_IRQHandler(void)
{
	
	if(__HAL_DMA_GET_FLAG(&g_dma_adc_handle,DMA_FLAG_TC1))//传输完成
	{
		g_adc_dma_sta = 1;//标志位置1
		__HAL_DMA_CLEAR_FLAG(&g_dma_adc_handle,DMA_FLAG_TC1);//清除传输完成标志位
		
	}
}

主函数 

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/delay/delay.h"
#include "led.h"
#include "usart.h"
#include "dma.h"
#include "adc.h"
#include "stdio.h"


#define ADC_DMA_REC_NumOf_3_BUFFSIZE     	50*3
extern DMA_HandleTypeDef g_dma_adc_handle;
extern ADC_HandleTypeDef hadc1,g_adc_dma_handle;
extern uint16_t adc_dma_rec_NumOf_3_buf[ADC_DMA_REC_NumOf_3_BUFFSIZE];
extern uint8_t g_adc_dma_sta;



int main(void)
{
    uint16_t adc_temp,i;
    uint32_t sum1,sum2,sum3;
    float adc_value;
    HAL_Init();                              /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9);      /* 设置时钟, 72Mhz */
    delay_init(72);                          /* 延时初始化 */
    LED_Init();                              /* LED初始化 */
    USART_Init(115200);

	ADC_DMA_NumOf_3_Init((uint32_t)&adc_dma_rec_NumOf_3_buf);
    ADC_DMA_Transfer(ADC_DMA_REC_NumOf_3_BUFFSIZE);
		
    while(1)
    { 
		if(g_adc_dma_sta==1)
		{
			sum1=sum2=sum3=0;
			for(i=0;i<50;i++)
			{
			sum1+=adc_dma_rec_NumOf_3_buf[(3*i)+0];//因为是CH11->CH2->CH3->CH11->CH2->CH3一直循环50次,所以同一个通道的数据之间位置相差3
			sum2+=adc_dma_rec_NumOf_3_buf[(3*i)+1];//因为是CH11->CH2->CH3->CH11->CH2->CH3一直循环50次,所以同一个通道的数据之间位置相差3
			sum3+=adc_dma_rec_NumOf_3_buf[(3*i)+2];//因为是CH11->CH2->CH3->CH11->CH2->CH3一直循环50次,所以同一个通道的数据之间位置相差3
			}

			adc_temp=sum1/50;
			adc_value = adc_temp*3.3/4096;
			printf("PC1\nadc_temp->%d\nadc_value->%.5f v\n\n\n\n",adc_temp,adc_value);
					
			adc_temp=sum2/50;
			adc_value = adc_temp*3.3/4096;
			printf("PA2\nadc_temp->%d\nadc_value->%.5f v\n\n\n\n",adc_temp,adc_value);
					
			adc_temp=sum3/50;
			adc_value = adc_temp*3.3/4096;
			printf("PA3\nadc_temp->%d\nadc_value->%.5f v\n\n\n\n",adc_temp,adc_value);
					
			delay_ms(2000);
			g_adc_dma_sta=0;
			ADC_DMA_Transfer(ADC_DMA_REC_NumOf_3_BUFFSIZE);	//开启下一次传输
		}
	 }
}


 

 

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

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

相关文章

镊子蜡烛如何抓住反转进行交易?昂首资本2步抓住反转

很多投资者通过之前的文章知道镊子烛台图&#xff0c;甚至可以通过镊子烛台图有多倍收益&#xff0c;但是很多投资者又迷惑了&#xff0c;为什么我没有通过镊子烛台图获得收益&#xff0c;甚至有时还会亏损收手。其实事情很容易理解&#xff0c;Anzo Capital昂首资本认为那是因…

【光线重塑技术】小姐姐,美得不可方物——lllyasviel/ic-light

在英伟达自18年宣布光追技术之后&#xff0c;RTX显卡也成了目前Steam游戏的常客。就连 AMD、Intel 和 Apple Silicon 都宣布要在GPU上支持光追算法。这次我要介绍的是huggingface上比较火的relight技术—— ic-light 介绍 IC-Light 是一个操纵图像照明的项目。 IC-Light &qu…

C语言 | Leetcode C语言题解之第80题删除有序数组中的重复项II

题目&#xff1a; 题解&#xff1a; int removeDuplicates(int* nums, int numsSize) {if (numsSize < 2) {return numsSize;}int slow 2, fast 2;while (fast < numsSize) {if (nums[slow - 2] ! nums[fast]) {nums[slow] nums[fast];slow;}fast;}return slow; }

双碳目标下基于“遥感+”集成技术的碳储量、碳排放、碳循环、温室气体等多领域监测与模拟

原文链接&#xff1a;双碳目标下基于“遥感”集成技术的碳储量、碳排放、碳循环、温室气体等多领域监测与模拟https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247604166&idx1&sn5f49d952a0c05ff50582ab2f60e2f371&chksmfa821621cdf59f377b8aeb3084289ac…

YOLO使用笔记

下载oss命令工具。 在OSS.exe文件下打开Power Shell, 输入指令&#xff1a; ./oss login之后输入用户名和密码。 选择将你想要上传的文件导入&#xff1a; ./oss cp {yourdir} oss://进入服务器实例中&#xff0c;打开终端下载数据 同样输入:oss login 进行登录。 登录成功…

嵌入式开发场景下怎么防止源代码泄密

在当今数字化时代&#xff0c;嵌入式系统在各行各业中扮演着至关重要的角色&#xff0c;从智能家居到工业自动化&#xff0c;都离不开这些嵌入式设备的支持。然而&#xff0c;随之而来的是对嵌入式代码安全的日益关注。在嵌入式开发场景下&#xff0c;代码的保护至关重要&#…

MATLAB | 最新版MATLAB绘图速查表来啦!!

之前看大佬Pjer做的MATLAB速查表 http://home.ustc.edu.cn/~pjer1316/matlabplot/ 感觉非常的实用&#xff0c;最近几次MATLAB更新围绕画图方面也有很多新东西&#xff0c;于是就有了自己做一张最新版的速查表的想法&#xff0c;这张表长这样&#xff1a; 这张表的配色基本上…

TCP协议建立连接的过程及其意义

目录 三次握手 四次挥手 三次握手的意义 在客户端与服务器传输数据之前&#xff0c;要在两台主机之间先建立连接&#xff0c;然后再传输业务数据。三次握手&#xff0c;就是建立连接的过程&#xff0c;是在传输业务之前&#xff0c;就要先进行。握手好了&#xff0c;才能进行…

(四十一)第 6 章 树和二叉树(包含双亲的树的孩子链表存储)

1. 背景说明 2. 示例代码 1) errorRecord.h // 记录错误宏定义头文件#ifndef ERROR_RECORD_H #define ERROR_RECORD_H#include <stdio.h> #include <string.h> #include <stdint.h>// 从文件路径中提取文件名 #define FILE_NAME(X) strrchr(X, \\) ? strrch…

使用rsync同步服务器目录及文件遇到的问题

背景&#xff1a;某天&#xff0c;客户找我倾诉了一个需求&#xff0c;问我是否有方法解决。诉求如下&#xff1a;有一个生产服务器&#xff08;我暂时把它称为主站服务器&#xff09;&#xff0c;还有一个专门用来备份主站服务器上目录和文件的服务器&#xff08;我姑且把它称…

SD-WAN异地组网的优点和应用场景

随着企业不断扩张&#xff0c;建立多个分支机构&#xff0c;异地组网已经成为提高通信效率和资源配置的关键手段。SD-WAN技术的出现为企业带来了更经济实惠、更有优势的异地组网解决方案。那么&#xff0c;如何搭建SD-WAN异地组网呢&#xff1f;我们一起来看看吧&#xff01; S…

免翻,这两款免费神器结合,游戏党的狂欢!

哈喽&#xff0c;各位小伙伴们好&#xff0c;我是给大家带来各类黑科技与前沿资讯的小武。 相信大家都听过Steam&#xff0c;这是一款全球知名的PC端游戏平台&#xff0c;像大家耳熟能详的绝地求生、永劫无间等大热PC端游戏都可以从中下载&#xff0c;当然&#xff0c;还有众多…

跨云厂商的不停机数据库迁移,使用NineData就可以了!

近日&#xff0c;Google私有云发生重大故障&#xff0c;在维护UniSuper客户配置&#xff0c;误删除所有数据&#xff08;包括异地备份数据&#xff09;。【重大故障】澳大利亚所有大学退休金数据被Google误删除&#xff0c;本地云服务总监被直接解雇 其实&#xff0c;所有企业…

工器具管理(基于若依)

文章目录 前言一、工器具管理项目总览 二、入库功能1. 前端1.1 界面展示1.2 具体操作实现1.3 js文件 2. 后端2.1 工器具信息回显2.2 工器具入库 三、领用功能1. 前端1.1 界面展示1.2 具体实现操作1.3 js文件 2. 后端2.1 工器具信息回显2.2 工器具领用 遇到的问题1. 同一页面展示…

下载wsl 网络出现问题,解决办法

查看能下载的wsl系统时&#xff0c;显示网络出现问题 解决办法&#xff1a;更换网络节点 最终效果&#xff1a;

从零开始详解OpenCV车道线检测

前言 车道线检测是智能驾驶和智能交通系统中的重要组成部分&#xff0c;对于提高道路安全、交通效率和驾驶舒适性具有重要意义。在本篇文章中将介绍使用OpenCV进行车道线的检测 详解 导入包 import cv2 import matplotlib.pyplot as plt import numpy as np读入图像并灰度化…

双点重发布

一&#xff0c;实验要求 二&#xff0c;实验操作 loopback 0&#xff1a; 抓取流量并做策略&#xff0c;导入ospf1 [r1]ip ip-prefix aa permit 1.1.1.0 24 [r1]route-policy aa permit node 10 [r1-route-policy]if-match ip-prefix aa [r1-ospf-1]import-route direct rou…

进程创建-fork

demo1代码状态变迁 demo2代码输出到stdout使用管道 demo1 代码 #include <pthread.h> #include <iostream> #include <unistd.h> int main(int argc, char const *argv[]) {// 1.pid_t x fork();// 2.pid_t y fork();// 3.printf("%d %d\n", x…

PSFRGAN量化:量化技术、实现步骤与常见问题解决

写在前面&#xff1a;本博客仅作记录学习之用&#xff0c;部分图片来自网络&#xff0c;如需引用请注明出处&#xff0c;同时如有侵犯您的权益&#xff0c;请联系删除&#xff01; 文章目录 背景PyTorch 量化量化流程动态量化训练后量化量化感知训练 Eager 模式量化训练后动态量…

分区恢复:恢复已删除/丢失的硬盘分区数据方法

通常情况下&#xff0c;如果分区正常&#xff0c;您可以直接在Windows资源管理器中看到并访问它。如果启动计算机时在Windows资源管理器中看不到某个分区&#xff0c;则该分区可能会丢失。将有一些解决方案可以帮助您修复和恢复已删除或丢失的硬盘驱动器分区&#xff0c;或从丢…