From dacd97c62aae044bc89f7654a3423bab1009a19d Mon Sep 17 00:00:00 2001
From: hanyongwei <2043702190@qq.com>
Date: Thu, 20 Aug 2026 15:05:12 +0800
Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8A=A8=E6=80=81=E4=BF=AE?=
=?UTF-8?q?=E6=94=B9=E9=A2=91=E7=8E=87=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
iar/plsr.dep | 2 +-
modbus/modbus_fc.c | 2 +
plsr/command/plsr_command.c | 71 +++++++++++++++++++++++++++++
plsr/command/plsr_command.h | 5 ++
plsr/param/plsr_param.h | 2 +-
plsr/path_plan/plsr_path_plan.c | 1 +
plsr/path_plan/plsr_path_plan.h | 2 +-
plsr/run_control/plsr_run_control.c | 21 +++++++--
8 files changed, 99 insertions(+), 7 deletions(-)
diff --git a/iar/plsr.dep b/iar/plsr.dep
index e6f1977..3f68f93 100644
--- a/iar/plsr.dep
+++ b/iar/plsr.dep
@@ -2134,7 +2134,7 @@
ICCARM
- 479 198 123 248 102 189 600 470 542 5 1 395 12 6 2 4 13 16 8 597 9 3 0 7 608 135 398 407 409 408 403 402 11 404 405 406 399 394 396 400 397 555 549 534 282 21 543 520 577 560 477 519 528 320 609
+ 479 198 123 248 102 189 600 470 542 5 1 395 12 6 2 4 13 16 8 597 9 3 0 7 608 135 398 407 409 408 403 402 11 404 405 406 399 394 396 400 397 555 549 534 282 21 543 520 577 560 477 519 528 548 320 609
diff --git a/modbus/modbus_fc.c b/modbus/modbus_fc.c
index c778d9d..39e2815 100644
--- a/modbus/modbus_fc.c
+++ b/modbus/modbus_fc.c
@@ -8,6 +8,7 @@
#include "modbus_data.h"
#include "modbus_port.h"
#include "plsr_param.h"
+#include "plsr_command.h"
#include
/*应答帧组帧缓冲 */
@@ -379,6 +380,7 @@ static void WriteMultiRegs(const uint8_t *frame, uint16_t len)
AppendCrcAndSend(g_modbus_tx_buf, 6U);
PlsrParamBlockOnHoldWrite(startAddr, quantity);
+ PlsrCommandOnSegFreqHoldWrite(startAddr, quantity);
}
/*============================================================================*/
diff --git a/plsr/command/plsr_command.c b/plsr/command/plsr_command.c
index 8ab2ac2..bb0b118 100644
--- a/plsr/command/plsr_command.c
+++ b/plsr/command/plsr_command.c
@@ -9,6 +9,8 @@
#include "modbus_rtu.h"
static uint16_t s_fault = PLSR_ERR_NONE;
+static volatile uint8_t s_live_freq_req;
+static volatile uint32_t s_live_freq_hz;
static void PlsrCommandWriteDWord(uint16_t addr, uint32_t value)
{
@@ -45,10 +47,71 @@ uint16_t PlsrCommandGetFault(void)
void PlsrCommandInit(void)
{
WriteHoldReg(PLSR_CTRL_REG, 0U);
+ s_live_freq_req = 0U;
+ s_live_freq_hz = 0U;
PlsrCommandClearFault();
PlsrCommandPublishMonitor();
}
+/**
+ * 上位机只改当前段频率:地址必须是当前段 FREQ_L,且一次写 2 字。
+ * 更新 s_seg[].freq_hz,置位由 Poll 调 ChangeFreq。
+ */
+void PlsrCommandOnSegFreqHoldWrite(uint16_t start_addr, uint16_t quantity)
+{
+ uint16_t cur1;
+ uint16_t seg0;
+ uint16_t off;
+ uint32_t f;
+ PlsrSeg_t *seg;
+
+ if (quantity != 2U)
+ {
+ return;
+ }
+ if (PlsrIsBusy() == 0U)
+ {
+ return;
+ }
+ if (start_addr < PLSR_REG_SEG1_BASE)
+ {
+ return;
+ }
+
+ off = (uint16_t)(start_addr - PLSR_REG_SEG1_BASE);
+ if ((off % PLSR_SEG_STRIDE) != PLSR_SEG_OFF_FREQ_L)
+ {
+ return;
+ }
+ seg0 = (uint16_t)(off / PLSR_SEG_STRIDE);
+ if (seg0 >= PLSR_SEG_MAX)
+ {
+ return;
+ }
+
+ cur1 = PlsrRunControlGetCurSeg();
+ if ((cur1 < 1U) || ((uint16_t)(cur1 - 1U) != seg0))
+ {
+ return;
+ }
+
+ f = (uint32_t)ReadHoldReg(start_addr) |
+ ((uint32_t)ReadHoldReg((uint16_t)(start_addr + 1U)) << 16);
+ if ((f < 1U) || (f > 100000U))
+ {
+ return;
+ }
+
+ seg = PlsrParamGetSeg(seg0);
+ if (seg != (PlsrSeg_t *)0)
+ {
+ seg->freq_hz = (int32_t)f;
+ }
+
+ s_live_freq_hz = f;
+ s_live_freq_req = 1U;
+}
+
void PlsrCommandPoll(void)
{
uint16_t ctrl = ReadHoldReg(PLSR_CTRL_REG);
@@ -80,5 +143,13 @@ void PlsrCommandPoll(void)
}
}
+ /* 动态改频:标志置位后按新目标重规划剩余脉冲 */
+ if (s_live_freq_req != 0U)
+ {
+ uint32_t f = s_live_freq_hz;
+ s_live_freq_req = 0U;
+ (void)PlsrChangeFreq(f);
+ }
+
PlsrCommandPublishMonitor();
}
diff --git a/plsr/command/plsr_command.h b/plsr/command/plsr_command.h
index e6a8b99..958b3f8 100644
--- a/plsr/command/plsr_command.h
+++ b/plsr/command/plsr_command.h
@@ -33,5 +33,10 @@ void PlsrCommandPoll(void);
void PlsrCommandSetFault(uint16_t code);
void PlsrCommandClearFault(void);
uint16_t PlsrCommandGetFault(void);
+/**
+ * FC10 写段频率双字后调用:仅当地址对应「当前运行段」频率时,
+ * 更新段表并置标志,由 Poll 调 ChangeFreq。
+ */
+void PlsrCommandOnSegFreqHoldWrite(uint16_t start_addr, uint16_t quantity);
#endif
diff --git a/plsr/param/plsr_param.h b/plsr/param/plsr_param.h
index ca581ae..6e63602 100644
--- a/plsr/param/plsr_param.h
+++ b/plsr/param/plsr_param.h
@@ -77,7 +77,7 @@ typedef enum {
typedef enum {
PLSR_POS_RELATIVE = 0, /* 脉冲数=相对位移 */
- PLSR_POS_ABSOLUTE = 1 /* 脉冲数=绝对坐标 */
+ PLSR_POS_ABSOLUTE = 1 /* 脉冲数=相对本次启动原点的绝对坐标 */
} PlsrPosMode_e;
typedef enum {
diff --git a/plsr/path_plan/plsr_path_plan.c b/plsr/path_plan/plsr_path_plan.c
index d6caeec..756c486 100644
--- a/plsr/path_plan/plsr_path_plan.c
+++ b/plsr/path_plan/plsr_path_plan.c
@@ -41,6 +41,7 @@ uint8_t PlsrPathPlanIsForward(uint16_t seg_0based, int32_t acc_pulse)
if (cfg->run_mode == PLSR_POS_ABSOLUTE)
{
+ /* move = 段目标 − 相对本次启动原点的位置 */
move = seg->pulse_cnt - acc_pulse;
}
else
diff --git a/plsr/path_plan/plsr_path_plan.h b/plsr/path_plan/plsr_path_plan.h
index ffe6414..356d0ee 100644
--- a/plsr/path_plan/plsr_path_plan.h
+++ b/plsr/path_plan/plsr_path_plan.h
@@ -21,7 +21,7 @@ int16_t PlsrPathPlanNextSeg(uint16_t cur_seg_0based);
/**
* @brief 判断该段运动方向
- * @param acc_pulse 当前累计脉冲(绝对模式算位移用)
+ * @param acc_pulse 相对本次启动原点的位置(绝对模式算位移用)
* @return 1=正向,0=反向
*/
uint8_t PlsrPathPlanIsForward(uint16_t seg_0based, int32_t acc_pulse);
diff --git a/plsr/run_control/plsr_run_control.c b/plsr/run_control/plsr_run_control.c
index af8660a..34c026e 100644
--- a/plsr/run_control/plsr_run_control.c
+++ b/plsr/run_control/plsr_run_control.c
@@ -49,6 +49,7 @@ static volatile uint32_t s_cur_freq;
static volatile int32_t s_done;
static volatile int32_t s_target;
static volatile int32_t s_acc_pulse;
+static int32_t s_abs_origin; /* 本次启动时累计作绝对原点 */
static INT32U s_dir_deadline;
static uint32_t s_wait_deadline_ms; /* TIM3:段后 WAIT 时间 / ACT※4 剩余 */
@@ -101,6 +102,7 @@ static uint16_t PlsrRunControlWaitTimeMs(const PlsrSeg_t *seg);
static void PlsrRunControlPlanSeg(uint32_t total, uint32_t f_from,
uint32_t f_tgt, uint32_t f_end,
uint16_t accel_ms, uint16_t decel_ms);
+static int32_t PlsrRunControlAbsLocalPos(void);
static uint32_t PlsrRunControlClampSpeed(uint32_t spd);
static uint8_t PlsrRunControlGetSegTargetFreq(int32_t freq_hz,
uint32_t default_spd,
@@ -153,7 +155,7 @@ static void PlsrRunControlCutSegToNext(void)
next0 = PlsrPathPlanResolveAfterSeg(s_cur_seg);
keep = 0U;
if ((next0 >= 0) && (s_pwm_on != 0U) && (s_cur_freq >= 1U) &&
- (PlsrPathPlanIsForward((uint16_t)next0, s_acc_pulse) == s_forward))
+ (PlsrPathPlanIsForward((uint16_t)next0, PlsrRunControlAbsLocalPos()) == s_forward))
{
keep = 1U;
}
@@ -199,7 +201,7 @@ static void PlsrRunControlActExpire(void)
if ((next0 >= 0) &&
((s_pwm_on != 0U) || (s_act_handoff_keep != 0U)) &&
(s_cur_freq >= 1U) &&
- (PlsrPathPlanIsForward((uint16_t)next0, s_acc_pulse) == s_forward))
+ (PlsrPathPlanIsForward((uint16_t)next0, PlsrRunControlAbsLocalPos()) == s_forward))
{
keep = 1U;
}
@@ -541,7 +543,7 @@ static uint8_t PlsrRunControlWillFollowKeep(uint16_t cur_seg)
{
return 0U;
}
- if (PlsrPathPlanIsForward((uint16_t)next0, s_acc_pulse) != s_forward)
+ if (PlsrPathPlanIsForward((uint16_t)next0, PlsrRunControlAbsLocalPos()) != s_forward)
{
return 0U;
}
@@ -674,6 +676,12 @@ static uint32_t PlsrRunControlRemainPulses(void)
return 0U;
}
+/** 绝对模式:相对本次启动原点的位置 */
+static int32_t PlsrRunControlAbsLocalPos(void)
+{
+ return s_acc_pulse - s_abs_origin;
+}
+
static void PlsrRunControlEnterDecel(uint32_t from_hz, uint32_t remain_pulses)
{
PlsrRunControlEnterPhase(PH_DECEL, from_hz);
@@ -966,7 +974,8 @@ static void PlsrRunControlBeginSeg(uint16_t seg_0)
if (cfg->run_mode == PLSR_POS_ABSOLUTE)
{
- move = cnt - s_acc_pulse;
+ /* 以本次启动时累计为原点:move = 段目标 − 相对原点位置 */
+ move = cnt - PlsrRunControlAbsLocalPos();
if (move == 0)
{
s_busy = 1U;
@@ -1052,6 +1061,7 @@ void PlsrRunControlInit(void)
s_done = 0;
s_target = 0;
s_acc_pulse = 0;
+ s_abs_origin = 0;
s_follow_cont = 0U;
s_chain_freq = 0U;
s_chain_valid = 0U;
@@ -1096,6 +1106,8 @@ uint8_t PlsrRunControlStart(uint16_t start_seg_1based)
s_chain_valid = 0U;
s_chain_freq = 0U;
s_cur_freq = PlsrRunControlClampSpeed(cfg->start_speed);
+ /* 绝对模式:本次启动瞬间累计作为坐标原点(不清零监控累计) */
+ s_abs_origin = s_acc_pulse;
PlsrSignalIoClearEdges();
PlsrRunControlBeginSeg((uint16_t)(start_seg_1based - 1U));
return 1U;
@@ -1375,6 +1387,7 @@ int32_t PlsrRunControlGetAccPulse(void)
void PlsrRunControlClearAccPulse(void)
{
s_acc_pulse = 0;
+ s_abs_origin = 0;
}
uint16_t PlsrRunControlGetCurSeg(void)