STM32输入捕获TIM2四通道
相比于一通道,原子的例程里因为清了计数时间,所以要对程序进行修改。
记录上升沿后的计数,然后记录下降沿的计数。相减后计算高电平时间,对于定时器中断间隔的边界要分开处理。
这里因为我的接收机时间是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资源,所以不在中断中处理。
STM32输入捕获TIM2四通道的更多相关文章
- STM32输入捕获模式设置并用DMA接收数据
参考: STM32的PWM输入模式设置并用DMA接收数据 Input capture mode The input stage samples the corresponding TIx input ...
- [置顶]
STM32 输入捕获的脉冲宽度及频率计算
输入捕获模式可以用来测量脉冲宽度或者测量频率.STM32 的定时器,除了 TIM6 和 TIM7,其他定时器都有输入捕获功能.以下是对脉冲宽度及频率的计算. 1.脉冲宽度 如下图所示,采集该高电平脉冲 ...
- STM32——输入捕获实验原理及配置步骤
输入捕获实验原理及配置步骤 一.输入捕获概念 STM32的输入捕获,简单的说就是通过检测 TIMx_CHx (定时器X的通道X)上的 边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将当前定 ...
- STM32 输入捕获的脉冲宽度及频率计算
输入捕获模式可以用来测量脉冲宽度或者测量频率.STM32 的定时器,除了 TIM6 和 TIM7,其他定时器都有输入捕获功能.以下是对脉冲宽度及频率的计算. 1.脉冲宽度 如下图所示,采集该高电平脉冲 ...
- STM32 输入捕获配置
在STM32 的定时器,除了 TIM6 和 TIM7,就是通过检测 TIMx_CHx 上的 边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候, 将当时定时器 的值(TIMx_CNT) 存放到对 ...
- stm32 输入捕获学习(二)
(本文参考STM32 开发指南 V1.3 -- ALIENTEK 战舰 STM32 开发板库函数教程 ) 1. 实验设计 我们用 TIM5 的通道 1(PA0)来做输入捕获,捕获 PA0 上高电 ...
- stm32 输入捕获学习(一)
输入捕获模式可以用来测量脉冲宽度或者测量频率.STM32 的定时器,除了 TIM6 和 TIM7,其他定时器都有输入捕获功能.STM32 的输入捕获,简单地说就是通过检测 TIMx_CHx 上的边沿信 ...
- stm32 输入捕获
根据定时器的计数频率,我们就可以算出t1-t2的时间,从而得到高电平脉宽 计算公式 N * ARR + CCRx2 首先设置定时器通道为上升沿捕获,这样在t1时刻,就会捕获到当前的CNT值,然后立即清 ...
- stm32f103_高级定时器——输入捕获/输出比较中断+pwm=spwm生成
****************************首选我们了解一下它们的功能吧********************************************************** ...
随机推荐
- P3956棋盘
传送 这看起来有点像个搜索,那我们就用搜索试试. dfs?bfs? 其实都可以,但是窝只会dfs.. 既然这里要用dfs,那么就要把每次搜到(m,m)时,使用的金币数量进行比较,取最小值. 在搜索过程 ...
- java.io.NotSerializableException错误解决方法
运行tomcat下面的 ssh项目,启动,打开某页面(让session起作用),停止:再启动,有可能会报类似如下的错误: org.apache.catalina.session.StandardMan ...
- Learn Python the hard way, ex39 列表的操作
#!/usr/bin/python #coding:utf-8 ten_things = "apples oranges crows telephone light sugar" ...
- 【ABAP系列】SAP ABAP模块-取整操作中CEIL和FLOOR用法
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP模块-取整操作中 ...
- SQL计算两个时间段相隔时间
SQL语句: select cast(floor(datediff(minute,时间1,时间2) / 1440) as varchar)+'天'+ cast(floor((datediff(minu ...
- win10设置python环境变量
1.点“我的电脑”,右键选“属性” 2.选择“高级系统设置”--->选“环境变量”--->在“系统变量”中选中“Path”,再点“编辑”--->再点“编辑文本”
- 网页导出excel
package site.action.ecom.backend.wechat.exportExcel; import java.lang.annotation.Documented;import j ...
- 【洛谷p1025】数的划分
数的划分[传送门] 算法的话,dfs+剪枝: 据说是01年之前的NOIp提高组: 思路: 这道题是求把n无序的划分成k份的方案数,最直接的搜索方法是依次枚举x1,x2……xk的值,然后判断,显然这么搜 ...
- 矩阵快速幂(queue递推)
http://acm.hdu.edu.cn/showproblem.php?pid=2604 Queuing Time Limit: 10000/5000 MS (Java/Others) Me ...
- python:while循环语句及练习题
while循环语句及练习题 Python 编程中 while 语句用于循环执行程序,即在某条件下,循环执行某段程序,以处理需要重复处理的相同任务.其基本形式为: while 判断条件: 执行语句... ...