STM32F767多通道ADC采集+DMA传输
文章目录
- 一、ADC简介
- 1、ADC采样频率
- 2、ADC转换时间
- 3、ADC寄存器
- 4、ADC引脚与外部通道对应关系
- 二、DMA简介
- 三、代码配置
- 1、ADC、DMA初始化配置
- 2、adc.h文件的配置
- 3、main.c文件配置
一、ADC简介
TM32F767xx系列有3个ADC,这些ADC可以独立使用,也可以使用双重/三重模式(提高采样率)。STM32F767的ADC是12位逐次逼近型的模拟数字转换器。它有19个通道,可测量16个外部源、2个内部源和Vbat通道的信号。我使用的是STM32F767IGT6。
1、ADC采样频率
不要让ADC的时钟超过36M,否则将导致结果准确度下降。STM32F767的ADC最大工作频率是36Mhz,而ADC时钟(ADCCLK)来自APB2,APB2频率一般是108Mhz,我们设置ADCPRE=01,即4分频,这样得到ADCCLK频率为27Mhz
2、ADC转换时间
ADC的转换时间: 总转换时间(Tcovn)=采样时间+12个周期
例如,当ADCCLK=27Mhz的时候,并设置3个周期的采样时间,则得到:Tcovn=3+12=15个周期=0.55us。
stm32f767的采样时间周期可以在stm32f7xx_hal_adc.h中选择,可以选择3~480个周期的采样时间。如下图所示:
3、ADC寄存器
ADC里面用到的寄存器有很多,常用的有以下几个,具体使用方法就不一一介绍了
4、ADC引脚与外部通道对应关系
二、DMA简介
DMA 全称Direct Memory Access,即直接存储器访问。
DMA传输将数据从一个地址空间复制到另一个地址空间。当CPU初始化这个传输动作,传输动作本身是由DMA控制器来实现和完成的。
DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场过程,通过硬件为RAM和IO设备开辟一条直接传输数据的通道,使得CPU的效率大大提高。
STM32最多有2个DMA控制器,2个DMA控制器总共有16个数据流(每个控制器8个)。每个DMA控制器都用于管理一个或者多个外设的存储器访问请求。
三、代码配置
1、ADC、DMA初始化配置
我将它们都配置在了adc.c文件中,代码如下所示:
#include "adc.h"#include "delay.h"#include "usart.h"#include "sdram.h"#include "led.h"#include "lcd.h"#define M 8 //定义M#define N 4u16 value[N][M];uint32_t ADC_ConvertedValueRead[4];uint32_t ADC_ConvertedValue[4];ADC_HandleTypeDef ADC1_Handler; //ADC句柄DMA_HandleTypeDef ADC1TxDMA_Handler; //DMA句柄//初始化ADCvoid MY_ADC_Init(void){ ADC_ChannelConfTypeDef ADC1_ChanConf;//GPIO初始化GPIO_InitTypeDef GPIO_Initure;__HAL_RCC_ADC1_CLK_ENABLE(); //使能ADC1时钟__HAL_RCC_GPIOA_CLK_ENABLE(); //开启GPIOA时钟__HAL_RCC_GPIOC_CLK_ENABLE(); //开启GPIOC时钟GPIO_Initure.Pin=GPIO_PIN_5|GPIO_PIN_7; //PA5GPIO_Initure.Mode=GPIO_MODE_ANALOG; //模拟GPIO_Initure.Pull=GPIO_NOPULL; //不带上下拉HAL_GPIO_Init(GPIOA,&GPIO_Initure);GPIO_Initure.Pin=GPIO_PIN_4|GPIO_PIN_5; //|GPIO_PIN_5; GPIO_Initure.Mode=GPIO_MODE_ANALOG; //模拟GPIO_Initure.Pull=GPIO_NOPULL; //不带上下拉HAL_GPIO_Init(GPIOC,&GPIO_Initure);//ADC1功能配置ADC1_Handler.Instance=ADC1;ADC1_Handler.Init.ClockPrescaler=ADC_CLOCK_SYNC_PCLK_DIV4; //4分频,ADCCLK=PCLK2/4=108/4=27MHZADC1_Handler.Init.Resolution=ADC_RESOLUTION_12B; //12位模式ADC1_Handler.Init.DataAlign=ADC_DATAALIGN_RIGHT; //右对齐ADC1_Handler.Init.ScanConvMode=ENABLE; //扫描模式,扫描模式用于多通道采集ADC1_Handler.Init.EOCSelection=DISABLE; //关闭EOC中断ADC1_Handler.Init.ContinuousConvMode=ENABLE; //开启连续转换模式,即不停地进行ADC转换 ADC1_Handler.Init.NbrOfConversion=4; //规则序列中有4个转换ADC1_Handler.Init.DiscontinuousConvMode=DISABLE; //禁止不连续采样模式ADC1_Handler.Init.NbrOfDiscConversion=0; //不连续采样通道数为0 ADC1_Handler.Init.ExternalTrigConv=ADC_SOFTWARE_START; //软件触发ADC1_Handler.Init.ExternalTrigConvEdge=ADC_EXTERNALTRIGCONVEDGE_NONE;//使用软件触发ADC1_Handler.Init.DMAContinuousRequests=ENABLE; //开启DMA请求ADC1_Handler.DMA_Handle=&ADC1TxDMA_Handler;HAL_ADC_Init(&ADC1_Handler); //初始化 //采样通道、顺序配置 ADC1_ChanConf.Channel=ADC_CHANNEL_7; //通道ADC1_ChanConf.Rank=1; //序列ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_480CYCLES; //采样时间ADC1_ChanConf.Offset=0; HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_ChanConf); //通道配置ADC1_ChanConf.Channel=ADC_CHANNEL_14; //通道ADC1_ChanConf.Rank=2; //序列ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_480CYCLES; //采样时间ADC1_ChanConf.Offset=0; HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_ChanConf); //通道配置ADC1_ChanConf.Channel=ADC_CHANNEL_15; //通道ADC1_ChanConf.Rank=3; //序列ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_480CYCLES; //采样时间ADC1_ChanConf.Offset=0; HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_ChanConf); //通道配置ADC1_ChanConf.Channel=ADC_CHANNEL_5; //通道ADC1_ChanConf.Rank=4; //序列ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_480CYCLES; //采样时间ADC1_ChanConf.Offset=0; HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_ChanConf); //通道配置}//初始化DMAvoid DMA_Config(void){__HAL_RCC_DMA2_CLK_ENABLE(); //DMA2时钟使能ADC1TxDMA_Handler.Instance=DMA2_Stream0; //数据流选择ADC1TxDMA_Handler.Init.Channel=DMA_CHANNEL_0; //通道选择ADC1TxDMA_Handler.Init.Direction=DMA_PERIPH_TO_MEMORY; //外设到存储器ADC1TxDMA_Handler.Init.PeriphInc=DMA_PINC_DISABLE; //外设非增量模式ADC1TxDMA_Handler.Init.MemInc=DMA_MINC_ENABLE; //存储器增量模式ADC1TxDMA_Handler.Init.PeriphDataAlignment=DMA_PDATAALIGN_WORD; //外设数据长度:32位ADC1TxDMA_Handler.Init.MemDataAlignment=DMA_MDATAALIGN_WORD; //存储器数据长度:32位ADC1TxDMA_Handler.Init.Mode=DMA_CIRCULAR; //外设流控模式 循环模式ADC1TxDMA_Handler.Init.Priority=DMA_PRIORITY_MEDIUM; //中等优先级ADC1TxDMA_Handler.Init.FIFOMode=DMA_FIFOMODE_DISABLE; ADC1TxDMA_Handler.Init.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL; ADC1TxDMA_Handler.Init.MemBurst=DMA_MBURST_SINGLE; //存储器突发单次传输ADC1TxDMA_Handler.Init.PeriphBurst=DMA_PBURST_SINGLE; //外设突发单次传输ADC1TxDMA_Handler.XferCpltCallback = HAL_DMA_IRQHandler;HAL_DMA_DeInit(&ADC1TxDMA_Handler); HAL_DMA_Init(&ADC1TxDMA_Handler);__HAL_LINKDMA(&ADC1_Handler,DMA_Handle,ADC1TxDMA_Handler); //将DMA与ADC1联系起来(发送DMA)HAL_NVIC_SetPriority(DMA2_Stream0_IRQn,0,0);HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);}void DMA2_Stream0_IRQHandler(void){HAL_DMA_IRQHandler(&ADC1TxDMA_Handler);}//采样函数void task_adc(void){ int i; HAL_ADC_Start_DMA(&ADC1_Handler,&ADC_ConvertedValueRead[0],4); for(i=0; i<M; i++){ delay_us(10);value[0][i] = (u16)(ADC_ConvertedValue[0]&0xFFF ); //获取ADC的值value[1][i] = (u16)(ADC_ConvertedValue[1]&0xFFF); //获取ADC的值value[2][i] = (u16)(ADC_ConvertedValue[2]&0xFFF); value[3][i] = (u16)(ADC_ConvertedValue[3]&0xFFF);// printf("\r\n 编号%d \t 编号%d \t AD值: %d\r\n", 0,i, value[0][i]);// printf("\r\n 编号%d \t 编号%d \t AD值: %d\r\n", 1,i, value[1][i]); // printf("\r\n 编号%d \t 编号%d \t AD值: %d\r\n", 2,i, value[2][i]);// printf("\r\n 编号%d \t 编号%d \t AD值: %d\r\n", 3,i, value[3][i]); LCD_ShowxNum(134,130,value[0][i],4,16,0); //显示ADCC采样后的原始值LCD_ShowxNum(134,150,value[1][i],4,16,0); //显示ADCC采样后的原始值LCD_ShowxNum(134,170,value[2][i],4,16,0); //显示ADCC采样后的原始值LCD_ShowxNum(134,190,value[3][i],4,16,0); //显示ADCC采样后的原始值 // delay_us(50);}HAL_ADC_Stop_DMA(&ADC1_Handler); //传输完成以后关闭串口DMA}/*** 函数功能: ADC转换完成回调函数* 输入参数: hadc:ADC外设设备句柄* 返 回 值: 无* 说 明: 读取ADC转化结果时,一定要关闭Cache,否则数组中的数据为空,即关闭Cache后读取数据,读完在打开。此函数在 void HAL_ADC_IRQHandler(ADC_HandleTypeDef* hadc) 中调用*/void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {uint32_t i;SCB_DisableDCache();for(i=0;i<4;i++){ADC_ConvertedValue[i] = ADC_ConvertedValueRead[i];}SCB_EnableDCache(); }
注意 :STM32767在使用时一定要注意Cache的问题
2、adc.h文件的配置
#ifndef __ADC_H#define __ADC_H#include "sys.h"/********* 扩展变量 **********/extern ADC_HandleTypeDef ADC1_Handler; //ADC句柄extern DMA_HandleTypeDef ADC1TxDMA_Handler; //DMA句柄/********* 函数声明**********/void MY_ADC_Init(void); //ADC通道初始化void DMA_Config(void);void task_adc(void);#endif
3、main.c文件配置
#include "sys.h"#include "delay.h"#include "usart.h"#include "led.h"#include "key.h"#include "lcd.h"#include "sdram.h"#include "adc.h"extern uint32_t ADC_ConvertedValueRead[4];int main(void){Cache_Enable(); //打开L1-CacheHAL_Init(); //初始化HAL库Stm32_Clock_Init(432,25,2,9); //设置时钟,216Mhz delay_init(216); //延时初始化uart_init(115200); //串口初始化LED_Init(); //初始化LEDKEY_Init(); //初始化按键SDRAM_Init(); //初始化SDRAMLCD_Init(); //LCD初始化MY_ADC_Init(); //初始化ADC1DMA_Config();POINT_COLOR=RED; LCD_ShowString(30,50,200,16,16,"Apollo STM32F4/F7"); LCD_ShowString(30,70,200,16,16,"ADC TEST"); LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");LCD_ShowString(30,110,200,16,16,"2019/4/18"); POINT_COLOR=BLUE;//设置字体为蓝色LCD_ShowString(30,130,200,16,16,"ADC1_PA7_VAL:");LCD_ShowString(30,150,200,16,16,"ADC1_PC4_VAL:");LCD_ShowString(30,170,200,16,16,"ADC1_PC5_VAL:");LCD_ShowString(30,190,200,16,16,"ADC1_PA5_VAL:"); printf("采样开始\r\n ");task_adc();printf("采样结束\r\n ");while(1);}
以上代码我亲测有效,当然,如果有什么问题,欢迎交流讨论。
STM32F767多通道ADC采集+DMA传输相关推荐
- STM32CubeMX关于ADC采集DMA传输
什么是ADC,ADC也叫做模数转换,既将外面的模拟信号转换为数字信号. 模拟信号:连续变化的物理量表示的信息,其信号的幅度,或频率,或相位随时间作连续变化,或在一段连续的时间间隔内,其代表信息的特征量 ...
- [STM32F4]STM32F407 ADC采集+DMA传输
前言 有的项目中需要对多个通道的电压进行一定频率的AD采样. 第一种:是使用定时器去读取,通过检查转换完成标志位来读取,但这样就会加重整个系统的负担,占用CPU资源. 第二种:是采用定时 ...
- STM32Cubemx——ADC采集+DMA传输
文章目录 一.准备工具 二.前置知识 1.ADC简介 2.DMA简介 2.STM32Cubemx配置 1.新建工程 2.时钟源选择及时钟树配置 3.时基选择调试接口选择 4.配置ADC采集 1.选择要 ...
- 基于STM32F4:多通道ADC采集,采用DMA的形式,亲测有效
基于STM32F4的多通道ADC采集 单片机源程序如下: #include "sys.h" #include "delay.h" #include " ...
- STM32——多通道ADC的DMA方式采集方法
前言: 最近在调试STM32F205芯片ADC多通道DMA方式采集数据,总结下STM32多通道ADC的DMA方式采集的使用方法. 硬件平台:STM32F205 软件平台:keil v5 函数库:标准库 ...
- axi dma 寄存器配置_STM32 ADC多通道转换的DMA传输示例
这里以STM32F334 Nucleo板作为硬件平台,使用ARM keil MDK集成开发环境. 对3个ADC通道进行连续.扫描转换,转换结果通过DMA传输到内存,再作为TIM2的3个比较寄存器的值, ...
- stm32f429之多通道ADC通过DMA数据采集
stm32f429之多通道ADC通过DMA数据采集 原来的程序使用时stm32f103的芯片,现在给为stm32f429的芯片,查看一下几家开发板例程,发现没有使用adc+dma的,在网上也搜索了一下 ...
- 瑞萨e2studio(16)----基于DTC的多通道ADC采集
瑞萨e2studio.16--基于DTC的多通道ADC采集 概述 视频教学 csdn课程 样品申请 完整代码下载 硬件准备 开发板 新建工程 工程模板 保存工程路径 芯片配置 工程模板选择 uart配 ...
- STM32h743开启cache后ADC采集DMA数据不更新问题
STM32h743开启cache后ADC采集DMA数据不更新问题 解决办法 解决办法 1.DMA数据缓存地址进行32字节对齐,即地址是0x20的整数倍: __attribute__((at(0x380 ...
最新文章
- python t检验_A or B A/B测试-python独立双样本t检验
- UVA10391复合词
- 机器学习笔记(十)——Logistic Function AND Softmax Function
- linux常用命令--实用小技巧
- leetcode 1164 python
- (10)FPGA面试技能提升篇10(MATLAB)
- 【java】序列化:ProtoBuf 与 JSON 的比较
- 炒菜机器人放食材的顺序_2年要开1000家 碧桂园旗下千玺机器人餐厅开业
- 3dmax 注意事项
- Mac电脑没声音了怎么办?苹果电脑没声音的解决方法
- 计算机组装与维护标准教程(2010-2012版)电子教材,计算机组装与维护标准教程(2015—2018版)...
- 目前计算机无法显示的四叠字,四叠字列表(共19个),还能用的四叠字大全,带拼音,部分注释!...
- R语言笔记3(NA解释)
- mysql表新增添加一列
- 服务器创建虚拟环境跑代码
- 王姨劝我学HarmonyOS鸿蒙2.0系列教程之一环境搭建跑起来模拟器!
- 金叉走势图解上半年暴跌行情,如何证明macd金叉死叉模型确实有用?
- BaoDing University热身赛 2020-1-31 13:50 3 hours
- 前端包管理器的依赖管理原理
- LoadLibrary