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生成
****************************首选我们了解一下它们的功能吧********************************************************** ...
随机推荐
- php远程抓取(下载)文件到本项目指定目录中
function httpcopy($url, $file="", $timeout=60) { $file = empty($file) ? pathinfo($url,PATH ...
- JSP中四种属性保存范围(1)
一.四种属性范围 在JSP中提供了四种属性保存范围 page:在一个页面内保存属性,跳转之后无效request:在一次服务请求范围内,服务器跳转后依然有效session:-在一次会话范围内,无论何种跳 ...
- ECMAScript 2015 迭代器协议:实现自定义迭代器
迭代器协议定义了一种标准的方式来产生一个有限或无限序列的值,并且当所有的值都已经被迭代后,就会有一个默认的返回值. 当一个对象只有满足下述条件才会被认为是一个迭代器:它实现了一个 next() 的方法 ...
- python模块 __name=='__main__' 用法
python模块 __name=='__main__' 用法1.ceshi_mod1.pydef test1(): print('111111')def test2(): print('2222')i ...
- Android手机、电视(盒子) 打开ADB调试 一览表
手机.电视(盒子) 打开ADB调试 一览表 一.手机打开ADB调试方法 序号 名称 描述 方式 1 华为手机 EMUI 1.设置 ->关于手机-> 版本号 点击(4~5次)2.返回设置 - ...
- (转)vue项目刷新当前页面
场景: 有时候我们在vue项目页面做了一些操作,需要刷新一下页面. 解决的办法及遇到的问题: this.$router.go(0).这种方法虽然代码很少,只有一行,但是体验很差.页面会一瞬间的白屏,体 ...
- 2. ZooKeeper基础
1. ZooKeeper的特性 ZooKeeper的特性主要从会话.数据节点,版本,Watcher,ACL权限控制,集群角色这些部分来了解,其中需要重点掌握的数据节点与Watcher 1.1 会话 客 ...
- 【JAVA】eclipse-使用入门及常用快捷键
目录 下载与安装 HelloWorld 新建项目 视图与视窗 快捷键 个性化设置 导入项目 jar包 下载与安装 下载 网址:官网下载 注意: 下载javaee版 注意与本机的java环境相匹配,32 ...
- k3 cloud库存管理中的直接调拨单权限分配出现问题
k3 cloud中给直接调拨单分配了对应的权限,但是客户端无法查看到对应的单据 解决办法: 是应为没有发布到对应的客户端和浏览器端,打开bos,找到对应的单据并点击发布,找到对应的目录,如图所示: 把 ...
- Linux学习笔记5(2)-CentOS7中Tomcat8修改jvm内存配置
1.进入tomcat的bin目录,比如我的在 /usr/local/apache-tomcat-8.5.16/bin 2.创建新的文件setenv.sh vi setenv.sh 并在此文件中添加以下 ...