关于Stm32定时器+ADC+DMA进行AD采样的实现
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组
}
关于Stm32定时器+ADC+DMA进行AD采样的实现的更多相关文章
- STM32 F4 ADC DMA Temperature Sensor
STM32 F4 ADC DMA Temperature Sensor Goal: detecting temperature variations using a temperature senso ...
- stm32的ADC规则组通道采样顺序设置
先看一下固件库手册 再看一下手册上的例子: 有两个通道,,并且顺序如下
- STM32定时器触发ADC多通道连续采样,DMA缓存结果
STM32的ADC使用非常灵活,采样触发方面:既支持软件触发,定时器或其他硬件电路自动触发,也支持转换完成后自动触发下一通道/轮转换.转换结果存储方面:既支持软件读取和转存,也支持DMA自动存储转换结 ...
- STM32 多通道ADC采样,采用Timer1进行采样率控制,利用DMA进行传输
http://blog.csdn.net/varding/article/details/17559399 http://www.51hei.com/stm32/3842.html https://w ...
- STM32 双ADC同步规则采样
最近需要用到两个ADC对电压电流进行同步采样,看了一下STM32的ADC介绍,发现STM32最多有3个独立ADC,有在双AD模式下可以进行同步测量,正好满足我的要求.参考官方给的例子在结合自己的需 ...
- STM32之ADC实例(基于DMA方式)
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/zouleideboke/article/details/75112224 ADC简介: ADC(An ...
- STM32中AD采样的三种方法分析
在进行STM32F中AD采样的学习中,我们知道AD采样的方法有多种,按照逻辑程序处理有三种方式,一种是查询模式,一种是中断处理模式,一种是DMA模式.三种方法按照处理复杂方法DMA模式处理模式效率最高 ...
- 【STM32】用DMA实现多路ADC通道数据采集
今天尝试了下STM32的ADC采样,并利用DMA实现采样数据的直接搬运存储,这样就不用CPU去参与操作了. 找了不少例子参考,ADC和DMA的设置了解了个大概,并直接利用开发板来做一些实验来验证相关的 ...
- 【STM32H7教程】第46章 STM32H7的ADC应用之DMA方式多通道采样
完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980 第46章 STM32H7的ADC应用之DMA方式多 ...
随机推荐
- 条件随机场之CRF++源码详解-开篇
介绍 最近在用条件随机场做切分标注相关的工作,系统学习了下条件随机场模型.能够理解推导过程,但还是比较抽象.因此想研究下模型实现的具体过程,比如:1) 状态特征和转移特征具体是什么以及如何构造 2)前 ...
- 文件压缩 ZipOutputStream类
先举一个压缩单个文件的例子吧: [例子1] import java.io.File; import java.io.FileInputStream; import java.io.FileOutput ...
- 论文笔记-Mining latent relations in peer-production environments
背景 用户合作产生内容的网站越来越多,有许多隐藏的信息可以去挖掘 wiki上保存了贡献者的编辑记录,提供了非常多的有用的信息 研究发现,大部分的贡献者仅仅会参与编辑很小数量的文章,修改的版本也有限制, ...
- Web大前端面试题-Day9
1. 请用至少3中方式实现数组去重? 方法一: indexOfvar arr1=[1,2,3,4,5,4,3,2,1]; function repeat1(arr){ for(var i=0, ...
- web开发 入门
插件 ,索引文件,js目录,视图目录,资产目录,css目录,数据目录,font-awesome-4.7.0目录,图像目录. 引导程序 框架.字体.layer,mockjs.paging分页.树网格.t ...
- Some Formulas.
目录 计数问题 在一个有\(n\)个点的完全图(complete graph)中有多少棵生成树 排列组合 1. 当 \(C_n^m\) 为奇数时,\((n\&m)==m\) 2. \[\sum ...
- 利用java编写的盲注脚本
之前在网上见到一个盲注的题目,正好闲来无事,便用java写了个盲注脚本,并记录下过程中的坑 题目源码: <?php header("Content-Type: text/html;ch ...
- 潭州课堂25班:Ph201805201 WEB 之 Ajax第八课 (课堂笔记)
js <——>jq <!DOCTYPE html> <html lang="en"> <head> <meta charset ...
- [BJOI2014]大融合
Description 给你一个n个点的森林,要求支持m个操作: 1.连接两个点 x,y 2.询问若断掉 x,y这条边,两点所在联通块乘积的大小 Hint: \(n,m<=10^5\) Solu ...
- SpringMVC统一转换null值为空字符串的方法
在SpringMVC中,可以通过在<mvc:annotation-driven>中配置<mvc:message-converters>,把null值统一转换为空字符串,解决这个 ...