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

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

[复制链接]
STMCU小助手 发布时间:2023-2-25 17:59
前言
* `3 ^( A, S( F, e% R5 Zic-mu基本情况介绍# k/ W5 M% `, _8 u! U$ j. A
' H! e$ k2 [" z5 e, U
IC_MU是一款离轴的1.28mm磁编码器,主要用于电机控制居多,当作磁编码器,优势是能使用多种通讯协议(SPI,BISS,SSI),但是目前中文网上使用资料较少,因此我自己写一篇关于IC_MU的SPI通讯读取方式的文章,读取芯片为stm32G4系列,然后代码在stm32G4和stm32F1系列基本通用。9 s5 z1 T  P1 Z/ Q, D! k
芯片基本介绍如下1 b/ f/ q9 v4 e; F. f

: L; k" S2 L0 J' V
325acfd031684154a51541ebaf3bc1f5.png ' }; R2 [+ y, j/ |2 @/ C- h( e/ U
" s  K- p9 @# {3 d
提示:以下是本篇文章正文内容,下面案例可供参考: c$ Z# A. r  j, S5 Y  T
  h3 U. e- M  R
一、硬件连接
4 w0 F! l5 H7 \3 }
按最小系统连接。IC-mu需连接eeprom存储角度,供电为5V
. a5 S2 n4 e# D6 [2 V4 G& |5 m" q! R  r' Z$ c# w
二、STM32 cubmx配置模式
* A; i& a* t9 c6 w( D! x; F& a4 J* RSTM32G491配置cubemx+ [: i, Q8 u: Y) H! k  w8 l* x4 K' E7 T

2 ?/ `3 }$ V1 p5 w" T' u
b31de8a144684fd8815c3aea74271bba.png : y. E. m! ?1 _& H* ^/ f# |

7 Q+ j1 f8 X& b% V- j/ O
/ @, r( R, s; ]% {& t8 l# |$ b$ u
如图几个关键点" L& l; d( S. J5 N1 c! r
1数值格式:可以选8bit,但是我觉得16比特配置更方便,如果要配8bit只需将数据拆分即可2 }$ B# k: X- K2 I
2波特率 没有明确要求,12M以下都可以
2 ?9 h( J* C" l& A) {3SPI模式,SPI一共4种模式
8 ]$ b) L2 g% ]3 I( X% g: b% o5 o( t4 A2 n
896f63f11e5f4a62b6e64e9527c395a0.png
: x% s# G' M' B$ \4 {' @% v- R/ W8 Z  X1 B6 g# \$ c# O, R5 f7 s: u
IC_MU只支持模式0和模式3,如上图所示采用模式3 CPOL选择High CPHA选择2Edge- B% U% o6 x8 \% B8 G

5 G# Z$ L4 ^0 d/ q$ L. t0 B
2e692f827e4048f38f0a6020450c06ec.png
3 O: E" j# ]+ h' q! g% o
5 H: z$ m# {# j& I2 v7 M7 u

6 L# a" n+ Q# d5 s( b- nSPI通道要设置为高速8 x- m1 e) x8 e6 |: E0 Q
除此之外还需要设置片选信号,默认为高电平
! V1 e0 X. Y7 n# J! a) Y! E
& d) v# f. V8 V1 P' u
e8715427ead043cd984ccaaf608c5208.png ! D# {( V5 v+ s3 B0 S$ D! y
( n) U! h! A1 P: P' E1 W6 Y
三、软件代码及思路; c8 J7 P4 ?1 y" S5 ?9 p
首先需要对整体进行说明,需要将编码器激活,配置在SPI通讯模式! n# t$ {3 t3 ]2 p; x% k

1 L6 G/ q. n  ?* `. R+ i$ O
1.寄存器指令介绍
& q; ~1 {  K  X$ X0xB083 Activate,激活
' x' P6 U; S% W1 I, U% U: x' G0xA6FF Position Read 位置读取命令
: g1 S; b/ ]( m5 m! q5 i0x8A Register Read (Continuous) 寄存器读取(连续)
( Y# f* X9 x* A' V# m0xCF Register Write(Continuous) 寄存器写入(连续)
; D4 M' }* U  n  V6 w1 D0x9C Read Status 读取状态寄存器 指令* L  k3 b# P- _1 |9 z" x, S
0x97 Register Read(Single) 寄存器读取(单次)$ j$ F: B7 d3 |) x7 t$ w; z
0xD2 Register Write(Single) 寄存器写入(单次)
- i1 @& t: x* H/ P2 Q! Z; L8 C/ G5 U; ]6 T$ J: D1 M% L; Y3 X9 }
* S9 G3 @( \1 b* k) u' J
2.代码介绍# J5 w0 f5 y. ^$ X, U" @
对片选进行宏定义,然后对SPI数据传输底层函数进行定义
5 `$ H5 r2 s  h" j9 I7 I* }( `; f  M5 v
) r# D( P1 _; H3 D& s9 T
1初始声明和定义
  1. #define    SPI_IC_MU_CS_LOW();       HAL_GPIO_WritePin(ABS_ENCODER_CSN_GPIO_Port, ABS_ENCODER_CSN_Pin, GPIO_PIN_RESET);
    % I9 ~, t3 V* N0 U+ ]& O) F8 ?4 D+ L
  2. #define          SPI_IC_MU_CS_HIGH() ;     HAL_GPIO_WritePin(ABS_ENCODER_CSN_GPIO_Port, ABS_ENCODER_CSN_Pin, GPIO_PIN_SET);
    , j, m. E6 ^7 d. \" ]
  3. # r/ L7 w- O: L4 t+ `
  4. uint16_t SPI_SendHalfWord(uint16_t HalfWord)
    * m. J; x; h+ f. N8 x  ?9 _) U
  5. {
    8 J+ P8 a- Q3 X$ f: `
  6.   
    % D% O. d* D' U: _4 x
  7.   SPITimeout = SPIT_LONG_TIMEOUT;# z) n) A. `. T, `
  8.   /* Loop while DR register in not emplty */  C3 U" o( f) K  B8 q. {
  9.   while (__HAL_SPI_GET_FLAG( &hspi1,  SPI_FLAG_TXE ) == RESET)
    8 p1 H4 Q9 z( Z  T- T
  10.   {* H9 L2 R" q/ }! H% B( }
  11.     if((SPITimeout--) == 0) return 0;6 U: t( Z2 t! {; s! h1 a
  12.   }
    1 u0 E: s/ L# I5 m3 p, A4 f  X7 G
  13.   /* Send Half Word through the SPIx peripheral */- r1 V5 y! e& s
  14.   WRITE_REG(hspi1.Instance->DR, HalfWord);
    5 o3 ^9 _& p! o8 p
  15. - p& n( O) ~& H% W, _; \( }+ i
  16.   SPITimeout = SPIT_LONG_TIMEOUT;" w+ m8 K) C9 |
  17.   /* Wait to receive a Half Word */1 M0 v  _, ^4 Z% o8 m) ?
  18.   while (__HAL_SPI_GET_FLAG( &hspi1, SPI_FLAG_RXNE ) == RESET)
    5 A- O5 f8 z) n; U3 c/ `
  19.    {% m0 w1 t! }3 ?; l' Q
  20.     if((SPITimeout--) == 0) return 0;
    1 z8 h* F3 k' H; W
  21.    }" M$ o5 f6 u# P9 X8 [7 V2 s
  22.   /* Return the Half Word read from the SPI bus */! }% {2 N* L1 |1 a% R* @" \. f
  23.   return READ_REG(hspi1.Instance->DR);
    . Y2 a$ u: a9 a0 b' R# w
  24.   
    , O' h" {% k7 V3 i/ C1 a
  25. }3 N. o  e& u. J
复制代码
" u1 T; }/ W" V' p
2激活寄存器( P- p; k$ b' H4 C* Q! ]
激活后才能对寄存器有操作7 C% [! T! R/ v0 b# c; q
  1. void ACTIVATE_FUN(void)
    7 p9 N; e/ q" o
  2. {' U0 ?& N- d/ _/ r& U7 }. T
  3.   uint32_t ICMU_Temp = 0;
    ) T6 h3 S; S2 D9 g- }
  4.   SPI_IC_MU_CS_LOW();
    ) @( O3 Y9 z+ \1 ]0 H. v* w
  5.   ICMU_Temp= SPI_SendHalfWord(0xB083);, B9 d. u, H& e
  6.   SPI_IC_MU_CS_HIGH();) D4 C2 u1 n8 X% Q
  7.    Delay(100);/ x  Y6 e, B: o- c
  8. }5 L( B7 S: W8 E9 m6 R' S9 o* e
复制代码

$ O8 T2 d2 o8 f3 P9 i4 M, M4 |" N2 Y3编码器初始化函数- E8 i+ t( m* i" Q* p
初始化发送0xB083激活编码器,编码器配置为单圈14位,具体见数据手册% L; j- w/ }, x& `4 f2 `
初始化完成后可删除函数,状态会固化在配套eeprom种,不会丢失; x( d) K, X, L, U! x
  1. void Init_ICMU(void)
    ! H8 A- }* F- x+ r0 q% t
  2. {
    2 V% o- W: Z$ b  `1 c
  3.    ACTIVATE_FUN();6 [- O  i: V: T+ t4 t0 |, l/ k
  4.   uint32_t ICMU_Temp = 0, ICMU_Temp1=0;
    3 s/ Z7 `, E- [( u8 r& y
  5.   SPI_IC_MU_CS_LOW();, h7 a, Z0 }9 l3 H  D$ E! k6 _
  6.   ICMU_Temp= SPI_SendHalfWord(0xCF00);% v# F0 a, m/ c' A; H0 P# X
  7. ICMU_Temp1= SPI_SendHalfWord(0x8E20);. s" @$ O6 ~: W6 y0 c2 T- _
  8.   SPI_IC_MU_CS_HIGH();  @' f+ l% h2 r+ W+ z/ Q
  9.    Delay(100);5 M1 ^2 `* \$ o5 {
  10. }
    ) e! w2 V; ^, k
复制代码
  j  Q5 d0 m: k6 C
4数据读取, M6 P# S/ T3 X, Q; u; o  L4 D
编码器数据读取,读取指令为0xA6- V5 Y$ `* o2 ]4 Z( _  {% j
  1. uint32_t SPI_SDAD_transmission_Fun ( void)
    % G! G, X$ Y9 N1 c% U- S2 e
  2. {& b2 _5 o+ b; I8 w- l' B$ D) L
  3.         , X" d/ l9 p7 O
  4.         uint32_t Temp = 0 , Temp1 = 0, Temp2 = 0 , Temp3 = 0 ;
    ' x# a: [  C! }! a
  5.   ACTIVATE_FUN();+ L5 g( ?" m' D5 W4 M2 }, d
  6.        
    # c8 n5 y% }# a2 [% b4 {9 g0 k. U1 Q
  7.    /* 开始通讯:CS低电平 */
    0 W# J/ L  C* L
  8.    SPI_IC_MU_CS_LOW();
    , T; m5 @& P: b5 {9 R6 A
  9.         Temp1=SPI_SendHalfWord(0xA6FF);
    , ?6 I& X* H% A, L( p: b5 M0 P
  10.         Temp2=SPI_SendHalfWord(0xFFFF);8 g7 F  ~" @+ W( g' @. V, [2 v
  11.         ( p3 n0 [3 T' e9 i
  12.         ) K1 m6 e- ^) }6 o' y3 z
  13.          /* 结束通讯:CS高电平*/3 R- O8 A3 `6 f2 A& j( L
  14.    SPI_IC_MU_CS_HIGH();2 W7 }0 A- ?% |! \8 b0 `6 i
  15.      
      P# k2 H6 |. V+ ~' H( h# S
  16. //  Temp = (  (Temp1 << 16) | (Temp2 << 8) | Temp3  )>> 5 ; //读出数据,右移5位,共24位,有效位为19位  
    ' [6 d& n+ |9 a- j. C
  17.    Temp=  (Temp1 << 16| Temp2) >> 13;   //总体32位 19位的话需右移13位
    % [% u. `4 w2 O% f3 A+ [
  18.           Delay(1000);3 a5 k0 t7 B) v# f# N3 L- G
  19.          return Temp;
    0 x3 w  V3 d' R# a+ B# g7 W3 Z
  20. }
    9 H% d4 X% W* ^0 H4 C
复制代码

, {/ {- m7 [) v' t* I/ t5角度计算0 R2 @& c0 g: r- P% z# z
角度我用了11位,初始默认存在一个数值因此将他减掉了,然后按照360度进行划分. x5 x, g  B) l5 N
  1. float Position_Calce()  z" I& G- r5 v/ e4 ^8 t
  2. {% V# N7 k8 m- f% i  d" H! _
  3.     uint32_t  a ;
    3 Y1 S8 t7 j$ ~5 n" G1 N9 F
  4.           double b;
    3 u/ D& h4 @2 `, L
  5.           float  c ;
      t* d! ?, D  A9 I9 C! O/ k
  6.                 uint32_t  www ;
    # ~( v3 m9 _2 v3 o" K" q1 s3 \
  7.                 double  n ;
    . [; \& ^6 I: r0 [" s# m" J
  8.      a=SPI_SDAD_transmission_Fun ();' T$ r" u8 o- d3 v! Q9 y3 H
  9.       n=((a-0x00053000)/2047);//计算角度
    - ]  a4 {$ _( r5 R. Y( d
  10.        b= 360.000* ((double)(a-0x53000)/2047);$ M  L+ O3 l5 x6 q) o
  11.       
    ! S$ p9 Q; F5 r0 C0 I5 g! N
  12.                         return b;                       
    * _% D$ W: h  j* y# p8 }) v; p+ M! ?
  13.   
    * w' M2 x5 e: n6 y. Y2 i
  14. }
复制代码

: y" N3 }+ }! c6主函数读取角度
! U' a7 A1 a% o6 I
  1. float position_fk_f=0;  //位置计算7 `7 x6 q9 I( [; \0 P( z" j
  2.        
    2 Z6 A$ B& y3 X( |; e: i" H! |3 C7 u
  3. while (1)* l  q6 _7 ]$ w" M/ p' m
  4.     {
    + W; g0 i+ c' ~0 h
  5.                   position_fk_f=        Position_Calce();
    ( K5 }7 w' C5 J6 B" b
  6.                   }! p5 x( H; o  Q  s8 }& K
复制代码
4 U! S! ]. t9 Q: {
总结

- c, k7 _0 \( a8 c当你转动电机轴能通过SPI发送0xA6读取到数值变化,基本就算成功了,剩下的就无非是处理一下
5 g+ w# T* d$ [! C8 c————————————————9 V9 {2 J4 p1 U6 b5 V3 D+ h
版权声明:超级馒头神8 S& G% o& j8 |8 I
, F' y+ \+ K0 c: g

3 _: W/ a$ G& j( s

点评

磁铁距离芯片的距离应该是多少啊  发表于 2026-5-15 15:22
赞 收藏 评论2 发布时间:2023-2-25 17:59

举报

2个回答
Dawn_11 回答时间:2026-7-14 14:07:29

可以把完整代码发出来嘛

所属标签

相似技术帖

官网相关资源

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