GD32F130C8T6定时器高精度PWM捕获模式

GD32F130C8T6定时器高精度PWM捕获模式

1.理论:PWM捕获有两种方法,第一种是通过定时器一个通道捕获检测到 上升沿开始捕获,下降沿结束捕获,即得到高电平时间(该方法正点原子视频有讲),第二种方法是通过定时器两个通道捕获一个通道捕获上升沿,一个通道捕获下降沿,捕获完了定时器计数值会自动复位。
第一种方法精度不高,第二种精度更高,第二种详细理论见(转载):https://blog.csdn.net/qq_29413829/article/details/52743273

第一种代码:

#include  "pwm.h"




u8  TIM16CH1_CAPTURE_STA=0;	//输入捕获状态	
float  CAPTURE_PWM_CNT=0;//进入中断次数
float CAPTURE_PWM_TIME=0;//高电平时间us
float CAPTURE_PWM_TIME_TEMP=0;


void Timer16_pwm_capture(void)
{
     TIMER_BaseInitPara    TIM_TimeBaseStructure;
     NVIC_InitPara         NVIC_InitStructure;
     GPIO_InitPara         GPIO_InitStructure;
     TIMER_ICInitPara      TIMER_ICInitParaStruct;

	 RCC_AHBPeriphClock_Enable(RCC_AHBPERIPH_GPIOB, ENABLE);//GPIO时钟使能
	 RCC_APB2PeriphClock_Enable(RCC_APB2PERIPH_CFG, ENABLE);     //映射时钟
	 RCC_APB2PeriphClock_Enable(RCC_APB2PERIPH_TIMER16, ENABLE);
	 
	 GPIO_InitStructure.GPIO_Pin    = GPIO_PIN_8; //输入捕获
	 GPIO_InitStructure.GPIO_Mode   = GPIO_MODE_AF;
	 GPIO_InitStructure.GPIO_Speed  = GPIO_SPEED_50MHZ;
	 GPIO_InitStructure.GPIO_OType  = GPIO_OTYPE_PP;
	 GPIO_InitStructure.GPIO_PuPd   = GPIO_PUPD_PULLDOWN;
	 GPIO_Init(GPIOB, &GPIO_InitStructure); 
	
	 GPIO_PinAFConfig( GPIOB, GPIO_PINSOURCE8, GPIO_AF_2); //TIM16_CH1
	

    TIM_TimeBaseStructure.TIMER_Period = 7200-1; 
    TIM_TimeBaseStructure.TIMER_Prescaler = 1-1; 
    TIM_TimeBaseStructure.TIMER_ClockDivision = TIMER_CDIV_DIV1; 
    TIM_TimeBaseStructure.TIMER_CounterMode = TIMER_COUNTER_UP;//向上计数 
    TIMER_BaseInit(TIMER16, &TIM_TimeBaseStructure); //使能定时器
		
		
	TIMER_ICInitParaStruct.TIMER_CH          = TIMER_CH_1;//捕获通道
	TIMER_ICInitParaStruct.TIMER_ICPolarity  =TIMER_IC_POLARITY_RISING;//捕获极性,上升沿捕获
	TIMER_ICInitParaStruct.TIMER_ICSelection =TIMER_IC_SELECTION_DIRECTTI;//映射关系
	TIMER_ICInitParaStruct.TIMER_ICPrescaler =TIMER_IC_PSC_DIV1;//分频系数
	TIMER_ICInitParaStruct.TIMER_ICFilter    =0x00;//滤波器
	**TIMER_ICInit(TIMER16,&TIMER_ICInitParaStruct);**
		
	NVIC_InitStructure.NVIC_IRQ = TIMER16_IRQn; //中断响应优先级     
	NVIC_InitStructure.NVIC_IRQPreemptPriority=0; 
	NVIC_InitStructure.NVIC_IRQSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQEnable = ENABLE;	 
	NVIC_Init(&NVIC_InitStructure);	
    
	TIMER_ClearIntBitState(TIMER16, TIMER_INT_UPDATE);//清除定时器中断标志
	TIMER_ClearIntBitState(TIMER16,TIMER_INT_CH1);
    TIMER_INTConfig(TIMER16, TIMER_INT_UPDATE | TIMER_INT_CH1, ENABLE);//使能定时器中断
    TIMER_SetCounter(TIMER16,0x0000);//设置计数器的值
    TIMER_Enable(TIMER16, ENABLE);//使能定时器
	
  
}



void TIM16_IRQHandler(void)
{
	
	if(TIMER_GetIntBitState(TIMER16,TIMER_INT_UPDATE)!= RESET)//更新事件
	{
		if(TIM16CH1_CAPTURE_STA)//捕获到了上升沿,但还没有捕获到下降沿,定时器中断就来了
		{
			CAPTURE_PWM_CNT++;
		}
	
		TIMER_ClearIntBitState(TIMER16,TIMER_INT_UPDATE);
	}

	if(TIMER_GetIntBitState(TIMER16,TIMER_INT_CH1)!= RESET)//捕获事件
	{
	
		if(TIM16CH1_CAPTURE_STA) // 捕获到了下降沿
		{
		    TIMER_ICInitPara  TIMER_ICInitParaStruct;//配置下次上升沿捕获
			
			TIM16CH1_CAPTURE_STA=0;//完成捕获,并清除标记状态	
			TIMER_GetCapture1(TIMER16);//获取捕获值
				
			//根据定时器配置,每进一次中断计数器就计数7200次,进了CAPTURE_PWM_CNT 次中断					
            CAPTURE_PWM_TIME_TEMP = (CAPTURE_PWM_CNT * 7200.0 + CAPTURE_PWM_TIME_TEMP) ;			
			
			//每一个计数值=(100.0/7200.0)us, 捕获到高电平时间=CAPTURE_PWM_TIME ;
			CAPTURE_PWM_TIME = CAPTURE_PWM_TIME_TEMP * (100.0/7200.0);

			CAPTURE_PWM_CNT=0;//清空中断次数
			
			TIMER_SetCounter(TIMER16,0x0000);//设置计数器的值
			
			
			TIMER_ICInitParaStruct.TIMER_CH = TIMER_CH_1;
			TIMER_ICInitParaStruct.TIMER_ICPolarity=TIMER_IC_POLARITY_RISING;
			TIMER_ICInitParaStruct.TIMER_ICSelection=TIMER_IC_SELECTION_DIRECTTI;//映射关系
			TIMER_ICInitParaStruct.TIMER_ICPrescaler=TIMER_IC_PSC_DIV1;//分频系数
			TIMER_ICInitParaStruct.TIMER_ICFilter=0x00;//滤波器
			TIMER_PWMCaptureConfig(TIMER16,&TIMER_ICInitParaStruct);
		}
		else //成功捕获到上升沿,并将通道配置为下降沿捕获
		{
			TIMER_ICInitPara  TIMER_ICInitParaStruct;//配置下次下降沿捕获
		    TIMER_SetCounter(TIMER16,0x0000);//设置计数器的值为0
			TIM16CH1_CAPTURE_STA=0x01;		//标记捕获到了上升沿
			
			TIMER_ICInitParaStruct.TIMER_CH = TIMER_CH_1;
			TIMER_ICInitParaStruct.TIMER_ICPolarity=TIMER_IC_POLARITY_FALLING;
			TIMER_ICInitParaStruct.TIMER_ICSelection=TIMER_IC_SELECTION_DIRECTTI;//映射关系
			TIMER_ICInitParaStruct.TIMER_ICPrescaler=TIMER_IC_PSC_DIV1;//分频系数
			TIMER_ICInitParaStruct.TIMER_ICFilter=0x00;//滤波器
			TIMER_PWMCaptureConfig(TIMER16,&TIMER_ICInitParaStruct);
		}
		
		TIMER_ClearIntBitState(TIMER16,TIMER_INT_CH1);
	}


}

第二种方法:

float CAPTURE_PWM_TIME_UP=0;
float CAPTURE_PWM_TIME_ALL=0;
float CAPTURE_PWM_TIME_LAST=0;
float CAPTURE_PWM_DUTY=0;//占空比
float CAPTURE_PWM_FRE=0;//pwm频率



/*----------------------------- TIMER14 500hz  -----------------------------------*/
void Timer15_pwm_capture(void)
{
	
     TIMER_BaseInitPara   TIM_TimeBaseStructure;
	 NVIC_InitPara        NVIC_InitStructure;
	 GPIO_InitPara        GPIO_InitStructure;
	 TIMER_ICInitPara     TIMER_ICInitParaStruct;
	
	
	 RCC_AHBPeriphClock_Enable(RCC_AHBPERIPH_GPIOA , ENABLE);//GPIO时钟使能
	 RCC_APB2PeriphClock_Enable(RCC_APB2PERIPH_CFG, ENABLE); //映射时钟
	 RCC_APB2PeriphClock_Enable(RCC_APB2PERIPH_TIMER15, ENABLE);
	
     GPIO_InitStructure.GPIO_Pin    = GPIO_PIN_3; //输入捕获
	 GPIO_InitStructure.GPIO_Mode   = GPIO_MODE_AF;
	 GPIO_InitStructure.GPIO_Speed  = GPIO_SPEED_50MHZ;
     GPIO_InitStructure.GPIO_OType  = GPIO_OTYPE_PP;
	 GPIO_InitStructure.GPIO_PuPd   = GPIO_PUPD_PULLDOWN;
	 GPIO_Init(GPIOA, &GPIO_InitStructure); 
	
	 GPIO_PinAFConfig(GPIOA,GPIO_PINSOURCE3,GPIO_AF_0);//配置映射为 TIM15_CH2
	

     TIMER_DeInit(TIMER15);
     TIM_TimeBaseStructure.TIMER_Period = 30000-1;   // 72000000/30000=2.4k
     TIM_TimeBaseStructure.TIMER_Prescaler = 1-1; 
     TIM_TimeBaseStructure.TIMER_ClockDivision = TIMER_CDIV_DIV1; 
     TIM_TimeBaseStructure.TIMER_CounterMode = TIMER_COUNTER_UP;//向上计数 
     TIMER_BaseInit(TIMER15, &TIM_TimeBaseStructure); //使能定时器
		
     NVIC_InitStructure.NVIC_IRQ = TIMER15_IRQn; //中断响应优先级     
	 NVIC_InitStructure.NVIC_IRQPreemptPriority=0; 
	 NVIC_InitStructure.NVIC_IRQSubPriority = 0;
	 NVIC_InitStructure.NVIC_IRQEnable = ENABLE;	 
	 NVIC_Init(&NVIC_InitStructure);	
		
	 //这里配置了一个通道,另一个通道会自动配置
	 TIMER_ICInitParaStruct.TIMER_CH          = TIMER_CH_2;//捕获通道  TIMER_CH_2
	 TIMER_ICInitParaStruct.TIMER_ICPolarity  =TIMER_IC_POLARITY_RISING;//捕获极性上升沿捕获
	 TIMER_ICInitParaStruct.TIMER_ICSelection =TIMER_IC_SELECTION_DIRECTTI;//映射关系
	 TIMER_ICInitParaStruct.TIMER_ICPrescaler =TIMER_IC_PSC_DIV1;//分频系数
	 TIMER_ICInitParaStruct.TIMER_ICFilter    =0x00;//滤波器
	 **TIMER_PWMCaptureConfig(TIMER15,&TIMER_ICInitParaStruct);**//第一种是配置   TIMER_ICInit(),现在这里配置的是TIMER_PWMCaptureConfig();

	 TIMER_SelectInputTrigger(TIMER15,TIMER_TS_TI2FP2);
	 TIMER_SelectSlaveMode(TIMER15,TIMER_SLAVE_MODE_RESET);
	 TIMER_SelectMasterSlaveMode(TIMER15,TIMER_MASTER_SLAVE_MODE_ENABLE);
		

	 TIMER_ClearIntBitState(TIMER15, TIMER_INT_UPDATE);//清除定时器中断标志
	 TIMER_ClearIntBitState(TIMER15, TIMER_INT_CH2);
	 TIMER_INTConfig(TIMER15,TIMER_INT_CH2, ENABLE);//使能定时器中断
		
		
	 TIMER_SetCounter(TIMER15,0x0000);//设置计数器的值
	 TIMER_Enable(TIMER15, ENABLE);//使能定时器
	
  
}



void TIM15_IRQHandler(void)
{
  CAPTURE_PWM_TIME_UP = (float)(TIMER15->CHCC1);//上升沿计数值,读取捕获值会自动清空中断标志
  CAPTURE_PWM_TIME_ALL   =(float)(TIMER15->CHCC2);//总pwm计数值,读取捕获值会自动清空中断标志
  if(CAPTURE_PWM_TIME_ALL!=0){
  	CAPTURE_PWM_DUTY=CAPTURE_PWM_TIME_UP /CAPTURE_PWM_TIME_ALL; //计算占空比
  	CAPTURE_PWM_FRE=72000000/CAPTURE_PWM_TIME_ALL;//计算捕获的PWM频率,72000000为该捕获定时器分频后的时钟,我这里没分频(1-1)
  }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值