STM32的捕获

2023-11-04

基础配置 

void TIM2_Capture_Init(u16 arr,u16 psc)
{
	GPIO_InitTypeDef GPIO_InitStructure;
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  TIM_ICInitTypeDef  TIM2_ICInitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
    //使能定时器和GPIO的时钟 
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能TIM2时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //使能GPIOA时钟
 //初始化IO口,模式为输入
  GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;  //PA0 清除之前设置  
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 输入  
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  GPIO_ResetBits(GPIOA,GPIO_Pin_0); //PA0 下拉 
 //初始化定时器2 TIM2  
	TIM_TimeBaseStructure.TIM_Period = arr; //设定计数器自动重装值 
	TIM_TimeBaseStructure.TIM_Prescaler =psc;  //预分频器   
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);   
 //初始化TIM2输入捕获参数
	TIM2_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01  选择输入端 IC1映射到TI1上
  TIM2_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕获
  TIM2_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上
  TIM2_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;  //配置输入分频,不分频 
  TIM2_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置输入滤波器 不滤波
  TIM_ICInit(TIM2, &TIM2_ICInitStructure); 
 //中断分组初始化
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  //TIM2中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;  //先占优先级2级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //从优先级0级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器  
	TIM_ITConfig(TIM2,TIM_IT_Update|TIM_IT_CC1,ENABLE);//允许更新中断 ,允许CC1IE捕获中断  
	
  TIM_Cmd(TIM2,ENABLE );  //使能定时器2 

}

中断函数配置

u8  Capture_State=0; //输入捕获状态          
u16 Capture_Value; //输入捕获值

	
void TIM2_IRQHandler(void)
{ 
  if((Capture_State&0X80)==0)//还未成功捕获 1000 0000 
 {   
  if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)   
  {     
   if(Capture_State&0X40)//已经捕获到高电平了0100 0000
   {
    if((Capture_State&0X3F)==0X3F)//高电平太长了 0011 1111
    {
     Capture_State|=0X80;//标记成功捕获了一次 1000 0000 
     Capture_Value=0XFFFF; //1111 1111
    }
    else 
       Capture_State++;
   }  
  }
 if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)//捕获1发生捕获事件
  { 
   if(Capture_State&0X40)//捕获到一个下降沿 0100 0000
   {      
    Capture_State|=0X80;//标记成功捕获到一次上升沿1000 0000 
    Capture_Value=TIM_GetCapture1(TIM2);
       TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Rising); //CC1P=0 设置为上升沿捕获
   }else //还未开始,第一次捕获上升沿
   {
    Capture_State=0;//清空
    Capture_Value=0;
     TIM_SetCounter(TIM2,0);
    Capture_State|=0X40;//标记捕获到了上升沿0100 0000
       TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Falling); //CC1P=1 设置为下降沿捕获
   }      
  }                     
  } 
    TIM_ClearITPendingBit(TIM2, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位 
}

主函数配置

extern u8  Capture_State;  //输入捕获状态          
extern u16 Capture_Value; //输入捕获值

void TIM2_Capture_Init(u16 arr,u16 psc);

int main()
{
	u32 temp=0; 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2

	TIM2_Capture_Init(0XFFFF,72-1);

   	while(1)
	{ 
		if(Capture_State&0X80)//成功捕获到了一次高电平
		{
			temp=Capture_State&0X3F;
			temp*=65536;     //溢出时间总和
			temp+=Capture_Value;  //得到总的高电平时间
			
			TIM_SetCounter(TIM2,0);
			TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Rising);
			Capture_State=0;   //开启下一次捕获
		}

	} 

}

 中断函数及主函数解析

初始定义Capture_State=0,temp=0,并且配置捕获完成后,等待引脚捕获高电平,当引脚捕获到高电平,此时程序第一次进入中断函数,进入if((Capture_State&0X80)==0),不进入更新中断if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET),然后进入捕获中断if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET),不进入if(Capture_State&0X40),进入else,把Capture_State,Capture_Value的值清零,把定时器清零,Capture_State|=0X40;标记捕获到了上升沿,把捕获设置为下降沿捕获,退出中断函数,等待下降沿到来。

若定时器溢出,进入中断函数,进入if((Capture_State&0X80)==0),进入更新中断if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET),进入if(Capture_State&0X40),不进入if((Capture_State&0X3F)==0X3F),进入else使Capture_State++,定时器在更新中断后自动清零重新计数

若未捕获到下降沿且if((Capture_State&0X3F)==0X3F)成立,则超出该程序设计的最大定时,进入if((Capture_State&0X3F)==0X3F)使得Capture_State|=0X80强迫标记成功捕获了一次
     Capture_Value=0XFFFF;主函数的if(Capture_State&0X80)成立,执行对脉冲宽度的计算

若期间捕获到了下降沿,则进入捕获中断if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET),进入if(Capture_State&0X40)使得Capture_State|=0X80标记成功捕获了一次,Capture_Value=TIM_GetCapture1(TIM2),主函数的if(Capture_State&0X80)成立,执行对脉冲宽度的计算

可见最大捕获时间跟TIM_Period(计数器自动重装值 ),TIM_Prescaler(预分频器)以及Capture_State的定义有关。

如果我们需要更大的捕获时间,可以从TIM_Period,Capture_State入手

如果我们需要调节捕获时间精度,可以从TIM_Prescaler入手,不过一般精度不会超过主频计数

如图为修改Capture_State的定义

中断代码如下

u16  Capture_State=0; //输入捕获状态          
u16 Capture_Value; //输入捕获值
	
void TIM2_IRQHandler(void)
{ 	
	if((Capture_State&0X8000)==0)//还未成功捕获 1000 0000 
 {   
  if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)   
  {     
   if(Capture_State&0X4000)//已经捕获到高电平了0100 0000
   {
    if((Capture_State&0X3FFF)==0X3FFF)//高电平太长了 0011 1111
    {
     Capture_State|=0X8000;//标记成功捕获了一次 1000 0000 
     Capture_Value=0XFFFF; //1111 1111
    }
    else 
       Capture_State++;
   }  
  }
 if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)//捕获1发生捕获事件
  { 
   if(Capture_State&0X4000)//捕获到一个下降沿 0100 0000
   {      
    Capture_State|=0X8000;//标记成功捕获到一次上升沿1000 0000 
    Capture_Value=TIM_GetCapture1(TIM2);
       TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Rising); //CC1P=0 设置为上升沿捕获
   }else //还未开始,第一次捕获上升沿
   {
    Capture_State=0;//清空
    Capture_Value=0;
     TIM_SetCounter(TIM2,0);
    Capture_State|=0X4000;//标记捕获到了上升沿0100 0000
       TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Falling); //CC1P=1 设置为下降沿捕获
   }      
  }                     
  } 
    TIM_ClearITPendingBit(TIM2, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位 
}

主函数代码如下

extern u16  Capture_State;  //输入捕获状态          
extern u16 Capture_Value; //输入捕获值

void TIM2_Capture_Init(u16 arr,u16 psc);

int main()
{
	u32 temp=0,t=0; 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
	TIM2_Capture_Init(0XFFFF,72-1);
   	while(1)
	{ 
			if(Capture_State&0X8000)//成功捕获到了一次高电平
		{
			temp=Capture_State&0X3FFF;
			temp*=65536;     //溢出时间总和
			temp+=Capture_Value;  //得到总的高电平时间
			
			TIM_SetCounter(TIM2,0);
			TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Rising);
			Capture_State=0;   //开启下一次捕获
		}
	} 

}

 我们可以通过设置预分配器TIM_Prescaler来设定时间单位,一般最少时间单位不会小于机器周期(1/主频)。

关于滤波器TIM_ICFilter,可以查看此文

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32的捕获 的相关文章

  • Stream filter()过滤有效数据

    filter 是一个中间操作 可以与 reduce collect map 等一起使用 filter一般适用于list集合 主要作用就是模拟sql查询 从集合中查询想要的数据 java官方文档语法如下 filter Predicate pr
  • 迭代器失效问题

    1 什么是迭代器失效 迭代器失效是一种现象 由特定操作引发 这些特定操作对容器进行操作 使得迭代器不指向容器内的任何元素 或者使得迭代器指向的容器元素发生了改变 2 可能引起迭代器失效的操作 插入元素 扩容引起的迭代器指向的元素或者空间发生
  • python矩阵_Python矩阵

    python矩阵 In this tutorial we will learn about Python Matrix In our previous tutorial we learnt about Python JSON operati

随机推荐

  • 【python 学习 01】命名规范

    命名其实是一个非常重要的事 根据Python之父Guido推荐的命名规范包括如下几点 包名 模块名 局部变量名 函数名 全小写 下划线式驼峰 example this is var 全局变量 全大写 下划线式驼峰 example GLOBA
  • Zabbix---5 监控linux服务器目录大小

    例如监控 root data 目录 一 添加自己脚本 root localhost sbin pwd usr local sbin root localhost sbin cat dir size sh bin bash du m root
  • STM32的CAN总线的接收双FIFO使用方法

    通过下面的框图我们可以看到 STM32F013有两个接收FIFO 但是实际的使用中如何让着两个FIFO都被使用呢 解决办法就在这里 1 STM32F103有0 13共14个过滤器组 每个过滤器组都可以绑定指定的FIFO 2 特别需要注意的一
  • K8s学习笔记二:Ubuntu安装minikube以及K8s简单体验

    Ubuntu安装minikube官方文档看这里 完成Docker十分钟了解Docker 我的Docker学习笔记 和kubectlUbuntu安装kubectl的下载安装后 就可以进行minikube的安装了 它能够帮助我们在本地非常容易的
  • 20145334 《信息安全系统设计基础》第8周学习总结

    转眼已经到了期中复习 听弟弟妹妹们说他们要期中考试了 我们大三上学期的课程也已经过半 考试试题 发现问题及时沟通 首先看一下每周检测解析 这个是比较重要的内容 也是复习和巩固所学知识点的好帮手 下面是老师给出的解析链接 https grou
  • 【mac 安全渗透测试】之SQL注入Demo

    一 关于sqlmap的介绍 1 SQLmap工具简介 SQLmap是一款开源的SQL注入漏洞检测 利用工具 可以检测动态页面中get post参数 cookie http头 它由Python语言开发而成 运行需要安装python环境 在ka
  • arm64架构的linux中断分析(零)

    文章目录 1 中断的概念和作用 2 Linux中断处理机制 2 1 中断请求 2 2 中断处理 2 3 中断完成 2 4 中断触发和处理步骤详解 2 4 1 异常向量表的解读 3 GICv3中断控制器 3 1 GICv3中断控制器设备树 3
  • 触摸屏tslib库交叉编译并移植ARM校准测试

    本文介绍 触摸屏tslib库交叉编译并移植ARM 校准及测试 下载tslib Tags libts tslib GitHub 在tslib的官方github上选择一个版本下载即可 本实验版本为 tslib 1 12 tar gz 1 配置
  • Chisel教程——04.Chisel中的控制流

    控制流 动机 本系列到目前为止 Chisel中的软硬件之间都有很强的对应关系 但引入控制流之后就不一样了 对软硬件的看法就应该有很大的分歧了 本节会在生成器软件和硬件中都引入控制流 如果重新连接到一个Chisel连线会怎么样呢 如何让一个多
  • normalize.css公共样式(vue)

    目录 一 npm安装 二 main ts或者main js引入 三 代码 1 main ts 2 main js 一 npm安装 npm i normalize css 二 main ts或者main js引入 import normali
  • Java在配置环境变量中的 . 是什么意思

    在CLASSPATH中 点号 表示当前目录 举例 CLASSPATH D JAVA LIB C DOC JavaT 这个路径就是包含多个可供选择的查询路径 它们之间用分号 分隔开 更具体的内容可以查阅 Java编程思想 第四版 P112 P
  • 【满分】【华为OD机试真题2023 JS】异常的打卡记录

    华为OD机试真题 2023年度机试题库全覆盖 刷题指南点这里 异常的打卡记录 知识点数组字符串哈希表循环 时间限制 1s 空间限制 256MB 限定语言 不限 题目描述 考勤记录是分析和考核职工工作时间利用情况的原始依据 也是计算职工工资的
  • 树的遍历(一题直接理解中序、后序、层序遍历,以及树的存储)

    题目如下 一个二叉树 树中每个节点的权值互不相同 现在给出它的后序遍历和中序遍历 请你输出它的层序遍历 输入格式 第一行包含整数 N 表示二叉树的节点数 第二行包含 N 个整数 表示二叉树的后序遍历 第三行包含 N 个整数 表示二叉树的中序
  • idea 编译突然报, java: 需要‘;‘

    这个和文件没关系 就是编码编译的时候不对了 需要idea设置下就完美解决了
  • mingw编译出C++正则表达式失效

    代码 include
  • GC 垃圾回收机制

    这里写自定义目录标题 描述一下 GC 的原理和回收策略 Java 中有四种引用类型 GC 如何判断对象的存活 引用计数算法 可达性分析 新生代 新时代又分3个部分 8 1 1 老年代 回收算法 标记 清除 标记 整理 复制 堆内存分配策略
  • 两个ESP8266相互通信

    ESP8266共有3种模式 STA AP STA AP STA ESP8266设备作客户端 AP ESP8266设备作服务器 STA AP 混合模式 服务器端ESP8266配置流程 1 配置AP模式 查询指令 AT CWMODE 功能 查询
  • java模块设计与实现_Java两个通用安全模块的设计与实现(SQL)

    3 系统方案设计 3 1 功能模块流程图 为了方便系统方案的设计与功能的开发 在方案设计前 根据前面的需求分析 将系统的功能划分为口令部分功能模块和文件安全传输部分功能模块 这两个模块又各自细分为各个小模块 各小模块的功能流程图如下 一 口
  • Nightingale滴滴夜莺监控系统入门(四)--聊聊夜莺的后端储存

    Nightingale滴滴夜莺监控系统入门 四 聊聊夜莺的后端储存 1 默认版本 默认是使用夜莺的两个组件来实现 TSDB INDEX TSDB实际上使用的是老牌的图形数据库rrdtool 记录ts和value 有很多老牌的监控使用比如Ca
  • STM32的捕获

    基础配置 void TIM2 Capture Init u16 arr u16 psc GPIO InitTypeDef GPIO InitStructure TIM TimeBaseInitTypeDef TIM TimeBaseStru