HAL配置STM32编码器接口模式-读码不正确

2019-07-21 01:14发布

本帖最后由 onesuifeng 于 2018-2-3 17:30 编辑

请教各位大神,我用CubeMX配置的编码器模式,4倍频,分频系数是3,转1圈是1000,重装载值是65535。SMT32F103和F407都试过,A、B、Z相都接,编码器是欧姆龙增量式E6B2,NPN开路集电极输出,1000线。 15171290498983.png
20180129084424.png
手拧编码器实测出来的效果是,低速时读取时也会有错误,稍微高速的话,漏码极其严重。
另外,使用I/O直接读引脚电平的话,准确度则高得多。以下编码器模式下低速手拧,串口3打印出来的数据,添加了时间戳
纯数字是每秒打印出来的实时计数器的值,Z..是Z相触发中断后读取的计数器值
0[2018-01-28 04:18:55.591]
Z..44[2018-01-28 04:18:56.412]
297[2018-01-28 04:18:56.591]
Z..1046[2018-01-28 04:18:57.104]
1647[2018-01-28 04:18:57.590]
Z..2049[2018-01-28 04:18:57.904]
2839[2018-01-28 04:18:58.591]
Z..3054[2018-01-28 04:18:58.629]
Z..4055[2018-01-28 04:18:58.919]
Z..5057[2018-01-28 04:18:59.202]
Z..6058[2018-01-28 04:18:59.486]
6549[2018-01-28 04:18:59.590]
Z..7058[2018-01-28 04:18:59.757]
Z..8059[2018-01-28 04:19:00.157]
Z..9064[2018-01-28 04:19:00.481]
9519[2018-01-28 04:19:00.591]
Z..10071[2018-01-28 04:19:00.769]
Z..11076[2018-01-28 04:19:01.006]
Z..12077[2018-01-28 04:19:01.172]
Z..13082[2018-01-28 04:19:01.496]
13515[2018-01-28 04:19:01.591]
Z..14089[2018-01-28 04:19:01.874]
Z..15092[2018-01-28 04:19:02.079]
15128[2018-01-28 04:19:02.591]
Z..15093[2018-01-28 04:19:02.605]
Z..14089[2018-01-28 04:19:03.124]
Z..13088[2018-01-28 04:19:03.414]
13062[2018-01-28 04:19:03.590]
Z..12082[2018-01-28 04:19:04.301]
11321[2018-01-28 04:19:04.590]
Z..11082[2018-01-28 04:19:04.835]
Z..10080[2018-01-28 04:19:05.497]
9871[2018-01-28 04:19:05.590]
Z..9077[2018-01-28 04:19:06.146]
Z..8075[2018-01-28 04:19:06.410]
7824[2018-01-28 04:19:06.591]
Z..7071[2018-01-28 04:19:06.941]
6093[2018-01-28 04:19:07.590]
Z..6065[2018-01-28 04:19:07.657]
Z..5062[2018-01-28 04:19:08.512]
4815[2018-01-28 04:19:08.590]
Z..4060[2018-01-28 04:19:08.922]
Z..3055[2018-01-28 04:19:09.385]
2976[2018-01-28 04:19:09.591]
Z..2049[2018-01-28 04:19:09.942]
1260[2018-01-28 04:19:10.590]
Z..1044[2018-01-28 04:19:10.665]
Z..39[2018-01-28 04:19:11.139]
Z..64572[2018-01-28 04:19:11.524]
64395[2018-01-28 04:19:11.594]
64388[2018-01-28 04:19:12.590]

以下是编码器模式下,高速手拧打印出来的数据,添加了时间戳
纯数字是每秒打印出来的实时计数器的值,Z..是Z相触发中断后读取的计数器值
0[2018-01-28 04:25:31.838]
Z..379[2018-01-28 04:25:32.552]
Z..1378[2018-01-28 04:25:32.773]
1667[2018-01-28 04:25:32.839]
Z..2375[2018-01-28 04:25:33.525]
Z..3372[2018-01-28 04:25:33.711]
3376[2018-01-28 04:25:33.838]
Z..4371[2018-01-28 04:25:34.194]
Z..5188[2018-01-28 04:25:34.733]
Z..5405[2018-01-28 04:25:34.766]
Z..5428[2018-01-28 04:25:34.766]
5888[2018-01-28 04:25:34.839]
Z..6240[2018-01-28 04:25:35.327]
Z..6486[2018-01-28 04:25:35.358]
7013[2018-01-28 04:25:35.838]
Z..7295[2018-01-28 04:25:35.863]
Z..7295[2018-01-28 04:25:35.885]
Z..7673[2018-01-28 04:25:35.914]
Z..8620[2018-01-28 04:25:36.404]
Z..8639[2018-01-28 04:25:36.433]
Z..8695[2018-01-28 04:25:36.460]
Z..9689[2018-01-28 04:25:36.519]
9761[2018-01-28 04:25:36.838]
Z..9968[2018-01-28 04:25:37.013]
Z..9968[2018-01-28 04:25:37.032]
Z..10277[2018-01-28 04:25:37.061]
Z..11140[2018-01-28 04:25:37.567]
Z..11125[2018-01-28 04:25:37.613]
Z..11101[2018-01-28 04:25:37.637]
Z..12004[2018-01-28 04:25:37.686]
12195[2018-01-28 04:25:37.839]
Z..12003[2018-01-28 04:25:38.179]
Z..11774[2018-01-28 04:25:38.228]
Z..10884[2018-01-28 04:25:38.276]
Z..10742[2018-01-28 04:25:38.692]
Z..9809[2018-01-28 04:25:38.735]
9553[2018-01-28 04:25:38.839]
Z..9348[2018-01-28 04:25:39.112]
Z..9992[2018-01-28 04:25:39.162]
Z..8996[2018-01-28 04:25:39.522]
Z..8364[2018-01-28 04:25:39.559]
7602[2018-01-28 04:25:39.838]
Z..7364[2018-01-28 04:25:39.934]
Z..6570[2018-01-28 04:25:39.975]
Z..6662[2018-01-28 04:25:40.055]
Z..6684[2018-01-28 04:25:40.400]
Z..5748[2018-01-28 04:25:40.446]
Z..5551[2018-01-28 04:25:40.829]
5421[2018-01-28 04:25:40.839]
Z..5028[2018-01-28 04:25:40.860]
Z..4581[2018-01-28 04:25:41.550]
Z..4463[2018-01-28 04:25:41.570]
Z..3553[2018-01-28 04:25:41.570]
Z..3497[2018-01-28 04:25:41.775]
Z..2863[2018-01-28 04:25:41.775]
2576[2018-01-28 04:25:41.848]
Z..2156[2018-01-28 04:25:42.203]
Z..1267[2018-01-28 04:25:42.634]
Z..493[2018-01-28 04:25:42.677]
Z..65234[2018-01-28 04:25:42.720]
64947[2018-01-28 04:25:42.839]
64946[2018-01-28 04:25:43.838]
64926[2018-01-28 04:25:44.838]

以下是读取高低电平打印的数据,这里一圈是2000
纯数字是每秒打印出来的实时计数器的值,Z...是Z相触发中断后读取的计数器值
2
2
33
825
Z...1619
1743
2350
3414
Z...3615
3661
3664
3664
3934
3701
Z...3616
3210
2314
Z...1616
1406
1362
1364
Z...1617
2512
Z...3615
3671
Z...3616
2667
Z...1618
1450
1348
1002
974
Z...1619
2488
Z...1618
1375
133
Z...65158
64878
63949
65049
Z...65163
577
1552
Z...1627
2724
3539
Z...3625
5222
Z...5623
5752
6932
Z...5620
5566
4745
Z...3620
3412
3133
2237
Z...1624
1341
218
Z...65166
64874
63878
Z...63170
62953
63028
Z...63173
Z...65171
65231
Z...1631
1893
2620
Z...3623
4507
Z...5619
5853
7238
Z...7615
Z...7616
6239
Z...5618
5460
4408
Z...3618
3335
2275
Z...1620
1368
Z...1621
Z...3619
3694
4667
Z...5617
5736
Z...5616
3971
Z...3620
2390
Z...1622
1182
481
Z...65168
64855
64037
Z...65173
134
990
Z...1635
1655
1653
1653

TIM1初始化代码
[mw_shl_code=c,true]TIM_HandleTypeDef htim1;

/* TIM1 init function */
void MX_TIM1_Init(void)
{
  TIM_Encoder_InitTypeDef sConfig;
  TIM_MasterConfigTypeDef sMasterConfig;

  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 3;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 65535;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  sConfig.EncoderMode = TIM_ENCODERMODE_TI12;
  sConfig.IC1Polarity = TIM_ICPOLARITY_FALLING;
  sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
  sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
  sConfig.IC1Filter = 0;
  sConfig.IC2Polarity = TIM_ICPOLARITY_FALLING;
  sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
  sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
  sConfig.IC2Filter = 0;
  if (HAL_TIM_Encoder_Init(&htim1, &sConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}[/mw_shl_code]


[mw_shl_code=c,true]void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef* tim_encoderHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(tim_encoderHandle->Instance==TIM1)
  {
  /* USER CODE BEGIN TIM1_MspInit 0 */

  /* USER CODE END TIM1_MspInit 0 */
    /* TIM1 clock enable */
    __HAL_RCC_TIM1_CLK_ENABLE();
  
    /**TIM1 GPIO Configuration   
    PA8     ------> TIM1_CH1
    PA9     ------> TIM1_CH2
    */
    GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  }
}[/mw_shl_code]

读取计数器值的函数,每秒运行一次
[mw_shl_code=c,true]void Task0(void)
{
        uint32_t CaptureNumber;
        
        CaptureNumber = __HAL_TIM_GET_COUNTER(&htim1);
        printf("%d ",CaptureNumber);
        Task_Delay[0]=TASK0_DELAY;
} [/mw_shl_code]

使用PA5接Z相,初始化为上拉输入,下降沿触发中断
下面是中断回调函数
[mw_shl_code=c,true]void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
        uint32_t CaptureNumber;
        
        switch(GPIO_Pin)
        {
                case GPIO_PIN_5:
                {
                        CaptureNumber = __HAL_TIM_GET_COUNTER(&htim1);
                        printf("Z..%d ",CaptureNumber);
//                        __HAL_TIM_SET_COUNTER(&htim1, 0);
                }
                break;
        }
}[/mw_shl_code]

以上就是大致的情况。

有考虑过编码器输出信号有问题,但用读取高低电平的方法,准确率却很高。
配置问题,网上搜索了不少资料,基本上都是用编码器模式,芯片根据A、B相的电平信息自动加减,另外可根据情况添加中断。
转速问题,频率输出基本都是在10KHz以下,理论上不会超过编码器的范围,手册上写的是最高100KHz。

另外有个比较有趣的是,STM32中文参考手册上提到“通常使用比较器将编码器的差分信号输出转换为数字信号。这样大幅提高了抗噪声性能”
20180129091047.png
查了一下,这种NPN开路集电极输出应该就是数字信号。
这里提到的使用比较器是怎么使用就搞不懂了。如果是内部的捕获比较通道好像在编码器模式下是没有使用的。
20180129092007.png
用一个I/O口设置成上拉输入,接到编码器A相,然后用示波器接A相跟0V(与单片机的GND共地),没有什么异样。显示波形如下:
20180203172612.jpg 20180203172619.jpg

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。