STM32输入捕获TIM2四通道
2024-08-30 06:54:12
相比于一通道,原子的例程里因为清了计数时间,所以要对程序进行修改。
记录上升沿后的计数,然后记录下降沿的计数。相减后计算高电平时间,对于定时器中断间隔的边界要分开处理。
这里因为我的接收机时间是1ms~2ms,而中断时间设置为20ms。所以根本不需要考虑时间延迟超过计时器时间。
下面是我的代码
//arr:自动重装值 psc:时钟预分频数
//定时器溢出时间计算:Tout=((arr+1)*(psc+1))/Ft us
//Ft = 定时器工作频率,单位Mhz
//TIM2在APB1上,为HCLK/2 36Mhz
void TIM2_CAP_Init(u16 arr, u16 psc)
{
GPIO_InitTypeDef GPIO_InitStruct;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_ICInitTypeDef TIM_ICInitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
//开启TIM2和GPIO时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
//PA0初始化
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD; //下拉输入
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct); //TIM2定时器初始化
TIM_TimeBaseInitStruct.TIM_Period = arr;
TIM_TimeBaseInitStruct.TIM_Prescaler = psc;
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct); //TIM2_CH1输入捕获初始化
TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;
TIM_ICInitStruct.TIM_ICFilter = 0x00; //不滤波
TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕获
TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1; //输入器不分频
TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到IC1
TIM_ICInit(TIM2, &TIM_ICInitStruct); TIM_ICInitStruct.TIM_Channel = TIM_Channel_2;
TIM_ICInitStruct.TIM_ICFilter = 0x00; //不滤波
TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕获
TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1; //输入器不分频
TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到IC2
TIM_ICInit(TIM2, &TIM_ICInitStruct); TIM_ICInitStruct.TIM_Channel = TIM_Channel_3;
TIM_ICInitStruct.TIM_ICFilter = 0x00; //不滤波
TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕获
TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1; //输入器不分频
TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到IC3
TIM_ICInit(TIM2, &TIM_ICInitStruct); TIM_ICInitStruct.TIM_Channel = TIM_Channel_4;
TIM_ICInitStruct.TIM_ICFilter = 0x00; //不滤波
TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕获
TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1; //输入器不分频
TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到IC4
TIM_ICInit(TIM2, &TIM_ICInitStruct); //中断分组初始化
NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = ;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = ;
NVIC_Init(&NVIC_InitStruct); TIM_ITConfig(TIM2, TIM_IT_CC1|TIM_IT_CC2|TIM_IT_CC3|TIM_IT_CC4, ENABLE); //更新中断和CC1IE捕获中断 TIM_Cmd(TIM2, ENABLE);
printf("Init TIM2 CAP success\n");
}
然后是中断处理函数
//捕获状态
//[7]:0,没有成功捕获;1,成功捕获到一次
//[6]:0,还没捕获到低电平;1,已经捕获到低电平了.
//[5:0]:捕获低电平后溢出第次数
u8 CAPTURE_STA_TIM2CH[] = {};
u16 CAPTURE_VAL_TIM2CH[];
u16 CAPTURE_UP_TIM2CH[], CAPTURE_DOWN_TIM2CH[];
void TIM2_IRQHandler(void)
{
// if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
// if((CAPTURE_STA_TIM2CH[1]&0x80) == 0) { //还未捕获成功
// if(CAPTURE_STA_TIM2CH[1]&0x40) { //已经捕获到高电平了
// if((CAPTURE_STA_TIM2CH[1]&0x3F)==0x3F) { //高电平太长了
// CAPTURE_STA_TIM2CH[1] |= 0x80; //标记成功捕获了一次
// CAPTURE_VAL_TIM2CH[1] = 0xFFFF;
// } else
// CAPTURE_VAL_TIM2CH[1]++;
// }
// }
// TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
// } if((CAPTURE_STA_TIM2CH[]&0x80) == ) { //还未捕获成功
if(TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET) { //捕获1发生捕获事件
if(CAPTURE_STA_TIM2CH[]&0x40) { //捕获到一个下降沿
CAPTURE_STA_TIM2CH[] |= 0x80; //标记成功捕获到一次高电平脉宽
CAPTURE_DOWN_TIM2CH[] = TIM_GetCapture1(TIM2);
if(CAPTURE_DOWN_TIM2CH[] >= CAPTURE_UP_TIM2CH[])
CAPTURE_VAL_TIM2CH[] = CAPTURE_DOWN_TIM2CH[] - CAPTURE_UP_TIM2CH[];
else
CAPTURE_VAL_TIM2CH[] = 0xffff + CAPTURE_DOWN_TIM2CH[] - CAPTURE_UP_TIM2CH[];
TIM_OC1PolarityConfig(TIM2, TIM_ICPolarity_Rising); //CC1P=0 设置为上升沿捕获
} else { //还未开始,第一次捕获上升沿
CAPTURE_STA_TIM2CH[] = ; //清空
CAPTURE_VAL_TIM2CH[] = ;
CAPTURE_UP_TIM2CH[] = TIM_GetCapture1(TIM2);
CAPTURE_STA_TIM2CH[] |= 0x40; //标记捕获到了上升沿
TIM_OC1PolarityConfig(TIM2, TIM_ICPolarity_Falling); //CC1P=1 设置为下降沿捕获
}
TIM_ClearFlag(TIM2, TIM_FLAG_CC1); //清除状态标志
}
} if((CAPTURE_STA_TIM2CH[]&0x80) == ) { //还未捕获成功
if(TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET) { //捕获2发生捕获事件
if(CAPTURE_STA_TIM2CH[]&0x40) { //捕获到一个下降沿
CAPTURE_STA_TIM2CH[] |= 0x80; //标记成功捕获到一次高电平脉宽
CAPTURE_DOWN_TIM2CH[] = TIM_GetCapture2(TIM2); //获取捕获2计数
if(CAPTURE_DOWN_TIM2CH[] >= CAPTURE_UP_TIM2CH[])
CAPTURE_VAL_TIM2CH[] = CAPTURE_DOWN_TIM2CH[] - CAPTURE_UP_TIM2CH[];
else
CAPTURE_VAL_TIM2CH[] = 0xffff + CAPTURE_DOWN_TIM2CH[] - CAPTURE_UP_TIM2CH[];
TIM_OC2PolarityConfig(TIM2, TIM_ICPolarity_Rising); //CC1P=0 设置为上升沿捕获
} else { //还未开始,第一次捕获上升沿
CAPTURE_STA_TIM2CH[] = ; //清空
CAPTURE_VAL_TIM2CH[] = ;
CAPTURE_UP_TIM2CH[] = TIM_GetCapture2(TIM2);
CAPTURE_STA_TIM2CH[] |= 0x40; //标记捕获到了上升沿
TIM_OC2PolarityConfig(TIM2, TIM_ICPolarity_Falling); //CC1P=1 设置为下降沿捕获
}
TIM_ClearFlag(TIM2, TIM_FLAG_CC2); //清除状态标志
}
} if((CAPTURE_STA_TIM2CH[]&0x80) == ) { //还未捕获成功
if(TIM_GetITStatus(TIM2, TIM_IT_CC3) != RESET) { //捕获2发生捕获事件
if(CAPTURE_STA_TIM2CH[]&0x40) { //捕获到一个下降沿
CAPTURE_STA_TIM2CH[] |= 0x80; //标记成功捕获到一次高电平脉宽
CAPTURE_DOWN_TIM2CH[] = TIM_GetCapture3(TIM2); //获取捕获2计数
if(CAPTURE_DOWN_TIM2CH[] >= CAPTURE_UP_TIM2CH[])
CAPTURE_VAL_TIM2CH[] = CAPTURE_DOWN_TIM2CH[] - CAPTURE_UP_TIM2CH[];
else
CAPTURE_VAL_TIM2CH[] = 0xffff + CAPTURE_DOWN_TIM2CH[] - CAPTURE_UP_TIM2CH[];
TIM_OC3PolarityConfig(TIM2, TIM_ICPolarity_Rising); //CC1P=0 设置为上升沿捕获
} else { //还未开始,第一次捕获上升沿
CAPTURE_STA_TIM2CH[] = ; //清空
CAPTURE_VAL_TIM2CH[] = ;
CAPTURE_UP_TIM2CH[] = TIM_GetCapture3(TIM2);
CAPTURE_STA_TIM2CH[] |= 0x40; //标记捕获到了上升沿
TIM_OC3PolarityConfig(TIM2, TIM_ICPolarity_Falling); //CC1P=1 设置为下降沿捕获
}
TIM_ClearFlag(TIM2, TIM_FLAG_CC3); //清除状态标志
}
}
if((CAPTURE_STA_TIM2CH[]&0x80) == ) { //还未捕获成功
if(TIM_GetITStatus(TIM2, TIM_IT_CC4) != RESET) { //捕获2发生捕获事件
if(CAPTURE_STA_TIM2CH[]&0x40) { //捕获到一个下降沿
CAPTURE_STA_TIM2CH[] |= 0x80; //标记成功捕获到一次高电平脉宽
CAPTURE_DOWN_TIM2CH[] = TIM_GetCapture4(TIM2); //获取捕获2计数
if(CAPTURE_DOWN_TIM2CH[] >= CAPTURE_UP_TIM2CH[])
CAPTURE_VAL_TIM2CH[] = CAPTURE_DOWN_TIM2CH[] - CAPTURE_UP_TIM2CH[];
else
CAPTURE_VAL_TIM2CH[] = 0xffff + CAPTURE_DOWN_TIM2CH[] - CAPTURE_UP_TIM2CH[];
TIM_OC4PolarityConfig(TIM2, TIM_ICPolarity_Rising); //CC1P=0 设置为上升沿捕获
} else { //还未开始,第一次捕获上升沿
CAPTURE_STA_TIM2CH[] = ; //清空
CAPTURE_VAL_TIM2CH[] = ;
CAPTURE_UP_TIM2CH[] = TIM_GetCapture4(TIM2);
CAPTURE_STA_TIM2CH[] |= 0x40; //标记捕获到了上升沿
TIM_OC4PolarityConfig(TIM2, TIM_ICPolarity_Falling); //CC1P=1 设置为下降沿捕获
}
TIM_ClearFlag(TIM2, TIM_FLAG_CC4); //清除状态标志
}
} //处理帧数据
if(CAPTURE_STA_TIM2CH[]&0x80) { //成功捕获到了一次上升沿 //溢出时间总和
myControl.remoteControl[] = CAPTURE_VAL_TIM2CH[]; //得到总的高电平时间
// printf("TIM2 CH1:%d\t", temp[0]);
CAPTURE_STA_TIM2CH[] = ;
}
if(CAPTURE_STA_TIM2CH[]&0x80) { //成功捕获到了一次上升沿 //溢出时间总和
myControl.remoteControl[] = CAPTURE_VAL_TIM2CH[]; //得到总的高电平时间
// printf("TIM2 CH2:%d\t", temp[1]);
CAPTURE_STA_TIM2CH[] = ;
}
if(CAPTURE_STA_TIM2CH[]&0x80) { //成功捕获到了一次上升沿 //溢出时间总和
myControl.remoteControl[] = CAPTURE_VAL_TIM2CH[]; //得到总的高电平时间
// printf("TIM2 CH3:%d\t", temp[2]);
CAPTURE_STA_TIM2CH[] = ;
}
if(CAPTURE_STA_TIM2CH[]&0x80) { //成功捕获到了一次上升沿 //溢出时间总和
myControl.remoteControl[] = CAPTURE_VAL_TIM2CH[]; //得到总的高电平时间
// printf("TIM2 CH4:%d\t", temp[3]);
CAPTURE_STA_TIM2CH[] = ;
}
}
这些printf函数会极大的占用MCU资源,所以不在中断中处理。
最新文章
- Form Builder的三种查询方法构建
- 那些强悍的PHP一句话后门
- Tomcat6环境JBPM4.4报错:java.lang.ClassNotFoundException: de.odysseus.el.util.SimpleResolver
- spring 小结
- [Windows驱动]流媒体驱动开发
- IOS 日志输出控制
- Linux Shell产生16进制随机数
- IOS动态修改按钮响应时间
- Unity 中关于 BuildSetting 中 “Optimize Mesh Data” 选项的“坑”
- Javascript中bind()方法的使用与实现
- (git fetch git push git pull)远程本地分支互相推送更新
- Qt带来的是更加低廉的开发成本和学习成本,对于很多小公司而言,这种优势足以让他们获得更大的利润空间 good
- Java学习之开篇—个人随想
- ios7禁止默认划动返回
- iOS11、iPhone X、Xcode9 适配
- Laravel5中使用阿里大于(鱼)发送短信验证码
- logback常用配置详解及logback简介
- ios定义数组和字典快捷方式
- 使用 STHTTPRequest 框架解析 Soap1.2 教程
- cdoj203-Islands 【并查集】