你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32-增量式旋转编码器测量

[复制链接]
STMCU小助手 发布时间:2022-1-16 17:55
一、增量式旋转编码器1、简介
  • 编码器(encoder)是将信号(如比特流)或数据进行编制、转换为可用以通讯、传输和存储的信号形式的设备。编码器把角位移或直线位移转换成电信号,前者称为码盘,后者称为码尺。
  • 按照读出方式编码器可以分为接触式和非接触式两种;
  • 按照工作原理编码器可分为增量式和绝对式两类。增量式编码器是将位移转换成周期性的电信号,再把这个电信号转变成计数脉冲,用脉冲的个数表示位移的大小。绝对式编码器的每一个位置对应一个确定的数字码,因此它的示值只与测量的起始和终止位置有关,而与测量的中间过程无关。 
  • 旋转编码器是集光机电技术于一体的速度位移传感器。它将被测的角位移直接转换成数字信号(高速脉冲信号)。
  • 我们通常用的是增量型编码器,可将旋转编码器的输出脉冲信号直接输入给PLC,利用PLC的高速计数器对其脉冲信号进行计数,以获得测量结果。不同型号的旋转编码器,其输出脉冲的相数也不同,有的旋转编码器输出A、B、Z三相脉冲,有的只有A、B相两相,最简单的只有A相。A、B为相差90度的脉冲,Z相信号在编码器旋转一圈只有一个脉冲,通常用来做零点的依据,连接时要注意PLC输入的响应时间。旋转编码器还有一条屏蔽线,使用时要将屏蔽线接地,提高抗干扰性。
  • 信号输出有正弦波(电流或电压),方波(TTL、HTL),集电极开路(PNP、NPN),推拉式多种形式,其中TTL为长线差分驱动(对称A,A-;B,B-;Z,Z-),HTL也称推拉式、推挽式输出,编码器的信号接收设备接口应与编码器对应。信号连接—编码器的脉冲信号一般连接计数器、PLC、计算机,PLC和计算机连接的模块有低速模块与高速模块之分,开关频率有低有高。如单相联接,用于单方向计数,单方向测速。A.B两相联接,用于正反向计数、判断正反向和测速。A、B、Z三相联接,用于带参考位修正的位置测量。A、A-,B、B-,Z、Z-连接,由于带有对称负信号的连接,在后续的差分输入电路中,将共模噪声抑制,只取有用的差模信号,因此其抗干扰能力强,可传输较远的距离。对于TTL的带有对称负信号输出的编码器,信号传输距离可达150米。
  • 线数:旋转一周信号线输出脉冲数,也成为分辨率
    . Z0 X( I4 G: q; w& B/ q
  • 5 f( R! }4 D6 R2 r

    / S4 }5 D! N! |4 \; b4 G
1248164-20180510192503629-93708335.png
% I# p( Y/ v0 K! |9 a
1248164-20180510195028614-102457577.png
2、型号
此篇文章使用的旋转编码器型号有两种。
传感器(增量式旋转编码器)

9 S( x& x0 q" Q1 q' R2 P8 L! U" S) h
型号
供电电压
输出方式
分辨率
品牌/厂家
输出电平
S20-1000型拉线位移传感器
5-24V
NPN集电极开路
400
Omron/欧姆龙
- r( z6 @- `7 }3 ]
DT100E40R1024-HI
增量型大孔径编码器
5-30V
HTL(推挽式)
1024
冬莅自动化技术(上海)有限公司
www.shdongli.cn
高:VCC*70%
低:1V

! i7 L& A7 V- v# l4 t- p& P

% v/ X9 [2 P& j二、硬件设计
  由于增量型编码器输出脉冲,可以直接接入PLC单片机,利用PLC高速计数器进行测量。将编码器接入STM32单片机需要一个定时器资源,并将定时器配置为编码器模式,稍后会简要介绍配置方法。根据传感器的输出方式,进而来判断是否需要进行信号预处理。对于集电极开路输出的传感器接入必须使用上拉电阻。注意STM32大多数引脚的输入电压都在3.3V左右,尽量不要过压。如果电压较大,最好加隔离电路,比如6N136光耦,类似下图

% c% A" R' U( i4 n7 q$ v
1248164-20180510200405732-66175176.png
. @$ B8 s7 A2 F. X* i; C
  我在这里并没有使用隔离电路,而是对传感器统一使用了5V供电,并在信号接入端人为加了3.3V上拉(上拉电阻1K),这种接口电路在我自己设计的采集板上统一留出了8个。编码器应用中并未使用Z相,仅使用了A、B两相进行编码器计数。按照线序说明接入STM32的定时器引脚,PA6、PA7对应TIM3的CH1、CH2通道,PB6、PB7对应TIM4的CH1、CH2通道。对于第二种传感器的推挽输出方式而言,实验证明这种接入电路也是可行的。(具体电路没有进行分析,只是图个方便。但是5*70%=3.5V应该是勉强可以直接接入stm32引脚的)

% a7 g$ u/ ?% U/ A
1248164-20180510202458411-1027273337.png
; m, _9 T/ V( g, S8 r3 }4 W
三、软件设计1、STM32定时器编码器模式简介
  参考官方文档,摘录几个要点:
  • 编码器接口模式基本上相当于使用了一个带有方向选择的外部时钟。
  • 两个输入TI1和TI2被用来最为增量编码器的接口,TI1FP1和TI2FP2是TI1和TI2在通过滤波器和极性控制后的信号,计数器由每次在TI1FP1和TI2FP2的有效跳变驱动,根据跳变顺序,产生计数脉冲和方向信号,计数器向上或向下计数,同时硬件对TIMx_CR1寄存器的DIR位进行相应设计
  • IC1、TI1概念理解:TI1是定时器输入通道,IC1是输入捕获通道(两者可以交错)。配置CCMR1寄存器的CC1S位可以指定IC1的映射方式。可配置滤波器和预分频器。
    6 ^- P2 T+ a* f2 O1 a

    9 [" B. R, U' C- U4 \: C
: N2 M- J0 G# v* o# @6 {' `
1248164-20180510211213519-2095565993.png

- h5 j& k6 K3 d  l
1248164-20180510210619647-836174267.png

1 Z% `5 r' F6 Z1 W
  • 计数方向与编码器信号的关系6 g" n* c; o4 z$ f% ]  r

    + a- P2 A) F5 P6 ^5 Y
6 n' g; w3 e7 v( ~
& ]1 {* h( h. F/ G3 Y: a, r' S* p
1248164-20180510211455433-476773874.png
  I# t) C! T6 Z, O! ]" f& M  b  K: ]& v2 U! ?, U$ l) _

/ @( c5 C! Q0 Z  A( P/ U# x; ]
2、软件实现
  1. 1 /********************************************  e3 x5 }* P! p- F
  2.   2
    ' c) v6 U! u  l" V$ o  |
  3.   3 TIM3、TIM4定时器编码器模式配置
    2 s  i/ w8 J" ]0 C+ b  P$ e3 C
  4.   4 * ^2 h. L/ [' U; K, s! |' N. m
  5.   5 *********************************************/1 Z% N% J  @- B8 k$ c5 ]* O- ?
  6.   6
    $ w- ~5 ^  L+ a8 b
  7.   7 #include "sys.h"4 B: u3 k0 g% f: m6 i4 i
  8.   8 #include "encoder.h"
    & g) E% v: f) D, g7 S8 j. x
  9.   9 % x: Z! R5 g9 |/ ?8 a4 C
  10. 10 int TIM3ITCount=0;//中断溢出次数
    3 _6 Q+ P7 J2 ]3 d1 {" r
  11. 11 int TIM4ITCount=0;//中断溢出次数
    & k! F" h  j- N& M. r: k
  12. 12
    ! |* [7 I: M, J! z! q8 p
  13. 13 void TIM3_IRQHandler(void)
    # l2 H( U8 h& t' p
  14. 14 {   " n5 g( i  K. U4 a/ f) `. N7 ]# \! J
  15. 15     if(TIM3->SR&0x0001)//溢出中断
    * y) X3 `  l8 Q7 r% C2 F% D
  16. 16     {. H. [8 e9 I$ q, I7 P& X
  17. 17         
    * G% U5 m& T- l7 l$ s
  18. 18     }   * Z: A/ x9 |* Z% L
  19. 19     TIM3->SR&=~(1<<0);//清除标志位   
    " [: _5 l7 N, F$ K0 H" }
  20. 20 }/ m6 Q- \  p8 a1 l5 |1 T6 u
  21. 21 % E( Q* q3 {' Q7 r' u
  22. 22 void TIM4_IRQHandler(void)  t1 M# s" e6 T( ^* M) c) S# i; f
  23. 23 {   
    ( C! r2 o) ~7 ^
  24. 24     if(TIM4->SR&0x0001)//溢出中断' T7 d, S. T- I/ C" i3 B
  25. 25     {# b: L. @5 S" U9 d3 H
  26. 26     }   5 I5 o1 `0 k' H/ m' h
  27. 27     TIM4->SR&=~(1<<0);//清除标志位    9 s: h4 T5 T: z, s' q3 [# G; d) T/ W
  28. 28 }
    6 g3 c, V: u0 L  W% _  b6 @* o
  29. 29
    . r+ h: w# q# u9 b+ g+ b
  30. 30 void TIM3_Encoder_Init()
    3 O* h# z/ a! s6 e/ n
  31. 31 {) B8 [  E( l7 }2 \  A2 a
  32. 32     TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    / x* [) V( a2 [4 U+ a/ i( H" @" j: P3 w  y
  33. 33     TIM_ICInitTypeDef TIM_ICInitStructure;
    . b. k# @& @0 {2 [. M) ]
  34. 34     GPIO_InitTypeDef GPIO_InitStructure;4 S0 i) f* Z- P! U+ f8 ]1 \: r
  35. 35     NVIC_InitTypeDef NVIC_InitStructure;
    $ D+ s9 x" n+ U, W- `
  36. 36     9 ?# K8 b: G& F
  37. 37     //时钟使能
    + R/ \  M4 Y, u: G4 w
  38. 38     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);  //使能 TIM3 时钟
    ; c. M3 n% i/ {  M  ~8 d3 d" A
  39. 39     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能 GPIOA 时钟2 ~( g" \0 I7 j6 }2 q
  40. 40     / F8 U5 w; c' P) ~
  41. 41     //GPIO配置$ G; \6 `7 v* |+ S, Q
  42. 42     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; //PA6、PA7设置7 j- o0 I3 u: ^2 g9 j! l" E
  43. 43     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入2 g( C4 r: q, I0 K9 |* \
  44. 44     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    2 B' g4 L  m6 l
  45. 45     GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 GPIOA! b2 p8 E/ [# k# H7 @
  46. 46     
    7 }! b  L% t0 f0 R% z; f6 e
  47. 47     //定时器初始化. _9 W2 Z2 B8 i. A
  48. 48     TIM_DeInit(TIM3);. }! r5 c! L; V# ~' d5 t
  49. 49     TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);2 Q# t& i/ v8 y: R
  50. 50     TIM_TimeBaseStructure.TIM_Period =65535;//预装载值2 F3 O0 e8 f0 z
  51. 51     TIM_TimeBaseStructure.TIM_Prescaler = 0;//预分频
    3 _) F  W# O2 s  `3 j+ I0 Z) u8 E* U
  52. 52     TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1 ;
    2 L9 {7 n4 P( S  N0 F4 j! G. E
  53. 53     TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    2 C  D7 }9 z" c+ J
  54. 54     TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); : \7 M" L' E" Y! t
  55. 55     
    - S) d- r7 `% [. b
  56. 56     //编码器模式配置
    1 x0 L$ B; O9 u
  57. 57     TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Falling, TIM_ICPolarity_Falling);
    4 `2 q( J3 b' D# H+ }% @+ h
  58. 58     TIM_ICStructInit(&TIM_ICInitStructure);
    % S8 d; i: g( }% D
  59. 59     TIM_ICInitStructure.TIM_ICFilter = 6;//ICx_FILTER;
    $ c5 ]' D, u" }/ s" }7 ~  N
  60. 60     TIM_ICInit(TIM3, &TIM_ICInitStructure);
    3 d# S, C# F6 z' b- q8 o5 W: v
  61. 61     . j+ ?& ~' K$ ~! z3 ~, \( D8 i9 h; G4 E
  62. 62     //初始化 NVIC 中断优先级分组
    & N& l0 q# j/ z0 ^; V
  63. 63     NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3 中断: p+ K2 H; ]/ t) S; ^
  64. 64     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占优先级 2 级( G- V$ R) x- N, B" K) C( a3 {
  65. 65     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级 0 级
    8 V1 Y. \2 N* \
  66. 66     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道被使能
    . k5 z& e8 s" z# V: {) a- w
  67. 67     NVIC_Init(&NVIC_InitStructure); //初始化 NVIC
    % S3 x1 f/ J$ w) e6 R6 a
  68. 68     5 ~* r' j7 x4 t" ?" ]1 H+ q( @
  69. 69     //中断配置
    / b$ h* x0 f( m5 Y
  70. 70     TIM_ClearFlag(TIM3, TIM_FLAG_Update);
    6 V  E! n1 l) m6 T! l( t& t
  71. 71     TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
    3 n9 `8 F7 N% D2 q5 ^
  72. 72     * d$ I7 _5 I9 f
  73. 73     //Reset counter
    & ?3 j! w% ]5 p8 _% B
  74. 74     TIM3->CNT = 0;
    % ^# N, f. P0 U5 ^
  75. 75     //使能定时器
    ; L9 s+ \" [! G, c$ Y9 z( K5 O
  76. 76     TIM_Cmd(TIM3, ENABLE);   
    $ u' M0 U8 U# l4 @. p$ R/ F8 t
  77. 77 }
    . c; B' t1 ]8 ?  n1 t
  78. 78
      q3 N0 S+ T1 a, E2 ]+ Q# n
  79. 79 void TIM4_Encoder_Init()# i7 p( c1 i6 {4 n( m0 l+ X' j
  80. 80 {
    2 a% n, ], w: M) h5 R
  81. 81     TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    , v8 R4 G' C7 {0 a+ w) ]! A9 S4 S
  82. 82     TIM_ICInitTypeDef TIM_ICInitStructure;
    # T5 A" l& w* a3 j8 [4 `# W5 m  x
  83. 83     GPIO_InitTypeDef GPIO_InitStructure;
    2 g7 D) P, f$ R: C
  84. 84     NVIC_InitTypeDef NVIC_InitStructure;
    2 m, @; N% ^# w
  85. 85     * D3 c4 w1 l  w2 I
  86. 86     //时钟使能
    ! U+ x& p1 B# @+ E# ^* v& {
  87. 87     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);  //使能 TIM4 时钟
    ; t5 T& ?$ c7 X4 f0 S
  88. 88     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能 GPIOB 时钟
    ; H5 {* J5 t& D+ f; \% Y
  89. 89     ; ?) u1 t% {& u6 B) i
  90. 90     //GPIO配置0 m6 d6 `  D. D7 S. X
  91. 91     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; //PB6、PB7设置; E9 K- Z. c8 V  A, i
  92. 92     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
    . A  E) m6 k2 x' b* K; ]
  93. 93     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    7 R+ H" g  t  H* W; T% ]
  94. 94     GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化 GPIOA
      D) N* t0 ?" d2 I
  95. 95     
    3 ?' S7 B8 k+ J# y
  96. 96     //定时器初始化
    ( ~5 k5 y7 E/ j9 y
  97. 97     TIM_DeInit(TIM4);6 |- U* L3 ]- C( N  q
  98. 98     TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
    + c! O% o2 U4 |4 N
  99. 99     TIM_TimeBaseStructure.TIM_Period =65535;//预装载值
    0 A, a, B- j) ~2 }6 F
  100. 100     TIM_TimeBaseStructure.TIM_Prescaler = 0;//预分频
    - c" f5 j9 ^- ^2 Q
  101. 101     TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1 ;3 \' V3 H. A4 U9 f- z
  102. 102     TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 1 M6 D1 b3 z3 O* R- M9 v% U
  103. 103     TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); 4 \- o8 d0 e4 `1 n& L: d" H  ?
  104. 104     ; y' ]+ x/ f" a' [
  105. 105     //编码器模式配置& x  W6 g1 u; z; v$ N5 v6 b
  106. 106     TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Falling, TIM_ICPolarity_Falling);
    4 Q# |8 V4 R7 k: u* K2 p( H6 J
  107. 107     TIM_ICStructInit(&TIM_ICInitStructure);2 x+ x" t3 D0 U+ q3 t
  108. 108     TIM_ICInitStructure.TIM_ICFilter = 6;//ICx_FILTER;, M0 Y* P' M" S7 C2 g& F' ]; N) d1 F
  109. 109     TIM_ICInit(TIM4, &TIM_ICInitStructure);/ ^; q9 j: M+ Y+ l+ @" R( @
  110. 110     ) }. F) _, ]" ]7 ]
  111. 111     //初始化 NVIC 中断优先级分组- m! N- I# A; c: r9 Y6 K
  112. 112     NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; //TIM4 中断
    * M2 M% B; e+ L' W
  113. 113     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占优先级 2 级
      k+ I- P& f4 b' F
  114. 114     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //从优先级 0 级/ u, [/ Z6 j+ ^9 O9 v& {
  115. 115     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道被使能
    # k3 J2 o5 D4 E& R' u3 ]
  116. 116     NVIC_Init(&NVIC_InitStructure); //初始化 NVIC
    & V  k6 s; R. G/ Z! L2 S1 F
  117. 117     
    ; M4 D7 r, X/ A% a- o/ i$ y
  118. 118     //中断配置
    . K7 P# ^% ^( ^  i
  119. 119     TIM_ClearFlag(TIM4, TIM_FLAG_Update);, ^8 F- }+ G1 A% r5 g# V
  120. 120     TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
    : l" b2 |2 k+ x5 n# v, C  D
  121. 121     0 g. m; O; g3 m# r+ e$ w
  122. 122     //Reset counter
    ; e0 ]3 K: [- K  C( I. L2 D
  123. 123     TIM4->CNT = 0;  M: Z6 C, t' J( C
  124. 124     //使能定时器
    , L/ u1 |6 R# ~8 |/ B
  125. 125     TIM_Cmd(TIM4, ENABLE);   0 @/ O2 `1 `9 y3 {0 ^2 T; i
  126. 126 }
    4 g6 S6 p$ X  M: [  d% i& M

  127. 2 t9 f- ?- I0 |, h
  128. encoder.c
复制代码

; M$ z6 g+ b: g
/ V6 Y* B$ ], C  ~9 K* W/ h
3、注意事项
  • 更新中断可以不开。但是由于没有使用Z相信号,所以这里保留更新中断,实际上目前中断里什么也没做
  • 由于是双相下降沿计数,所以转一次会输出两个脉冲,转一周脉冲数为分辨率*2,注意处理。当然你也可以配置为其它计数倍数
  • 这里预装载65535,可改为线数*2,即可对转一周的位置进行严格编码
  • TIMx->CNT的值即为编码器的位置(并不一定是输出脉冲值,跟旋转方向和预装载值有关,增量编码器的零点是初始化自己定义的)
  • GPIO配置为浮空输入模式。对于集电极开路输出的编码器,如果你没有外部上拉,则使用内部上拉,配置为上拉输入模式即可。
    / g( O$ o/ L/ L/ L
    & z' d$ F+ k" P' ^

4 q& a* N5 V6 L
! Q( e8 n1 }+ S
赞 收藏 评论0 发布时间:2022-1-16 17:55

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版