Stm32定时器中断触发AD采样

发布者:泉趣人最新更新时间:2018-12-27 来源: eefocus关键字:Stm32  定时器  中断触发  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  定时器  中断触发  AD采样 引用地址:Stm32定时器中断触发AD采样

上一篇:stm32NVIC中断优先管理
下一篇:stm32f1按键检测使用外部中断以及定时器延时方式去抖

推荐阅读最新更新时间:2024-03-16 16:21

8051单片机(STC89C52)定时器实现10ms精准定时
8051内部集成了2个16bits的计数器, 可以根据需要将其作为定时器使用. 这时, 定时器的计数频率为系统CLK/12. 如果CPU的晶振频率为12MHz, 那么定时器信号源的频率固定为12MHz/12 = 1MHz. 如果定时器的定时周期设定为50ms, 则需要50000个脉冲. 由于单片机定时器为加1计数器, 所以, 计数器初始值应设为65536 - 50000 = 15536 = 3CB0H. 另外, 还需要设置定时器工作模式寄存器TMOD, 如果使用定时器0, 16bits定时器方式, 则TMOD = 0x01. 定时器初始值计算解析: 若系统晶振频率为12MHz, 那么定时器信号源的频率固定为1MHz, 即每
[单片机]
8051单片机(STC89C52)<font color='red'>定时器</font>实现10ms精准定时
定时器定时的方式精准控制步进电机速度
摘要: 本节介绍用定时器定时的方式,精准控制脉冲时间,从而控制步进电机速度 一、计算过程 电机每一步的角速度等于走这一步所花费的时间,走一步角度等于步距角,走一步的时间等于一个脉冲的时间 TB6600及其他驱动器大多具有细分功能,考虑细分X之后,一个脉冲转动的角度为step/X,带入①式 电机速度通常使用单位为转速RPM(转/分),角速度(°/S)与转速之间的转换关系 将③带入②可得: 至此得到了步进电机一个脉冲的时间t,采用51单片机16位溢出定时器的模式去定时,可以得到: 将④带入⑤可得: 至此得到了转速n与定时初值C的函数关系 二、举例计算 步进电机使用二相四线电机,步距角为1.8°,驱动器细分值
[嵌入式]
用<font color='red'>定时器</font>定时的方式精准控制步进电机速度
STM32的开漏电路与推挽输出
开漏结构 所谓开漏电路概念中提到的“漏”就是指MOS FET的漏极。同理,开集电路中的“集”就是指三极管的集电极。开漏电路就是指以MOS FET的漏极为输出的电路。一般的用法是会在漏极外部的电路添加上拉电阻。完整的开漏电路应该由开漏器件和开漏上拉电阻组成。如图1所示: 图1 组成开漏形式的电路有以下几个特点: 1. 利用外部电路的驱动能力,减少IC内部的驱动。当IC内部MOSFET导通时,驱动电流是从外部的VCC流经R pull-up ,MOSFET到GND。IC内部仅需很下的栅极驱动电流。如图1。 2. 可以将多个开漏输出的Pin,连接到一条线上。形成“与逻辑”关系。如图1,当PIN_A、PIN_B、PIN_C任
[单片机]
<font color='red'>STM32</font>的开漏电路与推挽输出
结合STM32单片来讲讲结构体的运用
摘要:听说还有好多学单片机的小伙伴不会用结构体?指针和结构体是学单片机必须要掌握的,如果你C语言掌握的不牢,单片机根本学不到精髓,只能完成一些低级的项目。看得懂结构体并且能够灵活运用结构体才能说你入门了单片机。本篇将以最通俗的方式结合STM32单片来讲讲结构体的运用。解决你学完C语言、考过了计算机二级还是看不懂单片机结构体的苦恼。宝藏文章,记得点赞转发收藏。 大家知道指针和结构体是单片机的难点,所以就去学习C语言,找视频看书。 这里面每一个视频的播放量都非常高。对于单纯的学习C语言,这里讲的很清楚。看完你不禁在下面评论一句:哇!讲的真的太清楚了吧!但是等你真正的学单片机的时候,你会发现我不是学过C语言吗?计算机二级我也过了
[单片机]
Systick定时器
一。Systick原理和配置方法 Systick定时器就是系统滴答定时器,CM3 内核的处理器,内部包含了一个 SysTick 定时器, SysTick 是一个 24 位的倒计数定时器,当计到 0 时,将从 RELOAD 寄存器中自动重装载定时初值。只要不把它在 SysTick 控制及状态寄存器中的使能位清除,就永不停息,即使在睡眠状态下也能工作。 Systick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号:15)。 二。4个Systick相关的寄存器 CTRL SysTick控制和状态寄存器 LOAD SysTick自动重装载初值寄存器 VAL SysTick当前值寄存器 CALIB
[单片机]
STM32学习笔记之十七——雄关漫道真如铁,如今迈步从头越
一、前言 放下半年,继续STM32的学习。新的学习新起点,决心升级。单片机不换, 调试环境整体升级。包括以下几个方面: 1、调试器换JlinkV7,相比STlink在IAR环境下不用装驱动。虽说V8已经 面世但是针对我的应用V7已经足够。况且手里这个还是带串口的,用起来很方 便。 2、接口换用SWD,四线调试,节省接插件面积为以后电路板的小型化做好准 备。 3、开发板换豆皮,功能比较全面,有MP3和液晶屏幕的扩展板,价格便宜。 4、调试环境换IAR5.3,大势所趋,没办法新的3.0库已经不再支持IAR4 了。 5、固件库换3.0,经过半年发展应该比较完善了,全新的架构。 有了这些更新,等于
[单片机]
STM32内存管理(一)
STM32是指令和数据共用相同的地址空间,即程序存储器、数据存储器、寄存器和I/O端口在一个4GB的线性地址空间内。数据字节以小端格式存放在存储器中,一个字的最低地址字节被认为是该字的最低有效字节,而最高地址字节是最高有效字节。 一、STM32存储器架构 4G的地址空间即地址编码的范围,编码就是对每一个程序存储、数据存储器、寄存器和I/O端口分配唯一的地址编码,即“编址”或“地址映射”。 存储器映射是把芯片中或芯片外的Flash、RAM、外设、BOOTBLOCK等进行统一编址。 STM32的寻址空间大小为4G,也就是从0x0000 0000~0xFFFF FFFF这一块空间,分为8个主要块,
[单片机]
<font color='red'>STM32</font>内存管理(一)
如何有效地使用串口通讯接收数据
引言 在使用stm32或者其他单片机的时候,会经常使用到串口通讯,那么如何有效地接收数据呢?假如这段数据是不定长的有如何高效接收呢? 同学A:数据来了就会进入串口中断,在中断中读取数据就行了! 中断就是打断程序正常运行,怎么能保证高效呢?经常把主程序打断,主程序还要不要运行了? 同学B:串口可以配置成用DMA的方式接收数据,等接收完毕就可以去读取了! 这个同学是对的,我们可以使用DMA去接收数据,不过DMA需要定长才能产生接收中断,如何接收不定长的数据呢? DMA简介 题外话:其实,上面的问题是很有必要思考一下的,不断思考,才能进步。 什么是DMA DMA :全称Direct Memory Access,即直接存储器访问
[单片机]
如何有效地使用串口通讯接收数据
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved