基于STM32F4:多通道ADC采集,采用DMA的形式,亲测有效
基于STM32F4的多通道ADC采集
单片机源程序如下:
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "fliter.h"
#include "adc.h"
#include "oled.h"extern u8 AD_Flag; //AD转换完成标志位
extern u16 ADC_ConvertedValue[NOFCHANEL]; //用于存放ADC的转换值
extern float ADC_Final_DisplayValue[NOFCHANEL]; //用于存放最终显示值
extern u16 ADC_filter_Value[NOFCHANEL]; int main()
{ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2delay_init(168); //初始化延时函数uart_init(115200); //初始化串口波特率为115200ADC_X_Init(); //ADC初始化LED_Init(); //LED灯初始化OLED_Init(); //OLED初始化/************一开始的显示*************/OLED_ShowCHinese(12,0,0,1); //输OLED_ShowCHinese(24,0,1,1); //入OLED_ShowCHinese(36,0,4,1); //电OLED_ShowCHinese(48,0,5,1); //压OLED_ShowCHinese(60,0,10,1); //:OLED_ShowCHinese(12,12,2,1); //输OLED_ShowCHinese(24,12,3,1); //出OLED_ShowCHinese(36,12,6,1); //电OLED_ShowCHinese(48,12,7,1); //流OLED_ShowCHinese(60,12,10,1); //:OLED_ShowString(12,24,"DAC:",12);OLED_Refresh_Gram();//更新显示到OLED while(1){AD_Flag=AD_voltage; ADC_filter_Value[0]=middleValueFilter();AD_Flag=AD_current; ADC_filter_Value[1]=middleValueFilter();AD_Flag=AD_DAC; ADC_filter_Value[2]=middleValueFilter(); ADC_Final_DisplayValue[0] =(double) ADC_filter_Value[0]/4096*3.3*6; //电压检测ADC_Final_DisplayValue[1] =(double) ADC_filter_Value[1]/4096*3.3; //电流检测ADC_Final_DisplayValue[2] =(double) ADC_filter_Value[2]/4096*3.3; //DAC检测OLED_ShowFloatNum_12(72,0,ADC_Final_DisplayValue[0],2,12);OLED_ShowFloatNum_12(72,12,ADC_Final_DisplayValue[1],2,12);OLED_ShowFloatNum_12(72,24,ADC_Final_DisplayValue[2],2,12);OLED_Refresh_Gram();//更新显示到OLED delay_ms(500);}
}
#include "usart.h"
#include "adc.h"
#include "delay.h"
#include "fliter.h"
#include "led.h"extern u8 AD_Flag; //AD转换完成标志位
extern u16 ADC_ConvertedValue[NOFCHANEL]; //用于存放ADC的转换值
extern float ADC_Final_DisplayValue[NOFCHANEL]; //用于存放最终显示值
u16 ADC_filter_Value[NOFCHANEL]; extern u16 ADC_ConvertedValue[NOFCHANEL];
// 软件延时
void Delay_ruan(__IO uint32_t nCount)
{for(; nCount != 0; nCount--);
}
//中位值滤波
//方法:连续采样N次(N取奇数)把N次采样值按大小排列取中间值为本次有效值
//优点:能有效克服因偶然因素引起的波动干扰;对温度、液位等变化缓慢的被测参数有良好的滤波效果
//缺点:对流量,速度等快速变化的参数不宜#define N 30
u16 middleValueFilter() //会获取30个ADC转换值,然后取中间的一个作为本次采样周期的输出值
{u16 value_buf[N];u16 i,j,k,temp;for( i = 0; i < N; ++i){value_buf[i] = getValue();}for(j = 0 ; j < N-1; ++j){for(k = 0; k < N-j-1; ++k){//从小到大排序,冒泡法排序if(value_buf[k] > value_buf[k+1]){temp = value_buf[k];value_buf[k] = value_buf[k+1];value_buf[k+1] = temp;}}}return value_buf[(N-1)/2];
}/*******************获得ADC转换的值*******************/
u16 getValue()
{Delay_ruan(5); //软件延时一下再获取ADC的值,但是这个时间怎么确定呢?if(AD_Flag==AD_voltage) //获取ADC电压的值{return ADC_ConvertedValue[0]; //因为ADC1的数据数据寄存器地址连接到了ADC_ConvertedValue数组上,所以ADC1采集到的值会传输到数组中,}if(AD_Flag==AD_current) //获取ADC采集电流的值{return ADC_ConvertedValue[1];}if(AD_Flag==AD_DAC) //获取DAC的值{return ADC_ConvertedValue[2];}
}//**************疑问*************//
//ADC1用了两个通道,我怎么知道什么时候电流或者电压的值存放到数组里?是否存到了对应的位置?
//因为存储地址是连续的,所以ADC采集获得的值会根据顺序存入到数组中
#include "adc.h"
#include "delay.h" u8 AD_Flag; //AD转换完成标志位
u16 ADC_ConvertedValue[NOFCHANEL]={0}; //用于存放ADC的转换值
float ADC_Final_DisplayValue[NOFCHANEL]; //用于存放最终显示值/*********************IO口复用为ADC******************/void ADC_GPIO_Config(void){GPIO_InitTypeDef GPIO_InitStructure; //结构体定义/*=====================通道1======================*/ /********** 使能 GPIO 时钟****/RCC_AHB1PeriphClockCmd(ADC_GPIO_CLK1,ENABLE); /********配置 IO************/GPIO_InitStructure.GPIO_Pin = ADC_GPIO_PIN1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //引脚复用时,作为ADC或者DAC,不能选复用,必须选模拟输入,其他的都是复用 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;/*******初始化IO口*********/GPIO_Init(ADC_GPIO_PORT1, &GPIO_InitStructure);/*=====================通道2======================*//********** 使能 GPIO 时钟****/RCC_AHB1PeriphClockCmd(ADC_GPIO_CLK2,ENABLE); /********配置 IO************/GPIO_InitStructure.GPIO_Pin = ADC_GPIO_PIN2; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //引脚复用时,作为ADC或者DAC,不能选复用,必须选模拟输入,其他的都是复用 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;/*******初始化IO口*********/GPIO_Init(ADC_GPIO_PORT2, &GPIO_InitStructure); /*=====================通道3=======================*//********** 使能 GPIO 时钟****/RCC_AHB1PeriphClockCmd( ADC_GPIO_CLK3,ENABLE); /********配置 IO************/GPIO_InitStructure.GPIO_Pin =ADC_GPIO_PIN3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //引脚复用时,作为ADC或者DAC,不能选复用,必须选模拟输入,其他的都是复用 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;/*******初始化IO口*********/GPIO_Init(ADC_GPIO_PORT3, &GPIO_InitStructure);
}/***********配置ADC和DMA*************/void ADC_Mode_Config(void)
{DMA_InitTypeDef DMA_InitStructure; // DMA初始化结构体ADC_InitTypeDef ADC_InitStructure; // ADC初始化结构体ADC_CommonInitTypeDef ADC_CommonInitStructure;/*-------------------DMA Iint 结构体参数 初始化---------------------*//************开启DMA时钟*************************/RCC_AHB1PeriphClockCmd(DMAX_CLK, ENABLE); // 外设基址为:ADC 数据寄存器地址DMA_InitStructure.DMA_PeripheralBaseAddr =(u32)&ADC_X->DR; //外设的数据寄存器地址怎么确定,(u32)&name->DR(name为外设名)// 存储器地址,实际上就是一个内部SRAM的变量 DMA_InitStructure.DMA_Memory0BaseAddr =(u32)ADC_ConvertedValue; //存放ADC转换值的数组地址(可以理解为存放ADC转换值的寄存器与这个数组直接连接在一起)// 数据传输方向为外设到存储器 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; //确定方向很重要// 缓冲区大小为,指一次传输的数据量DMA_InitStructure.DMA_BufferSize = NOFCHANEL; //存放ADC转换值的数组的数据量// 外设寄存器只有一个,地址不用递增DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;// 存储器地址固定(这里明明写的是增加,为什么还说固定,是错误了么)DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //(这里应该是增加,因为要把多个数据存到一个数组里,地址应该是变化的)// // 外设数据大小为半字,即两个字节 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //这里指的是一个数据的大小,STM32是32位的,所以一个字是32位,半字是16位// 存储器数据大小也为半字,跟外设数据大小相同DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //外设数据大小是不是要和存储器数据大小相同?是的// 循环传输模式 (ADC要不断采集数据,所以要循环模式)DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;// DMA 传输通道优先级为高,当使用一个DMA通道时,优先级设置不影响DMA_InitStructure.DMA_Priority = DMA_Priority_High;// 禁止DMA FIFO ,使用直连模式DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; // FIFO 大小,FIFO模式禁止时,这个不用配置 DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; // 选择 DMA 通道,通道存在于流中DMA_InitStructure.DMA_Channel =DMA_Channel__x; //初始化DMA流,流相当于一个大的管道,管道里面有很多通道DMA_Init(DMA_Stream__x, &DMA_InitStructure);/****使能DMA流*********/DMA_Cmd(DMA_Stream__x, ENABLE);/*-------------ADC_X 初始化------------------*//***************使能ADC时钟*****************************/RCC_APB2PeriphClockCmd(ADC_CLK_ENABLE, ENABLE);/*-------------------ADC Common 结构体 参数 初始化---------------*/// 独立ADC模式ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;// 时钟为fpclk x分频 ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;// 禁止DMA直接访问模式 ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;// 采样时间间隔 ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles; //初始化ADC Common 结构体ADC_CommonInit(&ADC_CommonInitStructure); /* -------------------ADC Init 结构体 参数 初始化-----------------*/// ADC 分辨率ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;// 扫描模式,多通道采集需要 ADC_InitStructure.ADC_ScanConvMode = ENABLE; // 连续转换 ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //禁止外部边沿触发ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//外部触发通道,本例子使用软件触发,此值随便赋值即可ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;//数据右对齐 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//转换通道NOFCHANEL个ADC_InitStructure.ADC_NbrOfConversion = NOFCHANEL;/******ADC 结构体初始化*********/ ADC_Init(ADC_X, &ADC_InitStructure);/*----------------配置 ADC 通道转换顺序和采样时间周期-----------------*/// 配置 ADC 通道转换顺序和采样时间周期ADC_RegularChannelConfig(ADC_X,ADC_CHANNEL1, 1, ADC_SampleTime_56Cycles); //ADC通道1引脚是GPIOB_Pin_0ADC_RegularChannelConfig(ADC_X,ADC_CHANNEL2, 2, ADC_SampleTime_56Cycles); //ADC通道2引脚是GPIOB_Pin_1ADC_RegularChannelConfig(ADC_X,ADC_CHANNEL3, 3, ADC_SampleTime_56Cycles); //ADC通道3引脚是GPIOA_Pin_6// 使能DMA请求 after last transfer (Single-ADC mode)ADC_DMARequestAfterLastTransferCmd(ADC_X, ENABLE);/*************使能ADC DMA*************/ADC_DMACmd(ADC_X, ENABLE); /*************使能ADC******************/ADC_Cmd(ADC_X, ENABLE); //开始adc转换,软件触发ADC_SoftwareStartConv(ADC_X);}void ADC_X_Init(void)
{ADC_GPIO_Config();ADC_Mode_Config();
}
STM32工程下载:基于STM32F4的多通道ADC采集
基于STM32F4:多通道ADC采集,采用DMA的形式,亲测有效相关推荐
- 瑞萨e2studio(16)----基于DTC的多通道ADC采集
瑞萨e2studio.16--基于DTC的多通道ADC采集 概述 视频教学 csdn课程 样品申请 完整代码下载 硬件准备 开发板 新建工程 工程模板 保存工程路径 芯片配置 工程模板选择 uart配 ...
- STM32F4基于DMA的多通道ADC采集——遇到的问题解决
这几天在尝试用DMA实现规则通道多通道的ADC采集,遇到了不少问题,在这记录一下我遇到的问题,一方面理顺一下思路,也希望后人少走弯路. 一开始按照开发板资料中的程序源码编写,但无论如何配置,也无法实现 ...
- STM32F767多通道ADC采集+DMA传输
文章目录 一.ADC简介 1.ADC采样频率 2.ADC转换时间 3.ADC寄存器 4.ADC引脚与外部通道对应关系 二.DMA简介 三.代码配置 1.ADC.DMA初始化配置 2.adc.h文件的配 ...
- [STM32F4]STM32F407 ADC采集+DMA传输
前言 有的项目中需要对多个通道的电压进行一定频率的AD采样. 第一种:是使用定时器去读取,通过检查转换完成标志位来读取,但这样就会加重整个系统的负担,占用CPU资源. 第二种:是采用定时 ...
- 基于STM32F407使用ADC采集电压实验
核心板:STM32F407 实验目的:使用ADC采集电压值将其打印在串口助手上 目录 ADC简介 STM32F407 ADC通道对应的引脚 STM32F407中的数据寄存器 ADC 规则数据寄存器 ( ...
- STM32 F446RET6多通道ADC采集
本次配置是根据STM32CUBEIDE去开发的 DMA搬运数据规则 使用DMA搬运数据的时候我们会先建立一个数据缓冲区,将DMA采集的数据存放到数据缓冲区内.采集到的ADC的值根据通道的顺序一个一个的 ...
- STM32F103C8T6多通道adc采集(3通道)
本程序采用STM32F103C8T6的3通道adc采集,其中为PA1(ADC1,ch,1,),PA2(ADC1,ch,2,),PA3(ADC1,ch,1,) adc.c文件 #include &quo ...
- 立创梁山派GD32F450ZGT6--使用DMA实现多通道ADC采集
这次调试有些久,缺乏的知识很多,最重要的是ADC的引脚配置为浮空之后,如果没有接入东西,其读取的ADC值是不确定的,所以在测试的时候,一定要把对应的电压接入ADC引脚,测量的值才是准确的. 上代码. ...
- 第二十章 AT32F403A基于V2库 多通道adc+dma
目录 概述 硬件 软件 初始化 初始化代码 测试 最后 概述 本文主要是使用AT32F403A开发板,基于V2库adc采集多通道电压值并使用dma搬运数据. 串口工具使用的Atlink-ez自带的串口 ...
最新文章
- Linux终端实现自己的命令解释器----mybash
- 【Dlib】在GPU环境中运行dlib中的例子dnn_mmod_ex报错...dlib::cuda_error...Error while calling cudaMalloc...
- java jmx jboss_jboss中JMX的连接与Mbean的获取
- SpringMVC入门(二)—— 参数的传递、Controller方法返回值、json数据交互、异常处理、图片上传、拦截器
- 后台返回的数据换行显示
- sublime按ctrl+B不能运行
- Elasticsearch中如何进行日期(数值)范围查询
- 快速重置vuex数据 - Vue
- 解决org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)错误
- java压缩文件能否不压缩路径_如何在Java中压缩文件而不包含文件路径
- RedisTemplate清空所有键值对
- css checkbox自动换行,CSS checkbox
- Storyboard和Xib混用黑魔法-swift版
- Go语言基础练习题系列5
- offer oracle svp_SVP学校转非SVP学校——最新规定详解
- 计算机科学与技术双一流名单,重磅 | 解读“双一流”名单(附完整名单)
- 【C++】黑白矩阵(美团)
- Oralce 之 TM锁
- insist fortress g55 机械键盘得救了
- 学术英语理工(第二版)Unit4课文翻译
热门文章
- 科技爱好者周刊(第 208 期):晋升制度的问题
- 【剑桥摄影协会】色彩管理之色彩空间
- 我的翻译--针对Outernet卫星信号的逆向工程
- 腾讯游戏一口气发布44款产品内容;爱立信力争7月底完成收购Vonage | 美通企业日报...
- 支付宝称:已支持微信转账,结果被骂惨了...
- Android判断手机号码是否是正确的手机号码
- Esac代表什么意义?
- python发微信红包_微信公众号开发小记——5.python微信红包
- oa系统服务器什么意思,OA系统是什么意思
- Erlang开源20周年:这门编程语言见证了互联网的技术成长