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生成
****************************首选我们了解一下它们的功能吧********************************************************** ...
随机推荐
- Oracle 数据库优化
Oracle 数据库优化 参考网址
- 16/7/11_PHP-图形图像操作
GD库简介 GD指的是Graphic Device,PHP的GD库是用来处理图形的扩展库,通过GD库提供的一系列API,可以对图像进行处理或者直接生成新的图片. PHP除了能进行文本处理以外,通过GD ...
- jmeter 非GUI执行测试,没有响应数据保存到jtl文件办法
估计是jmeter为了减轻客户机负担,就没又默认把这些信息保存,如果想要保存,也可以,需要做出如下配置: 修改bin目录下的user.properties文件,追加配置: jmeter.save.sa ...
- Java数组相关算法一
一.数组反转 1.方法一:创建新数组 int[] arr = {6,29,0,4,3}; int[] arr2 = new int[arr.length]; for (int i = 0; i < ...
- SpringCloud异常
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could ...
- 《剑指offer》面试题5 从尾到头打印链表 Java版
书中方法一:反转应该立刻想到栈,利用一个栈完成链表的反转打印,但是用了额外的O(n)空间. public void printFromTail(ListNode first){ Stack<Li ...
- Android应用程序开发之图片操作(二)——工程图片资源的加载及OOM的处理
(一)工程图片资源的加载方法 在Android应用程序开发之图片操作(一)中,详细说明了如何操作各种资源图片,只是有的没有附上示例代码,在此,我将针对项目工程中的图片资源的显示加载进行说明.官方说明, ...
- 全文搜索引擎 elasticsearch.net
原文:https://www.cnblogs.com/lonelyxmas/p/10767436.html
- Windows 下 MySQL 备份脚本
@title MySQL备份脚本 @echo off @echo root@127.0.0.1:3306 set host=127.0.0.1 set port=3306 set user=root ...
- 2018-8-10-让-AE-输出-MPEG-
title author date CreateTime categories 让 AE 输出 MPEG lindexi 2018-08-10 19:17:19 +0800 2018-2-13 17: ...