热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

STM32输入捕获详细配置及通过编码器读电机转速

STM32输入捕获详细配置及通过编码器读电机转速STM32输入捕获工作过程通过检测TIMx_CHx上的边沿信号,在边沿信号发生跳变(比如上升沿下降沿&

STM32输入捕获详细配置及通过编码器读电机转速

STM32输入捕获工作过程
在这里插入图片描述
通过检测TIMx_CHx上的边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将当前定时器的值(TIMx_CNT)存放到对应的捕获/比较寄存器(TIMx_CCRx)里面,完成一次捕获。

STM32输入捕获设置
步骤1:设置输入捕获滤波器
在这里插入图片描述
首先,FDTS的频率由TIMx_CR1的CKD[1:0]的设置决定,为00时,FDTS=FCK_INT。
在这里插入图片描述其次,TIMx_CCMR1的ICF[3:0]这几个为用来设置输入采用频率和数字滤波器的长度,
在这里插入图片描述
在这里插入图片描述

上面N是滤波长度,例如,当N=8时,并设置IC1映射到通道1上,且为上升沿触发,那么捕获到上升沿的时候,再以Fck_int的频率,连续采样到8次通道1的电平,如果都是高电平,则说明是一个有效的触发,就会触发输入捕获中断,这样就可以滤除那些高电平脉宽低于8给采用周期的脉冲信号。不做滤波处理的话,将其设置为0000.

步骤2:设置输入捕获极性
在这里插入图片描述
在这里插入图片描述设置上升沿捕获还是下降沿捕获。

步骤3:设置输入捕获映射通道

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
步骤4:设置输入捕获分频器
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述步骤5:捕获到有效信号可以开启中断‘
在这里插入图片描述寄存器
一:捕获比较模式寄存器CCMR寄存器
在这里插入图片描述在这里插入图片描述在这里插入图片描述
二:捕获比较使能寄存器

在这里插入图片描述三:事件产生寄存器(TIMx_EGR)
在这里插入图片描述
四:中断使能寄存器
在这里插入图片描述在这里插入图片描述

输入捕获(高电平脉宽)函数详解

void TIM5_CH1_Cap_Init(u32 arr,u16 psc)
{ RCC->APB1ENR|&#61;1<<3; //TIM5时钟使能RCC->AHB1ENR|&#61;1<<0; //使能PORTA时钟//端口复用GPIO_Set(GPIOA,PIN0,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PD);GPIO_AF_Set(GPIOA,0,2); //PA0,AF2//设置自动重装载值与预分频系数TIM5->ARR&#61;arr; TIM5->PSC&#61;psc; TIM5->CCMR1|&#61;1<<0; //CC1S&#61;01 设置CC1通道为输入&#xff0c;IC1映射到T1上TIM5->CCMR1|&#61;0<<4; //IC1F&#61;0000 无滤波TIM5->CCMR1|&#61;0<<10; //IC1PS&#61;00 不分频TIM5->CCER|&#61;0<<1; //CC1P&#61;0 上升沿捕获TIM5->CCER|&#61;1<<0; //CC1E&#61;1 允许捕获计数器的值到捕获寄存器中//软件控制产生更新时间&#xff0c;使写入预分频器的值立即生效&#xff0c;否则要等到定时器溢出才生效TIM5->EGR&#61;1<<0; TIM5->DIER|&#61;1<<1; //允许捕获1中断TIM5->DIER|&#61;1<<0; //允许更新中断TIM5->CR1|&#61;0x01; //使能定时器2MY_NVIC_Init(2,0,TIM5_IRQn,2);//设置抢占优先级2&#xff0c;子优先级0&#xff0c;组2
}

设计一个寄存器&#xff0c;
第7位为捕获完成标志位
第6位为捕获到低电平标志位&#xff0c;
因为要检测高电平脉冲所持续的时间&#xff0c;所以需要判断目前捕获的电平是高电平还是低电平&#xff0c;当高电平来时记录计数器的当前值&#xff0c;将该标志位设置为0&#xff0c;然后将捕获中断改为下降沿捕获&#xff0c;当下降沿来临时再次记录计数器的值&#xff0c;将该标志位置1&#xff0c;通过两次计数器值的差值就可以记录高电平持续时间
第5-0位记录定时器溢出的次数&#xff0c;
因为在如果高电平的持续时间很长&#xff0c;计数器的值会溢出&#xff0c;再用两次当前值相减时需要加上计数器溢出的那几个周期。
在这里插入图片描述


u8 TIM5CH1_CAPTURE_STA&#61;0; //输入捕获状态
u32 TIM5CH1_CAPTURE_VAL; //输入捕获值
//中断服务程序
void TIM5_IRQHandler(void)
{ u16 tsr;tsr&#61;TIM5->SR;//成功捕获后便不会进入这段程序&#xff0c;只有当主函数把计数值读出来&#xff0c;然后把该寄存器清0后&#xff0c;//才会再次进入该程序&#xff0c;每次的执行过程是一样的&#xff0c;首先是上升沿捕获&#xff0c;然后将第6位标志位置1&#xff0c;//计数器清0&#xff0c;将触发模式改为下降沿捕获&#xff0c;然后进入下降沿捕获&#xff0c;记录成功捕获&#xff0c;//将触发模式改为上升沿&#xff0c;记录计数器的值。//然后便不会进入这段程序&#xff0c;等待主程序将计数器的值读出来&#xff0c;寄存器清0后&#xff0c;再次执行该程序。if((TIM5CH1_CAPTURE_STA&0X80)&#61;&#61;0)//没有成功捕获高电平{if(tsr&0X01)//定时器溢出中断{ if(TIM5CH1_CAPTURE_STA&0X40)//已经捕获到高电平{if((TIM5CH1_CAPTURE_STA&0X3F)&#61;&#61;0X3F)//高电平太长&#xff0c;计数器溢出{TIM5CH1_CAPTURE_STA|&#61;0X80; //直接标记成功捕获了一次TIM5CH1_CAPTURE_VAL&#61;0XFFFFFFFF;}else TIM5CH1_CAPTURE_STA&#43;&#43;;//每溢出一次加1} }if(tsr&0x02)//定时捕获中断发生{ if(TIM5CH1_CAPTURE_STA&0X40) //上一次捕获的是上升沿&#xff0c;这一次又发生捕获中断了&#xff0c;表明下降沿到了{ TIM5CH1_CAPTURE_STA|&#61;0X80; //标记成功捕获了一次高电平脉宽TIM5CH1_CAPTURE_VAL&#61;TIM5->CCR1; //获取当前计数器的值TIM5->CCER&&#61;~(1<<1); //CC1P&#61;0 设置为上升沿捕获}else //还未开始&#xff0c;第一次捕获上升沿{TIM5CH1_CAPTURE_STA&#61;0; //清空TIM5CH1_CAPTURE_VAL&#61;0;TIM5CH1_CAPTURE_STA|&#61;0X40; //标记捕获到上升沿TIM5->CR1&&#61;~(1<<0) ; //使能定时器2TIM5->CNT&#61;0; //计数器清空TIM5->CCER|&#61;1<<1; //CC1P&#61;1 设置为下降沿捕获TIM5->CR1|&#61;0x01; //使能定时器2} } }TIM5->SR&#61;0;//清楚中断标志位
}

if(TIM5CH1_CAPTURE_STA&0X80) //成功捕获到一次高电平{temp&#61;TIM5CH1_CAPTURE_STA&0X3F; temp*&#61;0XFFFFFFFF; //溢出时间总和temp&#43;&#61;TIM5CH1_CAPTURE_VAL; //得到总的高电平时间printf("HIGH:%lld us\r\n",temp);//打印输出TIM5CH1_CAPTURE_STA&#61;0; //寄存器清空&#xff0c;等待下一次捕获}

编码器接口模式&#xff1a;

官方解释
选择编码器接口模式的方法是&#xff1a;如果计数器只在TI2的边沿计数&#xff0c;则置TIMx_SMCR寄存器中的SMS&#61;001&#xff1b;如果只在TI1边沿计数&#xff0c;则置SMS&#61;010&#xff1b;如果计数器同时在TI1和TI2边沿计数&#xff0c;则置SMS&#61;011。
通过设置TIMx_CCER寄存器中的CC1P和CC2P位&#xff0c;可以选择TI1和TI2极性&#xff1b;如果需要&#xff0c;还可以对输入滤波器编程。两个输入TI1和TI2被用来作为增量编码器的接口。假定计数器已经启动(TIMx_CR1寄存器中的CEN&#61;’1’)&#xff0c;计数器由每次在TI1FP1或TI2FP2上的有效跳变驱动。TI1FP1和TI2FP2是TI1和TI2在通过输入滤波器和极性控制后的信号&#xff1b;如果没有滤波和变相&#xff0c;则TI1FP1&#61;TI1&#xff0c;TI2FP2&#61;TI2。根据两个输入信号的跳变顺序&#xff0c;产生了计数脉冲和方向信号。依据两个输入信号的跳变顺序&#xff0c;计数器向上或向下计数&#xff0c;同时硬件对TIMx_CR1寄存器的DIR位进行相应的设置。不管计数器是依靠TI1计数、依靠TI2计数或者同时依靠TI1和TI2计数。在任一输入端(TI1或者TI2)的跳变都会重新计算DIR位。
编码器接口模式基本上相当于使用了一个带有方向选择的外部时钟。这意味着计数器只在0到TIMx_ARR寄存器的自动装载值之间连续计数(根据方向&#xff0c;或是0到ARR计数&#xff0c;或是ARR到0计 数)。所以在开始计数之前必须配置TIMx_ARR&#xff1b;同样&#xff0c;捕获器、比较器、预分频器、触发输出特性等仍工作如常。在这个模式下&#xff0c;计数器依照增量编码器的速度和方向被自动的修改&#xff0c;因此计数器的内容始终指示着编码器的位置。计数方向与相连的传感器旋转的方向对应。下表列出了所有可能的组合&#xff0c;假设TI1和TI2不同时变换。
在这里插入图片描述一个外部的增量编码器可以直接与MCU连接而不需要外部接口逻辑。但是&#xff0c;一般会使用比较器将编码器的差动输出转换到数字信号&#xff0c;这大大增加了抗噪声干扰能力。编码器输出的第三个信号表示机械零点&#xff0c;可以把它连接到一个外部中断输入并触发一个计数器复位。
下图是一个计数器操作的实例&#xff0c;显示了计数信号的产生和方向控制。它还显示了当选择了双边沿时&#xff0c;输入抖动是如何被抑制的&#xff1b;抖动可能会在传感器的位置靠近一个转换点时产生。在这个例子中&#xff0c;我们假定配置如下&#xff1a;
● CC1S&#61;’01’ (TIMx_CCMR1寄存器&#xff0c;IC1FP1映射到TI1)
● CC2S&#61;’01’ (TIMx_CCMR2寄存器&#xff0c;IC2FP2映射到TI2)
● CC1P&#61;’0’ (TIMx_CCER寄存器&#xff0c;IC1FP1不反相&#xff0c;IC1FP1&#61;TI1)
● CC2P&#61;’0’ (TIMx_CCER寄存器&#xff0c;IC2FP2不反相&#xff0c;IC2FP2&#61;TI2)
● SMS&#61;’011’ (TIMx_SMCR寄存器&#xff0c;所有的输入均在上升沿和下降沿有效).
● CEN&#61;’1’ (TIMx_CR1寄存器&#xff0c;计数器使能)

在这里插入图片描述
在这里插入图片描述当定时器配置成编码器接口模式时&#xff0c;提供传感器当前位置的信息。使用第二个配置在捕获模式的定时器&#xff0c;可以测量两个编码器事件的间隔&#xff0c;获得动态的信息(速度&#xff0c;加速度&#xff0c;减速度)。指示机械零点的编码器输出可被用做此目的。根据两个事件间的间隔&#xff0c;可以按照固定的时间读出计数器。如果可能的话&#xff0c;你可以把计数器的值锁存到第三个输入捕获寄存器(捕获信号必须是周期的并且可以由另一个定时器产生)&#xff1b;也可以通过一个由实时时钟产生的DMA请求来读取它的值。

相关寄存器
1&#xff1a;SMCR寄存器
其中的SMS位用来设置编码器模式&#xff0c;主要影响的是 上面表格《计数方向与编码器信号的关系》 内的计数器的方向。
设置为011时&#xff1a;可理解为一共有两个定时器通道来采集编码器A、B相的脉冲信号&#xff0c;编码器模式3时&#xff0c;会根据另一个通道的电平信号&#xff0c;以及当前通道电平的变化&#xff08;上升、下降&#xff09;来决定计数器的计数方向&#xff08;增加/减少&#xff09;&#xff0c;例如当A相通道(TI1)电平信号为低电平时&#xff0c;B相通道(TI2)的电平跳变成高电平了&#xff0c;此时根据表格&#xff0c;计数器的值下降&#xff0c;编码器模式就是靠这个表格来计数的&#xff0c;这个数对应对应的就是编码器的位置
在这里插入图片描述2&#xff1a;CR1寄存器
编码器模式需要设置位6&#xff1a;5为边沿对齐模式&#xff0c;因为SMCR设置为011&#xff0c;TI1和TI2同时计数情况下&#xff0c;计数器的方向要根据计数器的DIR方向位进行改变&#xff0c;故其设置为00.
在这里插入图片描述

void Encoder_Init_TIM2(void)
{RCC->APB2ENR|&#61;1<<0; //开启辅助时钟AFIO->MAPR|&#61;1<<8; //01部分重映射RCC->APB1ENR|&#61;1<<0; //TIM2时钟使能RCC->APB2ENR|&#61;1<<2; //PORTA时钟使能RCC->APB2ENR|&#61;1<<3; //PORTB时钟使能GPIOA->CRH&&#61;0X0FFFFFFF;//PA15GPIOA->CRH|&#61;0X40000000;//浮空输入GPIOB->CRL&&#61;0XFFFF0FFF;//PB3GPIOB->CRL|&#61;0X00004000;//浮空输入TIM2->DIER|&#61;1<<0; //允许更新中断TIM2->DIER|&#61;1<<6; //允许触发中断MY_NVIC_Init(1,3,TIM2_IRQn,1);TIM2->PSC &#61; 0x0;//不分频TIM2->ARR &#61; ENCODER_TIM_PERIOD;//设置计数器自动重装载值TIM2->CR1 &&#61;~(3<<8);// 时钟分频&#xff0c;不分频TIM2->CR1 &&#61;~(3<<5);//选择计数模式&#xff0c;边沿对齐模式TIM2->CCMR1 |&#61; 1<<0; //CC1S&#61;&#39;01&#39; IC1FP1映射到TI1TIM2->CCMR1 |&#61; 1<<8; //CC2S&#61;&#39;01&#39; IC2FP2映射到TI2TIM2->CCER &&#61; ~(1<<1); //CC1P&#61;&#39;0&#39; IC1FP1不反相&#xff0c;ICIFP1&#61;TI1TIM2->CCER &&#61; ~(1<<5); //CC2P&#61;&#39;0&#39; IC2FP2不反相&#xff0c;IC2FP2&#61;TI2
// TIM2->CCMR1 |&#61; 3<<4; // 输入捕获滤波器TIM2 -> CNT&#61;0;TIM2->SMCR |&#61; 3<<0; //计数器同时在TI1和TI2边沿计数TIM2->CR1 |&#61; 0x01; //使能定时器
}

单位时间读取编码器的计数值&#xff0c;可以转化为速度
入口参数&#xff1a;定时器
返回值&#xff1a;速度值

int Read_Encoder(u8 TIMX)
{int Encoder_TIM; switch(TIMX){case 2: Encoder_TIM&#61; (short)TIM2 -> CNT; TIM2 -> CNT&#61;0; break;case 3: Encoder_TIM&#61; (short)TIM3 -> CNT; TIM3 -> CNT&#61;0; break;case 4: Encoder_TIM&#61; (short)TIM4 -> CNT; TIM4 -> CNT&#61;0; break; default: Encoder_TIM&#61;0;}return Encoder_TIM;
}

参考&#xff1a;《STM32中文参考手册_V10》
《STM32不完全手册_寄存器版本_V3.1》
《STM32F7中文参考手册》
正点原子官方教程


推荐阅读
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • IOS开发之短信发送与拨打电话的方法详解
    本文详细介绍了在IOS开发中实现短信发送和拨打电话的两种方式,一种是使用系统底层发送,虽然无法自定义短信内容和返回原应用,但是简单方便;另一种是使用第三方框架发送,需要导入MessageUI头文件,并遵守MFMessageComposeViewControllerDelegate协议,可以实现自定义短信内容和返回原应用的功能。 ... [详细]
  • 使用C++编写程序实现增加或删除桌面的右键列表项
    本文介绍了使用C++编写程序实现增加或删除桌面的右键列表项的方法。首先通过操作注册表来实现增加或删除右键列表项的目的,然后使用管理注册表的函数来编写程序。文章详细介绍了使用的五种函数:RegCreateKey、RegSetValueEx、RegOpenKeyEx、RegDeleteKey和RegCloseKey,并给出了增加一项的函数写法。通过本文的方法,可以方便地自定义桌面的右键列表项。 ... [详细]
  • UMTS基础知识汇总
    协议框架23G接口UMTS实体EntityNameDescriptionAuCAuthenticationCenterCBCCellBroadcastCenterC-RNCCon ... [详细]
  •   在Linux上,安装完成之后,在测试RMAN时可能会遇到如下错误:  [oracle@smsdbrac1oracle]$rmantarget/   ... [详细]
  • 本文由编程笔记#小编为大家整理,主要介绍了logistic回归(线性和非线性)相关的知识,包括线性logistic回归的代码和数据集的分布情况。希望对你有一定的参考价值。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文介绍了多因子选股模型在实际中的构建步骤,包括风险源分析、因子筛选和体系构建,并进行了模拟实证回测。在风险源分析中,从宏观、行业、公司和特殊因素四个角度分析了影响资产价格的因素。具体包括宏观经济运行和宏经济政策对证券市场的影响,以及行业类型、行业生命周期和行业政策对股票价格的影响。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  •   《WindowsAzurePlatform系列文章目录》  本文将介绍如何在AzureSQLDatabase创建只读用户。  请先按照笔者之前的文章:AzureSQLDatabas ... [详细]
  • 机器人学领域的顶级期刊总结
    本文转载自:https:www.sohu.coma116061841_470013,如有侵权请告知,立即删除摘要此前有不少博客总结了机 ... [详细]
author-avatar
球球小白痴_693
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有