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

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

[复制链接]
STMCU小助手 发布时间:2022-3-24 22:23
增量式编码器
) [1 B$ ?0 x# W8 C! m增量式编码器也成为正交编码器,是通过两个信号线的脉冲输出来进行数据处理,一个输出脉冲信号就对应于一个增量位移,编码器每转动固定的位移,就会产生一个脉冲信号  通过读取单位时间脉冲信号的数量,便可以达到测速的效果(v=s/t),通过对脉冲信号的累加,和编码器的码盘的周长(转一圈对应距离)  便可以达到计算行走距离的效果(s=n*d)% r4 ]8 s, v9 O5 K7 ^

6 h+ [' X0 o. u8 d' M" E编码器信号:
0 e0 _$ Z$ q, O9 X  ~: T4 iA 脉冲输出 9 f9 j; h% {7 m0 s) x+ `
B 脉冲输出
% ~3 s( U, C0 I; f* w8 U7 x+ b1 q- WZ 零点信号 当编码器旋转到零点时,Z信号会发出一个脉冲表示现在是零位置 表示编码器转了1圈,可用来记录编码器转了多少圈,从而知道运行距离3 {( p8 ~5 k' m' r" d4 ^; _9 a
VCC 电源线: m2 W% n3 V4 I+ h; N/ [  R
GND 地线
6 p$ a, C+ V  I8 v; Q% G3 j6 a3 C( [- N
U32%[W4JP3M_TZ(]ZN5~$QR.png
/ @4 T3 l0 b! R- k6 _
4 ~) q8 Z* c: D: N" i$ Z编码器线数:
8 K3 W: R: `( t编码器的线数 ,是说编码器转一圈输出多少个脉冲,,,如果一个编码器是500线,说明这个编码器转一圈对应的信号线会输出500个脉冲, A B两相转一圈发出的脉冲数一样的,不过存在90°相位差  ?$ B  S  U" _. P
/ \* Y' n* l  S
线数越高代表编码器能够反应的位置精度越高: ], J9 ^2 x/ ?  M! b

6 o+ i1 q! z+ X编码器原理:. @$ B) G/ m! Y
增量式编码器有两个脉冲输出,A相和B相,并且两个相位永远存在90°相位差。 如果两个信号相位差为90度,则这两个信号称为正交。由于两个信号相差90度,因此可以根据两个信号哪个先哪个后来判断方向、并且可以根据AB相脉冲信号数量测得速度,位移等,
6 G% J" d! e; x* B
4 t2 J  D+ Z1 `$ A编码器正反转:
, h  [& @# T4 U( K
2 ^# [2 t- D/ v3 ]" W 6JBEEVI3VCW3T9D43Y05L~5.png ) t+ b' S4 q& M8 W  q1 W5 D4 a
$ C7 u+ `( _9 w( i
正转的时候信号线A先输出信号,信号线B后输出  A相超前B相90度  证明是正转$ Z; C; Q& l2 M- y
! i, p$ o$ |8 Q
反转的时候信号线B先输出信号,信号线A后输出 B相超前A相90度 证明是反转
1 Y9 m4 U/ _: ]8 B* H5 V0 F+ E  [
STM32定时器编码器模式
6 k9 d+ {; i2 M3 [' P8 P  r: B* C0 v) b2 H  w  h
}4K`S)Y1VCY`85E5CRKTOG2.png , D& g5 D, n; h1 v, x) @8 b
+ v( d( I  U" O6 X- Q
STM32的编码器模式共有三种:; D* |" n* n$ A/ B, @9 t0 l7 R8 R
$ c; q) b- B% A6 _3 g
仅在TL1计数(A相)" S$ j( |$ o5 F; N2 @) k8 X
仅在TL2计数(B相)5 [5 E- ?- X* m% g5 a) _; C$ D
在TL1和TL2都计数(A相和B相都计数)
3 N% _9 t+ |0 S; ~$ \5 X: c  z+ W0 I6 v! b7 b/ V2 s

% u9 L1 j8 I% N- x9 j仅在TL1计数(A相)  R+ d* _7 @  l! u! X( q
, g$ t7 f$ b) f4 ^2 s  ]$ G9 V% Q
O9U9)SIQ`X][~@V(B4ZOD.png ) u# Z: x, s7 M, V7 z6 V7 j

. \) K& e9 y; n) {4 q6 t2 QTI2(B相)为高电平时:
- _/ ]: F& n; }; Z, ?3 Q3 @' m* R9 f, }0 a
1时刻: TI1(A相)下降沿,  则向上计数(正转)。
- t! ]- w, v$ ^7 }4 F" ~5 f
+ Q1 b1 x9 i* D' Z# h6 S3 x2时刻:TI1(A相)上升沿,   则向下计数(反转)
) g5 T: I6 @' q3 w) r; {3 V+ f1 U: j5 y3 Y- g
TI2(B相)为低电平时:
4 L2 E- k9 e, J$ [- ~. y- x* @8 i6 q6 P" H2 i$ A& Y
3时刻: TI1(A相)上升沿,  则向上计数(正转)。0 S/ `5 P& ?* Z

0 S+ ?) X9 V" L# O. C/ i/ c3 N4时刻:TI1(A相)下降沿,   则向下计数(反转)- T8 o- L, m. q! ]4 D

. }! y4 t3 p0 d6 L3 X仅在TL2计数(B相)6 G1 F: j) I- P- U# ~( h7 \1 D* Q
- t* r( D/ B! y. K- R
DKAKQFPH}S32)SJJIF0G)YQ.png , X$ l) N2 x1 T! g; w( a

/ ^. Q) E# M4 N# C* }2 zTI1(A相)为高电平时:0 @6 h! O! h2 c! f& I) Z: B

' S- {& h2 t! V/ {9 \1时刻: TI2(B相)上升沿,  则向上计数(正转)。
2 C* K8 t2 `. v$ y$ m2 k* ^/ B) z& u+ m3 f
2时刻:TI2(B相)下降沿,   则向下计数(反转)# Y9 q8 V5 b: E  E
: G+ D/ P. g; m& b1 ^
TI2(B相)为低电平时:- a8 R6 h) u3 A/ z; w& w
& b! X, `, S+ i1 S/ x
3时刻: TI2(B相)下降沿,  则向上计数(正转)。# s2 A" X, W! T
, Z0 H" k: a4 w4 b4 y4 l3 F: W1 Q
4时刻:TI2(B相)上升沿,   则向下计数(反转)
$ [; g# p1 e+ a" @: s. J: q# }, ^+ h* H" @# x8 e
在TL1和TL2都计数(A相和B相都计数)
% k! B4 O, A- m: K. \
0 Y0 B: d( [1 |; P! n$ ] NLQ1WVAR6}}L]2F@6TZM(0L.png
- `; v/ E. O3 w( D& }" m, ^5 @2 ~0 D: m2 O
一个脉冲信号周期完成4次跳变。精度提高/ l1 C- u+ k6 G, m+ i9 k0 \

2 w) X9 k6 `: w0 n% w0 z2 S1时刻:TI2为低电平,TI1上升沿跳变,计数器向上计数;1 s6 h/ }# r- Y  V; x6 \8 o, [- C( R
( {% z( a: l! i# I  X! _4 |6 x
2时刻:TI1为高电平,TI2上升沿跳变,计数器仍然向上计数;* m8 t, K7 j- q+ w

, C! n3 B- v# [5 l( m) w' O/ f3时刻:TI2为高电平,TI1下降沿跳变,计数器仍然向上计数;
1 W6 d; f. B) n- |, Q
+ |, m$ X3 N$ ^( u0 A/ o4 E4时刻:TI1为低电平,TI2下降沿跳变,计数器仍然向上计数。
% Z! R4 N1 N5 ]1 |' b
# R2 b& o0 W) ?, u. e1 a- U) }) B$ e5 }: @4 v' w: [# `
毛刺:只有一个相位脉冲   过滤掉 编码器转动过程中可能产生的毛刺过滤掉
- L4 y" U/ S8 W$ B* ^
( N+ n4 M% i2 ]计数器向下计数原理相同   看图即可很好理解。
/ C4 n3 D( H3 H, Z3 s( h
  m7 v( x0 y  H1 y( W( G2 k" k# k3 K计数器向下计数:# E* E' p. ~  q5 S! W, C' H% D, L

8 s; F( F# J2 P9 i: M  lA下降沿,B低电平' P5 e# P4 E" v9 Z
B下降沿,A高电平1 ]4 |3 T: G5 j4 Y9 F, \% S# M
B上升沿,A低电平
2 {( p+ p; O. I& MA上升沿,B高电平) u" M7 S  A) A6 X& ~

% f4 |5 f% E+ b% s注意事项:4 e% C6 X/ s, o4 }. P0 K. Q
1.需要增加测量的精度时,可以采用4倍频方式,即分别在A、B相波形的上升沿和下降沿计数,分辨率可以提高4倍,
2 A: j4 V# ^. z$ M% h0 T2.如果只是测速,不要求方向,那么只需要用单片机随意选择一个信号线就行了,,然后定时器边沿触发,检测脉冲计数即可
9 f# T0 }1 B6 {+ m3.一般是定时器的通道1和2才能作为编码器输入口,对应编码器输出的两相。; d. J, N" q' ^8 u) Y3 n; G
4.GPIO配置为配置为上拉输入模式
/ l! d* }6 L! {$ o$ N& D5.一个定时器做一种工作,如果你配置了编码器模式,那么剩下的通道就不能配置其他模式% B- e; E, A6 y. c# J* {  c, _
6.两相计数模式下,  读出来数需要/4          一个脉冲信号对应四次计数   
: ^: F. t" p, E/ l
# ]& O) L& M% ^" N编码器配置标准外设库
% T& T& \% G" l  }) ?TIM_EncoderInterfaceConfig,它就是编码器接口的配置函数。简单的只需要配置该函数,使能TIM,即可实现采集编码器上面的信息
/ _' h& q0 ]7 d9 ?5 _- m  [) j1 v5 i/ t/ E0 {
  1. void TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx, uint16_t TIM_EncoderMode,+ B( C7 v4 G. Q2 Q1 T+ p
  2.                                 uint16_t TIM_IC1Polarity, uint16_t TIM_IC2Polarity)
复制代码
( W; R$ ?: I- Q
TIMx参数就是使用哪个定时器作为编码器接口的捕捉定时器。3 m& R: j  o7 H
% c* T' W8 L: t
TIM_EncoderMode参数是模式,是单相计数(仅在TL1计数或仅在TL2计数)还是两相计数(在TL1和TL2都计数)。
1 B( `+ @# o' P6 r& z+ G% T
0 i% o: _6 Z2 F0 @, F7 K1 B& f8 ITIM_IC1Polarity和TIM_IC2Polarity参数就是通道1、2的捕捉极性。! D" s2 p: ?' W" C, v, T7 {

# o1 n7 _8 u1 x7 T. ~- r  r$ g$ L, w2 w, X( [7 ~1 [
相关寄存器配置5 }$ ^2 E, y1 ?9 D5 e( p. ~; d8 [
● CC1S=’01’ (TIMx_CCMR1寄存器,IC1FP1映射到TI1)% j5 p' ]5 G# G+ W; Q% U

* G& J( T" R: I● CC2S=’01’ (TIMx_CCMR2寄存器,IC2FP2映射到TI2)
9 T! F, n  }3 ^5 z; R, G- r  ]5 v. D! y; V1 |
● CC1P=’0’ (TIMx_CCER寄存器,IC1FP1不反相,IC1FP1=TI1)+ N2 G8 F& \; l( x
3 P- }" t9 U% u1 X
● CC2P=’0’ (TIMx_CCER寄存器,IC2FP2不反相,IC2FP2=TI2); d6 ~1 `- F+ @/ C

$ L9 ^& W7 N3 H2 ~- Z● SMS=’011’ (TIMx_SMCR寄存器,所有的输入均在上升沿和下降沿有效).
0 d7 K, N8 [2 Q' r" n( d8 l0 ?$ r: s0 P' K6 f3 t
● CEN=’1’ (TIMx_CR1寄存器,计数器使能)
! z5 D6 d( n9 U0 ^1 S& T
) G7 \" Y% r' J7 j+ F' f如果计数器只在TI2的边沿计数,则置TIMx_SMCR寄存器中的SMS=001;如果只在TI1边沿计数,则置SMS=010;如果计数器同时在TI1和TI2边沿计数,则置SMS=011
! \. _! B- d3 e+ i) P
9 L/ r/ T6 \0 s编码器模式功能:
2 C' \/ @7 i# @( L5 F6 q' k; ?9 j/ Z  stm32f407中定时器1、2、3、4、5、8提供编码器接口模式
( b) o) I: h: ^% w3 n2 J* G  可以对输入信号TI1,TI2进行滤波处理,数字滤波器由事件器组成,每N个事件才视为一个有效边沿,可以在TIMx_CCMR1、TIMx_CCMR2中的IC1F位域设置      也就是可以设置每产生几次脉冲才视为1次有效  4 U! I' J! Q5 e. K0 m% @4 a
各个值的计算:
# o& }6 |1 F0 j) F! |4 u转速计算方法:用捕获值(一秒内输出的脉冲数)/编码器线数(转速一圈输出脉冲数)/电机减数比(内部电机转动圈数与电机输出轴转动圈数比,即减速齿轮比    没有则不用除)5 f8 z% n& H( e- {. T3 L% |% b! i! Z

: T1 U. a. B7 _& c, I. a; F运动距离计算:输出的总脉冲数 / 编码器线数*编码器齿轮周长
: c/ {: F9 W* Z5 M" }& y% h* E1 `1 n& G  h& B3 n
所转角度计算:    输出的总脉冲数 / 编码器线数 *360     或    溢出中断次数*360+当前计数值
: n$ O" U/ G( Q% i0 ?
- X2 t( e; e( ]3 @转动方向: 方向在定时器CR1的DIR位里   dir=(TIMX->CR1 & 0x0010)>>4;     //取方向标志位
. e. b0 A! C9 @% T! Y  ?8 M* H8 kif(dir > 0)  //向下计数     else     //向上计数
1 Z. }, X! p4 k6 l$ k9 J! R, f) u0 D
那么我们直接看代码:
6 x0 ?5 c$ A% x7 s/ e1 D, e
- y! B# a7 N. g1 v. e0 f5 w定时器初始化设置
8 a) w* c2 V. O" _
4 W& H! G( M' Q- d
  1. void TIM3_Int_Init() # `. v. v; ^3 c; b# ~
  2. {1 H7 R# [& V9 l/ n8 E4 Q/ v4 z
  3.     TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;7 M" k! W. `6 d, c$ W1 R
  4.     TIM_ICInitTypeDef TIM_ICInitStructure;
    2 ]- T# g; X) e6 L' ^; s% T- A
  5.     NVIC_InitTypeDef NVIC_InitStructure;
    % H2 w& p9 F& V4 J$ u. Z; ]; }
  6. 3 b4 T3 w# U' N/ b, j1 e- U
  7.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
    7 ^8 M; V6 h* Z9 h

  8. & L% f' W! S1 T- X
  9. //定时器设置-------------------------------------------------------------    ) F# u0 j! B# R8 }
  10.   TIM_TimeBaseInitStructure.TIM_Period = 359*4;  //重装载值   , }7 S. H2 }! ~# v
  11.     TIM_TimeBaseInitStructure.TIM_Prescaler=0x0;  //预分频4 w2 C9 D5 J# |: w# I! p
  12.     TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数2 Y4 Z; K/ v$ p8 E
  13.     TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; //时钟分割) y- ^# C+ ?+ \" C1 E. L: {

  14. 7 I' F, x" Y! t9 d* @+ n
  15.     TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);//初始化TIM39 f6 F6 l. p- }! B( S9 H

  16. & c9 s* Z: o) b4 `2 w* d4 v2 r3 n1 Q
  17. //编码器模式设置--------------------------------------------------------------                 7 {$ X: N0 A8 |2 ?

  18. 3 Z- W( M6 D$ \
  19.     TIM_EncoderInterfaceConfig(TIM3,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//计数模式3
    6 f) D7 x+ \6 n; m
  20. % P* P- z2 W9 C
  21.     TIM_ICStructInit(&TIM_ICInitStructure); //将结构体中的内容缺省输入
    - L( n2 i) f# o& I
  22.     TIM_ICInitStructure.TIM_ICFilter = 0;//滤波器值
    * u) Z8 @% v2 b' G$ h: W) [; j, I
  23.     TIM_ICInit(TIM3, &TIM_ICInitStructure);  //将TIM_ICInitStructure中的指定参数初始化TIM3
    + O5 _0 m/ M- Q) M4 I$ ~
  24. //溢出中断设置--------------------------------------------------------------  
    / g& `: S  @6 b& g  a/ x7 w! k
  25.     TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //允许TIM3溢出中断2 G: ^& A' M  r  a& S

  26. ; K  e3 y$ u& `  w
  27.     NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; 6 }" [6 \6 [2 y" d' K
  28.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01;
    7 m% D  }* L6 n4 W& B$ m
  29.     NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x01;
    - G5 N; |( u/ Z" F% c' Y. D
  30.     NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;- `: t& w3 ^3 N% V# F" N
  31.     NVIC_Init(&NVIC_InitStructure);# H" d2 }6 b3 \8 u9 B. q* u
  32. ' z  i% e8 M6 c, z( O

  33. 3 b% m% L, O  a
  34.   TIM_SetCounter(TIM3,0); //TIM3->CNT=08 K3 e7 G/ w7 J+ @3 i0 h5 M& F
  35.   TIM_Cmd(TIM3, ENABLE);
    & V$ R; j( q  n' F& f8 G7 x3 M# S
  36. }
复制代码
$ s' w& R+ [1 J

; q+ E' ~% T% H  s重装载值:    (编码器线数-1 ) *4                因为我们是两相计数,一个脉冲信号4次计数,所以乘4,保证转完1整圈才触发中断
* w0 d& h$ h. H/ n( V  T
3 [# m4 [, \& W9 i) X6 p! V2 L中断设置:
4 G" `( W$ B0 d3 G6 P$ w4 ?) H7 m3 B2 P$ |' D
  1. int circle_count=0;//圈数
    1 B0 k1 {8 I% m! a
  2. void TIM3_IRQHandler(void)
    4 w, O/ v' \6 s! ^1 i+ E( `
  3. {: i/ r1 L* r; ^& W# o$ C
  4.     if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET). v- v- f& C. l1 v* h( K
  5.     {      
    ' N6 ]4 x( s  @- Q
  6.         if((TIM3->CR1>>4 & 0x01)==0) //DIR==05 x- S8 ^4 b7 C6 A
  7.             circle_count++;
    8 @/ v! u( E; V( f* w+ O
  8.         else if((TIM3->CR1>>4 & 0x01)==1)//DIR==1
    ) B, M( K0 ~$ d5 |4 j
  9.             circle_count--;! |0 G$ |5 }2 E* Y/ E3 W8 W
  10.     }
    ; ]' o( H- l& A; t" f* a9 _
  11.     TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
    9 x6 m  N+ ]* A. t# N/ a
  12. }
复制代码

4 C8 C4 l  O+ }各个值的计算:* D  A( L# s! P; E8 e" ~! O( V5 x

0 Q. Q5 W5 e; M/ E( c6 l1 P脉冲数:  TIM_GetCounter(TIM3)/4  0 S6 U/ ]2 l! X# a! y
% a& x7 t. ~& O
  1. int angle=0;  //转过总角度
      \% _+ d4 c" d) s; q: U
  2. int Realyangle = 0;  //当前实际角度 0~3607 n& B1 A+ b" ^  o
  3. int Distiance=0;   //运行距离
    - X) W$ ]" m" E- R5 T, H) u
  4. extern int circle_count;   //转过圈数
    / a' o7 E% O" q" q- z) T! g" ?
  5. % C$ B7 u. M5 d# [8 `- N% w1 p; a
  6. 3 P9 Q; k4 Z# H1 M0 j/ a. N+ B
  7. Realyangle = TIM_GetCounter(TIM3)/4/360 ;      //先除4   最后除编码器线数8 ~2 N  g5 ]( F* d6 w

  8. 9 v2 h; t1 N3 e$ `" t  X
  9. angle=Realyangle +circle_count*360;//当前角度. L7 S: ]. U* o
  10. ' J- {8 z; Y+ s4 k9 V0 Y
  11. / Q( Q7 g$ ?# j+ z
  12. Distiance = angle/360*编码器齿轮周长  + circle_count*编码器齿轮周长
复制代码
: ]+ z8 U5 N- C! }& l

. z3 ]( @/ J3 ^* F9 @$ y! I, c, _" R& H# ?, y
) K  K! p' w; X/ C. N7 w" P  `
收藏 2 评论0 发布时间:2022-3-24 22:23

举报

0个回答

所属标签

相似技术帖

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