STM32 HAL Nucleo F446RE正交编码器

时间:2018-01-20 21:17:03

标签: stm32 encoder stm32f4 nucleo cubemx

我在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 :(得分:0)

oscilloscope screenshot 显示大约416 Hz的频率。

  1. first shell output (非常粗略!)高两倍(问题已经指出)。 由于显示的配置

    ,这似乎对我几乎是正确的
    encoder.EncoderMode = TIM_ENCODERMODE_TI1;
    

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

  2. second screenshot TIM3配置错误导致的结果: 编码器模式(TIM_ENCODERMODE_TI1)假定两个通道仅在定向侧面上交替触发(请参见上面的AN链接)。

    如果两个通道之一触发的事件是 配置

    encoder.IC1Polarity = TIM_INPUTCHANNELPOLARITY_BOTHEDGE,
    

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

    65535u = 0xFFFF = -1
    

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


问题仍然在于,为什么第一张屏幕截图显示了800822之间的(可重现)测量结果。 我认为

  • 编码器信号的物理源以恒定的速度运行
  • 触发外壳输出的1 Hz计时器与TIM3 无关,并且
  • 在编码器计时器之前 已启动 (即,在显示的代码示例上方)。

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

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

404,4545 +/- 0.2975 [Hz]

对应于一个周期

2,4331 +/- 0,003 [ms]。

因此,测得的频率太低了约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上将花费大量时间。

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