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;//高电平时间usfloat 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);//设置计数器的值为0TIM16CH1_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;/*----------------------------- 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; //720-10k 2.5k 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计数值,读取捕获值会自动清空中断标志}