本文基于一块新兴的国产芯片平台Z20K142单片机设计的一款输入捕获方法,可以正确捕获到PWM的频率和占空比。
主要算法写在输入捕获回调函数里面:
主要考虑到以下几种条件,首先pwm是从高电平来的还是从低电平来的,其次考虑ccv计数值,是否快要接近mod值了,如果通过比较发现小于mod值,此pwm的频率就等于两次CCV值的差,相反的话就等于第二次CCV值减去第一次CCV值加上一个mod值,结果如下回调函数所示。
static uint32_t CapturePwmPeriod = 0xFF; //输入捕获到的PWM周期
static uint32_t CapturePwmDuty = 0xFF; //输入捕获到的PWM占空比
static int32_t Period1 = 0; //输入捕获到的PWM波形上升沿时刻的计数器值,前
static int32_t Period2 = 0; //输入捕获到的PWM波形上升沿时刻的计数器值,后
static int32_t Duty1 = 0; //输入捕获到的PWM波形下降沿时刻的计数器值
static uint32_t UnstableCounter = 0; //输入捕获无效值的过滤次数
/**************************************************************************************************
*函数: TimCallback
*功能: TIM输入捕获的回调函数,计算输入PWM波形的占空比和周期
*参数: NONE
*返值: NONE
*说明: 占空比和周期的计算结果会更新到静态变量中;用周期内高电平时间占比计算占空比
**************************************************************************************************/
void TimCallback()
{
if(GPIO_ReadPinLevel(CAPTURE_CHPORT,CAPTURE_CHPIN)==GPIO_HIGH) //识别上升沿
{
Period1 = Period2; //Period1更新前一个上升沿时刻的计数器值
Period2 = TIM_GetCCVal(CAPTURE_TIMID,CAPTURE_CH); //Period2更新当前上升沿时刻的计数器值
if(Period2 <= Period1)
{
CapturePwmPeriod = CAPTURE_COUNTERMAX + (Period2 - Period1); //输入PWM波形相邻边沿中间出现TIM溢出时,需要加TIM的溢出值再相减,得到周期
}
else
{
CapturePwmPeriod = Period2 - Period1; //输入PWM波形相邻边沿中间没有TIM溢出时,直接相减得到周期
}
}
else
{
Duty1 = TIM_GetCCVal(CAPTURE_TIMID,CAPTURE_CH); //Duty1更新当前下降沿时刻的计数器值
if(Duty1 <= Period2)
{
CapturePwmDuty = CAPTURE_COUNTERMAX + (Duty1 - Period2); //输入PWM波形相邻边沿中间出现TIM溢出时,需要加TIM的溢出值再相减,得到占空比
}
else
{
CapturePwmDuty = Duty1 - Period2; //输入PWM波形相邻边沿中间没有TIM溢出时,直接相减得到得到占空比
}
}
if(UnstableCounter<4)
{
UnstableCounter++; //输入捕获第1次边沿可能是假的需要丢弃,之后至少经过3次边沿,才能保证周期和占空比计算正确
}
}
/**************************************************************************************************
*函数: Bsp_GetPwmPeriod
*功能: 获取输入PWM波形的周期
*参数: NONE
*返值: 输入PWM波形的周期
*说明:
**************************************************************************************************/
uint32_t Bsp_GetPwmPeriod(void)
{
if(UnstableCounter<4)
{
return CAPTURE_COUNTERMAX; //输入捕获第1次边沿可能是假的需要丢弃,之后至少经过3次边沿,才能保证周期和占空比计算正确
}
return CapturePwmPeriod;
}
/**************************************************************************************************
*函数: Bsp_GetPwmDuty
*功能: 获取输入PWM波形的占空比
*参数: NONE
*返值: 输入PWM波形的占空比
*说明:
**************************************************************************************************/
uint32_t Bsp_GetPwmDuty(void)
{
if(UnstableCounter<4)
{
return CAPTURE_COUNTERMAX; //输入捕获第1次边沿可能是假的需要丢弃,之后至少经过3次边沿,才能保证周期和占空比计算正确
}
return CapturePwmDuty;
}