基于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的形式,亲测有效相关推荐

  1. 瑞萨e2studio(16)----基于DTC的多通道ADC采集

    瑞萨e2studio.16--基于DTC的多通道ADC采集 概述 视频教学 csdn课程 样品申请 完整代码下载 硬件准备 开发板 新建工程 工程模板 保存工程路径 芯片配置 工程模板选择 uart配 ...

  2. STM32F4基于DMA的多通道ADC采集——遇到的问题解决

    这几天在尝试用DMA实现规则通道多通道的ADC采集,遇到了不少问题,在这记录一下我遇到的问题,一方面理顺一下思路,也希望后人少走弯路. 一开始按照开发板资料中的程序源码编写,但无论如何配置,也无法实现 ...

  3. STM32F767多通道ADC采集+DMA传输

    文章目录 一.ADC简介 1.ADC采样频率 2.ADC转换时间 3.ADC寄存器 4.ADC引脚与外部通道对应关系 二.DMA简介 三.代码配置 1.ADC.DMA初始化配置 2.adc.h文件的配 ...

  4. [STM32F4]STM32F407 ADC采集+DMA传输

    前言        有的项目中需要对多个通道的电压进行一定频率的AD采样. 第一种:是使用定时器去读取,通过检查转换完成标志位来读取,但这样就会加重整个系统的负担,占用CPU资源. 第二种:是采用定时 ...

  5. 基于STM32F407使用ADC采集电压实验

    核心板:STM32F407 实验目的:使用ADC采集电压值将其打印在串口助手上 目录 ADC简介 STM32F407 ADC通道对应的引脚 STM32F407中的数据寄存器 ADC 规则数据寄存器 ( ...

  6. STM32 F446RET6多通道ADC采集

    本次配置是根据STM32CUBEIDE去开发的 DMA搬运数据规则 使用DMA搬运数据的时候我们会先建立一个数据缓冲区,将DMA采集的数据存放到数据缓冲区内.采集到的ADC的值根据通道的顺序一个一个的 ...

  7. STM32F103C8T6多通道adc采集(3通道)

    本程序采用STM32F103C8T6的3通道adc采集,其中为PA1(ADC1,ch,1,),PA2(ADC1,ch,2,),PA3(ADC1,ch,1,) adc.c文件 #include &quo ...

  8. 立创梁山派GD32F450ZGT6--使用DMA实现多通道ADC采集

    这次调试有些久,缺乏的知识很多,最重要的是ADC的引脚配置为浮空之后,如果没有接入东西,其读取的ADC值是不确定的,所以在测试的时候,一定要把对应的电压接入ADC引脚,测量的值才是准确的. 上代码. ...

  9. 第二十章 AT32F403A基于V2库 多通道adc+dma

    目录 概述 硬件 软件 初始化 初始化代码 测试 最后 概述 本文主要是使用AT32F403A开发板,基于V2库adc采集多通道电压值并使用dma搬运数据. 串口工具使用的Atlink-ez自带的串口 ...

最新文章

  1. Linux终端实现自己的命令解释器----mybash
  2. 【Dlib】在GPU环境中运行dlib中的例子dnn_mmod_ex报错...dlib::cuda_error...Error while calling cudaMalloc...
  3. java jmx jboss_jboss中JMX的连接与Mbean的获取
  4. SpringMVC入门(二)—— 参数的传递、Controller方法返回值、json数据交互、异常处理、图片上传、拦截器
  5. 后台返回的数据换行显示
  6. sublime按ctrl+B不能运行
  7. Elasticsearch中如何进行日期(数值)范围查询
  8. 快速重置vuex数据 - Vue
  9. 解决org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)错误
  10. java压缩文件能否不压缩路径_如何在Java中压缩文件而不包含文件路径
  11. RedisTemplate清空所有键值对
  12. css checkbox自动换行,CSS checkbox
  13. Storyboard和Xib混用黑魔法-swift版
  14. Go语言基础练习题系列5
  15. offer oracle svp_SVP学校转非SVP学校——最新规定详解
  16. 计算机科学与技术双一流名单,重磅 | 解读“双一流”名单(附完整名单)
  17. 【C++】黑白矩阵(美团)
  18. Oralce 之 TM锁
  19. insist fortress g55 机械键盘得救了
  20. 学术英语理工(第二版)Unit4课文翻译

热门文章

  1. 科技爱好者周刊(第 208 期):晋升制度的问题
  2. 【剑桥摄影协会】色彩管理之色彩空间
  3. 我的翻译--针对Outernet卫星信号的逆向工程
  4. 腾讯游戏一口气发布44款产品内容;爱立信力争7月底完成收购Vonage | 美通企业日报...
  5. 支付宝称:已支持微信转账,结果被骂惨了...
  6. Android判断手机号码是否是正确的手机号码
  7. Esac代表什么意义?
  8. python发微信红包_微信公众号开发小记——5.python微信红包
  9. oa系统服务器什么意思,OA系统是什么意思
  10. Erlang开源20周年:这门编程语言见证了互联网的技术成长