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

【经验分享】定时器---正交解码编码器模式详解

[复制链接]
STMCU小助手 发布时间:2022-3-24 22:23
增量式编码器. d% _6 I1 ^0 g2 S" o$ e
增量式编码器也成为正交编码器,是通过两个信号线的脉冲输出来进行数据处理,一个输出脉冲信号就对应于一个增量位移,编码器每转动固定的位移,就会产生一个脉冲信号  通过读取单位时间脉冲信号的数量,便可以达到测速的效果(v=s/t),通过对脉冲信号的累加,和编码器的码盘的周长(转一圈对应距离)  便可以达到计算行走距离的效果(s=n*d)9 E# K; _5 x8 \
4 A$ x6 L6 u( @6 M
编码器信号:
( y/ p9 \- N) T0 n& PA 脉冲输出
0 J3 K+ S$ V, m# d. i# h# i1 oB 脉冲输出 0 N9 _+ d( }9 U' m' f  T
Z 零点信号 当编码器旋转到零点时,Z信号会发出一个脉冲表示现在是零位置 表示编码器转了1圈,可用来记录编码器转了多少圈,从而知道运行距离
1 Z/ D% W- y) |# I5 JVCC 电源线- c$ ?" N- `1 a( q+ w1 R
GND 地线7 Q( F$ b; _! L3 F
) Q6 v5 u6 U6 E- N/ y' H1 x+ R% ]
U32%[W4JP3M_TZ(]ZN5~$QR.png
4 a& @" e1 a" L2 f6 B4 ~7 W8 u4 V1 v4 L/ y( D8 c
编码器线数:
& j* T- b8 |+ Z* n$ F' ~编码器的线数 ,是说编码器转一圈输出多少个脉冲,,,如果一个编码器是500线,说明这个编码器转一圈对应的信号线会输出500个脉冲, A B两相转一圈发出的脉冲数一样的,不过存在90°相位差
& d4 m8 J5 A0 H# e( n6 V
) W: W- G5 M3 t1 Q+ Z$ v线数越高代表编码器能够反应的位置精度越高  Z# u3 E, c/ ^& s" P# ?
0 [$ R$ k8 r4 w& C
编码器原理:' P( S) T* n- z3 p$ k* r, R
增量式编码器有两个脉冲输出,A相和B相,并且两个相位永远存在90°相位差。 如果两个信号相位差为90度,则这两个信号称为正交。由于两个信号相差90度,因此可以根据两个信号哪个先哪个后来判断方向、并且可以根据AB相脉冲信号数量测得速度,位移等,
+ l: `% t+ }5 @, b+ m6 J4 C, z1 q  [( p/ M; }8 A! {! @$ T/ E# B
编码器正反转:. y: q9 x) A) ~' B" W7 }3 \4 P& F

  L2 V3 y8 n0 p  V2 K( s 6JBEEVI3VCW3T9D43Y05L~5.png 5 e- I  {" h3 @) u/ A
9 W9 z  s/ C$ ~
正转的时候信号线A先输出信号,信号线B后输出  A相超前B相90度  证明是正转
. t, T: }) f4 x' I0 C. R8 e  K2 j4 C
反转的时候信号线B先输出信号,信号线A后输出 B相超前A相90度 证明是反转
" K& E. P" U* E- @# V) u8 u  d) [7 d
5 T4 S( M0 [3 {: J2 G7 {# VSTM32定时器编码器模式
, W; V& s$ g) N4 B3 n3 ^% ]5 h- _$ r! X* }
}4K`S)Y1VCY`85E5CRKTOG2.png
. d: Z; y4 l; h0 a" r/ f/ E9 w, Q3 z) c+ U& ~
STM32的编码器模式共有三种:* ^7 r- {4 O3 n1 a5 Z8 u
% ]" ~* C1 _+ {: v8 C
仅在TL1计数(A相)
$ o+ A2 x# L& t$ G% G0 U 仅在TL2计数(B相)8 @: m" }9 v( b$ a8 @3 L
在TL1和TL2都计数(A相和B相都计数)- w1 k( K  |1 }+ H8 f

. g' W' v$ V( J2 y: S
% P$ x/ Z1 S" q/ F仅在TL1计数(A相)8 b3 m# n/ O( s, R/ L3 O5 \% a' i5 k
% {# Z, O- U! Y: R- p
O9U9)SIQ`X][~@V(B4ZOD.png ) g+ N! Y! h$ {  ?
, R9 [4 H8 s( C4 E, w* M. j
TI2(B相)为高电平时:
" D/ P# g7 Q; I& ~3 E8 j
, o8 L0 s8 z' F) S+ G: q$ Z4 \: l) u9 F9 @1时刻: TI1(A相)下降沿,  则向上计数(正转)。
( d6 q. Y6 F- o1 q: P9 x0 l! @, U, H7 S3 B- u4 X' c9 q/ C
2时刻:TI1(A相)上升沿,   则向下计数(反转)! l! a/ W. A; d" {1 x) Q9 K  T
$ l: b( [2 a4 A% z
TI2(B相)为低电平时:
5 [# ^& S4 C* S
1 r' Y% ~+ r+ r' @& T8 e6 T# N: v3时刻: TI1(A相)上升沿,  则向上计数(正转)。
4 N8 k' U* \" F- e7 _( t# h) a/ v0 f: v: [
4时刻:TI1(A相)下降沿,   则向下计数(反转)1 f' O0 |6 m9 A$ u

1 h2 _: D% {+ `3 d: w仅在TL2计数(B相): J( e0 w/ W! I; q: D

3 c* q2 u, p9 v0 b& L DKAKQFPH}S32)SJJIF0G)YQ.png ( @/ j8 I/ H$ g3 R9 [- }
8 [) U; V2 l) ^0 j+ u$ G9 ]
TI1(A相)为高电平时:2 W, ?0 L) @5 D; j$ H
, E! F: a  E9 n* H  r
1时刻: TI2(B相)上升沿,  则向上计数(正转)。9 q4 N; J% q" G1 J! O  _
' P" y9 B# w( u
2时刻:TI2(B相)下降沿,   则向下计数(反转)* F1 q- P1 q, R( r1 z% X/ F4 I

0 g2 P; F" P7 G, E4 GTI2(B相)为低电平时:
5 D2 X6 c0 @+ B/ y7 ^& B. }* {6 f% k9 s, n: T8 x5 U
3时刻: TI2(B相)下降沿,  则向上计数(正转)。. ?4 C+ F8 p# r  |* H1 I4 J
7 Q+ ?" @9 H, i7 [6 R2 g6 f
4时刻:TI2(B相)上升沿,   则向下计数(反转)3 s7 e5 h1 R6 f# T: }3 |
; e; u8 k  O9 L) f$ S
在TL1和TL2都计数(A相和B相都计数)
4 P! |: {. t! N* f' R0 I4 u! M% p% Y2 h: f
NLQ1WVAR6}}L]2F@6TZM(0L.png & @  t$ X8 S' p! j% _) P
; V7 D- f) s- H
一个脉冲信号周期完成4次跳变。精度提高: G# r; G1 C7 q8 ?' \, d7 k

# _4 R! n( g% h# ^* g- S( ?- e2 t1时刻:TI2为低电平,TI1上升沿跳变,计数器向上计数;5 ^# j& R) T* `; ]7 w
! E( F; \% z- M
2时刻:TI1为高电平,TI2上升沿跳变,计数器仍然向上计数;7 Z( O5 w+ b8 j, R' O& t

) p4 d6 I/ \+ G: s# J2 E3时刻:TI2为高电平,TI1下降沿跳变,计数器仍然向上计数;
& ?. ^. r0 Z% {% V& n( ?, q3 j" d5 \% v% y( p+ ]
4时刻:TI1为低电平,TI2下降沿跳变,计数器仍然向上计数。4 k& h7 y  \# |$ R
9 Q+ r) A+ p& _' L- \
/ J% X5 Z) h" _5 f+ K- R4 ^
毛刺:只有一个相位脉冲   过滤掉 编码器转动过程中可能产生的毛刺过滤掉2 h3 ]; A; |' ]9 X7 W
! J) K3 E; o4 F, R' x! y- q
计数器向下计数原理相同   看图即可很好理解。
# V; \) \  ~# [  G' X$ n
* W/ r, ~  e" u: E- I' l计数器向下计数:1 e: K- C! C( j4 t- U9 n
+ i9 d: U$ W7 h) v' F+ ^) e
A下降沿,B低电平
/ p: \: r1 y' B  e% _2 AB下降沿,A高电平* p% J( o4 L, V) y/ E2 X! V) M5 s& D! w4 C
B上升沿,A低电平; s! \+ S) F% `  ]2 P5 J
A上升沿,B高电平8 r& j, x0 ]2 Y

* d! Z4 q. W7 i* ]; B" S) U注意事项:
( ^* L9 x# Q0 U1.需要增加测量的精度时,可以采用4倍频方式,即分别在A、B相波形的上升沿和下降沿计数,分辨率可以提高4倍,: e( d4 s) P8 A
2.如果只是测速,不要求方向,那么只需要用单片机随意选择一个信号线就行了,,然后定时器边沿触发,检测脉冲计数即可" x1 w1 o* r% t! }
3.一般是定时器的通道1和2才能作为编码器输入口,对应编码器输出的两相。
1 D/ P1 f3 x( _8 X6 `4.GPIO配置为配置为上拉输入模式
. k4 C' D" Z$ W6 e! k7 R! z5.一个定时器做一种工作,如果你配置了编码器模式,那么剩下的通道就不能配置其他模式
6 w0 A$ {$ A% T/ W6.两相计数模式下,  读出来数需要/4          一个脉冲信号对应四次计数   
" E) @& C1 E5 G% U
; |0 s: h# Z& s" k- b编码器配置标准外设库8 \: {( I! O& g! T
TIM_EncoderInterfaceConfig,它就是编码器接口的配置函数。简单的只需要配置该函数,使能TIM,即可实现采集编码器上面的信息
4 H7 O, d5 X! F& D% F
3 i/ y% _2 U* M( q2 m
  1. void TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx, uint16_t TIM_EncoderMode,4 }  C( O5 I8 o
  2.                                 uint16_t TIM_IC1Polarity, uint16_t TIM_IC2Polarity)
复制代码
' q( g$ C3 i3 a4 v& N3 k
TIMx参数就是使用哪个定时器作为编码器接口的捕捉定时器。0 d' |, h, h  s6 ?5 o" w, z& L
! z' p* y+ k' }. Y0 Z8 T9 f
TIM_EncoderMode参数是模式,是单相计数(仅在TL1计数或仅在TL2计数)还是两相计数(在TL1和TL2都计数)。
8 G% H3 S% h# o# C" q0 d& n. i1 c0 s; ^* [6 u& s9 `+ r, X
TIM_IC1Polarity和TIM_IC2Polarity参数就是通道1、2的捕捉极性。1 N* R' |3 @. n  H
+ P+ A- o$ M- J/ Q

) A. l  D# d" z相关寄存器配置
, y5 [" e$ r: M3 U, q. Q, b" U● CC1S=’01’ (TIMx_CCMR1寄存器,IC1FP1映射到TI1)7 }0 N3 Y$ r4 C4 U" S$ N- q. h% u
, w/ n7 J; N( B1 b8 e$ r6 v
● CC2S=’01’ (TIMx_CCMR2寄存器,IC2FP2映射到TI2)
6 A; H' }. M) C+ m4 G/ d, ~' @- Y* }  D4 c4 p
● CC1P=’0’ (TIMx_CCER寄存器,IC1FP1不反相,IC1FP1=TI1). U5 ?. r+ U0 j% ]+ m3 D/ M! w
! E/ b  s' ?: L- O6 _
● CC2P=’0’ (TIMx_CCER寄存器,IC2FP2不反相,IC2FP2=TI2): c8 j$ X- L$ |7 D+ I
( n& D! D7 c8 [1 V
● SMS=’011’ (TIMx_SMCR寄存器,所有的输入均在上升沿和下降沿有效)., K( N! e9 E, a8 n
! ]8 [9 o8 l) f' h+ l, i3 W
● CEN=’1’ (TIMx_CR1寄存器,计数器使能) ( a: j/ Q/ u8 z

  `0 C! Z( q( E8 r如果计数器只在TI2的边沿计数,则置TIMx_SMCR寄存器中的SMS=001;如果只在TI1边沿计数,则置SMS=010;如果计数器同时在TI1和TI2边沿计数,则置SMS=011 $ P* n: S" {; M

7 k: n" I6 t7 Z0 H编码器模式功能:
+ X& F- t4 l$ m, a5 [5 e( ^4 ~# [  stm32f407中定时器1、2、3、4、5、8提供编码器接口模式
$ S, t, A0 G6 r7 X/ r5 {1 ?2 m  可以对输入信号TI1,TI2进行滤波处理,数字滤波器由事件器组成,每N个事件才视为一个有效边沿,可以在TIMx_CCMR1、TIMx_CCMR2中的IC1F位域设置      也就是可以设置每产生几次脉冲才视为1次有效  
+ {$ R8 D7 i3 F( l各个值的计算:
/ y+ Q/ g' h9 c' M4 y转速计算方法:用捕获值(一秒内输出的脉冲数)/编码器线数(转速一圈输出脉冲数)/电机减数比(内部电机转动圈数与电机输出轴转动圈数比,即减速齿轮比    没有则不用除): V, X3 b5 S8 O% [4 x

! z3 c' _4 [& D  h运动距离计算:输出的总脉冲数 / 编码器线数*编码器齿轮周长; A, e* J  t( x; b
3 u/ b: [8 K9 X/ K1 U# S
所转角度计算:    输出的总脉冲数 / 编码器线数 *360     或    溢出中断次数*360+当前计数值 ! N8 x6 w+ p( `! ^

' j  l& R2 A4 q" s! {转动方向: 方向在定时器CR1的DIR位里   dir=(TIMX->CR1 & 0x0010)>>4;     //取方向标志位0 |! |9 ]) D# Q0 A
if(dir > 0)  //向下计数     else     //向上计数
# u4 {: i% u) e: F0 _2 p& F$ h5 z; l9 E& o; v' ^9 f; s
那么我们直接看代码:: \9 K3 ~  U6 E

) L8 O8 t' L; `7 y9 P定时器初始化设置2 J* \% r4 X1 ?) a/ l* H$ z+ a% q

$ V5 r- ~; e1 R7 X
  1. void TIM3_Int_Init()
    ) O4 @+ a* v' l7 D
  2. {
    ; V- ^5 R7 P6 j+ p. p
  3.     TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;' z( p* u/ G/ [! X0 }
  4.     TIM_ICInitTypeDef TIM_ICInitStructure;8 v3 ?! Q- B7 \& k2 U" @
  5.     NVIC_InitTypeDef NVIC_InitStructure;
    * r  ?+ h# n7 ]4 E
  6. . S% b9 A/ [- ~. F( S
  7.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); 1 a: ?6 E+ \1 c# M- T

  8. 3 C. O$ P4 a$ _
  9. //定时器设置-------------------------------------------------------------    " D" J; p& b9 S; i, r
  10.   TIM_TimeBaseInitStructure.TIM_Period = 359*4;  //重装载值   
    3 |; m! l0 D* F
  11.     TIM_TimeBaseInitStructure.TIM_Prescaler=0x0;  //预分频8 n3 a/ z& `0 Z7 E
  12.     TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数
    6 o0 R5 L7 v, N! y9 F+ S6 y8 o3 F
  13.     TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; //时钟分割
    ' O: K) D: H" H9 M2 C- ~5 q

  14. ) [5 `. N* s1 n. m* n
  15.     TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);//初始化TIM3
    : I) ^1 }6 {: I
  16. % s0 c/ G8 P1 D2 E. R
  17. //编码器模式设置--------------------------------------------------------------                 * T: Q- q5 I8 r
  18. / D# C" ^' @) O  p8 _4 j& j! d1 c
  19.     TIM_EncoderInterfaceConfig(TIM3,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//计数模式3
    2 [1 [4 F0 i0 V. ^1 |5 O
  20. . P- Z0 A( g1 R( [$ j- Z
  21.     TIM_ICStructInit(&TIM_ICInitStructure); //将结构体中的内容缺省输入& i& k" ?; F$ r9 Z7 c6 @8 y
  22.     TIM_ICInitStructure.TIM_ICFilter = 0;//滤波器值
    , U% V: f$ N; F  m7 i
  23.     TIM_ICInit(TIM3, &TIM_ICInitStructure);  //将TIM_ICInitStructure中的指定参数初始化TIM3& I" X0 X$ ~) `7 h
  24. //溢出中断设置--------------------------------------------------------------  
    ( c  A9 K9 {+ [5 B  b) k) {0 g
  25.     TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //允许TIM3溢出中断0 R- ?/ o+ F. D% T7 o
  26. ! N% h/ ?) G+ A
  27.     NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn;
    . `% r6 Q/ p1 V6 j1 s  G0 c
  28.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01; / U% V3 ]' t  `$ q0 a$ p2 w) ^
  29.     NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x01;
    ! l6 o- }; d0 q, r0 T* ]
  30.     NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;: z2 h5 m5 T7 q# v  K* s  J
  31.     NVIC_Init(&NVIC_InitStructure);
    9 F, }; X. p2 ]& [( P% P2 w$ R

  32. 0 X( C" `: [& W
  33. + f& [! B; B% p/ t9 I
  34.   TIM_SetCounter(TIM3,0); //TIM3->CNT=06 ]# t1 o  }' {. R/ L
  35.   TIM_Cmd(TIM3, ENABLE); $ p) K' H6 }8 k$ W9 \
  36. }
复制代码
3 {$ g. r$ k. Q6 Q- U

# I) ?" r5 \# E7 I. a重装载值:    (编码器线数-1 ) *4                因为我们是两相计数,一个脉冲信号4次计数,所以乘4,保证转完1整圈才触发中断9 k0 x9 {& r, a) h
. o0 N; d2 }& w# ?
中断设置:4 P6 A3 f6 O- ?% m: L% Y. X) r
; g0 P0 _0 y& _1 M% j, B6 t$ ^
  1. int circle_count=0;//圈数. C9 ?, O1 e! _6 F# g; b% W  C- `
  2. void TIM3_IRQHandler(void)
    ' r  ^2 k# b/ p+ R& b
  3. {; G0 l/ R# r) J
  4.     if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)
      b1 f) l6 L8 v
  5.     {      
      ^) z4 Q5 J( ^1 e; _; Y* v, S- m
  6.         if((TIM3->CR1>>4 & 0x01)==0) //DIR==0
    : I# o0 n/ ~2 w8 x
  7.             circle_count++;2 _9 R1 S2 u- l; }
  8.         else if((TIM3->CR1>>4 & 0x01)==1)//DIR==1
    % S- H( D- V2 q6 ?* r
  9.             circle_count--;
    + R& N3 d. q0 u9 F; c6 R
  10.     }! Z9 ^" ?$ M: g+ r' l- n
  11.     TIM_ClearITPendingBit(TIM3,TIM_IT_Update); 7 F8 U* |% y/ ~3 z) v0 c" Z
  12. }
复制代码
7 Z2 c' z( v8 K# o- v4 {: ]! u' V
各个值的计算:# ^4 p) q% U% D3 J# d& |
4 z! p) ^$ @2 [3 m8 F5 L' h
脉冲数:  TIM_GetCounter(TIM3)/4  
" t2 N* @& E( D& ^3 C6 S4 D2 k) z2 C9 Z
  1. int angle=0;  //转过总角度# d; h$ O. V0 D: w  p
  2. int Realyangle = 0;  //当前实际角度 0~3604 X) O. }7 P4 U
  3. int Distiance=0;   //运行距离' A! w+ I6 j/ [$ u0 }! k
  4. extern int circle_count;   //转过圈数
    & b. x2 t/ ~* c, S- u& ^$ ~

  5. 9 o* j/ z1 W! Y( g9 C7 o

  6. 5 S# j$ `9 i; s6 Z1 q/ R9 L
  7. Realyangle = TIM_GetCounter(TIM3)/4/360 ;      //先除4   最后除编码器线数1 x3 \: ]% |2 L1 H2 f

  8. ( y* W* I% E  R5 Y- _5 v7 k# x
  9. angle=Realyangle +circle_count*360;//当前角度! W5 ?- t" F2 c6 k, O2 T
  10. ( v: |0 g" r" D+ o* J

  11. 0 {& Q- F( s4 k0 H
  12. Distiance = angle/360*编码器齿轮周长  + circle_count*编码器齿轮周长
复制代码
9 \) m5 t- X' z/ H4 [

% {/ b$ G8 \- P" ?/ b" w' t' k2 y" p8 o& ?. b1 e
' O. `, Q5 E0 w$ g7 U0 f
赞 收藏 2 评论0 发布时间:2022-3-24 22:23

举报

0个回答

所属标签

相似技术帖

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