你的浏览器版本过低,可能导致网站不能正常访问!为了你能正常使用网站功能,请使用这些浏览器。
cpsrd570 发表于 2020-5-9 18:22! `2 L0 ~1 {' ]2 m' L" _1 Z3 j 电机相对运动的函数和中断函数看着像硬石开发板里面的代码。
小马哥STM32F103开源小四轴RoboFly全部资料大放送
【MCU实战经验】+STM32F103的uCOSII详细移植
STM32中BOOT的作用
STM32如何分配原理图IO
STM32的I2S外设
STM32电路知识学习
基于STM32F1的CAN通信之DMA
STM32怎么选型
简单分析STM32和51的区别
简单聊聊STM32的SPI外设
/* Initialize all configured peripherals */( J) T9 d4 G0 w9 C8 S7 W0 Y- {3 a
MX_GPIO_Init();: B1 K/ k3 ~2 ]9 @4 U
MX_USART2_UART_Init();
MX_TIM1_Init();
STEPMOTOR_TIMx_Init(); /定时器输出初始化
/* USER CODE BEGIN 2 */
STEPMOTOR_OUTPUT_DISABLE(); //TMC2160禁止使能 z) _* a) j# M0 C: ~( C2 d5 z! t+ m' ~
/* USER CODE END 2 */
/* Infinite loop */ p& g( P, O$ L8 p
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
STEPMOTOR_AxisMoveRel(6400*-2, 5000 , 5000 , 1200); //控制TMC2160驱动步进电机反转2圈(32细分,1.8度则一圈需要6400个脉冲)
LedOnOff(); //LED闪烁处理
STEPMOTOR_AxisMoveRel(6400*2, 5000 , 5000 , 1200); //控制TMC2160驱动步进电机反转2圈(32细分,1.8度则一圈需要6400个脉冲)
LedOnOff(); //LED闪烁处理
/* USER CODE BEGIN 3 */
}
/**) j c3 j, R) k6 @3 R* p9 V/ _+ l
* 函数功能: 相对位置运动:运动给定的步数
* 输入参数: step:移动的步数 (正数为顺时针,负数为逆时针).
accel 加速度,实际值为accel*0.1*rad/sec^28 k8 o6 y e9 v9 v( d* Y5 H
decel 减速度,实际值为decel*0.1*rad/sec^2- [3 m( N4 S Q* U# D6 \3 |- w. \
speed 最大速度,实际值为speed*0.1*rad/sec* a/ ?' P" r1 z+ v; h' I) D
* 返 回 值: 无/ {. F2 j2 j# I
* 说 明: 以给定的步数移动步进电机,先加速到最大速度,然后在合适位置开始, e. R) a5 K5 a. M
* 减速至停止,使得整个运动距离为指定的步数。如果加减速阶段很短并且2 B$ u G, ]- W
* 速度很慢,那还没达到最大速度就要开始减速
*/: Z) g8 L8 _- Y. e7 @4 r$ G% ~
void STEPMOTOR_AxisMoveRel(__IO int32_t step, __IO uint32_t accel, __IO uint32_t decel, __IO uint32_t speed)( f8 n3 H$ i8 }# N( f) Q
{ * e# s9 K9 N2 f. m! o1 J& p- q) V
__IO uint16_t tim_count;
// 达到最大速度时的步数" }' H# \, M! q" n9 D6 n( Q
__IO uint32_t max_s_lim;
// 必须要开始减速的步数(如果加速没有达到最大速度)
__IO uint32_t accel_lim;1 v! P% X1 g a3 W0 y$ B- h! m
( L; [9 w3 C: F
if(step < 0) // 步数为负数
{
srd.dir = CCW; // 逆时针方向旋转/ @' h% V2 {' s! R" L' c
STEPMOTOR_DIR_REVERSAL();8 }4 m) U( V6 e
step =-step; // 获取步数绝对值
}0 v' X. g4 Q* {& e; Z; e
else! X! E# H5 g- Z. D6 d! t0 N
{
srd.dir = CW; // 顺时针方向旋转; y3 H3 |9 v$ m% n3 c7 T' `
STEPMOTOR_DIR_FORWARD();
}7 W t" v' W# j3 ?. r
if(step == 1) // 步数为1$ Y0 y% f2 R9 w. q0 X
{! b8 U. _; V! x: B$ [
srd.accel_count = -1; // 只移动一步
srd.run_state = DECEL; // 减速状态.
srd.step_delay = 1000; // 短延时
}
else if(step != 0) // 如果目标运动步数不为05 v. S) f, l6 \ M. u
{% F" {/ s( P+ o9 T$ u
// 我们的驱动器用户手册有详细的计算及推导过程, z* Y1 V2 U5 \$ U& [
// 设置最大速度极限, 计算得到min_delay用于定时器的计数器的值。3 Y) ]3 ^9 V9 Z/ b/ i
// min_delay = (alpha / tt)/ w. Z; c6 ]( ]1 A8 U; m2 Q
srd.min_delay = (int32_t)(A_T_x10/speed);
- H; _/ z3 j# v6 }) t ^
// 通过计算第一个(c0) 的步进延时来设定加速度,其中accel单位为0.1rad/sec^2
// step_delay = 1/tt * sqrt(2*alpha/accel) b2 t% ] H% \1 d: t4 s7 P
// step_delay = ( tfreq*0.676/10 )*10 * sqrt( (2*alpha*100000) / (accel*10) )/100
srd.step_delay = (int32_t)((T1_FREQ_148 * sqrt(A_SQ / accel))/10);6 [+ q" b. W }% q5 o
// 计算多少步之后达到最大速度的限制
// max_s_lim = speed^2 / (2*alpha*accel) v# ]" g/ w' u7 i
max_s_lim = (uint32_t)(speed*speed/(A_x200*accel/10));
// 如果达到最大速度小于0.5步,我们将四舍五入为0
// 但实际我们必须移动至少一步才能达到想要的速度- ?8 s9 x9 y6 `. p
if(max_s_lim == 0){7 K. \) m( S. O0 s& y1 V& s
max_s_lim = 1;
}
// n1 = (n1+n2)decel / (accel + decel)
accel_lim = (uint32_t)(step*decel/(accel+decel));
// 我们必须加速至少1步才能才能开始减速.
if(accel_lim == 0){
accel_lim = 1;( x: A7 d! b8 r5 \
}
& L% g3 x+ Z9 d# O) i5 R. h
// 使用限制条件我们可以计算出减速阶段步数) k1 l7 [/ z6 D o
if(accel_lim <= max_s_lim){) s8 M$ v- t0 a3 g0 B- l' W/ h
srd.decel_val = accel_lim - step;0 o" ~$ u0 W0 r% l; T
}
else{4 h% ~4 N& n% N+ A% _8 P
srd.decel_val = -(max_s_lim*accel/decel);) w0 o5 @8 Q. [: U
}
// 当只剩下一步我们必须减速
if(srd.decel_val == 0){
srd.decel_val = -1;/ q+ p% g& T) v" ]& N p! w
}7 o+ ~; I/ p, R6 H: @. n
// 计算开始减速时的步数
srd.decel_start = step + srd.decel_val;
9 T+ {; y" q% t6 Z% C
// 如果最大速度很慢,我们就不需要进行加速运动% G# i9 D; H' o5 |: ]# v' \) w+ n
if(srd.step_delay <= srd.min_delay){
srd.step_delay = srd.min_delay; V! P' s8 o. E! |3 c7 I/ _! g
srd.run_state = RUN;
}& @+ X) y& ^% `" U
else{$ o0 y% [" ?, {8 ?" p
srd.run_state = ACCEL;
} 8 x' w) M/ P, h. c8 ~' H
// 复位加速度计数值6 V3 K8 v2 m* Q/ l. Z% s
srd.accel_count = 0;
}" G+ \! p6 G. Z) T. x# {( I6 M
MotionStatus = 1; // 电机为运动状态$ Z8 R# ]2 Q5 O$ m8 a
tim_count=__HAL_TIM_GET_COUNTER(&htimx_STEPMOTOR);) M1 e! q- q0 n0 t* T8 p* i9 p/ g
__HAL_TIM_SET_COMPARE(&htimx_STEPMOTOR,STEPMOTOR_TIM_CHANNEL_x,tim_count+srd.step_delay); // 设置定时器比较值- `* m$ e5 I9 l4 C! g a7 o6 e
TIM_CCxChannelCmd(STEPMOTOR_TIMx, STEPMOTOR_TIM_CHANNEL_x, TIM_CCx_ENABLE); // 使能定时器通道
STEPMOTOR_OUTPUT_ENABLE();
}. H% A( X! D% x- _
/**( Q" v1 u( W9 L/ R+ e
* 函数功能: 定时器中断服务函数1 `5 o+ ^& m# g- z
* 输入参数: 无& C* P- {6 m% m
* 返 回 值: 无
* 说 明: 实现加减速过程/ C5 s+ A+ b0 N' T6 L
*/, ?5 b: L' g- @9 r9 Q
void STEPMOTOR_TIMx_IRQHandler(void)//定时器中断处理5 y2 w4 q0 X, ^! U$ j# X
{
__IO uint16_t tim_count=0;
// 保存新(下)一个延时周期: A7 H1 ^/ Z, ^" M# c" {2 F
uint16_t new_step_delay=0;
// 加速过程中最后一次延时(脉冲周期).
__IO static uint16_t last_accel_delay=0;) Q6 N3 _3 K- o0 a1 S
// 总移动步数计数器
__IO static uint32_t step_count = 0;9 Y+ N: h2 _" V1 j/ g/ [
// 记录new_step_delay中的余数,提高下一步计算的精度6 A$ o' h8 k3 y# c# d: C+ _
__IO static int32_t rest = 0;5 O5 V+ z! Y5 ~* F5 p
//定时器使用翻转模式,需要进入两次中断才输出一个完整脉冲
__IO static uint8_t i=0;% u! y/ u5 z+ d1 i* @! p
if(__HAL_TIM_GET_IT_SOURCE(&htimx_STEPMOTOR, STEPMOTOR_TIM_IT_CCx) !=RESET)
{: U& j, y6 M, r& h+ J, K
// 清楚定时器中断' {) D4 W: q8 Z
__HAL_TIM_CLEAR_IT(&htimx_STEPMOTOR, STEPMOTOR_TIM_IT_CCx);% b. M( O8 z8 i$ B: }: I
0 G9 h8 U- F$ u: A. _
// 设置比较值9 C }! R0 [1 S+ G
tim_count=__HAL_TIM_GET_COUNTER(&htimx_STEPMOTOR);+ W) }8 V+ D6 f# p( G( {: @
__HAL_TIM_SET_COMPARE(&htimx_STEPMOTOR,STEPMOTOR_TIM_CHANNEL_x,tim_count+srd.step_delay);! B9 [6 {' y" D: K |
i++; // 定时器中断次数计数值
if(i==2) // 2次,说明已经输出一个完整脉冲
{
i=0; // 清零定时器中断次数计数值
switch(srd.run_state) // 加减速曲线阶段' ]# J5 J, c$ i1 J7 x* w5 [
{
case STOP:
step_count = 0; // 清零步数计数器) V4 k# Z" c7 `# K6 r- J
rest = 0; // 清零余值
// 关闭通道9 M' R$ G4 l7 \+ G
TIM_CCxChannelCmd(STEPMOTOR_TIMx, STEPMOTOR_TIM_CHANNEL_x, TIM_CCx_DISABLE); % j) I2 w& O. n3 k t6 N
__HAL_TIM_CLEAR_FLAG(&htimx_STEPMOTOR, STEPMOTOR_TIM_FLAG_CCx);) K1 w% }4 H: B) D8 U9 x- y
STEPMOTOR_OUTPUT_DISABLE(); `& g+ c$ v# b. \- {0 M
MotionStatus = 0; // 电机为停止状态
break;
0 |, G9 n9 }5 W
case ACCEL:+ ` O/ {0 K U b4 h$ U7 }6 u
step_count++; // 步数加1; Q" E1 E* |9 \' c8 m" D
if(srd.dir==CW)* d- [2 {: J8 D1 _& H; \
{
step_position++; // 绝对位置加1: l ~+ j1 e$ w
}
else
{% i0 s+ c( u0 r" R
step_position--; // 绝对位置减11 K6 P3 Y2 h* j/ d" {
}7 @9 b3 M2 }! k; u
srd.accel_count++; // 加速计数值加1. o m' N( G, q
new_step_delay = srd.step_delay - (((2 *srd.step_delay) + rest)/(4 * srd.accel_count + 1));//计算新(下)一步脉冲周期(时间间隔): R' n& {2 {: A- h: B( L' k
rest = ((2 * srd.step_delay)+rest)%(4 * srd.accel_count + 1);// 计算余数,下次计算补上余数,减少误差
if(step_count >= srd.decel_start)// 检查是够应该开始减速. E# M0 q, m8 a2 z9 T
{$ h9 `$ k% _4 |; D/ x6 c ? C
srd.accel_count = srd.decel_val; // 加速计数值为减速阶段计数值的初始值( @6 O. k6 T$ H: W
srd.run_state = DECEL; // 下个脉冲进入减速阶段
}; d- e" z/ r' p. J5 P+ f/ C# \
else if(new_step_delay <= srd.min_delay) // 检查是否到达期望的最大速度
{/ f! v9 f/ u+ Q& Z9 Y
last_accel_delay = new_step_delay; // 保存加速过程中最后一次延时(脉冲周期)$ e" a" k9 ?7 E
new_step_delay = srd.min_delay; // 使用min_delay(对应最大速度speed)
rest = 0; // 清零余值
srd.run_state = RUN; // 设置为匀速运行状态3 F A7 ^/ o* ^& l, P9 ?
}& X7 O, e) g) Y
break;
case RUN:- E( U; G* X# v0 F
step_count++; // 步数加12 P! v& \6 S4 Y, }3 G
if(srd.dir==CW)& d* }7 T+ C7 [
{ % L: ^( q6 @9 r% K3 T) v
step_position++; // 绝对位置加1
}
else
{
step_position--; // 绝对位置减1
}* z! k* d. H9 |' z# w x. ^. C" k4 T
new_step_delay = srd.min_delay; // 使用min_delay(对应最大速度speed)% |; R( }! G3 M) y$ E; Q
if(step_count >= srd.decel_start) // 需要开始减速3 N) x, L6 o1 r8 g& [% T# ~0 L
{
srd.accel_count = srd.decel_val; // 减速步数做为加速计数值
new_step_delay = last_accel_delay;// 加阶段最后的延时做为减速阶段的起始延时(脉冲周期)0 x7 _- k# V+ q% k; z c h6 s. A
srd.run_state = DECEL; // 状态改变为减速3 N; o7 B" V7 v: z9 W) n
}
break;1 u7 a" {3 G2 l: s9 V
case DECEL:
step_count++; // 步数加15 E0 @. |' e, ]- y( A
if(srd.dir==CW)6 [) L: o8 ^* F$ ?; n, n
{
step_position++; // 绝对位置加1 G. f2 g7 z+ {7 C
}6 T& M% `8 T" S9 I- L% l
else( r! x6 `8 b% T" c
{' F# L9 U8 U$ A7 F
step_position--; // 绝对位置减1- u/ j4 B- a1 I4 u9 ? a
}
srd.accel_count++;
new_step_delay = srd.step_delay - (((2 * srd.step_delay) + rest)/(4 * srd.accel_count + 1)); //计算新(下)一步脉冲周期(时间间隔)
rest = ((2 * srd.step_delay)+rest)%(4 * srd.accel_count + 1);// 计算余数,下次计算补上余数,减少误差
# [! F% Z" q* z W/ f( h
//检查是否为最后一步& X) c% {* c; T% k1 f
if(srd.accel_count >= 0)
{
srd.run_state = STOP;
}1 X2 R2 G2 w S
break;* F4 T/ l$ ^, r' K$ l2 @% J
}
srd.step_delay = new_step_delay; // 为下个(新的)延时(脉冲周期)赋值. K8 f9 K$ V& ?. o5 ^) A! q
}
}
}
如果确实需要原理图和PCB的用户,请联系我们的客服或管理员私下索取谢谢!& d5 ?& h6 h5 Z! s2 i0 f1 m Z
( t# \9 r) d: {: W* G E
2 p" O! r* K- Y3 G4 Z! @0 l
技术群:171897584& O# h2 \: D, w% Q( K/ L& s
公众号:游名开源
是的,参考他们的,有说明:写着参考硬石的