STM32 HAL Nucleo F446RE正交编码器

3

我在我的STM32F446RE / NUCLEO-F446RE上使用定时器TIM3的正交编码器模式时遇到了问题:

  1. TIM3在第一个信号上的每个上升沿计数。 CNT寄存器计数并以1Hz读取该值,然后将寄存器设置为0。

    当我查看示波器oscilloscope时, 频率是CNT register output (1hz)值的一半。

    为什么?

  2. TIM3在第一个信号的两个边缘上计数。 CNT register output (1 Hz)完全错误。

我的配置是:

GPIO_InitTypeDef sInitEncoderPin1;
sInitEncoderPin1.Pin                    = pin1Encoder.pin;  // A GPIO_PIN_6
sInitEncoderPin1.Mode                   = GPIO_MODE_AF_PP;
sInitEncoderPin1.Pull                   = GPIO_PULLUP;
sInitEncoderPin1.Speed                  = GPIO_SPEED_HIGH;
sInitEncoderPin1.Alternate              = altFunctionEncoder; // GPIO_AF2_TIM3

GPIO_InitTypeDef sInitEncoderPin2;
sInitEncoderPin2.Pin                    = pin2Encoder.pin; // A GPIO_PIN_7
sInitEncoderPin2.Mode                   = GPIO_MODE_AF_PP;
sInitEncoderPin2.Pull                   = GPIO_PULLUP;
sInitEncoderPin2.Speed                  = GPIO_SPEED_HIGH;
sInitEncoderPin2.Alternate              = altFunctionEncoder; // GPIO_AF2_TIM3

HAL_GPIO_Init(GPIOA, &sInitEncoderPin1);
HAL_GPIO_Init(GPIOA, &sInitEncoderPin2);

encoderTimer.Init.Period                        = 0xffff;
encoderTimer.Init.Prescaler                     = 0;
encoderTimer.Init.CounterMode                   = TIM_COUNTERMODE_UP;
encoderTimer.Init.ClockDivision                 = TIM_CLOCKDIVISION_DIV1;
encoderTimer.Init.RepetitionCounter             = 0;

HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 1);

encoder.EncoderMode                             = TIM_ENCODERMODE_TI1;
encoder.IC1Filter                               = 0x0f;
encoder.IC1Polarity                             = TIM_INPUTCHANNELPOLARITY_RISING; // TIM_INPUTCHANNELPOLARITY_BOTHEDGE
encoder.IC1Prescaler                            = TIM_ICPSC_DIV1;
encoder.IC1Selection                            = TIM_ICSELECTION_DIRECTTI;

encoder.IC2Filter                               = 0x0f;
encoder.IC2Polarity                             = TIM_INPUTCHANNELPOLARITY_RISING;
encoder.IC2Prescaler                            = TIM_ICPSC_DIV1;
encoder.IC2Selection                            = TIM_ICSELECTION_DIRECTTI;

HAL_TIM_Encoder_Init(&encoderTimer, &encoder);
HAL_TIM_Encoder_Start_IT(&encoderTimer, TIM_CHANNEL_ALL);
1个回答

0

示波器截图显示大约416赫兹的频率。

  1. 第一个shell输出中显示的值(非常粗略!)大约是问题所指出的两倍。在我看来,这似乎(几乎…)是正确的,因为所示配置

    encoder.EncoderMode = TIM_ENCODERMODE_TI1;
    

    选择“X2分辨率编码器模式”,每个信号周期计数2个CNT增量。在关于定时器概述的应用笔记中(Sec. 4.3.4 / Fig. 7),有一张插图详细说明了编码器模式的工作原理。

  2. 第二个截图的结果是由于TIM3的错误配置造成的:编码器模式(TIM_ENCODERMODE_TI1)假设两个通道只在交替方式下触发有向沿(请参见上面的AN链接)。

    如果由于以下配置中的一个通道触发了两倍的事件:

    encoder.IC1Polarity = TIM_INPUTCHANNELPOLARITY_BOTHEDGE,
    

    计数器只会向上计数一次,然后“检测到”一次“反转”事件(即方向的改变)。

    请记住

    65535u = 0xFFFF = -1
    

    第二个截图仅显示值为-1、0、+1,这与该解释完美地吻合。


问题在于为什么第一张截图显示了在 800822 之间的(可重复的)测量值。 我假设:
  • 编码器信号的物理源以恒定的速度运行
  • 触发 shell 输出的 1 Hz 计时器与 TIM3 是独立的,并且
  • 它已经在编码器计时器之前启动 (即上面显示的代码示例)。

这可能解释了为什么前两个值看起来像是无意义的(0:TIM3 尚未启动。 545:TIM3 在 shell 输出计时器周期内启动)。 舍弃前两个测量样本,所测得信号频率的平均值和标准差分别为

808.9091 +/- 0.5950 [每秒 X2 增量]

404.4545 +/- 0.2975 [Hz]

这对应于一个周期为

2.4331 +/- 0.003 [毫秒]。

因此,测量的频率偏低约11 Hz,即测量的周期偏高近30微秒,这个误差显然超出了统计噪声的范围。
问题提示了这个错误可能来自哪里:
CNT寄存器计数并以1 Hz读取该值,然后将寄存器设置为0。
每当1 Hz“轮询定时器”到期时,它会触发中断(或轮询软件中的逻辑事件)。
处理此中断/事件可能会有所延迟,具体取决于其他软件(IRQ:在软件的其他位置停用时间,轮询:直到轮询事件的循环持续时间)。
软件读取CNT值。
软件将CNT值重置为零,丢弃自读取CNT值以来的进一步增量。
TIM3继续计数(从零开始)。
这暗示着软件需要在(3.)和(4.)之间等待30微秒,在STM32F4上这将是相当长的时间。

编辑:我刚刚重新检查了示波器截图。错误是可见的,但我相信它比我最初估计的要小(从图片中计算边沿)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接