多通道输入捕获干扰问题,诉求大佬们帮忙解决,感谢!
[复制链接]
写了一个多通道输入捕获的代码,代码见附件。
目的是想通过TIM3的四个通道同时捕获风扇转速反馈回来的方波波形,再计算相应的转速,风扇方波波形如下图:
在调试过程中发现,如果我单独捕获某一个通道的频率时数值是很稳定的,但是两个或者多个一起捕获时,通道数值跳变的很厉害!一直找不到原因。在百度上搜索也没有相关资料,但是看到一篇关于多通道PWM波形输出时有类似情况,说是通道之间干扰。不知道是不是这个原因,也不知道如何去解决。还请大佬们帮忙提供下思路、难道非得一个定时器捕获一个风扇么?我总共12个风扇呐!
四通道输入捕获代码如下:
#include "stm32f10x.h" // Device header
/**
* 函 数:风扇转速捕获初始化
* 参 数:无
* 返 回 值:无
*/
void FG_Capture_Init(uint16_t ARR,uint16_t PSC)
{
/*开启时钟*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //开启TIM3的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //开启GPIOA的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //开启GPIOB的时钟
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure); //将PA6、PA7引脚初始化为上拉输入
GPIO_ResetBits(GPIOA,GPIO_Pin_6);
GPIO_ResetBits(GPIOA,GPIO_Pin_7); //将引脚电平全部拉低
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure); //将PB0、PB1引脚初始化为上拉输入
GPIO_ResetBits(GPIOB,GPIO_Pin_0);
GPIO_ResetBits(GPIOB,GPIO_Pin_1); //将引脚电平全部拉低
/*配置时钟源*/
TIM_InternalClockConfig(TIM3); //选择TIM3为内部时钟,若不调用此函数,TIM默认也为内部时钟
/*时基单元初始化*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; //定义结构体变量
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频,选择不分频,此参数用于配置滤波器时钟,不影响时基单元功能
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式,选择向上计数
TIM_TimeBaseInitStructure.TIM_Period = ARR; //计数周期,即ARR的值
TIM_TimeBaseInitStructure.TIM_Prescaler = PSC; //预分频器,即PSC的值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重复计数器,高级定时器才会用到
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure); //将结构体变量交给TIM_TimBaseInit,配置TIM3的时基单元
/*输入捕获初始化*/
TIM_ICInitTypeDef TIM_ICInitStructure; //定义结构体变量
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; //选择配置定时器通道1
TIM_ICInitStructure.TIM_ICFilter = 0x0; //输入滤波器参数,可以过滤信号抖动
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_ICInit,配置TIM3的输入捕获通道
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; //选择配置定时器通道2
TIM_ICInitStructure.TIM_ICFilter = 0x0;
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_ICInitStructure.TIM_Channel = TIM_Channel_3; //选择配置定时器通道3
TIM_ICInitStructure.TIM_ICFilter = 0x0;
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_ICInitStructure.TIM_Channel = TIM_Channel_4; //选择配置定时器通道4
TIM_ICInitStructure.TIM_ICFilter = 0x0;
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);
/*中断分组优先级初始化*/
NVIC_InitTypeDef NVIC_InitStructure; //定义结构体变量
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占优先级2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //从优先级2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //配置寄存器
/*
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //先占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //从优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure);*/ //配置寄存器
//允许更新中断,允许CCxIE捕获中断
// TIM_ITConfig(TIM3,TIM_IT_Update|TIM_IT_CC1|TIM_IT_CC2|TIM_IT_CC3|TIM_IT_CC4,ENABLE);
TIM_ITConfig(TIM3,TIM_IT_Update|TIM_IT_CC1|TIM_IT_CC3,ENABLE);
/*选择触发源及从模式*/
// TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1); //触发源选择TI1FP1
// TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset); //从模式选择复位
//即TI1产生上升沿时,会触发CNT归零
/*TIM使能*/
TIM_Cmd(TIM3,ENABLE); //使能TIM3,定时器开始运行
}
uint8_t TIM3CH_CAPTURE_STA[4] = {0}; //输入捕获状态数组
uint16_t TIM3CH_CAPTURE_VAL[4] = {0}; //输入捕获值数组
/*输入捕获状态数组位说明:
--------------------------------------------------------------
bit7 | bit6 | bit5~0
------------|----------------|--------------------------------
捕获完成标志|捕获到高电平标志|捕获到高电平后定时器溢出的次数
--------------------------------------------------------------
*/
/**
* 函 数:定时器3中断服务程序
* 参 数:无
* 返 回 值:无
*/
void TIM3_IRQHandler(void)
{
//CH1
if((TIM3CH_CAPTURE_STA[0] & 0X80) == 0) //若bit7为0,还未捕获到一个完整的周期
{
//溢出中断处理部分
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检测定时器3是否发生中断
{ //若发生中断
if(TIM3CH_CAPTURE_STA[0] & 0X40) //若bit6为1,即已经第一次捕获到高电平
{
if((TIM3CH_CAPTURE_STA[0] & 0X3F) == 0X3F) //若高电平太长,且溢出次数超过bit5~0可实现的计数
{
TIM3CH_CAPTURE_STA[0] |= 0X80; //将bit7赋值为1,标记成功捕获了一次
TIM3CH_CAPTURE_VAL[0] = 0XFFFF;
}
else
TIM3CH_CAPTURE_STA[0]++; //溢出次数+1
}
}
//捕获中断处理
if(TIM_GetITStatus(TIM3,TIM_IT_CC1) != RESET) //捕获1发生捕获事件
{
if(TIM3CH_CAPTURE_STA[0]&0X40) //捕获到第二个上升沿
{
TIM3CH_CAPTURE_STA[0] |= 0X80; //标记捕获到一个完整的周期,给主程序处理
TIM3CH_CAPTURE_VAL[0] = TIM_GetCapture1(TIM3); //获取事件
}
else //捕获到第一个上升沿
{
TIM3CH_CAPTURE_STA[0] = 0; //清空标志位
TIM3CH_CAPTURE_VAL[0] = 0; //清空计时器
TIM_SetCounter(TIM3,0); //清空定时器
TIM3CH_CAPTURE_STA[0] |= 0X40; //标记捕获到第一个上升沿
}
}
}
//清除中断标志位
TIM_ClearITPendingBit(TIM3, TIM_IT_CC1 | TIM_IT_Update);
//CH2
if((TIM3CH_CAPTURE_STA[1] & 0X80) == 0)
{
//溢出中断处理部分
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
{
if(TIM3CH_CAPTURE_STA[1] & 0X40)
{
if((TIM3CH_CAPTURE_STA[1] & 0X3F) == 0X3F)
{
TIM3CH_CAPTURE_STA[1] |= 0X80;
TIM3CH_CAPTURE_VAL[1] = 0XFFFF;
}
else
TIM3CH_CAPTURE_STA[1]++;
}
}
//捕获中断处理
if(TIM_GetITStatus(TIM3,TIM_IT_CC2) != RESET) //捕获2发生捕获事件
{
if(TIM3CH_CAPTURE_STA[1]&0X40)
{
TIM3CH_CAPTURE_STA[1] |= 0X80;
TIM3CH_CAPTURE_VAL[1] = TIM_GetCapture2(TIM3);
}
else
{
TIM3CH_CAPTURE_STA[1] = 0;
TIM3CH_CAPTURE_VAL[1] = 0;
TIM_SetCounter(TIM3,0);
TIM3CH_CAPTURE_STA[1] |= 0X40;
}
}
}
//清除中断标志位
TIM_ClearITPendingBit(TIM3, TIM_IT_CC2 | TIM_IT_Update);
//CH3
if((TIM3CH_CAPTURE_STA[2] & 0X80) == 0)
{
//溢出中断处理部分
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
{
if(TIM3CH_CAPTURE_STA[2] & 0X40)
{
if((TIM3CH_CAPTURE_STA[2] & 0X3F) == 0X3F)
{
TIM3CH_CAPTURE_STA[2] |= 0X80;
TIM3CH_CAPTURE_VAL[2] = 0XFFFF;
}
else
TIM3CH_CAPTURE_STA[2]++;
}
}
//捕获中断处理
if(TIM_GetITStatus(TIM3,TIM_IT_CC3) != RESET) //捕获3发生捕获事件
{
if(TIM3CH_CAPTURE_STA[2]&0X40)
{
TIM3CH_CAPTURE_STA[2] |= 0X80;
TIM3CH_CAPTURE_VAL[2] = TIM_GetCapture3(TIM3);
}
else
{
TIM3CH_CAPTURE_STA[2] = 0;
TIM3CH_CAPTURE_VAL[2] = 0;
TIM_SetCounter(TIM3,0);
TIM3CH_CAPTURE_STA[2] |= 0X40;
}
}
}
//清除中断标志位
TIM_ClearITPendingBit(TIM3, TIM_IT_CC3 | TIM_IT_Update);
//CH4
if((TIM3CH_CAPTURE_STA[3] & 0X80) == 0)
{
//溢出中断处理部分
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
{
if(TIM3CH_CAPTURE_STA[3] & 0X40)
{
if((TIM3CH_CAPTURE_STA[3] & 0X3F) == 0X3F)
{
TIM3CH_CAPTURE_STA[3] |= 0X80;
TIM3CH_CAPTURE_VAL[3] = 0XFFFF;
}
else
TIM3CH_CAPTURE_STA[3]++;
}
}
//捕获中断处理
if(TIM_GetITStatus(TIM3,TIM_IT_CC4) != RESET) //捕获4发生捕获事件
{
if(TIM3CH_CAPTURE_STA[3]&0X40)
{
TIM3CH_CAPTURE_STA[3] |= 0X80;
TIM3CH_CAPTURE_VAL[3] = TIM_GetCapture4(TIM3);
}
else
{
TIM3CH_CAPTURE_STA[3] = 0;
TIM3CH_CAPTURE_VAL[3] = 0;
TIM_SetCounter(TIM3,0);
TIM3CH_CAPTURE_STA[3] |= 0X40;
}
}
}
//清除中断标志位
TIM_ClearITPendingBit(TIM3, TIM_IT_CC4 | TIM_IT_Update);
}
主程序代码如下:
|