OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 10380|回复: 15

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

[复制链接]

1

主题

7

帖子

0

精华

新手上路

积分
35
金钱
35
注册时间
2018-1-15
在线时间
6 小时
发表于 2018-1-29 09:44:00 | 显示全部楼层 |阅读模式
5金钱
本帖最后由 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\r\n",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\r\n",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

最佳答案

查看完整内容[请看2#楼]

前两天看了个视频,发现是接线的问题。使用的是NPN型的编码器,A、B相都要接一个上拉电阻,然后再接入到单片机的I/O口,否者输出的电平就不好说了,这也是计数不准的原因,不是软件配置的问题。 再附上测试的打印数据,一圈是1000个脉冲,累计下来会有几个脉冲的偏差,但误差在可接受范围内。我接的是4.7K的电阻,其他的没试过。 Z..43039 42455 Z..42039 Z..41041 Z..40040 Z..39040 38597 Z..38038 Z..37039 Z..360 ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

7

帖子

0

精华

新手上路

积分
35
金钱
35
注册时间
2018-1-15
在线时间
6 小时
 楼主| 发表于 2018-1-29 09:44:01 | 显示全部楼层
前两天看了个视频,发现是接线的问题。使用的是NPN型的编码器,A、B相都要接一个上拉电阻,然后再接入到单片机的I/O口,否者输出的电平就不好说了,这也是计数不准的原因,不是软件配置的问题。 编码器接线.png

再附上测试的打印数据,一圈是1000个脉冲,累计下来会有几个脉冲的偏差,但误差在可接受范围内。我接的是4.7K的电阻,其他的没试过。
Z..43039
42455
Z..42039
Z..41041
Z..40040
Z..39040
38597
Z..38038
Z..37039
Z..36039
Z..35039
34951
Z..34039
Z..33040
Z..32040
32008
Z..31042
Z..30042
29341
Z..29042
Z..28041
Z..27040
26247
Z..26041
Z..25039
Z..24039
Z..23038
22728
Z..22040
Z..21038
Z..20038
19402
Z..19037
Z..18039
Z..17039
16647
Z..16038
Z..15038
Z..14038
13609
Z..13038
Z..12037
Z..11037
10431
Z..10038
Z..9040
Z..8039
7434
Z..7041
Z..6041
Z..5040
4320
Z..4040
Z..3040
Z..2039
1402
Z..1040
Z..43
Z..64576
63859
Z..63578
Z..62576
Z..61577
60778
Z..60578
Z..59579
59392
59393
59544

回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2018-1-30 01:09:58 | 显示全部楼层
帮顶
回复

使用道具 举报

8

主题

569

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2363
金钱
2363
注册时间
2015-5-8
在线时间
320 小时
发表于 2018-1-30 08:34:23 | 显示全部楼层
这个确实是个问题,丢步漏步挺多的
回复

使用道具 举报

1

主题

7

帖子

0

精华

新手上路

积分
35
金钱
35
注册时间
2018-1-15
在线时间
6 小时
 楼主| 发表于 2018-1-31 08:56:55 | 显示全部楼层
炫色康康 发表于 2018-1-30 08:34
这个确实是个问题,丢步漏步挺多的

我看了不少帖子,提起这个问题的人不多,还以为大部分人都没有这个问题~
回复

使用道具 举报

4

主题

349

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1046
金钱
1046
注册时间
2017-5-19
在线时间
335 小时
发表于 2018-1-31 11:43:21 | 显示全部楼层
示波器看过波形没?波形有没有问题,排除这个那就是软件的问题,与STM32本身关系应该是不大的
回复

使用道具 举报

8

主题

569

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2363
金钱
2363
注册时间
2015-5-8
在线时间
320 小时
发表于 2018-2-2 13:52:49 | 显示全部楼层
onesuifeng 发表于 2018-1-31 08:56
我看了不少帖子,提起这个问题的人不多,还以为大部分人都没有这个问题~

没用标准库搞过,也许是HAL库的问题
回复

使用道具 举报

2

主题

12

帖子

0

精华

初级会员

Rank: 2

积分
122
金钱
122
注册时间
2017-9-21
在线时间
17 小时
发表于 2018-2-2 14:44:22 | 显示全部楼层
本帖最后由 觉感123 于 2018-2-2 14:49 编辑

你现在解决了这个问题了吗   我用103的也有问题  只能计角度  不可以计转了多少圈数
回复

使用道具 举报

1

主题

7

帖子

0

精华

新手上路

积分
35
金钱
35
注册时间
2018-1-15
在线时间
6 小时
 楼主| 发表于 2018-2-3 17:31:07 | 显示全部楼层
wxjhby 发表于 2018-1-31 11:43
示波器看过波形没?波形有没有问题,排除这个那就是软件的问题,与STM32本身关系应该是不大的

用示波器看过,没有发现异样,之前也用库函数配置过,也是同样的问题
回复

使用道具 举报

0

主题

126

帖子

0

精华

高级会员

Rank: 4

积分
502
金钱
502
注册时间
2016-11-28
在线时间
97 小时
发表于 2018-2-5 07:35:35 | 显示全部楼层
没有用cubemx配置过,我是用寄存器配置的定时器,103和407都没出现问题,不过转速也不快。
回复

使用道具 举报

4

主题

349

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1046
金钱
1046
注册时间
2017-5-19
在线时间
335 小时
发表于 2018-2-5 10:28:59 | 显示全部楼层
本帖最后由 wxjhby 于 2018-2-5 10:30 编辑

[mw_shl_code=c,true]/*-----------------------------------------------------
* tim1 编码器配置函数
* param:
* return:
*/
void TIM1InitEncoder(void)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    NVIC_InitTypeDef  NVIC_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_ICInitTypeDef TIM_ICInitStructure;   
    //TIM1  72M
//   RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1|RCC_APB2Periph_GPIOA, ENABLE);
   
    GPIO_StructInit(&GPIO_InitStructure);//将GPIO_InitStruct中的参数按缺省值输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;         
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//PA8 PA9浮空输入  
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
    NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);     
   
    TIM_EncoderInterfaceConfig(TIM1, TIM_EncoderMode_TI12, \
                                     TIM_ICPolarity_BothEdge ,\
                                     TIM_ICPolarity_BothEdge);//使用编码器模式3,上升下降都计数
   
    TIM_TimeBaseStructure.TIM_Period =30000;  
    TIM_TimeBaseStructure.TIM_Prescaler = 0;
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
   
    TIM_ICStructInit(&TIM_ICInitStructure);//将结构体中的内容缺省输入
    TIM_ICInitStructure.TIM_ICFilter = 0;  //选择输入比较滤波器
    TIM_ICInit(TIM1, &TIM_ICInitStructure);//将TIM_ICInitStructure中的指定参数初始化TIM1
   
    TIM_ClearITPendingBit(TIM1,TIM_IT_Update);        
    TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);                //定时器更新中断允许
   
    //Reset counter
    TIM1->CNT = 0;//
   
    TIM_Cmd(TIM1,ENABLE);  
//        0x01&(TIM2 -> CR >> 4)

}[/mw_shl_code]

我找的网上的这个代码用的没问题
回复

使用道具 举报

13

主题

156

帖子

0

精华

高级会员

Rank: 4

积分
883
金钱
883
注册时间
2017-8-7
在线时间
200 小时
发表于 2018-2-5 10:31:32 | 显示全部楼层
帮顶  
回复

使用道具 举报

1

主题

7

帖子

0

精华

新手上路

积分
35
金钱
35
注册时间
2018-1-15
在线时间
6 小时
 楼主| 发表于 2018-3-15 09:54:47 | 显示全部楼层
本帖最后由 onesuifeng 于 2018-3-15 10:00 编辑

自己解决了。。
回复

使用道具 举报

1

主题

7

帖子

0

精华

新手上路

积分
35
金钱
35
注册时间
2018-1-15
在线时间
6 小时
 楼主| 发表于 2018-3-15 09:57:05 | 显示全部楼层
觉感123 发表于 2018-2-2 14:44
你现在解决了这个问题了吗   我用103的也有问题  只能计角度  不可以计转了多少圈数

外接上拉电阻解决了,不知道能否对你有帮助
回复

使用道具 举报

1

主题

7

帖子

0

精华

新手上路

积分
35
金钱
35
注册时间
2018-1-15
在线时间
6 小时
 楼主| 发表于 2018-3-15 09:59:37 | 显示全部楼层
leiyitan 发表于 2018-2-5 07:35
没有用cubemx配置过,我是用寄存器配置的定时器,103和407都没出现问题,不过转速也不快。

我现在使用的这款编码器最高响应频率是100KHz,一秒几十圈是没有问题的,NPN的话,有没有接上拉电阻。
回复

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
18
金钱
18
注册时间
2019-4-26
在线时间
3 小时
发表于 2019-5-19 17:28:04 | 显示全部楼层
请问,将AB相的输入配置成上拉输入后,NPN的编码器可以不用外接上拉电阻吗?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-25 20:51

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表