前言
" R6 E- B4 F$ x6 L$ R) [! Gic-mu基本情况介绍
- k. U1 O. f$ N; q: R. J& M* e+ {* j+ g7 v' `6 {
IC_MU是一款离轴的1.28mm磁编码器,主要用于电机控制居多,当作磁编码器,优势是能使用多种通讯协议(SPI,BISS,SSI),但是目前中文网上使用资料较少,因此我自己写一篇关于IC_MU的SPI通讯读取方式的文章,读取芯片为stm32G4系列,然后代码在stm32G4和stm32F1系列基本通用。
; {/ b, _1 l7 a. A& D4 Q芯片基本介绍如下
$ v! S* h9 H: V/ _* ]7 S" |9 z2 S' u. ^, w7 m' T
2 o" b6 B; e; k2 f1 d7 l. x1 o- o; Q% E& c3 ~% \" U _
提示:以下是本篇文章正文内容,下面案例可供参考
" K9 P+ s1 M p# ]+ p3 B* d0 C2 f9 W' }. i; R3 U' u+ R. u
一、硬件连接" A: U8 n. c1 ?! x% |
按最小系统连接。IC-mu需连接eeprom存储角度,供电为5V! L9 b: C" ~+ `. |
f* _/ E5 y: x% t# h
二、STM32 cubmx配置模式
O6 }- B6 q4 QSTM32G491配置cubemx
' m' ], `. a2 } @, }* M) K& K
$ u9 H, K5 f+ |& s* {- i: h* M* {
q3 f [3 Y( u! e1 R
0 Q" d3 m* e% H6 m5 V2 P+ Q( l# l4 N6 a( ] l4 l0 q
如图几个关键点
. ]- W5 |4 w* P% A' e1数值格式:可以选8bit,但是我觉得16比特配置更方便,如果要配8bit只需将数据拆分即可
$ r: q# S$ O. [* o, |) c5 k; ]2波特率 没有明确要求,12M以下都可以! `5 H0 H) x" L4 W, a. u
3SPI模式,SPI一共4种模式( O8 V2 a. t& a. E
3 W7 M* T% H5 ^4 |6 [
: m' T3 x8 {# p1 ^- k/ G9 B8 _. h
. a8 ~% H- g7 B1 t
IC_MU只支持模式0和模式3,如上图所示采用模式3 CPOL选择High CPHA选择2Edge$ [5 u R \( X5 i* J: S
, f% u( c/ X; u8 u* R* O' H
3 b4 |- t6 a3 p
, {# f" _. j. E/ c: G4 h* ]
" |9 d* d& s' x( fSPI通道要设置为高速
, ]6 H1 P7 Y3 `- H) S除此之外还需要设置片选信号,默认为高电平+ I, Y$ d) Q7 o* O& k2 l
: \8 V$ n. @; y, j
, p( g: S9 q5 @" i: m7 e9 f# ]
, d9 s' D% ?7 R& W三、软件代码及思路
. d4 G2 x( A; e9 R, |7 T0 i首先需要对整体进行说明,需要将编码器激活,配置在SPI通讯模式- ?& I; m/ L- d7 L6 j
! R6 g$ m! C& ]1.寄存器指令介绍
" c. r% [7 C( {0 t9 ~4 w6 d0xB083 Activate,激活% D0 q5 I/ }* P$ n4 F
0xA6FF Position Read 位置读取命令
( f7 O: f: j- _$ E0x8A Register Read (Continuous) 寄存器读取(连续)
* S2 _8 p! p# q% l. l% d0xCF Register Write(Continuous) 寄存器写入(连续)1 n3 Z5 _! Y5 |8 {8 w. C0 m& j
0x9C Read Status 读取状态寄存器 指令" n1 i, Z$ C! ]" ?
0x97 Register Read(Single) 寄存器读取(单次)
% u) f* e7 W1 R& z% Y. U0xD2 Register Write(Single) 寄存器写入(单次)
) E- b: a2 L2 m" a( m3 I
/ c# X1 l3 p( E3 ?7 W% G( \7 C; U
) b; S& i& W; m# E2.代码介绍
! s% |/ Y2 C; I8 K+ s8 J) s0 P对片选进行宏定义,然后对SPI数据传输底层函数进行定义* W; c3 i0 o% o7 p$ O
" s1 b! _: f K
1初始声明和定义- #define SPI_IC_MU_CS_LOW(); HAL_GPIO_WritePin(ABS_ENCODER_CSN_GPIO_Port, ABS_ENCODER_CSN_Pin, GPIO_PIN_RESET);* G) H- F% Z2 f' D! O N
- #define SPI_IC_MU_CS_HIGH() ; HAL_GPIO_WritePin(ABS_ENCODER_CSN_GPIO_Port, ABS_ENCODER_CSN_Pin, GPIO_PIN_SET);8 }5 S3 M$ R8 E- i1 ]
- ( W$ F9 t1 g% v7 u
- uint16_t SPI_SendHalfWord(uint16_t HalfWord)2 O3 p0 c! G( g6 l {
- {; D8 ?/ v; p# c& S5 V* Q# x
-
: [" h2 r6 h7 E" E - SPITimeout = SPIT_LONG_TIMEOUT;
& m1 m9 R# ?' C# f - /* Loop while DR register in not emplty */$ n8 s3 c* i: G
- while (__HAL_SPI_GET_FLAG( &hspi1, SPI_FLAG_TXE ) == RESET). C" r' `& |) y: m- ^
- {
8 g E1 e) R$ }% j3 a - if((SPITimeout--) == 0) return 0;
4 l2 \* ?6 h5 M, @9 o% f2 x- G F - }
0 I: z! e6 v+ x4 |* q - /* Send Half Word through the SPIx peripheral */
# t# C. b) x2 m$ s. Y7 K+ l9 N% L0 [ - WRITE_REG(hspi1.Instance->DR, HalfWord);. _' o1 D c) d7 b3 J$ k, h/ X
; l2 g1 o9 j# j1 D- SPITimeout = SPIT_LONG_TIMEOUT;
+ F6 [& ]4 }2 _$ U - /* Wait to receive a Half Word */
7 G/ `* Y9 E' ?1 S: s R8 } - while (__HAL_SPI_GET_FLAG( &hspi1, SPI_FLAG_RXNE ) == RESET) u) A" s5 X# ]' M
- {
& Q2 F7 x% p3 o+ g5 K - if((SPITimeout--) == 0) return 0;
7 `; }/ g# j7 R# z1 ]5 k8 C - }
% X0 n& w. Y. T8 @/ y0 c - /* Return the Half Word read from the SPI bus */- a3 q1 s1 H0 i3 }& U! f- w( \$ s
- return READ_REG(hspi1.Instance->DR);
# D9 m, {0 _6 X4 e* t -
: e& t' l5 c3 R. [2 h/ K - }) [' y6 k7 u4 H/ E. N, q6 B
复制代码
3 d& g0 A4 V* K+ W2激活寄存器% v# Q5 P& b# M% Q) o: W& A9 c
激活后才能对寄存器有操作& {" h: Z' |. q, d6 f6 j9 r6 `
- void ACTIVATE_FUN(void)
|$ L: L+ G9 q6 O. r - {
( X2 \# |' i1 t7 C, W - uint32_t ICMU_Temp = 0;
5 I& C, v. p0 N# W) O6 [ - SPI_IC_MU_CS_LOW();1 d9 t- [1 S. `( j. W
- ICMU_Temp= SPI_SendHalfWord(0xB083);: g" N8 q! d* M" L. d
- SPI_IC_MU_CS_HIGH();; W& T2 h, q5 c' K. }9 n" m5 a, c
- Delay(100);3 l$ S5 M" k9 Z# H
- }
, m `# A, Z H8 Q2 i B* F
复制代码 0 } s) O, r5 g4 s% f3 Q
3编码器初始化函数. D" \1 O8 |8 e7 l4 ~4 f' {: r
初始化发送0xB083激活编码器,编码器配置为单圈14位,具体见数据手册
2 Y8 j, B. o4 o! W' Z/ @初始化完成后可删除函数,状态会固化在配套eeprom种,不会丢失
2 j, n$ X. V9 g& l, O# N8 q; \- void Init_ICMU(void)
3 r j: X' S9 Z" Y7 ^ Y. u7 V - {
7 z$ O& U& O* v1 l$ N# G& y4 s* D3 l - ACTIVATE_FUN();
" b4 b! K1 C$ Q; v8 \/ J2 w9 N - uint32_t ICMU_Temp = 0, ICMU_Temp1=0;& w, F% D; u$ J1 k) K f2 ?& X
- SPI_IC_MU_CS_LOW();, ?" q; O. t8 w |' V8 a4 r" X
- ICMU_Temp= SPI_SendHalfWord(0xCF00);: W: n' ~& a( [+ i" N0 Y/ F6 `9 F9 a
- ICMU_Temp1= SPI_SendHalfWord(0x8E20);' v& c5 ~5 |7 ^6 ]
- SPI_IC_MU_CS_HIGH();
; n5 X9 E% R" U& T - Delay(100);
: \. j2 T% V; [, |* U2 R% t* m5 J - }
, M5 C p$ l, t# ?% v
复制代码 7 b2 d: P5 U8 e, X6 C
4数据读取
5 ^7 s/ {0 m j, W' a) H6 X编码器数据读取,读取指令为0xA6. E7 Q: z. P8 M& K3 i" A6 P
- uint32_t SPI_SDAD_transmission_Fun ( void)
. S( ]; \- g: r4 \ - {( k' M. p0 q; E8 V8 ^
- ! k& i, ~" ?2 z5 l- ~5 D {
- uint32_t Temp = 0 , Temp1 = 0, Temp2 = 0 , Temp3 = 0 ;7 P* k- K7 c' d* Y/ @0 k
- ACTIVATE_FUN();
5 ^: t8 T+ v) x/ {. V' O0 t -
6 \% T% a, v' V) `! c7 ] - /* 开始通讯:CS低电平 */# t" L Z7 _6 p* `
- SPI_IC_MU_CS_LOW();; M) Z0 j" D' p( r3 S0 p
- Temp1=SPI_SendHalfWord(0xA6FF);2 S. F. y! C" K; A9 a9 I) _" S" t
- Temp2=SPI_SendHalfWord(0xFFFF);1 g/ X# L/ z' w6 l
- ) ^7 L$ [' q- U5 J/ ?
-
; Y, x* V# n; ?' H. ] ~' r! j8 b1 V - /* 结束通讯:CS高电平*/
* g }* n4 w9 q7 b - SPI_IC_MU_CS_HIGH();
- Q& ]2 r% e6 t1 ^1 L; _ - ' |' R" y G2 E2 K3 f
- // Temp = ( (Temp1 << 16) | (Temp2 << 8) | Temp3 )>> 5 ; //读出数据,右移5位,共24位,有效位为19位 : m2 d% a- [( Z" R, m
- Temp= (Temp1 << 16| Temp2) >> 13; //总体32位 19位的话需右移13位
5 d- B k6 _4 k7 |+ J7 X6 O - Delay(1000);
5 k6 O0 r! S4 ~0 [: {% @ - return Temp;
/ C2 i- k6 e: O1 l0 N! M - }$ @' S/ K+ c! k& y
复制代码
# C4 Z% D8 X. h7 F) \7 D5角度计算# o. v: N- U. Y& X6 y) g& A* |. p
角度我用了11位,初始默认存在一个数值因此将他减掉了,然后按照360度进行划分3 B, W1 P: ^; Z
- float Position_Calce()! {) F/ v( T! H* B. Q
- {4 J1 s1 o( b& p! O+ f, B" K
- uint32_t a ;+ I$ R9 J; b7 _% V. @
- double b;) A& q6 O* D. V" X) H
- float c ;+ z! w+ g% y* E# o
- uint32_t www ;
! A! ?3 r" z, x7 Q - double n ;% n+ m# @7 @* X* L! V9 n
- a=SPI_SDAD_transmission_Fun ();
9 X% N9 Q6 Z* t- I" W4 m( Q. w - n=((a-0x00053000)/2047);//计算角度4 N: f ^" G: i7 q# u$ ]; g
- b= 360.000* ((double)(a-0x53000)/2047);
7 j' z% X8 n- q0 y9 s+ ~1 v - ! V8 T0 `8 V2 r
- return b;
& S( n: N- T, M7 C0 m -
6 ?0 ~$ \8 m% M - }
复制代码 : y* ^. R/ y: f" T
6主函数读取角度8 h2 B: s3 R/ w0 F
- float position_fk_f=0; //位置计算; {0 \& E$ ]8 q% W
- 2 C4 d( S& B# V1 m- u! B
- while (1)
9 D4 ^2 o. G$ A$ f5 F - {
. T. L3 T U( f/ d b - position_fk_f= Position_Calce();
! N7 q9 J5 T$ f) i& b! Z! e - }
: t: Y% w7 y7 k( d9 M5 \5 [
复制代码
- [, E' U' P& \ I' a总结
% X8 f1 |- Z. C' k' `当你转动电机轴能通过SPI发送0xA6读取到数值变化,基本就算成功了,剩下的就无非是处理一下
) m* p& K, ~$ y————————————————/ j' x# g& T/ o) B
版权声明:超级馒头神
/ B4 T& B5 T" q! F2 U6 k* H W! I% s; N: A8 s6 ?
+ [/ W% {& e$ z% q9 d& ~
|