stm32的定时器输入捕获与输出比较

发布者:Ampoule最新更新时间:2016-04-08 来源: eefocus关键字:stm32  定时器  输入捕获  输出比较 手机看文章 扫描二维码
随时随地手机看文章
明确一点对比AD的构造,stm32有3个AD,每个AD有很多通道,使用哪个通道就配置成哪个通道,这里定时器也如此,有很多定时器TIMx,每个定时器有很多CHx(通道),可以配置为输入捕捉-------测量频率用,也可以配置为输出比较--------输出PWM使用

输入捕捉:可以用来捕获外部事件,并为其赋予时间标记以说明此事件的发生时刻。

外部事件发生的触发信号由单片机中对应的引脚输入(具体可以参考单片机的datasheet),也可以通过模拟比较器单元来实现。

时间标记可用来计算频率,占空比及信号的其他特征,以及为事件创建日志,主要是用来测量外部信号的频率。

输出比较:定时器中计数寄存器在初始化完后会自动的计数。从bottom计数到top。并且有不同的工作模式。

另外还有个比较寄存器。一旦计数寄存器在从bottom到top计数过程中与比较寄存器匹配则会产生比较中断(比较中断使能的情况下)。

然后根据不同的工作模式计数寄存器将清零或者计数到top值。

1、朋友,可以解释一下输入捕获的工作原理不?

很简单,当你设置的捕获开始的时候,cpu会将计数寄存器的值复制到捕获比较寄存器中并开始计数,当再次捕捉到电平变化时,这是计数寄存器中的值减去刚才复制的值就是这段电平的持续时间,你可以设置上升沿捕获、下降沿捕获、或者上升沿下降沿都捕获。它没多大用处,最常用来测频率。

 

计数寄存器的初值,是自己写进去的吗?

是的,不过默认不要写入

 

我如果捕获上升沿,两个值相减,代表的时两个上升沿中间那段电平的时间。对不?

是的

 

timer1有五个通道(对应五个IO引脚),在同一时刻,只能捕获一个引脚的值,对不?

那是肯定的,通道很像ADC通道,是可以进行切换的。

 

那输出比较的原理你可以帮我介绍一下不?

这里有两个单元:一个计数器单元和一个比较单元,比较单元就是个双缓冲寄存器,比较单元的值是可以根据不同的模式设置的,与此同时,计数器在不停的计数,并不停的与比较寄存器中的值进行比较,当计数器的值与比较寄存器的值相等的时候一个比较匹配就发生了,根据自己的设置,匹配了是io电平取反、变低、还是变高,就会产生不同的波形了。

 

比较单元的值是人为设进去的吧?

是的,但是他要根据你的控制寄存器的配置,来初始化你的比较匹配寄存器。

 

 

上面这个总看不懂,好像不不止你说的那几种情况:“匹配了是io电平取反、变低、还是变高,就会产生不同的波形了”

就是比较匹配了你要IO电平怎么办?是清0还是置1?还是怎么样?这样才能产生波形啊要不然你要比较单元有什么用呢?

 

设置输出就是置1,清除输出就是置0,切换输出就是将原来的电平取反,对不?

是的你理解的很快

011:计数器向上计数达到最大值时将引脚置1,达到0时,引脚电平置0,,对不?

 

定时器1的输出比较模式怎么用。利用这个功能输出一个1KHZ,占空比为10%的程序怎么写啊?求高人指点

1、陪定时器1的功能为特殊功能,不是普通IO  在PERCFG这里
2、P1SEL引脚选择
3、P1DIR设为输出
4、T3CC0设置周期
5、T3CC1设置占空比
6、T3CCTL0 设置通道0
7、T3CCTL1 设置通道1
8、T3CTL设为模模式
9、用T3CTL打开即可

************以下是用定时器做频率源,用定时器测量该频率的应用程序!!!***********

调试STM32的定时器好几天了,也算是对STM32的定时器有了点清楚的认识了。我需要测量4路信号的频率然后通过DMA将信号的频率传输到存储器区域,手册说的很明白每个定时器有4个独立通道。然后我就想能不能将这4路信号都连接到一个定时器的4个通道上去。理论上应该是行的通的。刚开始俺使用的是 TIM2的123通道,TIM4的2通道来进行频率的测量。由于没有频率发生器,所以我用tim3作为信号源,用TIM2,TIM4来进行测量就ok了(刚好4个通道了)。

  请看一开始的程序,以TIM2的1,3通道为例子(2通道设置方法一样):

  TIM_ICInitStructure.TIM_ICMode =TIM_ICMode_ICAP;                //配置为输入捕获模式         

  TIM_ICInitStructure.TIM_Channel =TIM_Channel_1;                    //选择通道1

  TIM_ICInitStructure.TIM_ICPolarity =TIM_ICPolarity_Rising;      //输入上升沿捕获

  TIM_ICInitStructure.TIM_ICSelection =TIM_ICSelection_DirectTI;   //通道方向选择  

  TIM_ICInitStructure.TIM_ICPrescaler =TIM_ICPSC_DIV1;              //每次检测到捕获输入就触发一次捕获

  TIM_ICInitStructure.TIM_ICFilter =0x0;                           //滤波

  TIM_ICInit(TIM2, &TIM_ICInitStructure);   //TIM2通道1配置完毕

 

  TIM_ICInitStructure.TIM_ICMode = TIM_ICMode_ICAP;     //配置为输入捕获模式     

  TIM_ICInitStructure.TIM_Channel =TIM_Channel_3;                 //选择通道3

  TIM_ICInitStructure.TIM_ICPolarity =TIM_ICPolarity_Rising;      //输入上升沿捕获

  TIM_ICInitStructure.TIM_ICSelection =TIM_ICSelection_DirectTI;  //   

  TIM_ICInitStructure.TIM_ICPrescaler =TIM_ICPSC_DIV1;             //每次检测到捕获输入就触发一次捕获

 

  TIM_ICInitStructure.TIM_ICFilter = 0x0;             //滤波

  TIM_ICInit(TIM2, &TIM_ICInitStructure);   //TIM2通道3配置完毕

 

  以上是输入捕获配置

  还需要做的工作就是(参考stm32参考手册的TIM的结构框图):

  

    TIM_SelectInputTrigger(TIM2,TIM_TS_TI1FP1);                     //参考TIM结构图选择滤波后的TI1输入作为触发源,触发下面程序的复位

  

    TIM_SelectSlaveMode(TIM2,TIM_SlaveMode_Reset);         //复位模式-选中的触发输入(TRGI)的上升沿初始化计数器,并且产生一个更新线号

  

    TIM_SelectMasterSlaveMode(TIM2,TIM_MasterSlaveMode_Enable);      

  //主从模式选择

  这样我们就可以很轻松的就得到了连接在TIM2的通道1上的信号的频率,但是3通道的频率的值永远都是跳动的不准,测试了半天也没有找到根本原因,请看TIM的结构框图的一部分

  红色箭头所指,这才找到原因,触发的信号源只有这四种,而通道3上的计数器的值不可能在接受到信号的上升沿时候,有复位这个动作,找到原因了。这就是3 通道上的数据不停跳动的原因,要想得到信号的频率也是有办法的,可以取连续两次捕捉的值之差,这个值就是信号的周期,自己根据实际情况去算频率吧。

  有以上可以得到:

  stm32的TIM2的四个通道可以同时配置成输入捕捉模式,但是计算CH3,CH4信号的频率步骤有点繁琐(取前后捕捉的差值),但是他的CH1,和CH2可以轻松得到:

  通道1

  

    TIM_SelectInputTrigger(TIM2,TIM_TS_TI1FP1);                     //参考TIM结构图选择滤波后的TI1输入作为触发源,触发下面程序的复位

  

    TIM_SelectSlaveMode(TIM2,TIM_SlaveMode_Reset);         //复位模式-选中的触发输入(TRGI)的上升沿初始化计数器,并且产生一个更新线号

  TIMx->CRR1的值即为信号的周期

  通道2:

    TIM_SelectInputTrigger(TIM2,TIM_TS_TI2FP2);                    //参考TIM结构图选择滤波后的TI1输入作为触发源,触发下面程序的复位

 

  

    TIM_SelectSlaveMode(TIM2,TIM_SlaveMode_Reset);         //复位模式-选中的触发输入(TRGI)的上升沿初始化计数器,并且产生一个更新线号

  TIMx->CRR2的值即为信号的周期



STM32的定时器外设功能强大得超出了想像力,STM32一共有8个都为16位的定时器。其中TIM6、TIM7是基本定时器;TIM2、TIM3、TIM4、TIM5是通用定时器;TIM1和TIM8是高级定时器。这些定时器使STM32具有定时、信号的频率测量、信号的PWM测量、PWM输出、三相6步电机控制及编码器接口等功能,都是专门为工控领域量身订做的。
       基本定时器:具备最基本的定时功能,下面是它的结构:

我们来看看它的启动代码:
void TIM2_Configuration(void)
  基本定时器TIM2的定时配置的结构体(包含定时器配置的所有元素例如:TIM_Period= 计数值)
   TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
   设置TIM2_CLK为72MHZ(即TIM2外设挂在APB1上,把它的时钟打开。)      
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 ,ENABLE);
   设置计数值位1000
   TIM_TimeBaseStructure.TIM_Period=1000;
   将TIM2_CLK为72MHZ除以72 = 1MHZ为定时器的计数频率
   TIM_TimeBaseStructure.TIM_Prescaler= 71;
   这个TIM_ClockDivision是设置时钟分割,这里不分割还是1MHZ的计数频率
   TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
   设置为向上计数模式;(计数模式有向上,向下,中央对齐1,中央对齐2,中央对齐3)
   TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
   将配置好的设置放进stm32f10x-tim.c的库文件中
    TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
   清除标志位
    TIM_ClearFlag(TIM2,TIM_FLAG_Update);
   使能TIM2中断
   TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
   使能TIM2外设      
    TIM_Cmd(TIM2,ENABLE);                                                                                                
}
      通用定时器:就比基本定时器复杂得多了。除了基本的定时,它主要用在测量输入脉冲的频率、脉冲宽与输出PWM脉冲的场合,还具有编码器的接口。

我们来详细讲解:如何生成PWM脉冲
通用定时器可以利用GPIO引脚进行脉冲输出,在配置为比较输出、PWM输出功能时,捕获/比较寄存器TIMx_CCR被用作比较功能,下面把它简称为比较寄存器。
这里直接举例说明定时器的PWM输出工作过程:若配置脉冲计数器TIMx_CNT为向上计数,而重载寄存器TIMx_ARR(相当于库函数写法的TIM_Period的值N)被配置为N,即TIMx_CNT的当前计数值数值X在TIMxCLK时钟源的驱动下不断累加,当TIMx_CNT的数值X大于N时,会重置TIMx_CNT数值为0重新计数。
而在TIMxCNT计数的同时,TIMxCNT的计数值X会与比较寄存器TIMx_CCR预先存储了的数值A进行比较,当脉冲计数器TIMx_CNT的数值X小于比较寄存器TIMx_CCR的值A时,输出高电平(或低电平),相反地,当脉冲计数器的数值X大于或等于比较寄存器的值A时,输出低电平(或高电平)。
如此循环,得到的输出脉冲周期就为重载寄存器TIMx_ARR存储的数值(N+1)乘以触发脉冲的时钟周期,其脉冲宽度则为比较寄存器TIMx_CCR的值A乘以触发脉冲的时钟周期,即输出PWM的占空比为A/(N+1)。
如果不想看的可以直接看我标注的红色字体,就大体可以理解。
下面我们来编写具体代码和讲解:
void TIM3_GPIO_Config(void)
{配置TIM3复用输出PWM的IO
  GPIO_InitTypeDefGPIO_InitStructure;
  打开TIM3的时钟
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
  打开GPIOA和GPIOB的时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA| RCC_APB2Periph_GPIOB, ENABLE);
  配置PA6.PA7的工作模式
  GPIO_InitStructure.GPIO_Pin=  GPIO_Pin_6 |GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF_PP;      
  GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
  GPIO_Init(GPIOA,&GPIO_InitStructure);
  配置PB0.PB1的工作模式
  GPIO_InitStructure.GPIO_Pin=  GPIO_Pin_0 |GPIO_Pin_1;
  GPIO_Init(GPIOB,&GPIO_InitStructure);
}
void TIM3_Mode_Config(void)
{
       TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;//初始化TIM3的时间基数单位
       TIM_OCInitTypeDef  TIM_OCInitStructure;//初始化TIM3的外设

        u16 CCR1_Val= 500;      
        u16 CCR2_Val= 375;
        u16 CCR3_Val= 250;
        u16 CCR4_Val= 125;//PWM信号电平跳变值(即计数到这个数值以后都是低电平之前都是高电平)


  TIM3的时间基数单位设置(如计数终止值:999,从0开始;计数方式:向上计数)      
  TIM_TimeBaseStructure.TIM_Period= 999;      
  TIM_TimeBaseStructure.TIM_Prescaler= 0;         
  TIM_TimeBaseStructure.TIM_ClockDivision= TIM_CKD_DIV1 ;      
  TIM_TimeBaseStructure.TIM_CounterMode= TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
  TIM3的外设的设置
  TIM_OCInitStructure.TIM_OCMode= TIM_OCMode_PWM1;      //TIM脉冲宽度调制模式1   
  TIM_OCInitStructure.TIM_OutputState= TIM_OutputState_Enable;//这个暂时不知道,stm32固件库里没有搜到。应该是定时器输出声明使能的意思      
  TIM_OCInitStructure.TIM_Pulse =CCR1_Val;//设置了待装入捕获比较寄存器的脉冲值      
  TIM_OCInitStructure.TIM_OCPolarity= TIM_OCPolarity_High; //TIM输出比较极性高
  TIM_OC1Init(TIM3,&TIM_OCInitStructure);
      
  TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable);//使能或者失能TIMx在CCR1上的预装载寄存器
  下面3路PWM输出和上面的一样不再解说
  TIM_OCInitStructure.TIM_OutputState= TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse =CCR2_Val;      
  TIM_OC2Init(TIM3,&TIM_OCInitStructure);      
  TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);


  TIM_OCInitStructure.TIM_OutputState= TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse =CCR3_Val;      
  TIM_OC3Init(TIM3,&TIM_OCInitStructure);      
  TIM_OC3PreloadConfig(TIM3,TIM_OCPreload_Enable);


  TIM_OCInitStructure.TIM_OutputState= TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse =CCR4_Val;      
  TIM_OC4Init(TIM3,&TIM_OCInitStructure);      
  TIM_OC4PreloadConfig(TIM3,TIM_OCPreload_Enable);


  TIM_ARRPreloadConfig(TIM3,ENABLE);       //使能TIM3重载寄存器ARR           


  TIM_Cmd(TIM3,ENABLE);//使能TIM3         
}
太累了边看边写都这个点了2014年7月27日0:24:13在自己床上写的。下面是看看我们程序达到的4路PWM的效果:

可以看到明显占空比不同的4路pwm波。

关键字:stm32  定时器  输入捕获  输出比较 引用地址:stm32的定时器输入捕获与输出比较

上一篇:STM32 硬件I2C EEPROM命令解析
下一篇:S3C2440 Linux驱动移植——NAND驱动

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

STM32 内存管理 实现了malloc,free,remalloc等函数
这两天写的一个STM32上的内存管理函数,实现了malloc和free以及remalloc几个函数.还实现了一个内存使用率查询的函数. 实验环境:ALIENTEK STM32 Mini 开发板 思路如下: 将内存分块管理. 内存池等分为固定大小的内存块. 建立一个内存状态表,对应每个块,有多少个块,状态表就有多少个元素,一一对应. 通过状态表的值判断该块内存是否可用(为0则表示可用,为其他值则表示被占用了,而且占用的内存块数量,就是该值的数字) 初始化的时候,状态表的值全0,代表所有的内存块都未被占用.当需要分配的时候,malloc从内存块的最高地址往下查找,查找到连续的空内存大于等于要分配的内存的时候,结束此次分配,返回地址给
[单片机]
FlyMCU下载hex到STM32
习惯了使用ST-LINK,但也避免不免不了使用hex,故记录下载步骤。 一般情况下如果我们想用用串口下载代码,则必须配置BOOT0为1, BOOT1为0!!! 另外,BOOT1,启动选择配置引脚(仅上电时用,过后可配置为输出状态) 1)用户闪存 = 芯片内置的Flash。 2)SRAM = 芯片内置的RAM区,就是内存啦。 3)系统存储器 = 芯片内部一块特定的区域,芯片出厂时在这个区域预置了一段Bootloader,就是通常说的ISP程序。这个区域的内容在芯片出厂后没有人能够修改或擦除,即它是一个ROM区。 Step1、 双击打开软件“FlyMcu” ,点击搜索串口;如果此时控制电路通过 USB已经连接到电脑,则
[单片机]
FlyMCU下载hex到<font color='red'>STM32</font>
STM32 中 CAN进入错误回调函数后无法接收问题(HAL库)
CPU进入错误回调函数后 ,无法接收新的数据包 void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan) 经检查,如果CPU在进入错误回调函数之前,我们调用 HAL_CAN_Receive_IT(&Can1Handle, CAN_FIFO0); 一般来说,我们会认为CPU一直处于可以接收新的can包的状态,但是只要CPU进入错误回调函数之后,就无法接收新的数据包,进debug 单步运行后 得到问题的原因 void HAL_CAN_IRQHandler(CAN_HandleTypeDef* hcan) { ...................................
[单片机]
keil软件的安装和破解(STM32和C51都可使用)
教大家学会安装keil软件和破解(本篇以keil4软件为例) 第一步:运行mdk.exe软件,一直点默认即可 此处可以修改路径 第二步:点击next后,出现此框图,first name 和E-mail栏随便输入数字即可 第三步:等待安装完即可 第四步:安装完,点击next即可,最后点击finish,(出现黑框,点击关闭即可) 破解步骤: 第一步:运行keil软件 第二步:点击file,找到licence.. 选项,点开 复制CID选项下的内容 第三步:打开破解软件,即KEIL_Lic.exe软件 将所复制的CID码粘贴到CID处,同时选择Target为ARM模式 (注:STM32所用破解Target为A
[单片机]
keil软件的安装和破解(<font color='red'>STM32</font>和C51都可使用)
定时器的使用方法总结
首先理解看门狗定时器方式的使用,简单说,就是有个控制器,选择时钟源,计数方式,等等的控制参数,再配合一个一个累加计数器来确定时间,通过固定的时间间隔来执行中断函数,来得到自己想要的实验结果。 理解之后我们就对最简单的定时器有了一个简单的感念了,了解了基本的定时功能,现在了解下单片机中的TA和TB两个定时器: 首先看TA: 和学习之前的功能一样,先了解寄存器,以及寄存器功能: 定时器A的控制寄存器: 定时器A的计数器: 重点来了: 定时器A的捕获/比较功能寄存器以及中断向量寄存器: 前面的控制寄存器和计数器还好理解一点,主要是选择定时器A的功能和一些基本参数的,这里简单讲下设置步骤: ①选择TA的时钟源和分
[单片机]
<font color='red'>定时器</font>的使用方法总结
STM32F207 TIM1 比较输出 输出多路不同频率
void Motor_TIM1_NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure_E; //定时器时钟使能 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //使能GPIO时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE|RCC_AHB1Periph_GPIOD, ENABLE); //GPIO配置: TIM1 CH3 (PE13,PE14) SV_A,SV_B GPIO_I
[单片机]
STM32单片机(11) DS18B20温度传感器实验
本程序主要实现 DS18B20温度传感器数据获取,并利用串口通信把温度数据传至计算机 注:使用普中科技开发板测试时,需要拔掉Boot1插口,因为用到的是PA15管脚, 由开发板电路图可知,需要改变PA15 管脚的映射,将其设置成普通IO口 参考资料 DS18B20中文手册.pdf http://download.csdn.net/detail/leytton/7742193 STM32-外设篇 视频教程(Cortex-M3)-主讲人:刘洋 http://yun.baidu.com/pcloud/album/info?uk=2853967793&album_id=5492137931588632574 main.c /**
[单片机]
STMCU应用过程中与电源相关的案例分享
我们在从事STM32单片机的应用开发及调试过程中,往往会碰到各类异常。其中有不少比例的问题跟电源有关。对于一个电子产品而言,电源部分很关键、很重要,但在实际开发调试中,我们偶尔会有意无意的忽视它。这里分享几个实际案例,以加强刺激,加深印象。 毕竟因为电源问题可能导致的异常很多很多,这里分享几个案例算是抛砖引玉,希望大家在调试中对电源方面加以重视。个人认为,往往电源出问题时导致的异常时并不太好分析。多数时候异常表现得更为诡异或没章法。 注:下面提到的案例中异常原因都与电源有关,但并不是说出现类似异常时一定是电源的原因。 下面主要分享五个基于STM32应用的案例。 案例1:STM32芯片的PLL无法正常工作。 有人使用STM3
[单片机]
STMCU应用过程中与电源相关的案例分享
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

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