【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;//PC1ADC_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;//PA2ADC_sConfig.Rank	  = ADC_REGULAR_RANK_2;HAL_ADC_ConfigChannel(&g_adc_dma_handle, &ADC_sConfig);ADC_sConfig.Channel = ADC_CHANNEL_3;//PA3ADC_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->Mg_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,PA3GPIO_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=12MHAL_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和DMAHAL_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次,所以同一个通道的数据之间位置相差3sum2+=adc_dma_rec_NumOf_3_buf[(3*i)+1];//因为是CH11->CH2->CH3->CH11->CH2->CH3一直循环50次,所以同一个通道的数据之间位置相差3sum3+=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);	//开启下一次传输}}
}

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Django项目规范化(虚拟环境、目录结构、数据库权限、建表、Media、日志)

Django项目规范化&#xff08;虚拟环境、目录结构、数据库权限、建表、Media、日志&#xff09; 目录 Django项目规范化&#xff08;虚拟环境、目录结构、数据库权限、建表、Media、日志&#xff09;前言虚拟环境pycharm创建虚拟环境 创建Django项目调整目录结构数据库规范创建…

纯血鸿蒙APP第三方库——MpChart运动健康场景实践案例

介绍 MpChart是一个包含各种类型图表的图表库&#xff0c;主要用于业务数据汇总&#xff0c;例如销售数据走势图&#xff0c;股价走势图等场景中使用&#xff0c;方便开发者快速实现图表UI&#xff0c;MpChart主要包括线形图、柱状图、饼状图、蜡烛图、气泡图、雷达图、瀑布图…

C++青少年简明教程:C++程序结构

C青少年简明教程&#xff1a;C程序结构 一个简单的C程序源码如下&#xff1a; #include <iostream> using namespace std;int main() {cout << "Hello World" << endl;return 0; }下面解析一下。 1. #include <iostream> 这是一条预处理…

html中用frameset对窗口进行划分

html中&#xff0c;一般有<head><body>等部分&#xff0c;在用<frameset>对窗口进行区域划分时&#xff0c;<body>标签对就不再需要了。直接删除就可以了。 请看下面的示例&#xff1a; 由于使用frameset进行窗口划分时&#xff0c;对于电脑屏幕的划分…

HarmonyOS开发案例:【UIAbility内和UIAbility间页面的跳转】

UIAbility内和UIAbility间页面的跳转&#xff08;ArkTS&#xff09; 介绍 基于Stage模型下的UIAbility开发&#xff0c;实现UIAbility内和UIAbility间页面的跳转。包含如下功能&#xff1a; UIAbility内页面的跳转。跳转到指定UIAbility的首页。跳转到指定UIAbility的指定页…

[猫头虎分享21天微信小程序基础入门教程]第6天:与服务器进行数据交互

[猫头虎分享21天微信小程序基础入门教程]第6天&#xff1a;与服务器进行数据交互 第6天&#xff1a;与服务器进行数据交互 &#x1f310; 自我介绍 大家好&#xff0c;我是猫头虎&#xff0c;一名全栈软件工程师。今天我们将继续微信小程序的学习&#xff0c;重点了解如何与服…

Ubuntu扩展磁盘分区

Ubuntu扩展磁盘分区 报错Unable to satisfy all constraints on the partition 首先需要保证磁盘具有空闲分区&#xff0c;且与待扩展的分区相邻&#xff0c;比如扩展分区3&#xff0c;那剩余空间应与分区3相邻&#xff0c;如图所示&#xff1a; 然后选中文件系统分区3&#x…

“交个朋友”申请注册商标都已被驳回!

“ 交个朋友”在直播带货界非常有名&#xff0c;普推知产老杨在商标局官网上检索发现&#xff0c;“交个朋友”主体申请了以“交个朋友”四百多个相关商标&#xff0c;基本上都被驳回&#xff0c;其实这样的名称不应提报商标&#xff0c;专业商标人员一看就过不了&#xff0c;还…

C++牛客周赛题目分享(2)小红叕战小紫,小红的数组移动,小红的素数合并,小红的子序列求和

目录 ​编辑 1.前言 2.四道题目 1.小红叕战小紫 1.题目描述 2.输入描述 3.输出描述 4.示例 5.题解与思路 2.小红的数组移动 1.题目描述 2.输入描述 3.输出描述 4.示例 5.题解与思路 3.小红的素数合并 1.题目描述 2.输入描述 3.输出描述 4.示例 5.题解与思…

启动项目时出现SELinux is preventing

问题描述 启动项目时出现SELinux is preventing**** SELinux正在阻止systemd对文件AB.sevice进行读取访问。 我的是启zabbix是报该错&#xff1a; 最终解决方案 方法一&#xff1a;暂时禁用SELinux setenforce 0 方法二&#xff1a;禁用SELinux 在配置文件/etc/sysconfig/…

通过任意文件读取获取weblogic账号密码

对于weblogic获取到账号密码的前提是有任意文件读取存在&#xff0c;当任意文件读取存在时是可以读取配置文件来对账号密码进行解密。weblogic密码使用AES&#xff08;老版本3DES&#xff09;加密&#xff0c;对称加密可解密&#xff0c;只需要找到用户的密文与加密时的密钥即可…

Dread Hunger 海上狼人杀服务器开服教程

1、购买后登录服务器&#xff0c;百度莱卡云 1.1、第一次购买服务器会安装游戏端&#xff0c;大约5分钟左右&#xff0c;如果长时间处于安装状态请联系客服 2、创建端口 点击网络创建第二个端口作为副端口&#xff08;副端口的作用是用于第二局游戏&#xff0c;因为游戏BUG&am…