文章目录
- 定时器选择外部时钟源
- 配置GPIO
- 复习AFIO !
- 什么时候需要配置AFIO?
- "main function"和“alternate-default"有什么区别?
- full和partial remap是啥意思?
- 实验又有问题了。。。
摘要:本文记录 STM32 定时器使用外部时钟源(红外传感器)的实践过程。首先介绍如何通过
TIM_ETRClockMode2Config配置外部时钟模式 2 及触发极性;接着讲解 GPIO 浮空输入的配置要点,并深入复习 AFIO 相关知识(何时需要配置、main function 与 alternate-default 的区别、full/partial remap 的含义);最后记录实验中遇到的计数抖动问题,分析原因并给出通过 ETR 输入滤波解决的方案。
定时器选择外部时钟源
这个实验主要是实践“外部时钟模式2”。
要选择外部时钟就需要用这个function:TIM_ETRClockMode2Config。这里面的一个参数就是配置极性。这个极性如何配置取决于我们的功能需求和外接“时钟”的有效电平。这里“时钟”大引号主要是因为它不一定是一个以一定时间间隔产生脉冲的部件。比如我们的实验中,它是一个红外传感器。
实验的需求就是记录遮挡红外光的次数。
这个模块的“极性”是:
- 遮挡模块槽,DO输出高电平
- 不遮挡,DO输出低电平
所以,如果我们要检测遮挡次数,一般正常感知是“不遮挡->遮挡”算一次“遮挡”,那么就是电平上升算一次触发。根据RM中包括库代码中的定义
所以选择"non-inverted"高电平/上升沿触发比较符合我们的直觉。
配置GPIO
RM里推荐的GPIO Mode设置是浮空输入,
本来我也写这个,但是课程中老师觉得这个不靠谱,用了IPU。他补充了一下什么时候可以用浮空输入:如果外部输入信号功率很小,内部上拉电阻会影响到这个输入信号,可以用浮空输入,防止内部电路影响外部输入的电平。
那么,这个PA0作为了时钟输入,我需要动用AFIO给它做重映射么?
不需要,因为TIM2的ETR功能是PA0的默认功能,不需要执行重映射。
上面的表格有几点可以补充一下:
- 一个pin的default有很多,这些都不需要用AFIO做remap,只需要使能和配置这个GPIO然后相应使能其他外设即可。但是同时,这几个default不能同时使用,同一时刻pin脚只能时一个角色。。。
- TIM2_CH1_ETR其实表示的是TIM2_CH1或者TIM2_ETR,这两个不能同时使用。
- 只有当pin脚要用作“Remap”那一栏的功能时才需要动用AFIO
复习AFIO !
什么时候需要配置AFIO?
还是要关注datasheet中的这个pin definition 表格
- 当这个Pin脚要用alternate-remap这一栏的功能时:通过GPIO_PinRemapConfig
- 外部中断EXTI引脚选择:通过GPIO_EXTILineConfig
"main function"和“alternate-default"有什么区别?
这个表格里有这样两列
- main function:Pin脚初始化之后就是这个功能
- alternate-default:刚才也提到了,这是引脚的默认AF功能,只需要配置GPIO的模式和相应外设即可。
那么好像就有点问题了:这两栏里面列的功能,看起来都是这个Pin脚“上电就有的”功能啊。为什么要分成两列呢?
查了一下,尝试理解: - 从电路连接的角度来说,main function是这个pin脚物理直连的功能;
- STM32内部有多路复用器MUX,而alternate这里列的功能,是经过多路复用器连到的模块。对于那些不需要配置“remap”的功能,就列在default这一栏。
从代码来看,一个Pin脚用main function和用alternate-default好像很像,没有什么“set_main_function()"或者"set_alternate_default()"这样的function来进行配置。但是
- 如果这个GPIO用作”输入功能“的Pin脚,似乎它用作main 或者alternate-default配置的区别是不大。可以理解为:它作为输入的时候,整个板子都在监听信号,对于到底这个pin是main function还是alternate-default功能没有区别。
- 但是如果它是用于”输出“功能的pin脚,那其实是有区别的!区别就在于配置GPIO Mode!对于GPIO的输出模式,可是对AF有特殊照顾的。如果希望把这个pin脚作用作输出某个AF,但是还是配置成OUT_OD或者OUT_PP,那么这个pin的背后还是它的main function,而不是alternate-default,它是不会输出我们想要的功能的。
full和partial remap是啥意思?
在使用GPIO_PinRemapConfig会看到库里面提供的宏定义名字里面有类似于“GPIO_PartialRemap_USART3”,“GPIO_FullRemap_USART3”,也有不带Full/Partial的名字“GPIO_Remap_USART2”。
包括在RM中的表格里,也有提到这两个词
其实,partial和full时相对于第一列“no remap"也就是这个外设默认的引脚而言的。一个外设通常会用到多个引脚(比如很多时候会有RX和TX),
- 如果只有一部分引脚用了alternate function的pin脚,而剩下一部分和“no remap”的时候一样,那就是“partial remap”;
- 如果这个外设所有用的引脚都不是默认使用的引脚了,那就是"full remap"。
- 如果这个宏定义没有“full/partial”,我看了一下,通常好像都是full remap的情况。
其实区别可以从表格中看出来,比如上面这个USART3,partial remap的情况,有两个cell是和“no remap"共用的,如绿框所示。
实验又有问题了。。。
- 问题:每次挡光片遮上去,数值会加2或者加3甚至加5。
- debug:开启Keil的debug模式,观察了一下TIM的CNT寄存器值,发现我每次遮挡,它有时候+1,有时候直接增加其他值;有时候,它进入断点,我不挪开挡光片,它进入一次断点之后,自己又会进入第二次。
也做了一些查询,这个是因为遮挡的瞬间,信号不是一次干净的跳变,而是会有一系列抖动(之前GPIO实验中按键按下去的抖动一样)。而TIM的CNT记录的是脉冲,每次抖动就是一个脉冲,所以CNT会一下次增加很多。(当然这个最好是有示波器看一下波形。。不过没有。。。) - 解决方案:增加滤波。ETR输入之后有一个滤波模块,可以认为是一个低通滤波器。TIM_ETRClockMode2Config 最后一个参数就是配置这个滤波器的滤波参数的
其中f C K I N T f_{CK_INT}fCKINT就是内部时钟频率72MHz,f D T S f_{DTS}fDTS是另一个独立时钟基准,本质是由f C K I N T f_{CK_INT}fCKINT分频得到,分频系数是在TIM_TimeBaseInit的输入参数的TIM_ClockDivision 指定。这个部分在“定时器(3)”的文章中有详细描述。
对之前文章的补充:之前文章里面说到,在通用定时器的主电路图中没有体现 CK_INT和各个filter之间的关系。主图中确实没有,但是在解释“外部时钟输入2”的细节框图有体现(如下图)
而这里的采样频率就是基于f D T S f_{DTS}fDTS再分频,并且保证连续N个电平是高/低才认为目前处于高/低电平。
TIM_ClockDivision设置为了TIM_CKD_DIV1,也就是不分频;f D T S f_{DTS}fDTS则=72MHz。这里尝试过两种:
- 0100:采样频率36MHz,从采到一个新的电平开始,连续6个采样点为这个新的电平,滤波器才输出这个新电平。滤波窗口时6/36MHz = 167ns
- 0010: 采样频率72MHz,从采到一个新的电平开始,连续4个采样点为这个新的电平,滤波器才输出这个新电平。滤波窗口时4/72MHz = 56ns
前者是后者的3倍,滤波更强。
注:关于“滤波窗口”,并不是说信号必须保持这么长时间的高/低电平才能被认为是高/低电平。应该还是从离散采样来理解,如果6次采样都是高电平,但实际上在167ns内信号有一次低电平但是没有被这6个采样捕捉到,那么滤波器还是认为是高电平。
但是至于视频中老师没有用滤波就可以达到稳定的数值加1的原因,不能有肯定的结论。硬件不同也会导致结果不同。可能他的传感器质量比较好?(看到有的说可能是因为我的模块没有比较器,但是我看了一下,传感器板子上是有这个模块的,但是它有没有用就不知道了啊)
反正看起来,对于外部传感器输入,永远不要假设它是干净的,考虑加上滤波才是正解。