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

基于stm32平台上的IC-MU磁绝对值编码器SPI通讯和码盘数据处理

[复制链接]
STMCU小助手 发布时间:2023-2-25 17:59
前言) t: J8 _& K6 n6 H
ic-mu基本情况介绍; Y" R. `8 T  K. g! Z: p- y( Q4 L
- a9 R- c5 P$ @% d) ~  |
IC_MU是一款离轴的1.28mm磁编码器,主要用于电机控制居多,当作磁编码器,优势是能使用多种通讯协议(SPI,BISS,SSI),但是目前中文网上使用资料较少,因此我自己写一篇关于IC_MU的SPI通讯读取方式的文章,读取芯片为stm32G4系列,然后代码在stm32G4和stm32F1系列基本通用。
0 F" n4 M2 s( W* T* |' E; w+ L芯片基本介绍如下. S) I1 p8 L. l
2 d. V; p1 i3 v1 B9 b; v: t5 Y
325acfd031684154a51541ebaf3bc1f5.png ) f8 M9 P: w$ V: }, I# `  K$ j
# R: x  ^* ^' [7 ?+ [- h6 a, O
提示:以下是本篇文章正文内容,下面案例可供参考
; F, Z! a8 l$ v; b" X
/ X6 m+ x2 J9 S  `4 {
一、硬件连接
. Q9 j5 l4 `- ?7 o0 _4 J
按最小系统连接。IC-mu需连接eeprom存储角度,供电为5V6 A5 T! ?$ v# e8 d

7 s& x9 F' a/ U二、STM32 cubmx配置模式
! G3 l: l! b$ y+ Z4 G! N' uSTM32G491配置cubemx
3 Z' O. q; `6 W
$ _. r( K2 B. \; O$ [9 D; [
b31de8a144684fd8815c3aea74271bba.png
: L% ?+ h) O& N: F! c8 o) `+ G: K/ G6 X) {5 D8 p

4 y- e2 }8 X9 m如图几个关键点% M  w6 _  H7 e" c2 y1 W) F; K: ?$ H
1数值格式:可以选8bit,但是我觉得16比特配置更方便,如果要配8bit只需将数据拆分即可' }. d: L, B4 i  c* E4 K: e9 g
2波特率 没有明确要求,12M以下都可以2 c0 f: Y9 c( H
3SPI模式,SPI一共4种模式
! l) _2 u/ ?" n3 @$ f. X1 r! M  b$ p( U" v4 M6 l" K; `
896f63f11e5f4a62b6e64e9527c395a0.png
6 N" w4 U, p. G8 R3 G, M
! z2 b6 N; W$ e% Q+ N
IC_MU只支持模式0和模式3,如上图所示采用模式3 CPOL选择High CPHA选择2Edge4 b- q: }3 O2 k. W7 R

' o) ]# z( a0 W' }( G/ @+ Y% g# x/ w
2e692f827e4048f38f0a6020450c06ec.png
9 \# F9 S) Q+ }. l- E% D$ d) H# y" x  h; h- i
. j5 `- Y/ \: `3 f0 I3 n' L' J1 `4 u
SPI通道要设置为高速, ~2 z9 j4 |! H+ y* c
除此之外还需要设置片选信号,默认为高电平* I0 p9 `7 Z( x$ h

! t$ i3 \1 l8 g0 w* U6 r- v
e8715427ead043cd984ccaaf608c5208.png
! D4 ]: K& a, h2 _1 B, j- n3 i+ f6 x. y" P5 l7 \
三、软件代码及思路# A! t- l) p$ u1 A) ~; L' y
首先需要对整体进行说明,需要将编码器激活,配置在SPI通讯模式2 F7 N* q+ I+ H' }- R
# ?( Q: B, B8 _7 H6 ^
1.寄存器指令介绍: j, O6 U& L! i  p. D1 U, [
0xB083 Activate,激活
+ {3 p/ |+ U' d- p. s0xA6FF Position Read 位置读取命令- l+ o9 R- `* f+ K% T/ T
0x8A Register Read (Continuous) 寄存器读取(连续)
& ]) y; |6 \0 G+ k7 u5 g0xCF Register Write(Continuous) 寄存器写入(连续)
: E( F: T( @" Q1 _2 M6 G0x9C Read Status 读取状态寄存器 指令
4 T5 |% {8 V4 l1 d5 W7 V4 }. e0x97 Register Read(Single) 寄存器读取(单次)
2 I9 m; U: B& ?" }3 ^( C- d* _0xD2 Register Write(Single) 寄存器写入(单次)  y" |/ I/ N3 v
6 n( L5 r3 _: r, n, ^
$ k2 e& o* @. L+ y% |
2.代码介绍) n5 t! R% R2 ]9 \" X
对片选进行宏定义,然后对SPI数据传输底层函数进行定义
$ z# U5 d" x" J9 M( |- F* u0 Q" \( Z. C# z1 o
1初始声明和定义
  1. #define    SPI_IC_MU_CS_LOW();       HAL_GPIO_WritePin(ABS_ENCODER_CSN_GPIO_Port, ABS_ENCODER_CSN_Pin, GPIO_PIN_RESET);
    ' V* m7 i. d$ Z; [! I5 Z; q
  2. #define          SPI_IC_MU_CS_HIGH() ;     HAL_GPIO_WritePin(ABS_ENCODER_CSN_GPIO_Port, ABS_ENCODER_CSN_Pin, GPIO_PIN_SET);
    9 Y2 N+ M" e& F' t8 `. V- L
  3. ; W% D  r# t1 l1 H3 ~% `+ C. }  S& d4 D
  4. uint16_t SPI_SendHalfWord(uint16_t HalfWord)- h% I, E- F, q: m/ c
  5. {6 o0 I, {  G, N) y$ H
  6.   
    4 b( Z4 Z' d) J  N
  7.   SPITimeout = SPIT_LONG_TIMEOUT;6 ?% ^/ u- w1 U1 q
  8.   /* Loop while DR register in not emplty */: w5 C+ q  X2 g0 J. i6 `  G
  9.   while (__HAL_SPI_GET_FLAG( &hspi1,  SPI_FLAG_TXE ) == RESET)5 K6 x% m  U# y, L- b0 Z( c' k$ H
  10.   {
    : d2 i) D3 u' d" \
  11.     if((SPITimeout--) == 0) return 0;
    ( x; f' m9 P$ E
  12.   }
    7 E5 n, p- B( y( w# U
  13.   /* Send Half Word through the SPIx peripheral */( r* a+ e: j4 T' ]: k3 J( M3 Z
  14.   WRITE_REG(hspi1.Instance->DR, HalfWord);( v  L: W$ r& v% j: J7 R
  15. 5 |) F- E. P% J0 X0 U1 S* d
  16.   SPITimeout = SPIT_LONG_TIMEOUT;
    ) s) I8 X; q% q/ H
  17.   /* Wait to receive a Half Word */3 V; p$ z; q8 Z8 E* T& I
  18.   while (__HAL_SPI_GET_FLAG( &hspi1, SPI_FLAG_RXNE ) == RESET)8 {- l% N; T5 l9 {5 N( r) z% N5 q
  19.    {$ T; H. r' h0 R: S. u
  20.     if((SPITimeout--) == 0) return 0;  @, L3 W% V0 r- V
  21.    }2 K$ f, y0 k5 i- q+ _* N
  22.   /* Return the Half Word read from the SPI bus */
    7 h: }! l) U; ~! p* j% \; _
  23.   return READ_REG(hspi1.Instance->DR);
    % E) n. B0 \/ d# s/ L' p
  24.   
      R, P  D. s/ i
  25. }
      F, b  v, {; ^
复制代码
" M; }9 X: p7 g$ {/ l
2激活寄存器. R8 o% u. j5 g3 z! ]4 x# e  s
激活后才能对寄存器有操作2 k3 O# i' X$ [. h, b1 N6 K, \% m' U
  1. void ACTIVATE_FUN(void)
    0 n1 U/ _7 B+ l4 \0 x
  2. {
    5 U. C/ n# \% J. W" b. y2 v
  3.   uint32_t ICMU_Temp = 0;% z+ \. G6 U6 K0 d7 o% P, g1 q# @
  4.   SPI_IC_MU_CS_LOW();2 |% P, z  Z- R0 u
  5.   ICMU_Temp= SPI_SendHalfWord(0xB083);
    9 h8 J2 N. E8 W4 Z% N
  6.   SPI_IC_MU_CS_HIGH();
    ; H  r. I" ]5 J1 ?9 n
  7.    Delay(100);7 ?( U; m8 l" D1 J
  8. }
    & O5 W8 m. f$ c" v
复制代码
5 Y4 r8 P/ @2 l* b
3编码器初始化函数: H. g! b  c& W+ W% X
初始化发送0xB083激活编码器,编码器配置为单圈14位,具体见数据手册
& o3 _: h# f' P& t3 S+ O% C初始化完成后可删除函数,状态会固化在配套eeprom种,不会丢失( V& }' v9 x/ i* x9 t& r
  1. void Init_ICMU(void), b+ F3 I9 [. D1 I+ N% e
  2. {
    ) L% @3 _8 b# U; X6 z; b2 J% r
  3.    ACTIVATE_FUN();5 T5 M3 J, r2 C$ M; f' J7 b+ A
  4.   uint32_t ICMU_Temp = 0, ICMU_Temp1=0;
    ! b# T# m5 l7 ~: k- e: _' Z, W
  5.   SPI_IC_MU_CS_LOW();+ T- e, R" g# d3 C! W
  6.   ICMU_Temp= SPI_SendHalfWord(0xCF00);3 X4 A2 m( u% X& S1 `& T
  7. ICMU_Temp1= SPI_SendHalfWord(0x8E20);
    6 F( }, Y, q# a8 M
  8.   SPI_IC_MU_CS_HIGH();
    3 a$ Z$ y( |, V# @, |
  9.    Delay(100);8 F8 |% D1 d) A) w
  10. }# y6 [, V0 V& [: y
复制代码
7 h( @1 X: k: T
4数据读取
6 k( ]1 K1 `0 ]1 C0 r. v  T! ?编码器数据读取,读取指令为0xA6
, K# |  J1 i+ l! t, ~/ R2 }
  1. uint32_t SPI_SDAD_transmission_Fun ( void)3 f% B+ s* l: B1 d
  2. {
    0 D8 w9 K) P8 L4 S0 g
  3.         ! y* G+ l0 F$ w7 J3 r, X7 ~
  4.         uint32_t Temp = 0 , Temp1 = 0, Temp2 = 0 , Temp3 = 0 ;/ I' a, @/ @* a0 R2 i0 m
  5.   ACTIVATE_FUN();
    ' B9 N5 K4 |; N2 e7 O
  6.         + M3 k2 h$ o- s% q! c$ U
  7.    /* 开始通讯:CS低电平 */
    6 r$ [0 P6 P# C- v$ i
  8.    SPI_IC_MU_CS_LOW();7 v; L. h: W( }5 B" {" H4 b. Q
  9.         Temp1=SPI_SendHalfWord(0xA6FF);7 U5 n) n' e3 O  b- u& w9 n
  10.         Temp2=SPI_SendHalfWord(0xFFFF);2 A: o* Y8 V+ w' f5 J2 Y
  11.         2 t( r, k' ~$ V8 @3 e# x7 I
  12.        
      p7 @0 T# g- g2 w
  13.          /* 结束通讯:CS高电平*/" C; J; z& g0 z/ y1 \* L
  14.    SPI_IC_MU_CS_HIGH();
    , i. c8 D6 q8 O2 \$ s
  15.      5 @& F/ ]/ p" @4 f1 S4 R6 J
  16. //  Temp = (  (Temp1 << 16) | (Temp2 << 8) | Temp3  )>> 5 ; //读出数据,右移5位,共24位,有效位为19位  ! k1 h0 M3 l  J  ?1 B7 q7 J
  17.    Temp=  (Temp1 << 16| Temp2) >> 13;   //总体32位 19位的话需右移13位$ B1 n6 V4 |: A' Z& t
  18.           Delay(1000);
    % |7 S" ?: ^- B- {
  19.          return Temp;
    ; F& \3 K# v5 H4 e* l$ L; k! f
  20. }
    % p1 y4 _2 s7 K# B& S
复制代码
+ n) u! W0 [& s: t
5角度计算
* z# E4 A6 I- u. S7 Z, x  {) o( q角度我用了11位,初始默认存在一个数值因此将他减掉了,然后按照360度进行划分
( s/ p, l- A3 w# t# |; F
  1. float Position_Calce()
    8 G- H6 \( N4 o# `
  2. {, G2 _1 x0 z7 V9 s8 ~2 P) S+ S
  3.     uint32_t  a ;
    ) U  S7 Y, S( E% D. {' v) i4 J3 _
  4.           double b;4 B: V2 D/ B; E8 t4 a: p
  5.           float  c ;0 L- V# J/ v% W3 R3 u
  6.                 uint32_t  www ;
    3 n% _6 D$ P) F+ {2 t  T, @: ]* @" y
  7.                 double  n ;
    0 ?7 y8 E$ M% [2 ]2 g9 q9 v
  8.      a=SPI_SDAD_transmission_Fun ();
    ' s% R) E! m0 x
  9.       n=((a-0x00053000)/2047);//计算角度/ G8 \% p9 @: T1 N: `
  10.        b= 360.000* ((double)(a-0x53000)/2047);  `6 U! U* O4 @/ r0 i6 n5 N
  11.       
    1 R' D; \0 ?2 S4 F6 q
  12.                         return b;                       
    % A8 M8 G0 N7 z  X& N! D7 `, b
  13.   : {4 M. |8 o2 Q9 [7 T6 R
  14. }
复制代码
! d0 l, C" s, R& m2 _. @0 k
6主函数读取角度% b* Y2 ~/ y$ i& a
  1. float position_fk_f=0;  //位置计算
    ! B) j% i" T, R: G& j% z. P4 A
  2.        
    : v' u/ O% B# @
  3. while (1)
    3 W1 c4 z8 l3 e6 Z2 j3 J2 ~
  4.     {
    % z" ]; ^# u; ^% }4 o
  5.                   position_fk_f=        Position_Calce();$ ]) m3 Q# F# c
  6.                   }
    ( e' Z% k) p* m1 k( Q6 C6 B
复制代码
. |: T- p, Y2 @7 }3 D' o/ I
总结
$ q0 K+ `8 I5 G, e* R+ q  r. G- \/ v) y
当你转动电机轴能通过SPI发送0xA6读取到数值变化,基本就算成功了,剩下的就无非是处理一下
( W5 V5 m+ v' V————————————————
7 R! H; H# w+ b. [版权声明:超级馒头神
4 Z5 x2 a& s4 }( X3 I5 S
2 _" U/ M8 r6 `8 S  l' I, T, s( K- |) {% v) F1 E$ T
收藏 评论0 发布时间:2023-2-25 17:59

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版