
STM32ADC过采样及几种ADC采样的处理方法
STM32的启动模式配置与应用
小马哥STM32F103开源小四轴RoboFly全部资料大放送
STM32固件库分享,超全系列整理
STM32F10xxx 正交编码器接口应用笔记 及源代码
分享一个STM32F103的硬件IIC代码库,完美解决IIC问题!
OpenBLT移植到STM32F103战舰开发板上适用于所有STM32F103系列的Bootloader
MultiButton移植到STM32F103战舰开发板
UDS诊断服务
使用Nano板验证驱动SPI串口屏的颜色显示
/* Initialize all configured peripherals */1 I+ ^/ {7 m6 T, H: ~$ l, I
MX_GPIO_Init();
MX_USART2_UART_Init();" E8 b X0 f$ i' X) x2 @
MX_TIM1_Init();2 R5 E; @! H0 l6 ]7 q
STEPMOTOR_TIMx_Init(); /定时器输出初始化
/* USER CODE BEGIN 2 */: ~! T8 D8 V7 w0 A) [
STEPMOTOR_OUTPUT_DISABLE(); //TMC2160禁止使能# R2 m; _# a* Y& Z; A$ p8 u6 u
/* USER CODE END 2 */" l+ o) x6 T8 h: i% M$ v& ~
/* Infinite loop */5 f' ?: T, E6 \0 E
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */2 g0 Z( G8 \- J; h, F! W+ A1 v
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闪烁处理6 g' O, }9 f0 J! p& V
/* USER CODE BEGIN 3 */
} ; M% s1 i4 x) ^
/**
* 函数功能: 相对位置运动:运动给定的步数) s4 g! J/ a# ~: I0 k
* 输入参数: step:移动的步数 (正数为顺时针,负数为逆时针).
accel 加速度,实际值为accel*0.1*rad/sec^25 l l2 v. W0 V+ u* W
decel 减速度,实际值为decel*0.1*rad/sec^29 _( {& a6 h& N! U
speed 最大速度,实际值为speed*0.1*rad/sec
* 返 回 值: 无
* 说 明: 以给定的步数移动步进电机,先加速到最大速度,然后在合适位置开始
* 减速至停止,使得整个运动距离为指定的步数。如果加减速阶段很短并且0 f6 j/ T8 l/ Q- R+ F5 I h7 w/ T+ ?
* 速度很慢,那还没达到最大速度就要开始减速6 S t5 e' c* a' `9 m& v F
*/
void STEPMOTOR_AxisMoveRel(__IO int32_t step, __IO uint32_t accel, __IO uint32_t decel, __IO uint32_t speed)/ ^/ t) V. N J' o
{
__IO uint16_t tim_count;% O/ A/ P% J. n4 z. W
// 达到最大速度时的步数8 p# ?9 N7 X8 b9 S. A! p( B* {6 c5 b
__IO uint32_t max_s_lim;
// 必须要开始减速的步数(如果加速没有达到最大速度)
__IO uint32_t accel_lim;
if(step < 0) // 步数为负数
{- H% o9 p1 }/ h& A9 c; n! E( X9 H
srd.dir = CCW; // 逆时针方向旋转
STEPMOTOR_DIR_REVERSAL();
step =-step; // 获取步数绝对值
}5 K# @) k0 C- A) S
else$ z' M, L; i4 O
{
srd.dir = CW; // 顺时针方向旋转
STEPMOTOR_DIR_FORWARD();. ~+ Z. k4 I! S
}
9 K8 T J1 i% t7 {/ s
if(step == 1) // 步数为1
{/ F& r0 a7 ^% N# f; ?, @
srd.accel_count = -1; // 只移动一步6 m& ]& I9 L$ M& \- r
srd.run_state = DECEL; // 减速状态.
srd.step_delay = 1000; // 短延时
}1 Q$ b, E8 L# t+ ? i1 H
else if(step != 0) // 如果目标运动步数不为0
{
// 我们的驱动器用户手册有详细的计算及推导过程0 z9 U5 V3 U/ q
// 设置最大速度极限, 计算得到min_delay用于定时器的计数器的值。* p Q! s+ P) z+ M
// min_delay = (alpha / tt)/ w
srd.min_delay = (int32_t)(A_T_x10/speed);
/ x+ @" V( b% ^
// 通过计算第一个(c0) 的步进延时来设定加速度,其中accel单位为0.1rad/sec^2
// step_delay = 1/tt * sqrt(2*alpha/accel)
// 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);
) s" t9 S/ E5 Y1 a" \2 s
// 计算多少步之后达到最大速度的限制
// max_s_lim = speed^2 / (2*alpha*accel)
max_s_lim = (uint32_t)(speed*speed/(A_x200*accel/10));
// 如果达到最大速度小于0.5步,我们将四舍五入为0
// 但实际我们必须移动至少一步才能达到想要的速度( W/ g T4 |: v) `. A8 V
if(max_s_lim == 0){
max_s_lim = 1;
}
// n1 = (n1+n2)decel / (accel + decel)& v8 o5 Z+ x* l) Y, O8 g( v
accel_lim = (uint32_t)(step*decel/(accel+decel));) \- {# k0 a. ? d8 t) D5 B
// 我们必须加速至少1步才能才能开始减速.
if(accel_lim == 0){5 b0 R) a9 C7 `7 S( ?* L; c
accel_lim = 1;
}
) Q0 O8 X8 t' B7 v p+ [8 Q
// 使用限制条件我们可以计算出减速阶段步数0 }8 w' P, ?2 h. Z" Q
if(accel_lim <= max_s_lim){5 H5 t$ W! w' H1 ^2 {
srd.decel_val = accel_lim - step;* q% D* i7 \ M) \: e% b0 L( ~
}+ n8 y1 l" X- ?
else{4 j& o" f( K1 D6 }
srd.decel_val = -(max_s_lim*accel/decel);9 a' X+ K2 _2 K
}
// 当只剩下一步我们必须减速
if(srd.decel_val == 0){
srd.decel_val = -1;9 M) L- y& n. S: O ^
}2 L' {$ W& f% Z6 S
+ x2 ^. Y% o- k- |% C! M$ r1 ~
// 计算开始减速时的步数
srd.decel_start = step + srd.decel_val;
// 如果最大速度很慢,我们就不需要进行加速运动
if(srd.step_delay <= srd.min_delay){
srd.step_delay = srd.min_delay;$ A/ j* F; |. v0 P# K I
srd.run_state = RUN;
}
else{
srd.run_state = ACCEL;. A1 E& S( S0 C
} 1 D# h5 i9 [2 t( R. z+ r" W
// 复位加速度计数值+ h; c& C2 {) p6 _
srd.accel_count = 0;. g6 `- ?2 E) z0 @
}+ f0 Z$ C! K% T& W
MotionStatus = 1; // 电机为运动状态
tim_count=__HAL_TIM_GET_COUNTER(&htimx_STEPMOTOR);8 `; o$ D' w h& W
__HAL_TIM_SET_COMPARE(&htimx_STEPMOTOR,STEPMOTOR_TIM_CHANNEL_x,tim_count+srd.step_delay); // 设置定时器比较值% o( d. a. F' U
TIM_CCxChannelCmd(STEPMOTOR_TIMx, STEPMOTOR_TIM_CHANNEL_x, TIM_CCx_ENABLE); // 使能定时器通道 4 c* s. ]+ s2 q. C9 V$ }) N
STEPMOTOR_OUTPUT_ENABLE();' N# \" y, L. h( r: o
}
/**; c4 e9 S0 \/ l* ~4 X! D
* 函数功能: 定时器中断服务函数, ^ v: n( s+ z: J9 e
* 输入参数: 无
* 返 回 值: 无$ d7 Q4 t; [% Y' h. o5 x
* 说 明: 实现加减速过程
*/5 \, D" @7 V+ |
void STEPMOTOR_TIMx_IRQHandler(void)//定时器中断处理 M6 A/ i3 T8 V: D% N& h
{
__IO uint16_t tim_count=0; \8 o6 H6 T ]: M. g
// 保存新(下)一个延时周期5 E8 C9 G% x0 `/ N7 w1 g4 r
uint16_t new_step_delay=0;
// 加速过程中最后一次延时(脉冲周期).& T2 @' l4 z6 x' t$ `0 i4 _& l K' r9 U. s
__IO static uint16_t last_accel_delay=0;9 K" \: i6 L1 m
// 总移动步数计数器
__IO static uint32_t step_count = 0;+ c8 j# j+ L/ C ]+ I% j3 P5 Q4 x
// 记录new_step_delay中的余数,提高下一步计算的精度
__IO static int32_t rest = 0;+ m0 x$ r `' R& Q3 ^- R F
//定时器使用翻转模式,需要进入两次中断才输出一个完整脉冲5 z) Z% |3 Z/ [9 F/ C
__IO static uint8_t i=0;" Z2 f" ]; y* H# T' `1 K9 {
. [4 Y$ ~1 L! u
if(__HAL_TIM_GET_IT_SOURCE(&htimx_STEPMOTOR, STEPMOTOR_TIM_IT_CCx) !=RESET)
{7 u2 N; o! V6 N) C4 W" P7 r
// 清楚定时器中断+ `% I: ]& ]- X o1 j
__HAL_TIM_CLEAR_IT(&htimx_STEPMOTOR, STEPMOTOR_TIM_IT_CCx);
// 设置比较值* I& Z. y" c! f
tim_count=__HAL_TIM_GET_COUNTER(&htimx_STEPMOTOR);: y5 D2 p& R9 W9 j/ i9 _
__HAL_TIM_SET_COMPARE(&htimx_STEPMOTOR,STEPMOTOR_TIM_CHANNEL_x,tim_count+srd.step_delay);$ u# u; R, J7 q6 i0 c
/ _' e. m' C/ H7 Z4 L& a
i++; // 定时器中断次数计数值# @3 M, m4 `7 d- H% |
if(i==2) // 2次,说明已经输出一个完整脉冲
{
i=0; // 清零定时器中断次数计数值# G1 d, F6 B- w, \! {( Q
switch(srd.run_state) // 加减速曲线阶段
{2 t Q2 a( J1 S+ K
case STOP:
step_count = 0; // 清零步数计数器 ^6 |' z% P0 E3 r: v& X8 }
rest = 0; // 清零余值
// 关闭通道
TIM_CCxChannelCmd(STEPMOTOR_TIMx, STEPMOTOR_TIM_CHANNEL_x, TIM_CCx_DISABLE);
__HAL_TIM_CLEAR_FLAG(&htimx_STEPMOTOR, STEPMOTOR_TIM_FLAG_CCx);
STEPMOTOR_OUTPUT_DISABLE();
MotionStatus = 0; // 电机为停止状态
break;6 q8 [2 U/ h4 q# f6 W1 W3 _
case ACCEL:0 n6 _; G" C1 k8 h$ P3 R9 E0 A/ Z
step_count++; // 步数加1
if(srd.dir==CW)
{
step_position++; // 绝对位置加1' x. ?! a1 l5 J" o; F
}' m; ?$ s w& P4 b; D1 Z( O/ b
else
{
step_position--; // 绝对位置减1
}
srd.accel_count++; // 加速计数值加1" o, t5 m; W& E' ~
new_step_delay = srd.step_delay - (((2 *srd.step_delay) + rest)/(4 * srd.accel_count + 1));//计算新(下)一步脉冲周期(时间间隔)/ {0 ]( L' U2 I, U' F& C* q
rest = ((2 * srd.step_delay)+rest)%(4 * srd.accel_count + 1);// 计算余数,下次计算补上余数,减少误差
if(step_count >= srd.decel_start)// 检查是够应该开始减速
{
srd.accel_count = srd.decel_val; // 加速计数值为减速阶段计数值的初始值
srd.run_state = DECEL; // 下个脉冲进入减速阶段8 j S; D- ]& X C0 w9 Z0 ]* V
} J+ `3 c% [ W+ V! C
else if(new_step_delay <= srd.min_delay) // 检查是否到达期望的最大速度
{* m/ O8 ]2 a% X" T
last_accel_delay = new_step_delay; // 保存加速过程中最后一次延时(脉冲周期)" P5 @- M! p0 @ ^4 M$ n* I3 P
new_step_delay = srd.min_delay; // 使用min_delay(对应最大速度speed)6 R; K3 P( Z: g4 \
rest = 0; // 清零余值! g# d" C) y* u! e' `$ _
srd.run_state = RUN; // 设置为匀速运行状态
}
break;
case RUN:( {7 Q0 x# A7 v7 @
step_count++; // 步数加16 ]3 @8 |! ~) l
if(srd.dir==CW)$ U( p' l3 m! {! h# W: t# L7 n" ]: E
{ 5 i# @/ o3 r9 o0 @6 p
step_position++; // 绝对位置加1
}
else
{) s5 H5 R7 g5 ]2 y7 o( W* V
step_position--; // 绝对位置减1
}
new_step_delay = srd.min_delay; // 使用min_delay(对应最大速度speed)
if(step_count >= srd.decel_start) // 需要开始减速6 Y9 l1 T4 U: o/ j6 |" E' E' H5 ~) H
{
srd.accel_count = srd.decel_val; // 减速步数做为加速计数值) S; O( f: H" _3 |# G5 j* i9 b; Y
new_step_delay = last_accel_delay;// 加阶段最后的延时做为减速阶段的起始延时(脉冲周期)6 I6 A) B8 a2 q. T$ H, V
srd.run_state = DECEL; // 状态改变为减速# N( D4 Z7 c7 n' u2 O
}7 U @. Q1 ~" i1 h
break;& j. u) R/ h/ F+ M* d
case DECEL:
step_count++; // 步数加1
if(srd.dir==CW)+ V5 m8 f2 F( r8 y+ O+ M5 ^3 Q
{
step_position++; // 绝对位置加1& i- l. y I. ]/ U0 a! x
}
else
{
step_position--; // 绝对位置减1% l% |& u$ Z) Y* o: e$ _% w+ L) a9 q
}
srd.accel_count++;
new_step_delay = srd.step_delay - (((2 * srd.step_delay) + rest)/(4 * srd.accel_count + 1)); //计算新(下)一步脉冲周期(时间间隔)& V& x8 d `2 W, i. U1 G
rest = ((2 * srd.step_delay)+rest)%(4 * srd.accel_count + 1);// 计算余数,下次计算补上余数,减少误差4 W. D# P/ @6 X$ U. T) l
' l" n. V; M I& |( f$ K1 \: x
//检查是否为最后一步2 A" v7 P; E2 }2 P
if(srd.accel_count >= 0)# L# P" U5 i% D: Q6 h; r
{
srd.run_state = STOP;: X, ^) Z7 y( W8 K8 t, q; ~
}3 \. e0 S0 w1 C) K1 J( B
break;
}
srd.step_delay = new_step_delay; // 为下个(新的)延时(脉冲周期)赋值7 Q- ?/ R" y, S/ z& l4 B
}( W. \8 U7 j( q8 t, h0 l! {
}
}
如果确实需要原理图和PCB的用户,请联系我们的客服或管理员私下索取谢谢!' F& h8 t) }. i1 k! c' \7 Y. q) P
技术群:171897584& }" R: p/ Q2 L$ Z$ p
公众号:游名开源
是的,参考他们的,有说明:写着参考硬石的