3

我的 STM32F446RE / NUCLEO-F446RE的定时器 TIM3 的正交编码器模式有问题:

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

    当我查看 示波器时,频率是CNT 寄存器输出 (1hz) 值的一半 。

    为什么?

  2. TIM3 在第一个信号的两个边沿上计数。CNT 寄存器输出 (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);
4

1 回答 1

0

示波器屏幕截图显示 频率约为 416 Hz。

  1. 第一个 shell 输出中显示的值 是(非常粗略!)两倍高(正如问题已经指出的那样)。由于显示的配置,这对我来说(几乎......)是正确的

    encoder.EncoderMode = TIM_ENCODERMODE_TI1;
    

    选择“ X2 分辨率编码器模式”,CNT每个信号周期计数 2 个增量。在有关计时器概述的应用说明中 ,(第 4.3.4 节/图 7)中有一个说明图,说明了编码器模式如何详细工作。

  2. 第二 个屏幕截图 是由不正确的 TIM3 配置导致的:编码器模式 ( TIM_ENCODERMODE_TI1) 假定两个通道仅以交替方式在定向侧面触发(参见上面的 AN 链接)。

    如果两个通道之一由于配置而触发两倍的事件

    encoder.IC1Polarity = TIM_INPUTCHANNELPOLARITY_BOTHEDGE,
    

    计数器只会增加一个位置,然后“识别”一个“反转”事件(= 方向改变)。请记住,

    65535u = 0xFFFF = -1
    

    第二个屏幕截图仅显示值 -1、0、+1 - 这完全符合此解释。


问题仍然是为什么第一个屏幕截图显示800和之间的(可重复的)测量822。我假设

  • 编码器信号的物理源以恒定的速度运行
  • 触发 shell 输出的 1 Hz 定时器独立于 TIM3,并且
  • 它已在编码器计时器之前启动(即,在所示代码示例上方)。

这可以解释为什么前两个值看起来像废话(0: TIM3 尚未启动。545: TIM3 已在 shell 输出计时器期间启动)。丢弃前两个测量样本,测量信号频率的平均值和标准偏差分别为

808,9091 +/- 0,5950 [每秒 X2 增量]

404,4545 +/- 0,2975 [赫兹]

这对应于一个时期

2,4331 +/- 0,003 [毫秒]。

因此,测量频率太低了大约 11 Hz,即测量周期太高了近 30 µs,这个误差显然超出了统计噪声。

这个问题给出了这个错误可能来自哪里的提示:

CNT 寄存器向上计数,我以 1 Hz 读取值,然后将寄存器设置为 0。

  1. 每当 1 Hz“轮询计时器”到期时,它就会触发中断(或轮询软件中的逻辑事件)。
  2. 此中断/事件的处理可能会稍微延迟,具体取决于其他软件(IRQ:软件中其他地方的停用时间,轮询:直到轮询事件的循环持续时间)。
  3. 软件读取CNT值。
  4. 软件将值重置CNT为零,丢弃自CNT读取值以来的进一步增量。
  5. TIM3 继续计数(从零开始)。

这暗示软件在 (3.) 和 (4.) 之间需要 30 µs,这在 STM32F4 上将是相当多的时间。

编辑:我刚刚重新检查了示波器屏幕截图。该错误是可见的,但我相信它比我最初假设的要小(从图片中的侧面计算)。

于 2020-06-01T15:22:51.640 回答