高级定时器之输入捕获应用(PWM输入捕获)

发布时间:2022-09-20 17:00

高级定时器-输入捕获应用(PWM输入捕获)

​ 前面我们讲了用输入捕获测量了信号的脉宽,这一节我们讲输入捕获的一个特例—PWM输入

​ 普通的输入捕获可以使用定时器的四个通道,一路捕获占用一个捕获寄存器,而PWM输入则只能使用两个通道,即通道1和通道2,且一路PWM输入要占用两个捕获寄存器,一个用于捕获周期,一个用于捕获占空比

​ 在本实验中,我们用通用定时器产生的一路PWM信号,然后用高级定时器的通道1和通道2来捕获。


硬件设计

​ 实验中用到两个引脚,一个是通用定时器TIM3的通道1,即PA6,用于输出PWM信号,另一个是高级定时器TIM1的通道1,即PA8,用来PWM输入捕获,实验中,用一根杜邦线短接PA6和PA8即可,同时可用示波器监控PA6的波形,看看捕获的数据是否正确。

软件设计

AdvancedTime.c文件

#include "./advancedtime/bsp_advancedtime.h"

static void AdvancedTime_NVIC_Init(void)
{
	NVIC_InitTypeDef	NVIC_InitStructure = {0};
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitStructure.NVIC_IRQChannel = AdvancedTimeX_IRQn;//定时器1的捕获中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}
static void AdvancedTime_GPIO_Init(void)
{
	GPIO_InitTypeDef	GPIO_InitStructure = {0};
	//开启GPIO的时钟
	AdvancedTimeX_CH1_RCC_APB_CLKCMD(AdvancedTimeX_CH1_RCC_CLK_Periph,ENABLE);
	GPIO_InitStructure.GPIO_Pin = AdvancedTimeX_CH1_RCC_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(AdvancedTimeX_CH1_RCC_GPIO_PORT,&GPIO_InitStructure);
}
static void AdvancedTime_Mode_Init(void)
{
	TIM_TimeBaseInitTypeDef	TIM_TimeBaseInitStructure = {0};
	TIM_ICInitTypeDef	TIM_ICInitStructure = {0};
	//开启定时器时钟
	AdvancedTimeX_RCC_APB_CLKCMD(AdvancedTimeX_RCC_CLK_Periph,ENABLE);
	//时基配置
	TIM_TimeBaseInitStructure.TIM_Period = AdvancedTimeX_Period;
	TIM_TimeBaseInitStructure.TIM_Prescaler = AdvancedTimeX_PSC;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(AdvancedTimeX,&TIM_TimeBaseInitStructure);
	//输入捕获配置
	TIM_ICInitStructure.TIM_Channel = AdvancedTimeX_Channel;
	TIM_ICInitStructure.TIM_ICFilter = 0;
	TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
	TIM_PWMIConfig(AdvancedTimeX,&TIM_ICInitStructure);
	//配置输入触发信号
	TIM_SelectInputTrigger(AdvancedTimeX,TIM_TS_TI1FP1);
	//选择从模式:复位模式.PWM输入模式时,从模式必须工作在复位模式,当捕获开始时,计数器CNT会被复位
	TIM_SelectSlaveMode(AdvancedTimeX, TIM_SlaveMode_Reset);
	TIM_SelectMasterSlaveMode(AdvancedTimeX,TIM_MasterSlaveMode_Enable);	
	//清除中断标志位
	TIM_ClearITPendingBit(AdvancedTimeX,TIM_IT_CC1);
	//使能捕获中断,这个中断针对的是主捕获通道(测量周期这个)
	TIM_ITConfig(AdvancedTimeX,TIM_IT_CC1,ENABLE);
	//使能高级定时器,计数器开始计数
	TIM_Cmd(AdvancedTimeX,ENABLE);
}
void AdvancedTime_Init(void)
{
	AdvancedTime_NVIC_Init();
	AdvancedTime_GPIO_Init();
	AdvancedTime_Mode_Init();
}

AdvancedTime.h文件

#ifndef  __BSP_ADVANCEDTIME_H
#define  __BSP_ADVANCEDTIME_H

#include "stm32f10x.h"

#define     AdvancedTimeX								TIM1
#define     AdvancedTimeX_RCC_APB_CLKCMD				RCC_APB2PeriphClockCmd
#define     AdvancedTimeX_RCC_CLK_Periph				RCC_APB2Periph_TIM1

#define     AdvancedTimeX_CH1_RCC_APB_CLKCMD			RCC_APB2PeriphClockCmd
#define    	AdvancedTimeX_CH1_RCC_CLK_Periph			RCC_APB2Periph_GPIOA
#define     AdvancedTimeX_CH1_RCC_GPIO_PORT				GPIOA
#define     AdvancedTimeX_CH1_RCC_GPIO_PIN				GPIO_Pin_8

#define     AdvancedTimeX_IRQn							TIM1_CC_IRQn
#define     AdvancedTimeX_IRQHandler					TIM1_CC_IRQHandler
#define     AdvancedTimeX_Period						(1000-1)
#define     AdvancedTimeX_PSC							(72-1)
#define     AdvancedTimeX_Channel						TIM_Channel_1

extern void AdvancedTime_Init(void);

#endif

GeneralTime.c文件

#include "./generaltime/bsp_generaltime.h"

//定时器的GPIO配置
static void GeneralTime_GPIO_Init(void)
{
	GPIO_InitTypeDef	GPIO_InitStructure = {0};
	//开启时钟
	GeneralTimX_CH1_RCC_CLKCMD(GeneralTimeX_CH1_RCC_CLK_Periph,ENABLE);
	GeneralTimX_CH2_RCC_CLKCMD(GeneralTimeX_CH2_RCC_CLK_Periph,ENABLE);
	GeneralTimX_CH3_RCC_CLKCMD(GeneralTimeX_CH3_RCC_CLK_Periph,ENABLE);
	GeneralTimX_CH4_RCC_CLKCMD(GeneralTimeX_CH4_RCC_CLK_Periph,ENABLE);	
	//GPIO配置
	GPIO_InitStructure.GPIO_Pin = GeneralTimX_CH1_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GeneralTimX_CH1_GPIO_PORT,&GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin = GeneralTimX_CH2_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GeneralTimX_CH2_GPIO_PORT,&GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin = GeneralTimX_CH3_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GeneralTimX_CH3_GPIO_PORT,&GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GeneralTimX_CH4_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GeneralTimX_CH4_GPIO_PORT,&GPIO_InitStructure);
}
//定时器的Mode配置
static void GeneralTime_Mode_Init(void)
{
	TIM_TimeBaseInitTypeDef	TIM_TimeBaseInitStructure = {0};
	TIM_OCInitTypeDef	TIM_OCInitStructure = {0};
	//开启定时器时钟 
	GeneralTimeX_RCC_CLKCMD(GeneralTimeX_RCC_CLK_Periph,ENABLE);
	//时基配置
	TIM_TimeBaseInitStructure.TIM_Period = GeneralTimeX_Period;
	TIM_TimeBaseInitStructure.TIM_Prescaler = GeneralTimeX_PSC;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(GeneralTimeX,&TIM_TimeBaseInitStructure);
	//输出比较配置
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_Pulse = GeneralTimeX_CCR1;
	TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
	TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
	TIM_OC1Init(GeneralTimeX,&TIM_OCInitStructure);
	TIM_OC1PreloadConfig(GeneralTimeX,TIM_OCPreload_Enable);
	//输入捕获通道2
	TIM_OCInitStructure.TIM_Pulse = GeneralTimeX_CCR2;
	TIM_OC2Init(GeneralTimeX,&TIM_OCInitStructure);	
	TIM_OC2PreloadConfig(GeneralTimeX,TIM_OCPreload_Enable);
	//输入捕获通道3
	TIM_OCInitStructure.TIM_Pulse = GeneralTimeX_CCR3;
	TIM_OC2Init(GeneralTimeX,&TIM_OCInitStructure);	
	TIM_OC3PreloadConfig(GeneralTimeX,TIM_OCPreload_Enable);
	//输入捕获通道4
	TIM_OCInitStructure.TIM_Pulse = GeneralTimeX_CCR4;
	TIM_OC2Init(GeneralTimeX,&TIM_OCInitStructure);		
	TIM_OC4PreloadConfig(GeneralTimeX,TIM_OCPreload_Enable);
	//使能定时器
	TIM_Cmd(GeneralTimeX,ENABLE);
}
void GeneralTime_Init(void)
{
	GeneralTime_GPIO_Init();
	GeneralTime_Mode_Init();
}	

GeneralTime.h文件

#ifndef  __BSP_GENERALTIME_H
#define  __BSP_GENERALTIME_H

#include "stm32f10x.h"

#define      GeneralTimeX							TIM3
#define      GeneralTimeX_RCC_CLKCMD				RCC_APB1PeriphClockCmd
#define      GeneralTimeX_RCC_CLK_Periph			RCC_APB1Periph_TIM3

#define      GeneralTimeX_Period					(10-1)
#define      GeneralTimeX_PSC						(72-1)

#define      GeneralTimeX_CCR1						5
#define      GeneralTimeX_CCR2						4
#define      GeneralTimeX_CCR3						3
#define      GeneralTimeX_CCR4						2

#define      GeneralTimX_CH1_RCC_CLKCMD				RCC_APB2PeriphClockCmd
#define      GeneralTimeX_CH1_RCC_CLK_Periph		RCC_APB2Periph_GPIOA
#define      GeneralTimX_CH1_GPIO_PORT				GPIOA
#define      GeneralTimX_CH1_GPIO_PIN				GPIO_Pin_6

#define      GeneralTimX_CH2_RCC_CLKCMD				RCC_APB2PeriphClockCmd
#define      GeneralTimeX_CH2_RCC_CLK_Periph		RCC_APB2Periph_GPIOA
#define      GeneralTimX_CH2_GPIO_PORT				GPIOA
#define      GeneralTimX_CH2_GPIO_PIN				GPIO_Pin_7

#define      GeneralTimX_CH3_RCC_CLKCMD				RCC_APB2PeriphClockCmd
#define      GeneralTimeX_CH3_RCC_CLK_Periph		RCC_APB2Periph_GPIOB
#define      GeneralTimX_CH3_GPIO_PORT				GPIOB
#define      GeneralTimX_CH3_GPIO_PIN				GPIO_Pin_0

#define      GeneralTimX_CH4_RCC_CLKCMD				RCC_APB2PeriphClockCmd
#define      GeneralTimeX_CH4_RCC_CLK_Periph		RCC_APB2Periph_GPIOB
#define      GeneralTimX_CH4_GPIO_PORT				GPIOB
#define      GeneralTimX_CH4_GPIO_PIN				GPIO_Pin_1

extern void GeneralTime_Init(void);
#endif

中断服务函数文件

__IO uint16_t IC2Value = 0;
__IO uint16_t IC1Value = 0;
__IO float DutyCycle = 0;
__IO float Frequency = 0;

void SysTick_Handler(void)
{
}
void AdvancedTimeX_IRQHandler(void)
{
  /* 清除中断标志位 */
  TIM_ClearITPendingBit(AdvancedTimeX, TIM_IT_CC1);
	//获取输入捕获值
  IC1Value = TIM_GetCapture1(AdvancedTimeX);
  IC2Value = TIM_GetCapture2(AdvancedTimeX);	
  // 注意:捕获寄存器CCR1和CCR2的值在计算占空比和频率的时候必须加1
	if (IC1Value != 0)
  {
    /* 占空比计算 */
    DutyCycle = (float)((IC2Value+1) * 100) / (IC1Value+1);
    /* 频率计算 */
    Frequency = (72000000/(AdvancedTimeX_PSC+1))/(float)(IC1Value+1);
	printf("占空比:%0.2f%%   频率:%0.2fHz\n",DutyCycle,Frequency);
  }
  else
  {
    DutyCycle = 0;
    Frequency = 0;
  }
}

main.c文件

#include "stm32f10x.h"
#include "bsp_led.h"
#include "./generaltime/bsp_generaltime.h"
#include "./usart/bsp_usart.h"
#include "./advancedtime/bsp_advancedtime.h"

int main(void)
{		 
	GeneralTime_Init();
	USART_Config();
	AdvancedTime_Init();
	
	while (1)
	{

	}
}

学有所成,以图强国!

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号