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

【经验分享】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米。
  • 线数:旋转一周信号线输出脉冲数,也成为分辨率
    & I' z6 U3 f, {# U! {
  • 8 h  j4 V' L7 M# D8 d1 e8 H9 b) g

    $ @! C5 B$ [9 l% J
1248164-20180510192503629-93708335.png

* I" ^0 k/ ?) a; ]3 n' o7 x2 e1 c4 {
1248164-20180510195028614-102457577.png
2、型号
此篇文章使用的旋转编码器型号有两种。
传感器(增量式旋转编码器)

& l  B: S. O, Y: _
型号
供电电压
输出方式
分辨率
品牌/厂家
输出电平
S20-1000型拉线位移传感器
5-24V
NPN集电极开路
400
Omron/欧姆龙
$ q; C- M  f7 U$ n" n3 ]
DT100E40R1024-HI
增量型大孔径编码器
5-30V
HTL(推挽式)
1024
冬莅自动化技术(上海)有限公司
www.shdongli.cn
高:VCC*70%
低:1V

$ A+ X. h4 F5 `; t6 @4 _* X
6 R! Q4 k; `, M1 _! L0 Z
二、硬件设计
  由于增量型编码器输出脉冲,可以直接接入PLC单片机,利用PLC高速计数器进行测量。将编码器接入STM32单片机需要一个定时器资源,并将定时器配置为编码器模式,稍后会简要介绍配置方法。根据传感器的输出方式,进而来判断是否需要进行信号预处理。对于集电极开路输出的传感器接入必须使用上拉电阻。注意STM32大多数引脚的输入电压都在3.3V左右,尽量不要过压。如果电压较大,最好加隔离电路,比如6N136光耦,类似下图
3 H4 o1 z, w9 _8 m) f
1248164-20180510200405732-66175176.png

1 E* }$ X$ P) U/ G7 g) j6 p* x! h4 E
  我在这里并没有使用隔离电路,而是对传感器统一使用了5V供电,并在信号接入端人为加了3.3V上拉(上拉电阻1K),这种接口电路在我自己设计的采集板上统一留出了8个。编码器应用中并未使用Z相,仅使用了A、B两相进行编码器计数。按照线序说明接入STM32的定时器引脚,PA6、PA7对应TIM3的CH1、CH2通道,PB6、PB7对应TIM4的CH1、CH2通道。对于第二种传感器的推挽输出方式而言,实验证明这种接入电路也是可行的。(具体电路没有进行分析,只是图个方便。但是5*70%=3.5V应该是勉强可以直接接入stm32引脚的)
- o! O1 W+ w. q4 T, q4 g  `+ b
1248164-20180510202458411-1027273337.png

3 t# |$ o* @4 x5 Z三、软件设计1、STM32定时器编码器模式简介
  参考官方文档,摘录几个要点:
  • 编码器接口模式基本上相当于使用了一个带有方向选择的外部时钟。
  • 两个输入TI1和TI2被用来最为增量编码器的接口,TI1FP1和TI2FP2是TI1和TI2在通过滤波器和极性控制后的信号,计数器由每次在TI1FP1和TI2FP2的有效跳变驱动,根据跳变顺序,产生计数脉冲和方向信号,计数器向上或向下计数,同时硬件对TIMx_CR1寄存器的DIR位进行相应设计
  • IC1、TI1概念理解:TI1是定时器输入通道,IC1是输入捕获通道(两者可以交错)。配置CCMR1寄存器的CC1S位可以指定IC1的映射方式。可配置滤波器和预分频器。
    8 x2 X' U1 F$ O6 g: `4 s; U
    $ S; x$ A- E) ~9 k! @0 @

0 ]7 H7 [+ T' k1 ?: q. Y
1248164-20180510211213519-2095565993.png

- D% O% V2 k" n8 [" e/ R
1248164-20180510210619647-836174267.png

, \) X* v0 Q* J2 U
  • 计数方向与编码器信号的关系
    + \8 f# ?5 U6 M% T7 c

      S' K: t4 [$ `/ p9 r# A

5 \4 h1 C- A0 G5 {; v# g$ E; Q
" D* _3 N  Y; Q4 G6 z/ S/ U+ |$ B
1248164-20180510211455433-476773874.png
8 m4 x) E  I* K& x) o8 w1 T6 q3 Y. J0 s' B2 j

. Y/ M7 O3 A0 T+ ~' l" V
2、软件实现
  1. 1 /********************************************  i+ j8 [% ^- k; z, X. e" ]' Z
  2.   2 3 o0 d/ B( x  ?$ S. V
  3.   3 TIM3、TIM4定时器编码器模式配置5 C) f: z/ A- x. z; M/ J4 a4 e* \" V
  4.   4 4 O: Z! l" H4 R; `, {% i$ C! x
  5.   5 *********************************************/
    8 p% E4 V% N5 O/ X
  6.   6
    ' L1 ~1 a4 \& s( Y- W& Q
  7.   7 #include "sys.h"
    0 w7 u+ d" G- N  z, g1 y6 R- Y
  8.   8 #include "encoder.h"9 ~. B, F& F0 @7 D3 u* _
  9.   9 & c3 H- O* x8 V' n8 ~$ b1 j
  10. 10 int TIM3ITCount=0;//中断溢出次数" `! D2 x" A% |8 r) [+ n" }4 G
  11. 11 int TIM4ITCount=0;//中断溢出次数
    & k- W) [* u1 g6 f2 M
  12. 12 ) H2 _( g. a5 }8 E
  13. 13 void TIM3_IRQHandler(void)
    0 c. u5 N& k8 m4 [8 S. J
  14. 14 {   
    - H) y$ W$ P5 \! d% x
  15. 15     if(TIM3->SR&0x0001)//溢出中断: h' h* ?, A1 H( B% b
  16. 16     {
    . V' c/ j9 H- C9 u. k; g/ [
  17. 17         ; X7 T4 A  Y- q) ]
  18. 18     }   
    - e' {9 y- p! O9 T4 f: `
  19. 19     TIM3->SR&=~(1<<0);//清除标志位   
    6 Z$ w/ B/ T  m
  20. 20 }3 q/ N: _* u' h( R: E" l; S: g
  21. 21
    + x1 k! z! q0 p" r$ x) u) u6 c
  22. 22 void TIM4_IRQHandler(void)
    & m1 E4 Z! F9 g/ e
  23. 23 {   * M3 Y! ]. Y( t' A0 j/ N3 g1 M; z
  24. 24     if(TIM4->SR&0x0001)//溢出中断
    0 |0 s3 E' A$ n9 M9 ]4 T2 F8 @! J
  25. 25     {% E9 Y5 m& L) s
  26. 26     }   
    & N  r( y7 d$ ]% r
  27. 27     TIM4->SR&=~(1<<0);//清除标志位   
    # F9 i7 S. \& r6 r* }) @0 [
  28. 28 }( t  i+ L- w4 Q7 g+ T
  29. 29 6 B) h# ^/ B8 g9 A/ s2 z
  30. 30 void TIM3_Encoder_Init()3 @! Q8 L$ c( `6 i. K
  31. 31 {+ ~9 w! X) ^  F" v" c
  32. 32     TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    ) @7 F0 L; a) \2 S- f3 W0 r
  33. 33     TIM_ICInitTypeDef TIM_ICInitStructure;# z# G5 \. n. ~. `9 V3 q9 d9 r
  34. 34     GPIO_InitTypeDef GPIO_InitStructure;
    4 S  t. d  q* L4 l) U# D! _# Y
  35. 35     NVIC_InitTypeDef NVIC_InitStructure;
    ; _$ o/ ?% @" p* }5 Z- L
  36. 36     % j; {; W+ j% F" ]9 {, `+ Q
  37. 37     //时钟使能( ~1 T5 B) X5 d6 o5 u) R
  38. 38     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);  //使能 TIM3 时钟
    2 B# a9 ]) |/ @
  39. 39     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能 GPIOA 时钟
    , j9 w- Z7 K  N2 y" O. _2 f/ z
  40. 40     
    ! U! Q8 ?/ B8 n; ]0 Q( @
  41. 41     //GPIO配置
    * i5 w5 F+ b0 x- B4 _
  42. 42     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; //PA6、PA7设置  D% D# Q3 c3 U8 f/ G6 @
  43. 43     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
    ' o2 b0 }3 k( l3 Q, a  }- T1 _
  44. 44     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;3 P& m, [* i; v5 Z# l% N: L$ G) I) l7 D
  45. 45     GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 GPIOA
    % X! U4 d5 Q( s) b; U: q
  46. 46     4 ?- V$ h! d$ c# p
  47. 47     //定时器初始化
    4 Z& ?; E& s% \
  48. 48     TIM_DeInit(TIM3);
    & A9 J/ l. h( }5 Y0 i
  49. 49     TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);, c# q3 a' Y. l# f, G4 T
  50. 50     TIM_TimeBaseStructure.TIM_Period =65535;//预装载值
    5 b' M) ], e! k7 C3 h3 u/ [
  51. 51     TIM_TimeBaseStructure.TIM_Prescaler = 0;//预分频
    : ~- i  ^8 X6 G; }6 ~
  52. 52     TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1 ;
      }) X3 }' b2 S; f: ~) J
  53. 53     TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 2 W9 y$ |, O) ?9 w! `% S
  54. 54     TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); 6 |0 u! ^' X, T: M+ [; f) l
  55. 55     : \5 w( a5 s# j0 f
  56. 56     //编码器模式配置
    7 \$ l1 t, C0 V6 ~
  57. 57     TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Falling, TIM_ICPolarity_Falling);5 q- P' ?& u/ L$ ~
  58. 58     TIM_ICStructInit(&TIM_ICInitStructure);" h  u0 m3 U8 S) ^% J
  59. 59     TIM_ICInitStructure.TIM_ICFilter = 6;//ICx_FILTER;
    / p7 H1 ^: O: w) D2 Q+ V
  60. 60     TIM_ICInit(TIM3, &TIM_ICInitStructure);
    * y2 x: r, v6 m
  61. 61     0 o! d4 ?& l5 f$ \$ D+ ^
  62. 62     //初始化 NVIC 中断优先级分组9 X# c& G9 R! T& o7 d) a
  63. 63     NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3 中断% S  E* Q$ a9 y& q7 P
  64. 64     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占优先级 2 级; Y( G1 b2 U$ g4 {/ n' j* f
  65. 65     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级 0 级) l& x& @: W& V$ Q# K/ o% B$ O+ [
  66. 66     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道被使能
    $ C/ E6 b' B. {9 h
  67. 67     NVIC_Init(&NVIC_InitStructure); //初始化 NVIC6 a) E0 B& V# ^6 c" @
  68. 68     " w7 S+ g. Z2 h0 q* r# l
  69. 69     //中断配置
    ! @/ I$ V; p/ A( R: \9 I. b
  70. 70     TIM_ClearFlag(TIM3, TIM_FLAG_Update);1 Q: s1 j7 l/ w) m& B/ F6 X
  71. 71     TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
    9 z& k  g# T0 J* T% G
  72. 72     $ }9 x# R3 n" Z6 o
  73. 73     //Reset counter
    6 _: B( @: ]2 ?& w
  74. 74     TIM3->CNT = 0;) v: }1 W( a- z( d" n5 c9 {
  75. 75     //使能定时器8 c' I/ L6 z& I; c6 d" L+ D  H  i) }
  76. 76     TIM_Cmd(TIM3, ENABLE);   : Y. q* I  @# S5 \
  77. 77 }
    4 D! J0 _/ e) z
  78. 78 6 ~0 E* y& j+ N5 I& Y6 f
  79. 79 void TIM4_Encoder_Init()
    4 p% Z& ^' x! \* c% q) o
  80. 80 {
    8 q* \% g/ g8 E4 A; |. m& f, f
  81. 81     TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    : B1 u+ V- l7 u7 U0 v4 I% `
  82. 82     TIM_ICInitTypeDef TIM_ICInitStructure;  w( M  X( `1 @+ Z2 f
  83. 83     GPIO_InitTypeDef GPIO_InitStructure;
    - e- k* _" j+ u6 u! a
  84. 84     NVIC_InitTypeDef NVIC_InitStructure;
    7 v& n1 _: E) e5 ^
  85. 85     / V! z& r3 o4 o) v
  86. 86     //时钟使能
    2 L; C3 I! U  _3 P% p9 m( g
  87. 87     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);  //使能 TIM4 时钟
    1 Y( c! r4 p' @: ^5 S9 A* F5 o
  88. 88     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能 GPIOB 时钟/ I2 N- k$ e! W2 Z$ w6 E2 z
  89. 89     
    2 p  y% t0 m3 U  \
  90. 90     //GPIO配置& [5 F2 G) L0 W' n8 m3 b
  91. 91     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; //PB6、PB7设置. r# t% F- m$ F( ]* \; ~/ @( v
  92. 92     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
    9 {2 W- ]8 G& j! e8 `, U
  93. 93     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;' N2 S" I: G4 n  X' ~5 H# n9 R
  94. 94     GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化 GPIOA" Z( F/ t; h. B4 N  U/ U
  95. 95     
    - [% L! t! k3 r' ]
  96. 96     //定时器初始化  k' G7 ?; Q: q% ?6 `
  97. 97     TIM_DeInit(TIM4);/ c% a. z. N7 w& p( z7 v( J; i
  98. 98     TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
    7 [8 N7 Q8 c& Q/ T
  99. 99     TIM_TimeBaseStructure.TIM_Period =65535;//预装载值
    3 H# o' P' d' Z% O& X+ P+ m# F5 z
  100. 100     TIM_TimeBaseStructure.TIM_Prescaler = 0;//预分频
    8 i2 e( Q# ?; Z" m( }
  101. 101     TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1 ;
    % }6 u# Z5 V  I5 C9 j" M
  102. 102     TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    + A5 _7 u+ v" N( x. R) ^0 l; x
  103. 103     TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
    - U5 h+ o5 V2 K3 F. I2 N2 m7 B
  104. 104     
    7 I8 E. D# G) Q3 i7 p0 ~
  105. 105     //编码器模式配置4 s, i" R( @) G3 u
  106. 106     TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Falling, TIM_ICPolarity_Falling);" y& z. p. L5 p
  107. 107     TIM_ICStructInit(&TIM_ICInitStructure);+ W' C8 B( k8 W  q
  108. 108     TIM_ICInitStructure.TIM_ICFilter = 6;//ICx_FILTER;( h. {% u0 F7 U2 @) [( C
  109. 109     TIM_ICInit(TIM4, &TIM_ICInitStructure);- y) E1 a! K7 b, p+ O
  110. 110     2 Q) Q9 o* Y+ j& o6 p; h
  111. 111     //初始化 NVIC 中断优先级分组
    " t. ?9 U8 |! ]5 D1 B2 R2 F- ]
  112. 112     NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; //TIM4 中断
    - ^+ h. b1 g! o5 `0 s6 R) K" d, K
  113. 113     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占优先级 2 级- l$ a0 M4 e' Q" B2 n& s
  114. 114     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //从优先级 0 级
    2 L- a' }* L1 h" U  S2 ^6 S
  115. 115     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道被使能
    . g4 l3 g+ i, C3 F' ?: b& s) D
  116. 116     NVIC_Init(&NVIC_InitStructure); //初始化 NVIC
    & i4 E7 {& l( A4 G8 o% G. h+ d
  117. 117     0 q) Z& |- ^! W6 W
  118. 118     //中断配置
    6 T% A9 s' a. T. q
  119. 119     TIM_ClearFlag(TIM4, TIM_FLAG_Update);, ^* r3 m5 K" }, t
  120. 120     TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);( v" Z/ e# S3 h3 q2 H
  121. 121     
    ' j4 D. w2 J& Z  N( ^: y/ U, p
  122. 122     //Reset counter
    % T) k) e" A7 o( b- Y
  123. 123     TIM4->CNT = 0;& ~0 d/ p$ T9 y
  124. 124     //使能定时器
    ! }, K5 ]* ^0 Q: T* X3 V3 z
  125. 125     TIM_Cmd(TIM4, ENABLE);   9 J( a' z' y: e1 S& h! m: c/ X
  126. 126 }
    " P- y9 K. ?6 P4 y7 P& M2 t
  127. 7 j+ K( ^5 q8 G0 I6 S! l
  128. encoder.c
复制代码
7 c; S8 H1 A, g

  H9 I" L! }4 j$ Q! |: Z/ [; b3、注意事项
  • 更新中断可以不开。但是由于没有使用Z相信号,所以这里保留更新中断,实际上目前中断里什么也没做
  • 由于是双相下降沿计数,所以转一次会输出两个脉冲,转一周脉冲数为分辨率*2,注意处理。当然你也可以配置为其它计数倍数
  • 这里预装载65535,可改为线数*2,即可对转一周的位置进行严格编码
  • TIMx->CNT的值即为编码器的位置(并不一定是输出脉冲值,跟旋转方向和预装载值有关,增量编码器的零点是初始化自己定义的)
  • GPIO配置为浮空输入模式。对于集电极开路输出的编码器,如果你没有外部上拉,则使用内部上拉,配置为上拉输入模式即可。3 w, K" J% V' E" M/ d- r
    7 t3 E! ?* W6 ?/ h( T5 F; O, H. D. @

( }2 r7 w6 Z! a2 s! p9 [$ ]1 N% Z, {5 ~2 j+ b% C* s8 a! D$ h: S
收藏 评论0 发布时间:2022-1-16 17:55

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版