使用STM32CubeMx配置STM32输入捕获功能

2023-11-15

  1. 输入捕获原理

    在输入捕获模式下,当检测到ICx信号上相应的边沿后,计数器的当前值被锁存到捕获/比较寄存
    器(TIMx_CCRx)中。当发生捕获事件时,相应的CCxIF标志(TIMx_SR寄存器)被置1,如果开放
    了中断或者DMA操作,则将产生中断或者DMA请求。如果发生捕获事件时CCxIF标志已经为
    高,那么重复捕获标志CCxOF(TIMx_SR寄存器)被置1。写CCxIF=0可清除CCxIF,或读取存储
    在TIMx_CCRx寄存器中的捕获数据也可清除CCxIF。写CCxOF=0可清除CCxOF。
    摘自《STM32参考手册中文》

  2. 简单解释:定时器一直在计数,如果检测到设置的极性边沿,会把当前的计数值存下来,并触发中断;

  3. 比如,定时器设置为TIM2,预分频719,计数周期0xFFFF,则TIM2 10us计数一次,计数到0xFFFF,重装载到0;现在设置的输入捕获极性为上升沿捕获,则当某通道捕获到一次上升沿后,触发中断,并将当前的计数值存在对应通道的CCR值;

  4. 所以无论是设置为上升沿捕获还是下降沿捕获,都只能得到整个脉冲的周期时间;如果是想获得高电平占整个周期的百分比呢?

  5. 那么我就需要在最开始设置为上升沿捕获,当捕获到一个上升沿后,把极性设置为下降沿捕获,依次类推,这样我们就可以得到高电平时间和周期时间了;注意要设置好标志位

  6. 这里的话会出现一个问题,比如我的上升沿时间点在上一个周期,下降沿时间点在下一个周期,那么在下降沿-上升沿之前还要再加上一个定时器周期

  7. 以下是我的STM32CubeMx配置

在这里插入图片描述
在这里插入图片描述在这里插入图片描述
8. 以下是比较重要的代码

/* Private variables ---------------------------------------------------------*/
uint16_t 	Channel1HighTime, Channel2HighTime, Channel3HighTime, Channel4HighTime;
uint16_t 	Channel1Period, Channel2Period, Channel3Period, Channel4Period;
uint8_t  	Channel1Edge = 0, Channel2Edge = 0, Channel3Edge = 0, Channel4Edge = 0;
uint16_t 	Channel1Percent, Channel2Percent, Channel3Percent, Channel4Percent;
uint16_t	Channel1PercentTemp[3] = {0, 0, 0};
uint8_t 	Channel1TempCount = 0;
uint16_t 	Channel1RisingTimeLast=0, Channel1RisingTimeNow, Channel1FallingTime;
uint16_t 	Channel2RisingTimeLast=0, Channel2RisingTimeNow, Channel2FallingTime;
uint16_t 	Channel3RisingTimeLast=0, Channel3RisingTimeNow, Channel3FallingTime;
uint16_t 	Channel4RisingTimeLast=0, Channel4RisingTimeNow, Channel4FallingTime;
/* USER CODE END PV */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_TIM2_Init();
  /* USER CODE BEGIN 2 */
	HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
	HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2);
	HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_3);
	HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_4);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
		HAL_Delay(500);
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */

  }
  /* USER CODE END 3 */

}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(htim);
  /* NOTE : This function Should not be modified, when the callback is needed,
            the __HAL_TIM_IC_CaptureCallback could be implemented in the user file
   */
	if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
	{
		if(Channel1Edge == 0)
		{
			Channel1RisingTimeNow = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_1);//获取上升沿时间点
			__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING);//切换捕获极性
			HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
			Channel1Edge = 1;
			if(Channel1RisingTimeLast == 0)
			{
				Channel1Period = 0;
			}
			else
			{
				if(Channel1RisingTimeNow > Channel1RisingTimeLast)
				{
					Channel1Period = Channel1RisingTimeNow - Channel1RisingTimeLast;
				}
				else
				{
					Channel1Period = Channel1RisingTimeNow + 0xffff - Channel1RisingTimeLast + 1;
				}
			}
			Channel1RisingTimeLast = Channel1RisingTimeNow;
		}
		else if(Channel1Edge == 1)
		{
			Channel1FallingTime = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_1);	
			__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);
			HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
			
			if(Channel1FallingTime < Channel1RisingTimeNow)
			{
				Channel1HighTime = Channel1FallingTime + 0xffff - Channel1RisingTimeNow + 1;
			}
			else
			{
				Channel1HighTime = Channel1FallingTime - Channel1RisingTimeNow;
			}
			if(Channel1Period != 0)
			{
				Channel1Percent = (uint8_t)(((float)Channel1HighTime / Channel1Period) * 1000);
				printf("Channel1 = %d	", Channel1Percent);
			}
			Channel1Edge = 0;
		}
	}
	else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
	{
		if(Channel2Edge == 0)
		{
			Channel2RisingTimeNow = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_2);
			__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_2, TIM_INPUTCHANNELPOLARITY_FALLING);
			HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2);
			Channel2Edge = 1;
			if(Channel2RisingTimeLast == 0)
			{
				Channel2Period = 0;
			}
			else
			{
				if(Channel2RisingTimeNow > Channel2RisingTimeLast)
				{
					Channel2Period = Channel2RisingTimeNow - Channel2RisingTimeLast;
				}
				else
				{
					Channel2Period = Channel2RisingTimeNow + 0xffff - Channel2RisingTimeLast + 1;
				}
			}
			Channel2RisingTimeLast = Channel2RisingTimeNow;
		}
		else if(Channel2Edge == 1)
		{
			Channel2FallingTime = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_2);	
			__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_2, TIM_INPUTCHANNELPOLARITY_RISING);
			HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2);
			
			if(Channel2FallingTime < Channel2RisingTimeNow)
			{
				Channel2HighTime = Channel2FallingTime + 0xffff - Channel2RisingTimeNow + 1;
			}
			else
			{
				Channel2HighTime = Channel2FallingTime - Channel2RisingTimeNow;
			}
			if(Channel2Period != 0)
			{
				Channel2Percent = (uint8_t)(((float)Channel2HighTime / Channel2Period) * 1000);
				printf("Channel2 = %d	", Channel2Percent);
			}
			Channel2Edge = 0;
		}
	}
	else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_3)
	{
		if(Channel3Edge == 0)
		{
			Channel3RisingTimeNow = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_3);
			__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_3, TIM_INPUTCHANNELPOLARITY_FALLING);
			HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_3);
			Channel3Edge = 1;
			if(Channel3RisingTimeLast == 0)
			{
				Channel3Period = 0;
			}
			else
			{
				if(Channel3RisingTimeNow > Channel3RisingTimeLast)
				{
					Channel3Period = Channel3RisingTimeNow - Channel3RisingTimeLast;
				}
				else
				{
					Channel3Period = Channel3RisingTimeNow + 0xffff - Channel3RisingTimeLast + 1;
				}
			}
			Channel3RisingTimeLast = Channel3RisingTimeNow;
		}
		else if(Channel3Edge == 1)
		{
			Channel3FallingTime = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_3);	
			__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_3, TIM_INPUTCHANNELPOLARITY_RISING);
			HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_3);
			
			if(Channel3FallingTime < Channel3RisingTimeNow)
			{
				Channel3HighTime = Channel3FallingTime + 0xffff - Channel3RisingTimeNow + 1;
			}
			else
			{
				Channel3HighTime = Channel3FallingTime - Channel3RisingTimeNow;
			}
			if(Channel3Period != 0)
			{
				Channel3Percent = (uint8_t)(((float)Channel3HighTime / Channel3Period) * 1000);
				printf("Channel3 = %d	", Channel3Percent);
			}
			Channel3Edge = 0;
		}
	}
	else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4)
	{
		if(Channel4Edge == 0)
		{
			Channel4RisingTimeNow = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_4);
			__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_4, TIM_INPUTCHANNELPOLARITY_FALLING);
			HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_4);
			Channel4Edge = 1;
			if(Channel4RisingTimeLast == 0)
			{
				Channel4Period = 0;
			}
			else
			{
				if(Channel4RisingTimeNow > Channel4RisingTimeLast)
				{
					Channel4Period = Channel4RisingTimeNow - Channel4RisingTimeLast;
				}
				else
				{
					Channel4Period = Channel4RisingTimeNow + 0xffff - Channel4RisingTimeLast + 1;
				}
			}
			Channel4RisingTimeLast = Channel4RisingTimeNow;
		}
		else if(Channel4Edge == 1)
		{
			Channel4FallingTime = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_4);	
			__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_4, TIM_INPUTCHANNELPOLARITY_RISING);
			HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_4);
			
			if(Channel4FallingTime < Channel4RisingTimeNow)
			{
				Channel4HighTime = Channel4FallingTime + 0xffff - Channel4RisingTimeNow + 1;
			}
			else
			{
				Channel4HighTime = Channel4FallingTime - Channel4RisingTimeNow;
			}
			if(Channel4Period != 0)
			{
				Channel4Percent = (uint8_t)(((float)Channel4HighTime / Channel4Period) * 1000);
				printf("Channel4 = %d\n", Channel4Percent);
			}
			Channel4Edge = 0;
		}
	}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用STM32CubeMx配置STM32输入捕获功能 的相关文章

  • listView闪烁的问题

    用了一个ListView来实时的显示数据传输情况 于是问题就来了 当数据量比较大 而且处理速度很快时 这该死的界面闪得人眼花 废话不多说 直接上代码 首先 自定义一个类ListViewNF 继承自 System Windows Forms
  • stata 数据处理

    目录 按类别求均值 然后创建一个新的变量 缩尾处理 日期处理 连续变量处理成虚拟变量 按条件删除数据 按类别求均值 然后创建一个新的变量 bysort year industry egen meanvariable mean variabl
  • MySQL系列---事务与锁详解

    table of contents 1 背景 2 事务隔离级别 2 1 事务及其ACID属性 2 2 并发事务带来的问题 2 3 数据库事务隔离级别 3 锁机制 3 1 定义 3 2 分类 3 2 1 性能上划分 悲观乐观 3 2 2 从对
  • 解决微信小程序button的hover-class不生效问题

    在小程序开发过程中我们会遇到button添加style样式后即使添加hover class样式也没有点击效果的问题 产生该问题的原因为 在css中 内联样式style的优先级要高于class选择器的优先级 所以在我们添加style标签后即使
  • RabbitMq 报 An unexpected connection driver error occured和socket close异常处理

    进入rabbitMQ后台 1 后台地址为http localhost 15672 如果state状态为无法访问 那么我们就需要把这个链接给关掉 2 点击地址 找到close this connection 选择force close强制关闭
  • Centos7配置静态IP

    Centos7配置服务器静态IP 1 使用 ip addr 查看当前网卡信息 通过执行结果我们可以看到我们使用的网卡名称为ens33 2 配置服务器静态IP vi etc sysconfig network scripts ifcfg en
  • STL list

    文章目录 一 list 类的模拟实现 list 是一个带头双向循环链表 可以存储任意类型 模板参数 T 表示存储元素的类型 Alloc 是空间配置器 一般不用传 一 list 类的模拟实现 iterator 和 const iterator
  • 傅里叶图像相关性匹配-《医学图像处理》小作业五-Python代码/Matlab代码

    天津中医药大学 20级医学信息工程 教师 王翌 学生 邓集亲 学长我是用的python写的 matlab同样可以参考 实验五 相关性匹配 作业要求 参考 傅里叶变换 课的内容 采用快速傅里叶变换 FFT 进行相关性匹配 如下图示例输出结果图

随机推荐

  • 数据结构(第2版)陈越主编课后习题_【课后习题答案】离散数学(第2版)—课后习题答案...

    资 源 介 绍 本次分享内容为课程课后习题答案 教材名称 离散数学 第2版 主编作者 屈婉玲 耿素云 张立昂 出版社 高等教育出版社 ISBN 9787040419085 课后习题答案 01 习题一 02 习题二 03 习题三 04 习题四
  • java.io.IOException: Connection reset by peer

    接口要是返回的是字节 1 首先查看本地调用是否能正常返回 2 其次判断同样的参数测试环境是否正常返回 3 本地要是正常 测试环境异常的话 很大可能就是http协议版本不一致导致 解决办法 在nginx conf的location里加上 pr
  • Angular4基础开发文档

    Angular4基础开发文档
  • netstat命令详解

    命令介绍 netstat命令用于显示与IP TCP UDP和ICMP协议相关的统计数据 一般用于检验本机各端口的网络连接情况 netstat是在内核中访问网络及相关信息的程序 它能提供TCP连接 TCP和UDP监听 进程内存管理的相关报告
  • java/php/net/pythonMES生产线控制系统设计

    本系统带文档lw万字以上 答辩PPT 查重 如果这个题目不合适 可以去我上传的资源里面找题目 找不到的话 评论留下题目 或者站内私信我 有时间看到机会给您发 生产线控制系统 的设计主要是为了满足生产线管理员的实际需求 因此 它需要通过Int
  • 移动应用开发期末总结

    移动应用开发 什么是intent 问答题 Intent是一个动作的完整描述 包含了动作的产生组件 接收组件和传递的数据信息 Intent为Activity Service和BroadcastReceiver等组件提供交互能力 将一个组件的数
  • 使用Modelarts快速开发Hilens Kit实现人脸识别功能

    导语 在华为云平台上线的Modelarts模型训练平台结合华为智能终端产品Hilens kit 对Hilens Kit进行开发 实现产品的快速使用以及功能的实现 自从2020年疫情开始 使得人与人的接触变得更加不方便 间接促使了人工智能产业
  • Java中9种常见的CMS GC问题分析与解决

    目前 互联网上 Java 的 GC 资料要么是主要讲解理论 要么就是针对单一场景的 GC 问题进行了剖析 对整个体系总结的资料少之又少 前车之鉴 后事之师 美团的几位工程师历时一年多的时间 搜集了内部各种 GC 问题的分析文章 并结合个人的
  • unity开发小贴士之三 UGUI-Lua Component回收

    ugui tolua local test test b gameobjecttest c gameobject GetComponent typeof UnityEngine UI Button 首先调用UnityEngine GameO
  • Java Logging

    最后一次实验要求用日志来记录信息 学习的内容整理如下 Java 中的 Logging API 让 Java 应用可以记录不同级别的信息 它在debug过程中非常有用 如果系统因为各种各样的原因而崩溃 崩溃原因可以在日志中清晰地追溯 日志工作
  • 在小程序中使用图标

    因为最近在自学微信小程序 掌握了他的基础的使用 包括小程序的语法 小程序的自有组件 小程序的自有API及小程序的自定义组件 在学玩以上的各方面的知识体系后 我就想着学了这么就的微信小程序 自己总要写出点什么东西来才对的起自己这段时间来的努力
  • Android退出应用程序方法总结

    Android退出应用程序方法总结 在Android开发中 我们运行了应用程序后 都需要退出应用的 那么该如何退出应用 又都有哪些实现方式呢 今天就为大家整理分享一些退出应用程序的方法 一起来看看吧 更新内容 Ver v1 任务管理器方法补
  • 简短的char*与char[]

    include
  • 这就是搜索引擎——索引压缩

    对于海量数据 建立倒排索引往往需要较大的磁盘空间 尤其是一些常见的单词 这些单词对应的倒排列表可能有几百兆 如果搜索引擎在相应用户查询的时候 用户查询包含了常见的单词 就需要将大量的倒排列表信息从磁盘读入内存 由于磁盘读写速度往往是个瓶颈
  • RLHF 技术:如何能更有效?又有何局限性?

    编者按 自ChatGPT推出后 基于人类反馈的强化学习 RLHF 技术便成为大模型构建和应用人员关注的热点 但该方法一些情况下效果却差强人意 有些基础模型经RLHF调优后反而表现更差 RLHF技术的适用性和具体操作细节似乎成谜 这篇文章探讨
  • 平板电脑黑苹果EFI_保姆级别教你安装黑苹果,提供大量EFI与工具驱动!

    最近无聊 在电脑上装了个黑苹果 可能是我的机型比较好找吧 安装的过程中没有遇到太大的问题 接下教大家安装 也为大家准备了大量的EFI N卡驱动 蓝牙驱动 键盘驱动等工具 需要工具的小伙伴可以点击此处 所需要工具 1 黑果镜像 2 U盘 3
  • Python音视频剪辑库MoviePy1.0.3中文教程导览及可执行工具下载

    前往老猿Python博文目录 一 简介 MoviePy是一个用于视频编辑的Python模块 可用于进行视频的基本操作 如剪切 拼接 标题插入 视频合成 也称非线性编辑 视频处理或创建高级效果 它可以读写最常见的视频格式 MoviePy能处理
  • Xshell连接Ubuntu详细过程

    一 打开虚拟机VMware 二 启动虚拟机 输入密码 进入Ubuntu系统界面 三 鼠标右键 选择 在终端打开 出现终端对话框 四 在命令行输入 sudo apt get install openssh server 安装openssh s
  • 2017校招Java开发笔试题集

    美丽联合 二分查找要求结点 A 有序 顺序存储 B 有序 链接存储 C 无序 顺序存储 D 无序 链接存储 答案选 A 引入线索二叉树的目的是 A 加快查找结点的前驱或后继结点的速度 B 为了能在二叉树中方便插入和删除 C 为了能方便找到双
  • 使用STM32CubeMx配置STM32输入捕获功能

    输入捕获原理 在输入捕获模式下 当检测到ICx信号上相应的边沿后 计数器的当前值被锁存到捕获 比较寄存 器 TIMx CCRx 中 当发生捕获事件时 相应的CCxIF标志 TIMx SR寄存器 被置1 如果开放 了中断或者DMA操作 则将产