STM32学习笔记-输入捕获

输入捕获:当TIMx_CHx通道引脚出现指定电平跳变时,当前时基单元的CNT值会被所存到CCR寄存器中,这样可以用于测量PWM波形的频率,占空比,脉冲间隔,电平持续时间等参数;

PWM测量:

1个TIMx-CHx引脚经过输入滤波器(输入引脚抖动滤波)和边沿检测器(指定上升、下降沿)处理后,可以产生两个输出,TIxFP1和TIxFP2(两路信号的滤波和边沿检测可以单独设定);同时送给两个捕获寄存器(可做预分频);这样可以实现一个通道上测量PWM信号,上升沿电平触发,将CNT值转运到CCR1,下降沿电平触发,将CNT值转运到CCR2;就可以实现占空比和频率的测量;

主从模式:

输入捕获下,每次当TIMX-CHX在有信号(如上图TI1FP1)变化导致CNT值向CCR转运时,同时会触发从模式控制;完成CNT的清零;

主模式:将定时器内部的信号,映射到TRGO,用于触发别的外设(其他外设包括其他定时器);

从模式:接受其他外设或者自身外设的信号,用于控制自身定时器的运行;

同时转运也会在触发一个捕获事件,同时在状态寄存器中置标志位,可以产生中断,利用中断去处理某些任务;

GPIO初始化:参考GPIO操作,模式选择上拉输入,高阻可能导致信号抖动误触发;

1、使能GPIO时钟;

2、创建GPIO_InitTypeDef类型的结构体并赋值;

3、调用GPIO_Init()函数初始化GPIO

输入捕获单元设置:

1、创建TIM_OCInitTypeDef类型的结构体并赋值,涉及

typedef struct
{

  uint16_t TIM_Channel;      /*定时器输入捕获通道1~4*/

  uint16_t TIM_ICPolarity;   /*边沿选择,上升沿?下降沿?*/

  uint16_t TIM_ICSelection;  /*输入极性(直接输入,1对1,2对2,;还是交叉输入,1通道触发2的CCR,2通道触发1的CCR) */

  uint16_t TIM_ICPrescaler;  /*分频器设置,1/2/4/8分频 */

  uint16_t TIM_ICFilter;     /*以系统时钟72M进行滤波,0x0 and 0xF可设定 */
} TIM_ICInitTypeDef;

2、捕获单元初始化void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);

时基单元设置:

1、开启定时器时钟使能;

2、选择内部时钟:TIM_InternalClockConfig(TIMx);

3、创建TIM_TimeBaseInitTypeDef类型的结构体并赋值,涉及

typedef struct
{
  uint16_t TIM_Prescaler;         /*PSC预分频值 */

  uint16_t TIM_CounterMode;       /*上升沿下降沿模式*/

  uint16_t TIM_Period;            /*自动重装值 */ 

  uint16_t TIM_ClockDivision;     /*外部时钟的分频系数,使用内部时钟无效 */

  uint8_t TIM_RepetitionCounter;  /*重复计数,高级定时器有效 */
} TIM_TimeBaseInitTypeDef; 

4、初始化时基单元TIM_TimeBaseInit();

从模式触发源选择:

void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);
/*从模式的触发源选择,TRGI的前级信号选择*/

触发源:3/4通道没有作为触发源,不能自动触发从模式,如要清零CNT,就需要进中断手动处理

  *     @arg TIM_TS_ITR0: Internal Trigger 0
  *     @arg TIM_TS_ITR1: Internal Trigger 1
  *     @arg TIM_TS_ITR2: Internal Trigger 2
  *     @arg TIM_TS_ITR3: Internal Trigger 3
  *     @arg TIM_TS_TI1F_ED: TI1 Edge Detector
  *     @arg TIM_TS_TI1FP1: Filtered Timer Input 1
  *     @arg TIM_TS_TI2FP2: Filtered Timer Input 2
  *     @arg TIM_TS_ETRF: External Trigger input

上述配置完成后,在有外部边沿触发信号过来时,在经过滤波极性等操作后,送到分频器以为,同时还会有TI1FP1信号被触发送出,此时若从模式触发源原则为TI1FP1,则会进入从模式进行响应操作;

从模式操作命令

从模式下有8种动作,4种为编码器相关,另外介绍,剩下4种,测量PWM频率,需要将时基单元的CNT清零,故选择RESET

  *     @arg TIM_SlaveMode_Reset: Rising edge of the selected trigger signal (TRGI) re-initializes
  *                               the counter and triggers an update of the registers.
  *     @arg TIM_SlaveMode_Gated:     The counter clock is enabled when the trigger signal (TRGI) is high.
  *     @arg TIM_SlaveMode_Trigger:   The counter starts at a rising edge of the trigger TRGI.
  *     @arg TIM_SlaveMode_External1: Rising edges of the selected trigger (TRGI) clock the counter.

函数调用TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);

使能计数器:TIM_Cmd(TIM3, ENABLE);

如此计数器自动计数,在GPIO有边沿触发后将CNT值转移到CCR寄存器中同时清零CNT值;

最后调用TIM_GetCapture1(TIMx)函数返回值,即两个上升沿/下降沿之间的CNT,换算为频率;

代码如下:

#include "stm32f10x.h"                  // Device header

void IC_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	TIM_InternalClockConfig(TIM3);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;		//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;		//PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
	
	TIM_ICInitTypeDef TIM_ICInitStructure;
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
	TIM_ICInitStructure.TIM_ICFilter = 0xF;
	TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
	TIM_ICInit(TIM3, &TIM_ICInitStructure);
	
	TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
	TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
	
	TIM_Cmd(TIM3, ENABLE);
}

uint32_t IC_GetFreq(void)
{
	return 1000000 / (TIM_GetCapture1(TIM3) + 1);
}

PWMI模式:

在PWM基础上,1个GPIO触发时,设置两组触发信号分别送到两个CCR中,一个为上升沿触发,一个为下降沿触发,上升沿触发转运CNT值转运到CCR1并通过TI1FP1触发从模式清零CNT;下降沿触发CNT值转运到CCR2;CCR1可以计算PWM频率,CCR2可以计算占空比;

GPIO初始化:参考GPIO操作,模式选择上拉输入,高阻可能导致信号抖动误触发;

1、使能GPIO时钟;

2、创建GPIO_InitTypeDef类型的结构体并赋值;

3、调用GPIO_Init()函数初始化GPIO

输入捕获单元设置:

1、创建TIM_OCInitTypeDef类型的结构体并赋值,涉及

typedef struct
{

  uint16_t TIM_Channel;      /*定时器输入捕获通道1~4*/

  uint16_t TIM_ICPolarity;   /*边沿选择,上升沿?下降沿?*/

  uint16_t TIM_ICSelection;    /*输入极性(直接输入,1对1,2对2,;还是交叉输入,1通道触发2的CCR,2通道触发1的CCR) */

  uint16_t TIM_ICPrescaler;  /*分频器设置,1/2/4/8分频 */

  uint16_t TIM_ICFilter;     /*以系统时钟72M进行滤波,0x0 and 0xF可设定 */
} TIM_ICInitTypeDef;

2、捕获单元初始化

void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);/*设定捕获通道设置*/

TIM_PWMIConfig(TIMx, &TIM_ICInitStructure);/*极性选择交叉输入,若结构体原设定通道1,则此设置触发2通道的CCR,若原通道2,则触发CCR1,同时,通道选择根据原设定对换2或者1,同时将上面结构体中的边沿检测取反,用来触发反向通道的CCR*/

TIM_PWMIConfig函数说明如下:

/**
  * @brief  Configures the TIM peripheral according to the specified
  *         parameters in the TIM_ICInitStruct to measure an external PWM signal.
  * @param  TIMx: where x can be  1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the TIM peripheral.
  * @param  TIM_ICInitStruct: pointer to a TIM_ICInitTypeDef structure
  *         that contains the configuration information for the specified TIM peripheral.
  * @retval None
  */
void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct)
{
  uint16_t icoppositepolarity = TIM_ICPolarity_Rising;
  uint16_t icoppositeselection = TIM_ICSelection_DirectTI;
  /* Check the parameters */
  assert_param(IS_TIM_LIST6_PERIPH(TIMx));
  /* Select the Opposite Input Polarity */
  if (TIM_ICInitStruct->TIM_ICPolarity == TIM_ICPolarity_Rising)
  {
    icoppositepolarity = TIM_ICPolarity_Falling;
  }
  else
  {
    icoppositepolarity = TIM_ICPolarity_Rising;
  }
  /* Select the Opposite Input */
  if (TIM_ICInitStruct->TIM_ICSelection == TIM_ICSelection_DirectTI)
  {
    icoppositeselection = TIM_ICSelection_IndirectTI;
  }
  else
  {
    icoppositeselection = TIM_ICSelection_DirectTI;
  }
  if (TIM_ICInitStruct->TIM_Channel == TIM_Channel_1)
  {
    /* TI1 Configuration */
    TI1_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity, TIM_ICInitStruct->TIM_ICSelection,
               TIM_ICInitStruct->TIM_ICFilter);
    /* Set the Input Capture Prescaler value */
    TIM_SetIC1Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler);
    /* TI2 Configuration */
    TI2_Config(TIMx, icoppositepolarity, icoppositeselection, TIM_ICInitStruct->TIM_ICFilter);
    /* Set the Input Capture Prescaler value */
    TIM_SetIC2Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler);
  }
  else
  { 
    /* TI2 Configuration */
    TI2_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity, TIM_ICInitStruct->TIM_ICSelection,
               TIM_ICInitStruct->TIM_ICFilter);
    /* Set the Input Capture Prescaler value */
    TIM_SetIC2Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler);
    /* TI1 Configuration */
    TI1_Config(TIMx, icoppositepolarity, icoppositeselection, TIM_ICInitStruct->TIM_ICFilter);
    /* Set the Input Capture Prescaler value */
    TIM_SetIC1Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler);
  }
}

时基单元设置:

1、开启定时器时钟使能;

2、选择内部时钟:TIM_InternalClockConfig(TIMx);

3、创建TIM_TimeBaseInitTypeDef类型的结构体并赋值,涉及

typedef struct
{
  uint16_t TIM_Prescaler;         /*PSC预分频值 */

  uint16_t TIM_CounterMode;       /*上升沿下降沿模式*/

  uint16_t TIM_Period;            /*自动重装值 */ 

  uint16_t TIM_ClockDivision;     /*外部时钟的分频系数,使用内部时钟无效 */

  uint8_t TIM_RepetitionCounter;  /*重复计数,高级定时器有效 */
} TIM_TimeBaseInitTypeDef; 

4、初始化时基单元TIM_TimeBaseInit();

从模式触发源选择:

void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);
/*从模式的触发源选择,TRGI的前级信号选择*/

上述配置完成后,在有外部边沿触发信号过来时,在经过滤波极性等操作后,送到分频器以为,同时还会有TI1FP1信号被触发送出,此时若从模式触发源原则为TI1FP1,则会进入从模式进行响应操作;

从模式操作命令

从模式下有8种动作,4种为编码器相关,另外介绍,剩下4种,测量PWM频率,需要将时基单元的CNT清零,故选择RESET

  *     @arg TIM_SlaveMode_Reset: Rising edge of the selected trigger signal (TRGI) re-initializes
  *                               the counter and triggers an update of the registers.
  *     @arg TIM_SlaveMode_Gated:     The counter clock is enabled when the trigger signal (TRGI) is high.
  *     @arg TIM_SlaveMode_Trigger:   The counter starts at a rising edge of the trigger TRGI.
  *     @arg TIM_SlaveMode_External1: Rising edges of the selected trigger (TRGI) clock the counter.

函数调用TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);

使能计数器:TIM_Cmd(TIM3, ENABLE);

如此计数器自动计数,在GPIO有边沿触发后将CNT值转移到CCR寄存器中同时清零CNT值;

最后调用TIM_GetCapture1(TIM1)的函数返回值,即两个上升沿/下降沿之间的CNT,换算为频率;调用TIM_GetCapture1(TIM2)的函数返回值,即高电平的CNT累加书,换算为占空比;

代码如下:

#include "stm32f10x.h"                  // Device header

void IC_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	TIM_InternalClockConfig(TIM3);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;		//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;		//PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
	
	TIM_ICInitTypeDef TIM_ICInitStructure;
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
	TIM_ICInitStructure.TIM_ICFilter = 0xF;
	TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
	TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);

	TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
	TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
	
	TIM_Cmd(TIM3, ENABLE);
}

uint32_t IC_GetFreq(void)
{
	return 1000000 / (TIM_GetCapture1(TIM3) + 1);
}

uint32_t IC_GetDuty(void)
{
	return (TIM_GetCapture2(TIM3) + 1) * 100 / (TIM_GetCapture1(TIM3) + 1);
}

  • 34
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值