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

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

[复制链接]
STMCU小助手 发布时间:2023-2-25 17:59
前言
- c" B7 R3 @! O5 x$ Lic-mu基本情况介绍5 \1 o' L' l8 N  N
2 C& S  O; L" k! n
IC_MU是一款离轴的1.28mm磁编码器,主要用于电机控制居多,当作磁编码器,优势是能使用多种通讯协议(SPI,BISS,SSI),但是目前中文网上使用资料较少,因此我自己写一篇关于IC_MU的SPI通讯读取方式的文章,读取芯片为stm32G4系列,然后代码在stm32G4和stm32F1系列基本通用。
0 B6 p- H4 U( R: c' j& d/ N+ c芯片基本介绍如下2 K2 j; {5 E1 H+ o$ `5 s

3 C) n" }2 l5 V, g2 E6 ~& F
325acfd031684154a51541ebaf3bc1f5.png
9 q! h) F# ^! X/ e  c
+ n2 S9 L. g  m, e5 l4 k提示:以下是本篇文章正文内容,下面案例可供参考! C+ Q, S$ a* X! z' q

. A9 {/ h" c6 I4 ~8 F) t& _一、硬件连接

$ ?* b, w8 W; R- L* P  L) Z按最小系统连接。IC-mu需连接eeprom存储角度,供电为5V
) C* p8 ]0 q2 Q" F* U0 h! `' L' \' o( S, B7 ^# L9 j
二、STM32 cubmx配置模式/ |4 M* C6 i2 G$ O2 z* ?
STM32G491配置cubemx
4 J/ a+ e+ ]: v
8 ]# [3 [3 z3 ?
b31de8a144684fd8815c3aea74271bba.png
9 ?' |# P% H6 W# s1 K% k% Z+ N% O; u' ^* d- h
6 X. N1 L# D4 ?& b  E7 n
如图几个关键点
; p# `8 H" Y8 V( k/ t1数值格式:可以选8bit,但是我觉得16比特配置更方便,如果要配8bit只需将数据拆分即可
/ P% _4 d0 o  z8 f* ]" O2波特率 没有明确要求,12M以下都可以
/ O0 i) t+ M% p6 X$ y4 }3SPI模式,SPI一共4种模式! q9 {, q0 h! u
' f& k2 \! }% i0 t# L
896f63f11e5f4a62b6e64e9527c395a0.png / C) P* O3 }1 e( C8 A; a
" z, N1 c$ e9 W8 L* i+ p3 r
IC_MU只支持模式0和模式3,如上图所示采用模式3 CPOL选择High CPHA选择2Edge
$ r# g, F5 o+ R, U& _( k2 X( M2 r7 S, X3 i8 o: N2 G
2e692f827e4048f38f0a6020450c06ec.png
; K0 b5 `: g0 h' ?/ [
1 Z9 V/ t7 [. {  E+ w# s$ X
! _, l1 Z/ C& m: y: S5 I
SPI通道要设置为高速
7 U2 f- T% Q2 f* L* `% Z2 v除此之外还需要设置片选信号,默认为高电平
5 \+ Z" P  u; A' h4 @; S7 ^. d6 G0 \/ z% I- S6 A1 N4 b2 N+ R
e8715427ead043cd984ccaaf608c5208.png ' R' l6 T( g$ t% l! T
% F7 x9 ^( V* G& T9 i; J: z7 q
三、软件代码及思路
0 ~7 v' l5 q/ k0 |! O  @首先需要对整体进行说明,需要将编码器激活,配置在SPI通讯模式
3 G* `8 R" h8 |( E6 L0 p
# @3 e; I( q6 ~0 `5 ^6 W" U
1.寄存器指令介绍3 f* ~% s8 g7 c( j) J
0xB083 Activate,激活
% I5 T& G" c$ d, S0xA6FF Position Read 位置读取命令
# H: j" A% l& C0 n# z7 ]( W, [  m& Z0x8A Register Read (Continuous) 寄存器读取(连续)$ z5 b, |) R$ s" t
0xCF Register Write(Continuous) 寄存器写入(连续)- p) Q) m6 W: Z+ S& x' t% z
0x9C Read Status 读取状态寄存器 指令
8 j( M, e2 b! ~, Z: H1 x6 c0x97 Register Read(Single) 寄存器读取(单次): X2 y0 O& z& U2 x3 f
0xD2 Register Write(Single) 寄存器写入(单次)
& l' w4 j% m: c& n1 R- l- b. ]" `+ b9 }+ }; t6 F* q- r5 p7 ^

/ q( q- L6 H, F. L' Q. c2.代码介绍9 E1 P4 n* D1 `" a3 b; g
对片选进行宏定义,然后对SPI数据传输底层函数进行定义
% d4 m8 M7 B. ~  C( Z6 G, W9 K- H/ `) A1 m8 @( r# c7 A
1初始声明和定义
  1. #define    SPI_IC_MU_CS_LOW();       HAL_GPIO_WritePin(ABS_ENCODER_CSN_GPIO_Port, ABS_ENCODER_CSN_Pin, GPIO_PIN_RESET);
    2 p6 c& n. N0 A5 C
  2. #define          SPI_IC_MU_CS_HIGH() ;     HAL_GPIO_WritePin(ABS_ENCODER_CSN_GPIO_Port, ABS_ENCODER_CSN_Pin, GPIO_PIN_SET);
    ! f& T/ u5 R" I9 z$ n
  3. ( W. }9 [* o" y- w' h6 h
  4. uint16_t SPI_SendHalfWord(uint16_t HalfWord)
    5 \5 X1 v. T3 l6 R$ n) z7 {
  5. {
    0 t7 o5 o$ h1 J4 R' a1 b! q4 Y
  6.   5 [5 i( w3 B9 {
  7.   SPITimeout = SPIT_LONG_TIMEOUT;
      G% _' ~- _" h; h
  8.   /* Loop while DR register in not emplty */
    , K6 J  H8 X% g# J6 M
  9.   while (__HAL_SPI_GET_FLAG( &hspi1,  SPI_FLAG_TXE ) == RESET)
    9 `% J0 }. _3 ?, C7 e
  10.   {9 \: Y8 G" }# U7 [
  11.     if((SPITimeout--) == 0) return 0;
    * i" c4 O0 s. P/ u8 }) O
  12.   }
    ! W- z9 s' Q( p8 l. l
  13.   /* Send Half Word through the SPIx peripheral */9 G& T5 E* K, s
  14.   WRITE_REG(hspi1.Instance->DR, HalfWord);6 t4 u/ m- g% I' R6 V
  15. . Z7 a7 s3 k! c- R9 J
  16.   SPITimeout = SPIT_LONG_TIMEOUT;$ S( {" q1 f# O4 h* U* }/ u
  17.   /* Wait to receive a Half Word */
    / ?# u9 T0 d  L
  18.   while (__HAL_SPI_GET_FLAG( &hspi1, SPI_FLAG_RXNE ) == RESET). y) i. Z; C# m4 x3 e% I% g
  19.    {! ~# X5 F* ]% L! M) |$ @
  20.     if((SPITimeout--) == 0) return 0;( ?. u3 l" }/ N9 b$ `9 ]
  21.    }
    1 J* @5 C( K0 \5 E/ v+ j
  22.   /* Return the Half Word read from the SPI bus */' P  {& f0 m( u. G
  23.   return READ_REG(hspi1.Instance->DR);
    / ^3 l+ P+ M8 M
  24.   3 o7 Q9 H* U. ~0 _( A( w9 A
  25. }4 @2 l8 [; @+ g1 ~* u/ p
复制代码

- h( w# R1 ^/ t( h1 C4 y8 ?2激活寄存器' L( \. L5 F6 Q( i& A" k2 x8 s; B: q
激活后才能对寄存器有操作
+ ^" g! W9 j. v* N
  1. void ACTIVATE_FUN(void)
    ! h# U9 r9 M4 V+ m
  2. {- L  Y6 J6 z" E+ s/ S
  3.   uint32_t ICMU_Temp = 0;- B! C/ G* F2 o4 v
  4.   SPI_IC_MU_CS_LOW();# S1 G2 N4 M7 Y" k
  5.   ICMU_Temp= SPI_SendHalfWord(0xB083);  |" f% L0 l% G3 {) {/ y7 x! d
  6.   SPI_IC_MU_CS_HIGH();2 g5 r# z0 W1 |
  7.    Delay(100);8 `. w4 A  c/ F6 C) M' g: ]9 E
  8. }) o6 D# U$ q5 W* {
复制代码
; d$ ?3 K$ q. y+ N) i- \! f: M
3编码器初始化函数
* S9 h! m7 M3 v6 I初始化发送0xB083激活编码器,编码器配置为单圈14位,具体见数据手册
' g( q% u0 e$ l初始化完成后可删除函数,状态会固化在配套eeprom种,不会丢失6 Y, z2 N# E( U$ u! q: ^
  1. void Init_ICMU(void)  n! U7 ?; ^5 j& u5 e' v" ^
  2. {9 ?& ]" Q! I: `3 o0 V8 l( |) j$ F
  3.    ACTIVATE_FUN();5 V+ d  A* O+ `
  4.   uint32_t ICMU_Temp = 0, ICMU_Temp1=0;" @7 Y6 O7 @$ _; Q- c
  5.   SPI_IC_MU_CS_LOW();2 f9 f" L0 F% D" g; r( J
  6.   ICMU_Temp= SPI_SendHalfWord(0xCF00);
      e  j2 U9 I* I" c& ~% I1 w4 q$ ^
  7. ICMU_Temp1= SPI_SendHalfWord(0x8E20);
    1 S' Q" x& c" p: f) P8 A5 h5 e0 _6 A
  8.   SPI_IC_MU_CS_HIGH();7 c  v4 F. P! ^1 s& E) Z
  9.    Delay(100);
    7 b/ w$ C- L  y5 r4 U; B
  10. }- y# ^, t, f# J) y/ D1 T6 K) k# G# V
复制代码

0 M; a8 X; r) W4 p! U( v4数据读取
  W: O& b3 J( M3 x编码器数据读取,读取指令为0xA64 _+ E4 s( ]! S" r9 N$ G3 X- k
  1. uint32_t SPI_SDAD_transmission_Fun ( void)* Y  X4 N1 I9 S$ i2 V7 R2 O( n
  2. {
    1 B3 Z9 d3 T0 g# n3 C3 d
  3.        
      q: I# c; d* T! Y; _
  4.         uint32_t Temp = 0 , Temp1 = 0, Temp2 = 0 , Temp3 = 0 ;# d, w6 K1 z  @* e  U
  5.   ACTIVATE_FUN();
    . a5 J8 e( c: f
  6.        
    " g. @, m- p) k9 I# M; h
  7.    /* 开始通讯:CS低电平 */0 O4 `+ E, n% W
  8.    SPI_IC_MU_CS_LOW();
    ! ?$ V# `' U1 z$ q+ M
  9.         Temp1=SPI_SendHalfWord(0xA6FF);( |; x! Y  |5 x6 e4 m9 ]  L( Y
  10.         Temp2=SPI_SendHalfWord(0xFFFF);
    6 b8 v$ L) |- z8 o
  11.        
    % ^7 Q# @, r+ H: p# X0 A9 n
  12.         ; U1 b+ D' G/ {9 }! l3 t6 N8 i
  13.          /* 结束通讯:CS高电平*/
    1 B) C9 ^# }. k6 \& K
  14.    SPI_IC_MU_CS_HIGH();
    4 ^% C6 E0 F) S' K) _  \3 p7 z
  15.      2 i' J% Z# H4 [- K
  16. //  Temp = (  (Temp1 << 16) | (Temp2 << 8) | Temp3  )>> 5 ; //读出数据,右移5位,共24位,有效位为19位  
    * D, |; R1 u( K; i  i
  17.    Temp=  (Temp1 << 16| Temp2) >> 13;   //总体32位 19位的话需右移13位
    ( Z8 f5 D/ @! J1 _
  18.           Delay(1000);2 l+ W' P+ u9 `; C* t8 V+ e, u3 K
  19.          return Temp;
    3 g9 S/ b! F4 _! J
  20. }: g6 w9 u0 v* w
复制代码

" _4 Y7 y/ u. P5 \6 @5角度计算8 R" }( B, c$ y: P$ s
角度我用了11位,初始默认存在一个数值因此将他减掉了,然后按照360度进行划分
. U6 V8 B5 E' F1 S0 Z8 _$ X3 m& b( h
  1. float Position_Calce()
    $ n( \, h% }& R5 E
  2. {
    6 u( K: N3 Y' v
  3.     uint32_t  a ;9 [# ]9 w& H$ o. o; ?) J+ S) Q
  4.           double b;0 J& h( K) A# U" o7 m: n! R$ Q/ @
  5.           float  c ;1 S$ f! {, ~8 B) R: w
  6.                 uint32_t  www ;
    ! B, R2 v& O1 E8 A* F! x
  7.                 double  n ;5 \' k- p( q* L' ~
  8.      a=SPI_SDAD_transmission_Fun ();& ?, u0 e# |' v4 Z* k/ I& T
  9.       n=((a-0x00053000)/2047);//计算角度' t2 r2 T" _$ h9 K
  10.        b= 360.000* ((double)(a-0x53000)/2047);" C/ J% {( V1 {9 ]% B+ C5 ]/ h
  11.       
    ) g* _; o( M& }. f# k
  12.                         return b;                       
    " y1 \; O& c# L& N( w" M5 K8 I; u
  13.   
    $ b  v3 i+ r( J# b% C! a
  14. }
复制代码

$ q8 W8 l! K8 ]  y6主函数读取角度5 W# `. B: d& P2 _1 d
  1. float position_fk_f=0;  //位置计算
    1 Z8 K5 x# b7 K6 I3 h+ k$ M
  2.        
    5 M5 Z/ f- O# F0 @
  3. while (1)9 n& S+ O1 S& s8 O% q
  4.     {
    + i1 i! c( A  M) v
  5.                   position_fk_f=        Position_Calce();
      L& Z6 X7 e- N) ~
  6.                   }5 C/ c/ Z, x6 Y& j
复制代码

$ Z% d6 _( ^# b总结
+ x8 f# S! ~1 S1 Q# l. J) [
当你转动电机轴能通过SPI发送0xA6读取到数值变化,基本就算成功了,剩下的就无非是处理一下
: {, i8 K- ?9 q0 a/ J, a0 x* p————————————————% o+ X9 h: o1 b* ]  B& l. `
版权声明:超级馒头神
$ U" n* P: ]6 D. _8 E/ d2 R
: I. N9 u$ W# R0 z! ]) L
" @$ R. `/ N9 L& j/ w

点评

磁铁距离芯片的距离应该是多少啊  发表于 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 手机版