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

游名科技:STM32F103+TMC2160:86步进电机和驱动一体原理图/PCB...  

[复制链接]
mmuuss586 发布时间:2020-4-29 12:18
阅读主题, 点击返回1楼
2 收藏 2 评论73 发布时间:2020-4-29 12:18
73个回答
mmuuss586 回答时间:2020-4-29 12:53:36
初始化程序如下参考:: ]! T: m8 g0 b; b: N0 |. w
  /* Initialize all configured peripherals */9 P2 W4 E4 Q2 H( Y
  MX_GPIO_Init();
. V; Z9 g/ O1 w  MX_USART2_UART_Init();# s# M! [0 a8 @* k6 c4 Q" w
  MX_TIM1_Init();0 j" ^1 Y9 {' x3 G) `0 w) I
        STEPMOTOR_TIMx_Init();                /定时器输出初始化
" a, ?9 R7 Y, u( Z. ~2 E/ g  /* USER CODE BEGIN 2 */! i" B7 \% w% ^+ e0 q& `9 h4 L3 M
        STEPMOTOR_OUTPUT_DISABLE();        //TMC2160禁止使能
/ U1 f+ ?4 r+ h4 M+ M8 @  /* USER CODE END 2 */. n( ?. \) A) T1 H1 A, l
  /* Infinite loop */
6 E" t/ Y" ?5 ~5 y3 n  /* USER CODE BEGIN WHILE */6 b  F8 S' G0 U
  while (1)0 r3 p+ G8 J2 x
  {4 y9 t, O- X, s. a2 ~
    /* USER CODE END WHILE */( Q# @+ K9 z. y. j3 @0 X0 ~6 X
                STEPMOTOR_AxisMoveRel(6400*-2, 5000 , 5000 , 1200);                        //控制TMC2160驱动步进电机反转2圈(32细分,1.8度则一圈需要6400个脉冲)
9 f$ H4 p' S4 M: E1 |3 \% r! y                LedOnOff();                                //LED闪烁处理# s: }/ W6 R, d- [6 y4 {
                STEPMOTOR_AxisMoveRel(6400*2, 5000 , 5000 , 1200);                        //控制TMC2160驱动步进电机反转2圈(32细分,1.8度则一圈需要6400个脉冲)
/ s1 @3 E$ U( l2 h7 f. y3 R                LedOnOff();                                //LED闪烁处理+ S/ _9 x+ |8 ?5 y2 w
    /* USER CODE BEGIN 3 *// g/ Z) o3 u; \
  } 9 l- x& u$ [" L$ g& A! |! T* A
mmuuss586 回答时间:2020-4-29 12:54:33
//相对位置移动参考(参考硬石的电机开发板资料): a# d! w. t/ m( u9 j
/**1 Z* R# i' \' k6 Y7 H
  * 函数功能: 相对位置运动:运动给定的步数8 s( G% J/ u# l
  * 输入参数: step:移动的步数 (正数为顺时针,负数为逆时针).
( }# `* h+ q% Z1 R+ k              accel  加速度,实际值为accel*0.1*rad/sec^2
& }1 v$ c  ~1 M, G4 n. z/ ^5 h              decel  减速度,实际值为decel*0.1*rad/sec^2
9 B. t+ ^3 ~; ~; O& G( q              speed  最大速度,实际值为speed*0.1*rad/sec  R3 e8 D7 T9 b: L! P
  * 返 回 值: 无
1 T6 E# T  u3 d5 f, d& c4 v  * 说    明: 以给定的步数移动步进电机,先加速到最大速度,然后在合适位置开始
, U) W' @  Z- [2 m; u" x0 [  {  *           减速至停止,使得整个运动距离为指定的步数。如果加减速阶段很短并且
, `1 W7 o0 p( M1 @) s  *           速度很慢,那还没达到最大速度就要开始减速( p) K; P5 U1 Q! I& E1 Z2 @0 j6 T4 m
  */
& R9 R/ @8 E+ a; i: Gvoid STEPMOTOR_AxisMoveRel(__IO int32_t step, __IO uint32_t accel, __IO uint32_t decel, __IO uint32_t speed)( Q  X& O8 x, O  Q4 U
{  % y/ h# D1 w# c' H6 ~# v8 l) y
  __IO uint16_t tim_count;
& |/ u8 O0 W4 Q  // 达到最大速度时的步数
' j4 X2 b6 {, u) s  __IO uint32_t max_s_lim;, j9 L0 w. n& S( W, r( p( e
  // 必须要开始减速的步数(如果加速没有达到最大速度)( M! w3 a: d2 C9 ^# O7 O# p8 p
  __IO uint32_t accel_lim;
$ [0 p" \) {$ Y( L7 O: ^# p0 a4 t/ |
  if(step < 0) // 步数为负数
( a- r* x. n' l+ P! g  {/ ^$ _$ y2 k/ I
    srd.dir = CCW; // 逆时针方向旋转* z0 W: _+ u7 B9 k
    STEPMOTOR_DIR_REVERSAL();( }2 z1 z5 U: K( c* a, S
    step =-step;   // 获取步数绝对值
7 ^! Y" q1 }4 y- w  P  }
% Y' S/ H$ ^, G  else; H3 q! G- R% n5 ]
  {3 P: V, Z1 T! U1 j8 D
    srd.dir = CW; // 顺时针方向旋转5 x2 K% c9 Q  k% `) Y
    STEPMOTOR_DIR_FORWARD();
9 d! `2 f: r8 W* S4 L  }
! y# s4 c& H2 E! D0 m  Y! d9 f7 I  . ]4 N8 ]% Q# w0 Q/ O) I: A, ]
  if(step == 1)    // 步数为1- B0 r. Z% l# z  |' Y9 S
  {) S. T6 i4 I4 d2 L
    srd.accel_count = -1;   // 只移动一步
2 K9 p( @3 y( V  Z    srd.run_state = DECEL;  // 减速状态.6 o0 M  o3 w) D7 i" ~2 S- w
    srd.step_delay = 1000;        // 短延时        6 r. ?8 |8 Z6 W
  }
6 v( z5 g6 {$ W6 T* Q% q! R, M3 z  else if(step != 0)  // 如果目标运动步数不为0
5 M& Z) D8 [- r3 d0 |  G, @. G2 w; n; y  {& D! |6 w* Y" m: u* V
    // 我们的驱动器用户手册有详细的计算及推导过程2 h3 F' ^  e0 H+ |/ L: F4 h

4 g9 n  e+ L3 n2 }8 M7 F  O2 }    // 设置最大速度极限, 计算得到min_delay用于定时器的计数器的值。
, f1 F; I9 ~# n; e+ K    // min_delay = (alpha / tt)/ w
) K! ~" C# Q1 o    srd.min_delay = (int32_t)(A_T_x10/speed);
% t$ E. w/ P  m! o% K. H. b. E) Z( d2 }' M% u
    // 通过计算第一个(c0) 的步进延时来设定加速度,其中accel单位为0.1rad/sec^2. Q- F, N, V" w( g" K) ~  \
    // step_delay = 1/tt * sqrt(2*alpha/accel)/ {1 R& ^/ }7 L
    // step_delay = ( tfreq*0.676/10 )*10 * sqrt( (2*alpha*100000) / (accel*10) )/100* P' ]9 ^* y: P$ }
    srd.step_delay = (int32_t)((T1_FREQ_148 * sqrt(A_SQ / accel))/10);
# y" e0 v6 p3 ~7 S5 t$ N: E0 \- d9 T  q1 h! I1 ^8 I1 `
    // 计算多少步之后达到最大速度的限制
1 P) p' s# g! [6 t! F* h+ b    // max_s_lim = speed^2 / (2*alpha*accel)
1 M5 U# ~9 H' P7 Y; A3 v5 h    max_s_lim = (uint32_t)(speed*speed/(A_x200*accel/10));9 Q2 V: b7 v+ G3 w
    // 如果达到最大速度小于0.5步,我们将四舍五入为0' b  s4 L$ R# \, D( w
    // 但实际我们必须移动至少一步才能达到想要的速度% U7 K/ U! r$ b9 @% @5 ?6 L
    if(max_s_lim == 0){
; y- H, a  a( Y4 ^& H1 z      max_s_lim = 1;
2 }7 c. u" o: J' }; Q8 N3 t    }2 e+ V9 N  J0 c0 F" V4 m
mmuuss586 回答时间:2020-4-29 12:55:03
// 计算多少步之后我们必须开始减速
2 Q" Q: D: t4 `) L! o& ]7 L+ K    // n1 = (n1+n2)decel / (accel + decel)
$ q+ S0 @% L$ v, @  w+ @' \    accel_lim = (uint32_t)(step*decel/(accel+decel));+ ]$ q, H. y, b+ s. M
    // 我们必须加速至少1步才能才能开始减速.
0 l, y/ A% J, E- x" q    if(accel_lim == 0){! d: J% c5 l3 v5 f% E
      accel_lim = 1;
- A# g0 M) z3 x: a# y: I/ t6 P    }
8 P, D5 ^; B6 k; R5 x. z5 b1 ]; M! v2 @  l8 i
    // 使用限制条件我们可以计算出减速阶段步数- C5 \: `% u" I& N
    if(accel_lim <= max_s_lim){, V8 P2 g; t# z  A& m% o& ^
      srd.decel_val = accel_lim - step;
6 H  t' R# C0 H! k2 E; n7 ~/ B1 V" ~    }
3 T9 ?( E9 N; C! v    else{9 I! o/ j: J; [/ ?4 C0 ]
      srd.decel_val = -(max_s_lim*accel/decel);; L- k# b* v" D. j' i) G4 w/ r
    }2 Y9 ]+ S4 R# W5 X; c# W/ N
    // 当只剩下一步我们必须减速3 M% H4 P- E1 Z% E4 ^! M- A
    if(srd.decel_val == 0){
/ c0 I# E, w8 s6 _      srd.decel_val = -1;
* z/ W7 h9 G4 U5 ~! [3 _    }( l. b  o1 L3 s: M3 q' h# f

; ]' a# ^6 p. \/ m6 q    // 计算开始减速时的步数- ?- j# b' y9 v" [5 [6 X
    srd.decel_start = step + srd.decel_val;4 K: F6 ~4 R7 w

* O1 h- ?8 D, h0 K3 s! X4 w    // 如果最大速度很慢,我们就不需要进行加速运动
, z; y( V. Y+ C% v, q    if(srd.step_delay <= srd.min_delay){
% d4 F: i; @3 m! d. i$ o      srd.step_delay = srd.min_delay;
& y# ]: B5 e! M* q/ B7 c- m      srd.run_state = RUN;
' ?* }. }) v4 |6 j* r    }+ ^( R0 |. }4 @) h1 u5 h
    else{% b, i" d* g0 ~) n7 l
      srd.run_state = ACCEL;4 j: A! d1 P8 h
    }   
5 u5 ]3 l0 S* K* R    // 复位加速度计数值, z5 f. X$ P! X- l
    srd.accel_count = 0;
* U/ g5 O- e2 o. G  }% e. F: V5 E, c: n! D
  MotionStatus = 1; // 电机为运动状态
+ w; \7 r( ~' Z. M  tim_count=__HAL_TIM_GET_COUNTER(&htimx_STEPMOTOR);
8 R1 T4 [0 K# S# `  __HAL_TIM_SET_COMPARE(&htimx_STEPMOTOR,STEPMOTOR_TIM_CHANNEL_x,tim_count+srd.step_delay); // 设置定时器比较值4 L- F4 F9 \# Q+ n% a
  TIM_CCxChannelCmd(STEPMOTOR_TIMx, STEPMOTOR_TIM_CHANNEL_x, TIM_CCx_ENABLE);                                                                // 使能定时器通道
3 u0 S0 h* k' q# t: h  STEPMOTOR_OUTPUT_ENABLE();3 t' ^( T' ?/ S% L1 I; a
}4 c5 |! {4 t. B$ C  _( ]
mmuuss586 回答时间:2020-4-29 12:55:37
//定时器中断函数参考
) O2 ^' S  y8 B  \; Y8 p& T/**& E* I  Q5 d6 P# @8 J8 M
  * 函数功能: 定时器中断服务函数4 P- X" n; o5 B. ]" X1 r( J4 t0 j7 e
  * 输入参数: 无
0 Z% S, m! i. ^, S3 V: `+ o9 D  * 返 回 值: 无9 E3 [/ {! c. q. e& y
  * 说    明: 实现加减速过程1 g6 b) R2 @( O5 k& w1 Z% `
  */  S7 x* u$ [. i+ S
void STEPMOTOR_TIMx_IRQHandler(void)//定时器中断处理
1 e9 A3 W1 ]) }{
4 }, [8 s) _4 L  __IO uint16_t tim_count=0;3 F& u8 T( ?5 I
  // 保存新(下)一个延时周期
% G( e7 Q6 _4 q4 y  uint16_t new_step_delay=0;
; Y8 P; W% i! p! f; k  // 加速过程中最后一次延时(脉冲周期).
' c% h8 q6 z2 r$ ?9 P  __IO static uint16_t last_accel_delay=0;6 s7 ]/ T: G6 f; {$ _" j7 e" B
  // 总移动步数计数器; s3 b7 K, H. a. v  ]- W
  __IO static uint32_t step_count = 0;/ `* b; ]3 D. D  r4 W8 e0 u
  // 记录new_step_delay中的余数,提高下一步计算的精度1 x8 r2 k  }/ u  h
  __IO static int32_t rest = 0;& C# n  P3 N/ X3 ?7 {  ~4 Q
  //定时器使用翻转模式,需要进入两次中断才输出一个完整脉冲8 G0 V2 Q$ [0 r  D, P, L
  __IO static uint8_t i=0;& M- D, G4 c0 h3 t' [$ _
    U; B1 T$ B6 U6 A9 H8 b; [- b9 m1 k
  if(__HAL_TIM_GET_IT_SOURCE(&htimx_STEPMOTOR, STEPMOTOR_TIM_IT_CCx) !=RESET)9 g2 T' T& M. y- t5 V8 L; c
  {
$ ]; a9 ], b6 v3 r, ~. \    // 清楚定时器中断6 t. n( S; C$ R' ^8 k
    __HAL_TIM_CLEAR_IT(&htimx_STEPMOTOR, STEPMOTOR_TIM_IT_CCx);
. K# t7 ]* l; O& E; o! p: N) @! n5 m   
4 ~; u# s' Q$ |' D/ R- Y4 _    // 设置比较值# Z' f" q; c4 F
    tim_count=__HAL_TIM_GET_COUNTER(&htimx_STEPMOTOR);
* C2 y' k" x5 U" c  z3 r$ |' Y    __HAL_TIM_SET_COMPARE(&htimx_STEPMOTOR,STEPMOTOR_TIM_CHANNEL_x,tim_count+srd.step_delay);+ g+ X& `. Z+ e0 V# Z* _
4 g9 ?* L3 N9 |" r: Y" y$ r, K
    i++;     // 定时器中断次数计数值
7 L  H5 j$ C' S! m2 A    if(i==2) // 2次,说明已经输出一个完整脉冲1 A+ ~2 p3 }2 e' Z6 R% l
    {
" e3 N! `1 W6 H+ D. k      i=0;   // 清零定时器中断次数计数值( h* V; J, g4 U2 }) x
      switch(srd.run_state) // 加减速曲线阶段
+ d$ ]( [: h2 [8 g1 X6 {      {. t! P6 ?2 I( I5 S
        case STOP:1 ^8 T  z1 j* o' u( g. L* L! |
          step_count = 0;  // 清零步数计数器
1 g2 @$ R4 u" H, i1 n          rest = 0;        // 清零余值
( Y# F1 h3 U' j$ }# `0 `1 i          // 关闭通道( L( s: L. [; X5 Z2 a: M
          TIM_CCxChannelCmd(STEPMOTOR_TIMx, STEPMOTOR_TIM_CHANNEL_x, TIM_CCx_DISABLE);        - ?2 s* L, P8 [& D5 q7 L* A
          __HAL_TIM_CLEAR_FLAG(&htimx_STEPMOTOR, STEPMOTOR_TIM_FLAG_CCx);
# y& o/ U/ I+ q- ^+ Z& l          STEPMOTOR_OUTPUT_DISABLE();
+ J5 S, e( K6 L' G: }- s1 `& x          MotionStatus = 0;  //  电机为停止状态     0 u# n, p. |, b! b( N' R. X
          break;
+ n  e1 H+ P5 U
& b5 o1 B/ E$ Y' O/ M% h/ K( c" ^1 w, x        case ACCEL:1 Y) R1 p3 Q$ ]1 z, S/ s& ?
          step_count++;      // 步数加1
. A7 x' z$ k1 s+ i$ m4 b. X; z          if(srd.dir==CW)
+ B6 u: p$ L1 u          {                  ( Y8 Y- V# F% q0 D% n4 s/ R1 S
            step_position++; // 绝对位置加1
+ b1 O9 b# K4 W7 ]; w& H* t8 g5 `          }% P" `6 n( s* h
          else' u- R  B. P% o7 d: ^% b3 z+ Y0 T4 Q4 {
          {& _6 y( v' A  A7 D/ F9 P' [. E
            step_position--; // 绝对位置减1  n5 T, k' U' H3 \- s
          }7 N6 s4 J  k! S- B  F
          srd.accel_count++; // 加速计数值加1
' b+ V, M/ t2 m; O2 M9 o# H: z          new_step_delay = srd.step_delay - (((2 *srd.step_delay) + rest)/(4 * srd.accel_count + 1));//计算新(下)一步脉冲周期(时间间隔)
: }3 d& `! J. j0 |/ J          rest = ((2 * srd.step_delay)+rest)%(4 * srd.accel_count + 1);// 计算余数,下次计算补上余数,减少误差! f1 J0 |) I# [% z" N6 T, p, R
          if(step_count >= srd.decel_start)// 检查是够应该开始减速" g* e9 Q, A1 W( ]* J/ I
          {
% G7 T/ v; m0 J: x8 z( a0 _) h/ U            srd.accel_count = srd.decel_val; // 加速计数值为减速阶段计数值的初始值
1 }  m0 ~" ^5 J0 @            srd.run_state = DECEL;           // 下个脉冲进入减速阶段
( g" t% B- b* _, L5 a9 i          }
) N" }. k8 Z2 e; x          else if(new_step_delay <= srd.min_delay) // 检查是否到达期望的最大速度
6 i! C0 }. `/ ~& y4 t3 W          {
6 t- ^8 b8 b$ b# Z' z8 G" S            last_accel_delay = new_step_delay; // 保存加速过程中最后一次延时(脉冲周期)  J- t4 }6 G3 C$ Z  ^. @
            new_step_delay = srd.min_delay;    // 使用min_delay(对应最大速度speed)8 `- Y! Z/ g0 ?5 M2 c0 d# g0 m
            rest = 0;                          // 清零余值4 K7 h& h- e! [/ m6 `- @" ?
            srd.run_state = RUN;               // 设置为匀速运行状态. c# z6 ~7 M# D9 Q# z' P2 g# C
          }. J  D6 h% `2 {/ y' W6 ]7 I& ?$ c. s9 g
          break;+ ?& w# k1 d7 A1 }; R7 \0 @

8 g5 D) a  O) |1 W5 O) ]7 ^1 h        case RUN:( M* Q1 I1 O% n4 I( p; A$ G
          step_count++;  // 步数加1
$ R7 r. m- _  Y7 ^          if(srd.dir==CW)% y# [& U' b& U
          {                 
& G* y3 X- z7 y# L% X# l            step_position++; // 绝对位置加15 y" J8 a7 B, K3 C+ i
          }
9 X, j5 L9 u0 s9 k0 A- a+ {          else
+ l7 W2 h2 f& ~0 M7 v( U7 e0 a- Y- c, w          {
- O- T* c8 o; ~5 e* r            step_position--; // 绝对位置减1- I3 i# H; S* g3 v8 q* `9 X
          }" _8 P) U( w& ^2 q
          new_step_delay = srd.min_delay;     // 使用min_delay(对应最大速度speed)) a8 L6 V6 O' Z: u& E( W
          if(step_count >= srd.decel_start)   // 需要开始减速- n5 K! t7 ~# S
          {# h9 ^1 O3 X% {+ u( M
            srd.accel_count = srd.decel_val;  // 减速步数做为加速计数值
" c" ]- u' N* L/ t6 U            new_step_delay = last_accel_delay;// 加阶段最后的延时做为减速阶段的起始延时(脉冲周期)
  B4 S% S& [- V, }4 T; A            srd.run_state = DECEL;            // 状态改变为减速+ G: D9 i1 Z5 Y2 p% r" K7 F
          }0 @: K3 F5 ]: A) F& k  e1 V  M
          break;% Z5 @; `' {+ `) s
, q  o# {* ^1 Q
        case DECEL:0 H9 X0 S0 k  w1 O/ G( }, n
          step_count++;  // 步数加1( I, m! o+ ~1 s8 j
          if(srd.dir==CW)
; T! A* Z5 @. E3 {  C" A" d          {                  / r" I# |# \( k- A9 t0 P# I* x! j6 c
            step_position++; // 绝对位置加1
/ q$ I3 R! F( I: ^          }/ ]; L* Z+ K8 m6 e3 [
          else
' p  V& a1 k% C# d          {
6 `# R' ^! C# F            step_position--; // 绝对位置减16 J" w% O. Y8 u
          }
3 ]; c3 |- [; d" Q          srd.accel_count++;
: B/ Q9 I8 d# r2 |* G- ?          new_step_delay = srd.step_delay - (((2 * srd.step_delay) + rest)/(4 * srd.accel_count + 1)); //计算新(下)一步脉冲周期(时间间隔)
% \7 d+ M, L  r3 h  }, O          rest = ((2 * srd.step_delay)+rest)%(4 * srd.accel_count + 1);// 计算余数,下次计算补上余数,减少误差
) q+ Z$ A9 T1 p7 v" B% \          " |" ^$ {, q/ S% i) D9 @
          //检查是否为最后一步5 R( x8 a& A% L; o
          if(srd.accel_count >= 0)# K4 z& S2 N% x5 M
          {/ O( z4 B# g1 ?
            srd.run_state = STOP;
& a" x0 t9 S$ ?. i4 L; w          }. E: j0 k- f+ M$ G3 u
          break;' N: r  N- g+ F# _/ _4 ]
      }      / T7 t7 i, S. f, ]4 r
      srd.step_delay = new_step_delay; // 为下个(新的)延时(脉冲周期)赋值
' G" ^- k: G) F' n    }, {. s2 Q- L. q0 x' f" n
  }
# D( y* A. n( E% Q) ~- V}
, b8 V; p: G6 ]6 S8 ~  @
mmuuss586 回答时间:2020-4-29 12:56:22
五、开源补充说明
2 T$ ^( X" b3 a+ B; Z3 b    如果确实需要原理图和PCB的用户,请联系我们的客服或管理员私下索取谢谢!1 H' c! E2 _- W; L: I* S
! g  [8 M9 ^6 g' ~9 O) D' H* a
mmuuss586 回答时间:2020-4-29 12:56:49
如对文档有疑问或有技术问题需要交流,可联系Trinamic原厂或我们。% \2 j# a4 h6 I' [
3 x7 d0 w3 f% d+ Y& b6 l
技术群:171897584
7 z0 W% X" i& f4 J) |  Y% o公众号:游名开源
$ Z8 w7 E. Q3 S; T
mmuuss586 回答时间:2020-4-30 10:19:43
mmuuss586 回答时间:2020-5-1 21:22:14
mmuuss586 回答时间:2020-5-5 19:56:35
mmuuss586 回答时间:2020-5-9 13:16:00
cpsrd570 回答时间:2020-5-9 18:22:38
电机相对运动的函数和中断函数看着像硬石开发板里面的代码。
mmuuss586 回答时间:2020-5-11 12:28:03
cpsrd570 发表于 2020-5-9 18:22
! \% X3 L- x, e( n* j电机相对运动的函数和中断函数看着像硬石开发板里面的代码。
* _/ u' O2 m0 F! v9 l7 F
是的,参考他们的,有说明:写着参考硬石的
mmuuss586 回答时间:2020-5-16 20:42:48
mmuuss586 回答时间:2020-5-20 12:07:25
mmuuss586 回答时间:2020-5-21 16:26:39

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版