已知起点和终点,数控装置按算法把中间点「数据密化」出来,刀具实际沿小折线走,宏观上就是那条直线——这个过程叫插补。

| 大类 | 思路 | 适用 |
|---|---|---|
| 脉冲增量插补(行程标量) | 每次插补输出一个行程增量脉冲,脉冲当量 = 一个脉冲的移动量 | 步进电机开环系统 |
| 数字增量插补(时间标量) | 粗插补算各轴增量 + 精插补出速度指令 | 闭环/半闭环系统 |
脉冲增量法里有逐点比较法、数字积分法、最小偏差法等,本章主角是逐点比较法:每走一步都与规定图形比较一次,偏了就往回「找补」。
四个步骤周而复始:① 偏差判别 → ② 坐标进给 → ③ 偏差计算 → ④ 终点判别。


设直线终点 $(X_e, Y_e)$、动点 $P(X_i, Y_i)$,偏差判别式:
偏差递推(免乘法,只用到终点坐标和上一步偏差):
终点判别三种:总步长法($|X_e|+|Y_e|$ 为总步数,每步减 1,减到 0 停——本实验采用)、终点坐标法、投影法。
四个象限的进给规则(偏差公式不变,对绝对值坐标计算;符号与第一象限相反的轴电机反向即可):

| 象限 | F > 0 进给 | F < 0 进给 |
|---|---|---|
| 第一象限 | +X | +Y |
| 第二象限 | −X | +Y |
| 第三象限 | −X | −Y |
| 第四象限 | +X | −Y |
X 轴用接口三(TIM8_CH3=PI7、DIR3=PB2、EN3=PF11),Y 轴用接口四(TIM8_CH4=PC9、DIR4=PH2、EN4=PH3),两根丝杆滑台组成 X-Y 平台,1.0A、8 细分。PWM2 模式:比较值 = Speed、ARR = Speed×2,输出恰好 50% 占空比。
/* 直线增量插补:算总步数并完成第一步进给 */
void line_incmove(uint32_t IncX, uint32_t IncY, uint32_t Speed)
{
g_pol_par.f_e = 0; /* 偏差置零 */
g_pol_par.end_x = IncX; g_pol_par.end_y = IncY;
g_pol_par.end_pulse = g_pol_par.end_y + g_pol_par.end_x; /* 总步长法 */
if (g_pol_par.end_y > g_pol_par.end_x) { /* F=0 按终点定方向 */
g_pol_par.act_axis = AXIS_Y; /* 先进给 Y 轴 */
g_pol_par.f_e = g_pol_par.f_e + g_pol_par.end_x; /* F += Xe */
} else {
g_pol_par.act_axis = AXIS_X; /* 先进给 X 轴 */
g_pol_par.f_e = g_pol_par.f_e - g_pol_par.end_y; /* F -= Ye */
}
__HAL_TIM_SET_AUTORELOAD(&g_atimx_handle, Speed * 2);
}/* 更新中断里完成后续每一步插补 */
if (g_pol_par.f_e > 0) { /* 在线上方 → 向 X 进给 */
g_pol_par.act_axis = AXIS_X;
g_pol_par.f_e = g_pol_par.f_e - g_pol_par.end_y;
} else if (g_pol_par.f_e < 0) { /* 在线下方 → 向 Y 进给 */
g_pol_par.act_axis = AXIS_Y;
g_pol_par.f_e = g_pol_par.f_e + g_pol_par.end_x;
} else if (g_pol_par.f_e == 0) { /* 在线上,比较终点再走 */
if (g_pol_par.end_y > g_pol_par.end_x)
{ g_pol_par.act_axis = AXIS_Y; g_pol_par.f_e += g_pol_par.end_x; }
else
{ g_pol_par.act_axis = AXIS_X; g_pol_par.f_e -= g_pol_par.end_y; }
}
if (axis != g_pol_par.act_axis) { /* 换进给轴时切换通道 */
TIM_CCxChannelCmd(TIM8, st_motor[axis].pulse_channel, TIM_CCx_DISABLE);
TIM_CCxChannelCmd(TIM8, st_motor[g_pol_par.act_axis].pulse_channel,
TIM_CCx_ENABLE);
}
g_pol_par.end_pulse--; /* 终点判别:总步数减 1 */
if (g_pol_par.end_pulse == 0) g_motor_sta = STATE_STOP;实验:KEY0 启动后依次走第一、四、三、二象限(line_inpolation(5*1600, ±5*1600, 2000)),坐标正负号决定各轴电机方向,最终轨迹是一个正方形。