Stm32的ADC有DMA功能这都毋庸置疑,也是我们用的最多的!然而,如果我们要对一个信号(比如脉搏信号)进行定时采样(也就是隔一段时间,比如说2ms),有三种方法:

1、使用定时器中断每隔一定时间进行ADC转换,这样每次都必须读ADC的数据寄存器,非常浪费时间!

2、把ADC设置成连续转换模式,同时对应的DMA通道开启循环模式,这样ADC就一直在进行数据采集然后通过DMA把数据搬运至内存。但是这样做的话还得加一个定时中断,用来定时读取内存中的数据!

3、使用ADC的定时器触发ADC转换的功能,然后使用DMA进行数据的搬运!这样只要设置好定时器的触发间隔,就能实现ADC定时采样转换的功能,然后可以在程序的死循环中一直检测DMA转换完成标志,然后进行数据的读取,或者使能DMA转换完成中断,这样每次转换完成就会产生中断,我是采用第二种方法。下面上代码:我这里使用的单通道

//定时器初始化

void TIM2_Configuration(void)

 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 
 TIM_OCInitTypeDef TIM_OCInitStructure; 
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE); 
 TIM_TimeBaseStructure.TIM_Period = 1999;//设置2ms一次TIM2比较的周期
 TIM_TimeBaseStructure.TIM_Prescaler = 71;//系统主频72M,这里分频71,相当于1000K的定时器2时钟 
 TIM_TimeBaseStructure.TIM_ClockDivision = 0x0; 
 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
 TIM_TimeBaseInit(TIM2, & TIM_TimeBaseStructure);
    
 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//下面详细说明 
 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//TIM_OutputState_Disable; 
 TIM_OCInitStructure.TIM_Pulse = 1000; 
 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;//如果是PWM1要为Low,PWM2则为High 
 TIM_OC2Init(TIM2, & TIM_OCInitStructure);   
// TIM_InternalClockConfig(TIM2);
// TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable); 
// TIM_UpdateDisableConfig(TIM2, DISABLE);
}

//ADC_DMA初始化配置

void ADC_DMA_Config(void)
{
  DMA_InitTypeDef DMA_InitStructure; // 注:ADC为12位模数转换器,只有ADCConvertedValue的低12位有效
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//使能DMA时钟
  DMA_DeInit(DMA1_Channel1);//开启DMA1的第一通道 
  DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;//DMA对应的外设基地址
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedValue; //内存存储基地址
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //DMA的转换模式为SRC模式,由外设搬移到内存
  DMA_InitStructure.DMA_BufferSize = 1;//DMA缓存大小,1个
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //接收一次数据后,设备地址禁止后移
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; //关闭接收一次数据后,目标内存地址后移
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//定义外设数据宽度为16位
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //DMA搬移数据尺寸,HalfWord就是为16位
  DMA_InitStructure.DMA_Mode =DMA_Mode_Circular;//循环转换模式
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;//DMA优先级高
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//M2M模式禁用
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);         
  DMA_ITConfig(DMA1_Channel1,DMA_IT_TC, ENABLE);//使能传输完成中断
}

//ADC初始化

void PulseSenosrInit(void)
{
//当外部触发信号被选为ADC规则或注入转换时,只有它的上升沿可以启动转换     
  ADC_InitTypeDef ADC_InitStructure;
  ADC_GPIO_Configuration();//IO口配置
  TIM2_Configuration(); //定时器配置
  ADC_DMA_Config();//ADC_DMA配置
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //独立的转换模式 ADC_DUALMOD[3:0]=0000;
  ADC_InitStructure.ADC_ScanConvMode =DISABLE;//关闭扫描模式 因为只有一个通道
  ADC_InitStructure.ADC_ContinuousConvMode =DISABLE;//关闭连续转换模式 否则只要触发一次,
  //后续的转换就会永不停歇(除非CONT清0),这样第一次以后的ADC,就不是由TIM2_CC2来触发了
  ADC_InitStructure.ADC_ExternalTrigConv =ADC_ExternalTrigConv_T2_CC2;//软件转换模式
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//对齐方式,ADC为12位中,右对齐方式 ADC_ALIGN=0;
  ADC_InitStructure.ADC_NbrOfChannel = 1;//开启通道数,1个  ADC_SQR1[23:20]=0000;
  //ADC_SQR1[23:20] 设置通道数目的选择
  ADC_Init(ADC1, &ADC_InitStructure);
 // RCC_ADCCLKConfig(RCC_PCLK2_Div6);//配置时钟(12MHz),在RCC里面还应配置APB2=AHB时钟72MHz
 
  ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 1,ADC_SampleTime_1Cycles5);
  //ADC_SMPR2 ADC_SMPR1 设置每个通道的采样时间 
  //ADC_SQR1[19:0]DC_SQR1[29:0]DC_SQR3[29:0]  设置对应通道的转换顺序  适用于多通道采样
  //ADC通道组, 第3个通道 采样顺序1,转换时间
  ADC_ExternalTrigConvCmd(ADC1, ENABLE);//设置外部触发模式使能(这个“外部“其实仅仅是相//对于ADC模块的外部,
 
  ADC_DMACmd(ADC1, ENABLE);   
 
  ADC_Cmd(ADC1, ENABLE);  //ADC命令,使能  ADC_ADON=1
    
  ADC_ResetCalibration(ADC1);   //重新校准
 
  while(ADC_GetResetCalibrationStatus(ADC1));  //等待重新校准完成
 
  ADC_StartCalibration(ADC1);  //开始校准  ADC_RSTCAL=1; 初始化校准寄存器
 
  while(ADC_GetCalibrationStatus(ADC1));    //等待校准完成  ADC_CAL=0;  
 
   //ADC_SoftwareStartConvCmd(ADC1, ENABLE); //连续转换开始,ADC通过DMA方式不断的更新RAM区。
  //ADC_SWSTART=1 开始规则转换 切记 软件触发也属于外部事件  要设置  ADC_EXTTRIG=1
  //实际上还是在STM32内部)
  TIM_Cmd(TIM2, ENABLE);//最后面打开定时器使能
  DMA_Cmd(DMA1_Channel1, ENABLE);//使能DMA    
}

//中断处理函数

void  DMA1_Channel1_IRQHandler(void)
{
   if(DMA_GetITStatus(DMA1_IT_TC1)!=RESET){

//自己的中断处理代码 但是记住程序不要太复杂  最好不要超过中断时间
         DMA_ClearITPendingBit(DMA1_IT_TC1);
 }
 }

//中断配置

NVIC_InitTypeDef NVIC_InitStructure;  
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    NVIC_InitStructure.NVIC_IRQChannel =DMA1_Channel1_IRQn;  
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; 
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

void ADC_GPIO_Configuration(void)        //ADC配置函数
{
  GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1|RCC_APB2Periph_GPIOA, ENABLE);   //使能ADC和GPIOA时钟                      
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;        //管脚2
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;    //模拟输入模式
  GPIO_Init(GPIOA, &GPIO_InitStructure);     //GPIO组
}

转载于:https://www.cnblogs.com/zym0805/p/7149340.html

关于Stm32定时器+ADC+DMA进行AD采样的实现相关推荐

  1. 我的第一篇文章——stm32的ADC+DMA+滤波算法

    stm32的ADC+DMA+滤波算法 一 工程目的 (1)外设配置 (2)源码 头文件 主文件 二 调试过程遇到的问题 1 如果打开中断 2 无法打开ADC 3 变量无法赋值 三 参考资料 四 写在最 ...

  2. STM32使用ADC+DMA进行多通道模拟量采集 (踩坑及傻瓜式解析)

    STM32使用ADC+DMA进行多通道模拟量采集 (踩坑及通俗解析) ​ 利用STM32的片上外设可采集多个模拟量(如传感器数值),并在嵌入式程序中使用.如果只使用了一个通道,用时令ADC转换而后读取 ...

  3. STM32定时器触发DMA循环完成数据搬运

    通过TIM8的事件触发DMA,从内存中的地址搬运数据到外设的寄存器,例子中的中断部分可以关闭,与功能无关,仅为测试时观察方便. 定时器每产生一次事件(本文以UPDATE为例,CC等其他事件也可实现), ...

  4. STM32 H7系列ADC DMA模式过采样设置详解 cubeMX

    最近做项目需要用H743的ADC采样,发现和M3及M4的差别还是蛮多的,MPU的配置对DMA读取数据的影响.过采样机制等,其中H7的硬件过采样是个很实用的东西,硬汉大佬也进行了测试: STM32H7的 ...

  5. 低门槛DIY示波器,CH32示波器,完全兼容STM32,ADC+DMA+TIM+USB,仅需一块最小系统板

    文章目录 前言 一.先看成果 二.使用步骤 1 运行软件 1.1 Windows用户直接运行打包好的软件 1.2 安装Python环境运行源代码(入坑) 2 选择端口 三.源码分析 1 程序总体流程图 ...

  6. STM32定时器+ADC制作简易示波器

    一.方案 先用 LCD制作 一个格子图形,然后定时器触发ADC采样.再将采集到的数据绘制成曲线显示在格子图形上,通过读取 图形上的点来测量信号. 本文使用的是原子哥的F103ZET6的战舰开发板. 二 ...

  7. STM32F407 ADC+DMA+定时器 定时采样模拟量

    STM32F407 ADC+DMA+定时器 定时采样模拟量 文章目录 STM32F407 ADC+DMA+定时器 定时采样模拟量 前言 一.硬件原理 1.1 ADC 1.2 定时器 3. DMA 二. ...

  8. STM32学习1之ADC+DMA(使用定时器触发)

    笔者之前用STM32的ADC外设通过DMA通道来传输数据,通常有两种方法,一个是直接通过DMA通道传输数据,二是通过定时器触发.相较而言,后者在实际中比较常使用,因为ADC读取传感器数据需要一段时间, ...

  9. STM32 HAL库ADC+DMA(非定时器)代码和遇到的问题

    目录 一.整体说明 二.部分知识点预览 三.代码部分 四.遇到的问题及现象 (1)仿真进入错误 (2)非连续模式软件触发时adcbuf里面的数据不对 (3)HAL库的ADC DMA相关中断的嵌套实现 ...

  10. STM32之ADC实例(基于DMA方式)

    出处:https://blog.csdn.net/zouleideboke/article/details/75112224?locationNum=9&fps=1 ADC简介: ADC(An ...

最新文章

  1. 3438亿美元!互联网内容产业新机会
  2. [zt]数学之美番外篇:平凡而又神奇的贝叶斯方法
  3. TypeError: Cannot red property 'style' of null 错误解决
  4. JavaScript实现depth First Search深度优先搜索算法(附完整源码)
  5. [Java基础]接口组成(默认方法,静态方法,私有方法)
  6. BizTalk Server 2010 + SQL Server 2008 R2 - 通过集成创造更大价值 [ 上篇 ]
  7. 30岁之前创业想成功必看
  8. 深度学习2.0-20.Keras高层API-metrics
  9. 渗透测试-SQL注入检测
  10. WPF 点击按钮打开新窗口
  11. temp的作用c语言,temp的使用
  12. 用计算机美化演讲稿过程,计算机应用基础第10章--PowerPoint应用—制作论文答辩演讲稿.ppt...
  13. 如何去除视频文件中的杂音爆音?
  14. Learning ImageMagick 1: Lomo效果
  15. Android Kernel wakeup_sources分析
  16. c语言中缺少函数标题,error C2332: “struct”: 缺少标记名
  17. 关于 trello 和 slack 的感想及使用经验
  18. html5 3d引擎 星空,使用3D引擎threeJS实现星空粒子移动效果
  19. Vue视频插件vue-video-player的使用
  20. 涠洲岛日出日落时间表,2月14日涠洲岛开船时间表/日出日落/天气预报

热门文章

  1. 年轻人,在公司混日子,伤害的是自己!
  2. mnist数据集_探索Tensorflow2中神经网络算法——基于Mnist数据集(一)
  3. linux unix域socket_计算机通信之谜,带你彻底理解socket网络编程(一)
  4. KNN (K近邻算法) - 识别手写数字
  5. Pwn-10月25-Hitcon(三)
  6. 谷歌地图自定义popup框
  7. 软件工程第四次作业——例行报告
  8. 实现四台服务器的负载均衡
  9. Debit credit problem
  10. Dot net GC