浏览代码

删掉二分降峰后重复判断逻辑

Signed-off-by: hanyongwei <2043702190@qq.com>
dev3
hanyongwei 2 周前
父节点
当前提交
5bd7cb9c53
共有 10 个文件被更改,包括 1887 次插入1853 次删除
  1. +811
    -826
      plsr/accel_curve/plsr_accel_curve.c
  2. +6
    -3
      plsr/accel_curve/plsr_accel_curve.h
  3. +29
    -38
      plsr/command/plsr_command.c
  4. +41
    -39
      plsr/param/plsr_param.c
  5. +1
    -1
      plsr/plsr.c
  6. +3
    -3
      plsr/plsr.h
  7. +273
    -266
      plsr/pulse_driver/plsr_pulse_driver.c
  8. +4
    -4
      plsr/pulse_driver/plsr_pulse_driver.h
  9. +682
    -647
      plsr/run_control/plsr_run_control.c
  10. +37
    -26
      plsr/signal_io/plsr_signal_io.c

+ 811
- 826
plsr/accel_curve/plsr_accel_curve.c
文件差异内容过多而无法显示
查看文件


+ 6
- 3
plsr/accel_curve/plsr_accel_curve.h 查看文件

@@ -80,20 +80,23 @@ typedef struct {
uint8_t freq_rising; /* 1=频率升高,0=降低 */ uint8_t freq_rising; /* 1=频率升高,0=降低 */
uint8_t is_active; /* 1=当前相仍在运行 */ uint8_t is_active; /* 1=当前相仍在运行 */
uint8_t freq_table_id; /* 0=不用表,1=加速表,2=减速表 */ uint8_t freq_table_id; /* 0=不用表,1=加速表,2=减速表 */
PlsrAccelMode_e curve_mode;
PlsrAccelMode_e curve_mode; /* 直线 / S / 正弦 */
} PlsrAccelRuntime_t; } PlsrAccelRuntime_t;


/* 当前段唯一的曲线规划和逐拍状态,run_control 直接使用,不再另存副本。 */ /* 当前段唯一的曲线规划和逐拍状态,run_control 直接使用,不再另存副本。 */
extern PlsrAccelPlan_t g_plsr_accel_plan;
extern PlsrAccelRuntime_t g_plsr_accel_runtime;
extern PlsrAccelPlan_t g_plsr_accel_plan; /* 本段三相规划结果 */
extern PlsrAccelRuntime_t g_plsr_accel_runtime; /* 当前相 ISR 逐拍状态 */


/** PlanSeg 后调用:预建 S/正弦加减速频率表(勿在 ISR) */ /** PlanSeg 后调用:预建 S/正弦加减速频率表(勿在 ISR) */
void PlsrAccelPrebuildFreqTables(const PlsrAccelPlan_t *plan); void PlsrAccelPrebuildFreqTables(const PlsrAccelPlan_t *plan);


/** 进入加速相:起→峰,并绑加速预建表 */
void PlsrAccelBeginAccel(PlsrAccelRuntime_t *runtime, void PlsrAccelBeginAccel(PlsrAccelRuntime_t *runtime,
const PlsrAccelPlan_t *plan); const PlsrAccelPlan_t *plan);
/** 进入减速相:峰→止,并绑减速预建表 */
void PlsrAccelBeginDecel(PlsrAccelRuntime_t *runtime, void PlsrAccelBeginDecel(PlsrAccelRuntime_t *runtime,
const PlsrAccelPlan_t *plan); const PlsrAccelPlan_t *plan);
/** 进入匀速相:钉峰值,ISR 不再改频 */
void PlsrAccelBeginConstSpeed(PlsrAccelRuntime_t *runtime, void PlsrAccelBeginConstSpeed(PlsrAccelRuntime_t *runtime,
const PlsrAccelPlan_t *plan); const PlsrAccelPlan_t *plan);




+ 29
- 38
plsr/command/plsr_command.c 查看文件

@@ -30,9 +30,9 @@
* s_live_freq_req — 运行中写频请求标志,Poll 消费后清 0 * s_live_freq_req — 运行中写频请求标志,Poll 消费后清 0
* s_live_freq_hz — 待应用的 new_tgt_hz * s_live_freq_hz — 待应用的 new_tgt_hz
*/ */
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 uint16_t s_fault = PLSR_ERR_NONE; /* 故障码镜像,与 0x2006 同步 */
static volatile uint8_t s_live_freq_req; /* 1=运行中改频待 Poll 消费 */
static volatile uint32_t s_live_freq_hz; /* 待应用的新目标频率 Hz */


/** /**
* @brief 写 32 位值到相邻两个modbus保持寄存器 * @brief 写 32 位值到相邻两个modbus保持寄存器
@@ -57,9 +57,9 @@ static void PlsrCommandPublishMonitor(void)


if (g_plsr_busy != 0U) if (g_plsr_busy != 0U)
{ {
PlsrCommandWriteDWord(PLSR_MON_FREQ_L, g_plsr_output_freq_hz);
WriteHoldReg(PLSR_MON_RUN_STATUS, 1U);
WriteHoldReg(PLSR_MON_CUR_SEG, (uint16_t)(g_plsr_cur_seg_idx + 1U));
PlsrCommandWriteDWord(PLSR_MON_FREQ_L, g_plsr_output_freq_hz); /* 0x2002/03 当前频 */
WriteHoldReg(PLSR_MON_RUN_STATUS, 1U); /* 0x2004 运行中 */
WriteHoldReg(PLSR_MON_CUR_SEG, (uint16_t)(g_plsr_cur_seg_idx + 1U)); /* 0x2005 1-based */
} }
else else
{ {
@@ -118,18 +118,18 @@ void PlsrCommandInit(void)
*/ */
void PlsrCommandOnSegFreqHoldWrite(uint16_t start_addr, uint16_t quantity) void PlsrCommandOnSegFreqHoldWrite(uint16_t start_addr, uint16_t quantity)
{ {
uint16_t cur_seg;//当前运行段
uint16_t seg;//当前改频段
uint16_t offset;//偏移量
uint16_t cur_seg; /* 当前运行段(1-based) */
uint16_t seg; /* 本次写入对应的段下标(0-based) */
uint16_t offset;
uint32_t freqency; uint32_t freqency;


if (quantity != 2U) if (quantity != 2U)
{ {
return;
return; /* 须为频率双字 */
} }
if (g_plsr_busy == 0U) if (g_plsr_busy == 0U)
{ {
return;
return; /* 空闲改频走参数块,不走本路径 */
} }
if (start_addr < PLSR_REG_SEG1_BASE) if (start_addr < PLSR_REG_SEG1_BASE)
{ {
@@ -139,7 +139,7 @@ void PlsrCommandOnSegFreqHoldWrite(uint16_t start_addr, uint16_t quantity)
offset = (uint16_t)(start_addr - PLSR_REG_SEG1_BASE); offset = (uint16_t)(start_addr - PLSR_REG_SEG1_BASE);
if ((offset % PLSR_SEG_STRIDE) != PLSR_SEG_OFF_FREQ_L) if ((offset % PLSR_SEG_STRIDE) != PLSR_SEG_OFF_FREQ_L)
{ {
return;
return; /* 地址须对齐该段 FREQ_L */
} }
seg = (uint16_t)(offset / PLSR_SEG_STRIDE); seg = (uint16_t)(offset / PLSR_SEG_STRIDE);
if (seg >= PLSR_SEG_MAX) if (seg >= PLSR_SEG_MAX)
@@ -150,24 +150,22 @@ void PlsrCommandOnSegFreqHoldWrite(uint16_t start_addr, uint16_t quantity)
cur_seg = (uint16_t)(g_plsr_cur_seg_idx + 1U); cur_seg = (uint16_t)(g_plsr_cur_seg_idx + 1U);
if ((cur_seg < 1U) || ((uint16_t)(cur_seg - 1U) != seg)) if ((cur_seg < 1U) || ((uint16_t)(cur_seg - 1U) != seg))
{ {
return;
return; /* 仅允许改当前运行段 */
} }


freqency = (uint32_t)ReadHoldReg(start_addr) | freqency = (uint32_t)ReadHoldReg(start_addr) |
((uint32_t)ReadHoldReg((uint16_t)(start_addr + 1U)) << 16); ((uint32_t)ReadHoldReg((uint16_t)(start_addr + 1U)) << 16);
/* 运行中改频非法不改段表、不请求 ChangeFreq */
if ((freqency < 1U) || (freqency > 100000U)) if ((freqency < 1U) || (freqency > 100000U))
{ {
PlsrCommandSetFault(PLSR_ERR_FREQ_ILLEGAL);
PlsrCommandSetFault(PLSR_ERR_FREQ_ILLEGAL); /* 非法:不改段表、不请求 */
return; return;
} }


g_plsr_segs[seg].freq_hz = (int32_t)freqency;
/* 运行中改频只把该段频率写入 BKP */
PlsrPersistSaveSegFreqToBkp(seg, freqency);
g_plsr_segs[seg].freq_hz = (int32_t)freqency; /* 更新运行段表 */
PlsrPersistSaveSegFreqToBkp(seg, freqency); /* 仅该段频率落 BKP */


s_live_freq_hz = freqency; s_live_freq_hz = freqency;
s_live_freq_req = 1U;
s_live_freq_req = 1U; /* 交 Poll → ChangeFreq */
} }


/** /**
@@ -183,63 +181,56 @@ void PlsrCommandOnSegFreqHoldWrite(uint16_t start_addr, uint16_t quantity)
void PlsrCommandPoll(void) void PlsrCommandPoll(void)
{ {
uint16_t ctrl = ReadHoldReg(PLSR_CTRL_REG); uint16_t ctrl = ReadHoldReg(PLSR_CTRL_REG);
uint8_t skip_monitor = 0U;
uint8_t skip_monitor = 0U; /* 精确等待时跳过本拍监控刷新 */


if (ctrl != 0U) if (ctrl != 0U)
{ {
WriteHoldReg(PLSR_CTRL_REG, 0U);
WriteHoldReg(PLSR_CTRL_REG, 0U); /* 立即清,避免重复触发 */


if ((ctrl & PLSR_CTRL_BIT_STOP) != 0U) if ((ctrl & PLSR_CTRL_BIT_STOP) != 0U)
{ {
PlsrStop();/*停止输出*/
PlsrStop(); /* 急停 */
} }


if ((ctrl & PLSR_CTRL_BIT_CLR) != 0U) if ((ctrl & PLSR_CTRL_BIT_CLR) != 0U)
{ {
PlsrClearAccPulse();/*清零累计脉冲与绝对原点*/
PlsrCommandClearFault(); /* 清故障码同步清累计脉冲 */
PlsrClearAccPulse(); /* 清累计 + 绝对原点 */
PlsrCommandClearFault(); /* 同步清故障码 */
} }


/* 同时有停止位时不启动 */
/* START:同拍有 STOP 则不启 */
if (((ctrl & PLSR_CTRL_BIT_START) != 0U) && if (((ctrl & PLSR_CTRL_BIT_START) != 0U) &&
((ctrl & PLSR_CTRL_BIT_STOP) == 0U)) ((ctrl & PLSR_CTRL_BIT_STOP) == 0U))
{ {
if (g_plsr_busy != 0U) if (g_plsr_busy != 0U)
{ {
/* 0x0C:运行中重复 START,启动无效 */
PlsrCommandSetFault(PLSR_ERR_DUP_START);
PlsrCommandSetFault(PLSR_ERR_DUP_START); /* 0x0C 重复启动 */
} }
/*如果禁止启动,使用停止指令*/
else if (PlsrCommandIsStartBlocked() != 0U) else if (PlsrCommandIsStartBlocked() != 0U)
{ {
/* 0x04~0x0B 故障码:禁止启动 */
PlsrStop();
PlsrStop(); /* 0x04~0x0B:拒启,仅停 */
} }
/*如果允许运行,先停止清标志位,再开始输出*/
else else
{ {
PlsrStop();
/*启动输出入口*/
PlsrStop(); /* 先清残留再启 */
(void)PlsrStart(PlsrParamGetStartSeg()); (void)PlsrStart(PlsrParamGetStartSeg());
/*如果不需要精确等待,就跳过监控*/
if (PlsrRunControlIsPreciseWait() != 0U) if (PlsrRunControlIsPreciseWait() != 0U)
{ {
skip_monitor = 1U;
skip_monitor = 1U; /* 换向/WAIT 精确等 TIM5 */
} }
} }
} }
} }


/* 动态改频:标志置位后按新目标重规划剩余脉冲 */
if (s_live_freq_req != 0U) if (s_live_freq_req != 0U)
{ {
uint32_t freq = s_live_freq_hz; uint32_t freq = s_live_freq_hz;
s_live_freq_req = 0U; s_live_freq_req = 0U;
(void)PlsrChangeFreq(freq);/*动态改频函数入口*/
(void)PlsrChangeFreq(freq); /* 重规划剩余脉冲 */
} }


if (skip_monitor == 0U) if (skip_monitor == 0U)
{ {
PlsrCommandPublishMonitor();/*刷新全部监控寄存器*/
PlsrCommandPublishMonitor(); /* 回写 0x2000~0x2006 */
} }
} }

+ 41
- 39
plsr/param/plsr_param.c 查看文件

@@ -17,30 +17,30 @@
#include "modbus_rtu.h" #include "modbus_rtu.h"
#include "ucos_ii.h" #include "ucos_ii.h"


PlsrCfg_t g_plsr_config;
PlsrSeg_t g_plsr_segs[PLSR_SEG_MAX];
PlsrCfg_t g_plsr_config; /* 公共参数运行映像 */
PlsrSeg_t g_plsr_segs[PLSR_SEG_MAX]; /* 段表运行映像(最多 PLSR_SEG_MAX) */


static OS_EVENT *s_param_sem; /* 分帧收齐后唤醒 ParamBlockTask */ static OS_EVENT *s_param_sem; /* 分帧收齐后唤醒 ParamBlockTask */
static volatile uint16_t s_expect_frames; /* 本批期望总帧数 = 5 + 段数 */ static volatile uint16_t s_expect_frames; /* 本批期望总帧数 = 5 + 段数 */
static volatile uint16_t s_recv_frames; /* 已收帧计数 */ static volatile uint16_t s_recv_frames; /* 已收帧计数 */
static volatile uint8_t s_xfer_active; /* 1=正在接收一批分帧 */ static volatile uint8_t s_xfer_active; /* 1=正在接收一批分帧 */


/** @return 有效段数,须在[0, PLSR_SEG_MAX]之间 */
/** @return 有效段数,软钳到 [0, PLSR_SEG_MAX] */
uint16_t PlsrParamGetSegCount(void) uint16_t PlsrParamGetSegCount(void)
{ {
if (g_plsr_config.seg_count < 1U) if (g_plsr_config.seg_count < 1U)
{ {
return 0U;
return 0U; /* 无有效段 */
} }
if (g_plsr_config.seg_count > PLSR_SEG_MAX) if (g_plsr_config.seg_count > PLSR_SEG_MAX)
{ {
return (uint16_t)PLSR_SEG_MAX;
return (uint16_t)PLSR_SEG_MAX; /* 超上限钳住 */
} }
return g_plsr_config.seg_count; return g_plsr_config.seg_count;
} }


/** /**
* @brief 启动段 1-based
* @brief 启动段 1-based,软钳到 [1, seg_count]
*/ */
uint16_t PlsrParamGetStartSeg(void) uint16_t PlsrParamGetStartSeg(void)
{ {
@@ -48,7 +48,7 @@ uint16_t PlsrParamGetStartSeg(void)


if (n < 1U) if (n < 1U)
{ {
return 1U;
return 1U; /* 无段时仍返回 1 */
} }
if (g_plsr_config.start_seg < 1U) if (g_plsr_config.start_seg < 1U)
{ {
@@ -56,7 +56,7 @@ uint16_t PlsrParamGetStartSeg(void)
} }
if (g_plsr_config.start_seg > n) if (g_plsr_config.start_seg > n)
{ {
return n;
return n; /* 超出则钳到末段 */
} }
return g_plsr_config.start_seg; return g_plsr_config.start_seg;
} }
@@ -120,6 +120,7 @@ static uint8_t PlsrParamIsSegFrameWrite(uint16_t start_addr, uint16_t quantity)
#define PLSR_PARAM_SPD_MIN_HZ 1U #define PLSR_PARAM_SPD_MIN_HZ 1U
#define PLSR_PARAM_SPD_MAX_HZ 100000U #define PLSR_PARAM_SPD_MAX_HZ 100000U


/** 速度 Hz 是否落在 [1, 100k](默认速度/段频非 0) */
static uint8_t PlsrParamIsSpeedHzValid(uint32_t hz) static uint8_t PlsrParamIsSpeedHzValid(uint32_t hz)
{ {
return ((hz >= PLSR_PARAM_SPD_MIN_HZ) && (hz <= PLSR_PARAM_SPD_MAX_HZ)) ? 1U : 0U; return ((hz >= PLSR_PARAM_SPD_MIN_HZ) && (hz <= PLSR_PARAM_SPD_MAX_HZ)) ? 1U : 0U;
@@ -181,41 +182,41 @@ uint8_t PlsrParamBlockApplyFromHold(void)
uint16_t base; uint16_t base;
uint16_t fault = PLSR_ERR_NONE; uint16_t fault = PLSR_ERR_NONE;


g_plsr_config.pulse_y = ReadHoldReg(PLSR_REG_PULSE_Y);
g_plsr_config.pulse_y = ReadHoldReg(PLSR_REG_PULSE_Y); /* 脉冲端子 Y0~Y2 */
if (g_plsr_config.pulse_y > 2U) if (g_plsr_config.pulse_y > 2U)
{ {
fault = PLSR_ERR_PULSE_Y;
fault = PLSR_ERR_PULSE_Y; /* 0x07:端子非法 */
} }


g_plsr_config.dir_y = ReadHoldReg(PLSR_REG_DIR_Y);
g_plsr_config.dir_y = ReadHoldReg(PLSR_REG_DIR_Y); /* 方向端子须为 Y3 */
if (g_plsr_config.dir_y != 3U) if (g_plsr_config.dir_y != 3U)
{ {
fault = PLSR_ERR_DIR_Y;
fault = PLSR_ERR_DIR_Y; /* 0x08 */
} }


g_plsr_config.wait_x_sel = ReadHoldReg(PLSR_REG_WAIT_X) ? 1U : 0U;
g_plsr_config.ext_x_sel = ReadHoldReg(PLSR_REG_EXT_X) ? 1U : 0U;
g_plsr_config.wait_x_sel = ReadHoldReg(PLSR_REG_WAIT_X) ? 1U : 0U; /* 0=X4,1=X5 */
g_plsr_config.ext_x_sel = ReadHoldReg(PLSR_REG_EXT_X) ? 1U : 0U; /* 0=X4,1=X5 */
g_plsr_config.send_mode = (PlsrSendMode_e)(ReadHoldReg(PLSR_REG_SEND_MODE) ? 1U : 0U); g_plsr_config.send_mode = (PlsrSendMode_e)(ReadHoldReg(PLSR_REG_SEND_MODE) ? 1U : 0U);
g_plsr_config.dir_delay_ms = ReadHoldReg(PLSR_REG_DIR_DELAY);
g_plsr_config.dir_delay_ms = ReadHoldReg(PLSR_REG_DIR_DELAY); /* 换向延时 ms */
g_plsr_config.dir_logic = (ReadHoldReg(PLSR_REG_DIR_LOGIC) != 0U) ? g_plsr_config.dir_logic = (ReadHoldReg(PLSR_REG_DIR_LOGIC) != 0U) ?
PLSR_DIR_LOGIC_NEG : PLSR_DIR_LOGIC_POS;
PLSR_DIR_LOGIC_NEG : PLSR_DIR_LOGIC_POS; /* 方向电平逻辑 */
g_plsr_config.accel_mode = (PlsrAccelMode_e)ReadHoldReg(PLSR_REG_ACCEL_MODE); g_plsr_config.accel_mode = (PlsrAccelMode_e)ReadHoldReg(PLSR_REG_ACCEL_MODE);
g_plsr_config.run_mode = (ReadHoldReg(PLSR_REG_RUN_MODE) != 0U) ? g_plsr_config.run_mode = (ReadHoldReg(PLSR_REG_RUN_MODE) != 0U) ?
PLSR_POS_ABSOLUTE : PLSR_POS_RELATIVE;
PLSR_POS_ABSOLUTE : PLSR_POS_RELATIVE; /* 绝对/相对 */


n = ReadHoldReg(PLSR_REG_SEG_COUNT); n = ReadHoldReg(PLSR_REG_SEG_COUNT);
g_plsr_config.seg_count = n; g_plsr_config.seg_count = n;
if ((n < 1U) || (n > PLSR_SEG_MAX)) if ((n < 1U) || (n > PLSR_SEG_MAX))
{ {
fault = PLSR_ERR_SEG_COUNT;
fault = PLSR_ERR_SEG_COUNT; /* 0x09:段数越界 */
} }


g_plsr_config.start_seg = ReadHoldReg(PLSR_REG_START_SEG);
g_plsr_config.start_seg = ReadHoldReg(PLSR_REG_START_SEG); /* 1-based 启动段 */
if ((n >= 1U) && (n <= PLSR_SEG_MAX)) if ((n >= 1U) && (n <= PLSR_SEG_MAX))
{ {
if ((g_plsr_config.start_seg < 1U) || (g_plsr_config.start_seg > n)) if ((g_plsr_config.start_seg < 1U) || (g_plsr_config.start_seg > n))
{ {
fault = PLSR_ERR_START_SEG;
fault = PLSR_ERR_START_SEG; /* 0x0A:启动段越界 */
} }
} }
else if (g_plsr_config.start_seg < 1U) else if (g_plsr_config.start_seg < 1U)
@@ -226,23 +227,23 @@ uint8_t PlsrParamBlockApplyFromHold(void)
g_plsr_config.default_speed = PlsrParamReadDWord(PLSR_REG_DEFAULT_SPD_L); g_plsr_config.default_speed = PlsrParamReadDWord(PLSR_REG_DEFAULT_SPD_L);
if (PlsrParamIsSpeedHzValid(g_plsr_config.default_speed) == 0U) if (PlsrParamIsSpeedHzValid(g_plsr_config.default_speed) == 0U)
{ {
fault = PLSR_ERR_DEFAULT_SPD;
fault = PLSR_ERR_DEFAULT_SPD; /* 0x0B:默认速度非法 */
} }


g_plsr_config.start_speed = PlsrParamReadDWord(PLSR_REG_START_SPD_L);
g_plsr_config.start_speed = PlsrParamReadDWord(PLSR_REG_START_SPD_L); /* 起跳频,0 合法 */
if (PlsrParamIsStartEndSpeedValid(g_plsr_config.start_speed) == 0U) if (PlsrParamIsStartEndSpeedValid(g_plsr_config.start_speed) == 0U)
{ {
fault = PLSR_ERR_START_END_SPD; fault = PLSR_ERR_START_END_SPD;
} }


g_plsr_config.end_speed = PlsrParamReadDWord(PLSR_REG_END_SPD_L);
g_plsr_config.end_speed = PlsrParamReadDWord(PLSR_REG_END_SPD_L); /* 止速,0 合法 */
if (PlsrParamIsStartEndSpeedValid(g_plsr_config.end_speed) == 0U) if (PlsrParamIsStartEndSpeedValid(g_plsr_config.end_speed) == 0U)
{ {
fault = PLSR_ERR_START_END_SPD; fault = PLSR_ERR_START_END_SPD;
} }


g_plsr_config.accel_ms = ReadHoldReg(PLSR_REG_ACCEL_MS);
g_plsr_config.decel_ms = ReadHoldReg(PLSR_REG_DECEL_MS);
g_plsr_config.accel_ms = ReadHoldReg(PLSR_REG_ACCEL_MS); /* 加速参考时间 */
g_plsr_config.decel_ms = ReadHoldReg(PLSR_REG_DECEL_MS); /* 减速参考时间 */


if ((n >= 1U) && (n <= PLSR_SEG_MAX)) if ((n >= 1U) && (n <= PLSR_SEG_MAX))
{ {
@@ -253,32 +254,32 @@ uint8_t PlsrParamBlockApplyFromHold(void)
(int32_t)PlsrParamReadDWord((uint16_t)(base + PLSR_SEG_OFF_FREQ_L)); (int32_t)PlsrParamReadDWord((uint16_t)(base + PLSR_SEG_OFF_FREQ_L));
if (PlsrParamIsSegFreqValid(g_plsr_segs[i].freq_hz) == 0U) if (PlsrParamIsSegFreqValid(g_plsr_segs[i].freq_hz) == 0U)
{ {
fault = PLSR_ERR_FREQ_ILLEGAL;
fault = PLSR_ERR_FREQ_ILLEGAL; /* 0x04:段频率非法 */
} }


g_plsr_segs[i].pulse_cnt = g_plsr_segs[i].pulse_cnt =
(int32_t)PlsrParamReadDWord((uint16_t)(base + PLSR_SEG_OFF_PULSE_L)); (int32_t)PlsrParamReadDWord((uint16_t)(base + PLSR_SEG_OFF_PULSE_L));
if (PlsrParamIsPulseCntValid(g_plsr_segs[i].pulse_cnt) == 0U) if (PlsrParamIsPulseCntValid(g_plsr_segs[i].pulse_cnt) == 0U)
{ {
fault = PLSR_ERR_PULSE_RANGE;
fault = PLSR_ERR_PULSE_RANGE; /* 0x05:脉冲数 INT_MIN */
} }


g_plsr_segs[i].wait_type = g_plsr_segs[i].wait_type =
(PlsrWaitType_e)ReadHoldReg((uint16_t)(base + PLSR_SEG_OFF_WAIT)); (PlsrWaitType_e)ReadHoldReg((uint16_t)(base + PLSR_SEG_OFF_WAIT));
g_plsr_segs[i].wait_ms = g_plsr_segs[i].wait_ms =
ReadHoldReg((uint16_t)(base + PLSR_SEG_OFF_WAIT_MS));
ReadHoldReg((uint16_t)(base + PLSR_SEG_OFF_WAIT_MS)); /* 段后等待 ms */
g_plsr_segs[i].act_ms = g_plsr_segs[i].act_ms =
ReadHoldReg((uint16_t)(base + PLSR_SEG_OFF_ACT_MS));
ReadHoldReg((uint16_t)(base + PLSR_SEG_OFF_ACT_MS)); /* ACT 定时 ms */
g_plsr_segs[i].jump_seg = g_plsr_segs[i].jump_seg =
ReadHoldReg((uint16_t)(base + PLSR_SEG_OFF_JUMP));
ReadHoldReg((uint16_t)(base + PLSR_SEG_OFF_JUMP)); /* 跳转目标段 */
} }
} }


PlsrCommandSetFault(fault);
PlsrCommandSetFault(fault); /* 写 0x2006 镜像 */


if (fault == PLSR_ERR_NONE) if (fault == PLSR_ERR_NONE)
{ {
return 1U;
return 1U; /* 可落存 BKP */
} }
return 0U; return 0U;
} }
@@ -301,32 +302,33 @@ void PlsrParamBlockOnHoldWrite(uint16_t start_addr, uint16_t quantity)
if ((start_addr == PLSR_REG_COMMON_F1_BASE) && if ((start_addr == PLSR_REG_COMMON_F1_BASE) &&
(quantity >= PLSR_PARAM_COMMON_FRAME1_WORDS)) (quantity >= PLSR_PARAM_COMMON_FRAME1_WORDS))
{ {
/* 公共帧 1:开新一批,期望 5+段数 */
uint16_t seg_n = ReadHoldReg(PLSR_REG_SEG_COUNT); uint16_t seg_n = ReadHoldReg(PLSR_REG_SEG_COUNT);
if (seg_n > PLSR_SEG_MAX) if (seg_n > PLSR_SEG_MAX)
{ {
seg_n = (uint16_t)PLSR_SEG_MAX;
seg_n = (uint16_t)PLSR_SEG_MAX; /* 计数软钳,避免 expect 溢出 */
} }
s_expect_frames = (uint16_t)(PLSR_PARAM_COMMON_FRAMES + seg_n); s_expect_frames = (uint16_t)(PLSR_PARAM_COMMON_FRAMES + seg_n);
s_recv_frames = 1U;
s_xfer_active = 1U;
s_recv_frames = 1U; /* 帧 1 已计入 */
s_xfer_active = 1U; /* 开始收批 */
} }
else if ((s_xfer_active != 0U) && else if ((s_xfer_active != 0U) &&
((PlsrParamIsCommonTailFrameWrite(start_addr, quantity) != 0U) || ((PlsrParamIsCommonTailFrameWrite(start_addr, quantity) != 0U) ||
(PlsrParamIsSegFrameWrite(start_addr, quantity) != 0U))) (PlsrParamIsSegFrameWrite(start_addr, quantity) != 0U)))
{ {
s_recv_frames++;
s_recv_frames++; /* 公共帧 2~5 或段帧 +1 */
} }
else else
{ {
return;
return; /* 非本批帧 / 未开批 → 忽略 */
} }


if ((s_xfer_active != 0U) && (s_recv_frames >= s_expect_frames)) if ((s_xfer_active != 0U) && (s_recv_frames >= s_expect_frames))
{ {
s_xfer_active = 0U;
s_xfer_active = 0U; /* 收齐 */
if (s_param_sem != (OS_EVENT *)0) if (s_param_sem != (OS_EVENT *)0)
{ {
(void)OSSemPost(s_param_sem);
(void)OSSemPost(s_param_sem); /* 唤醒 ParamBlockTask */
} }
} }
} }


+ 1
- 1
plsr/plsr.c 查看文件

@@ -50,7 +50,7 @@ void PlsrInit(void)
*/ */
void PlsrTask(void *pArg) void PlsrTask(void *pArg)
{ {
static uint8_t s_booted = 0U;
static uint8_t s_booted = 0U; /* 1=已完成首次延迟对齐(等 Modbus 填 hold) */


(void)pArg; (void)pArg;




+ 3
- 3
plsr/plsr.h 查看文件

@@ -25,9 +25,9 @@
#include <stdint.h> #include <stdint.h>


/* run_control 拥有的共享运行状态;段下标从 0 开始。 */ /* run_control 拥有的共享运行状态;段下标从 0 开始。 */
extern volatile uint8_t g_plsr_busy;
extern volatile uint16_t g_plsr_cur_seg_idx;
extern volatile int32_t g_plsr_accumulated_pulses;
extern volatile uint8_t g_plsr_busy; /* 运行忙标志(上位机监控) */
extern volatile uint16_t g_plsr_cur_seg_idx; /* 当前段下标(0-based) */
extern volatile int32_t g_plsr_accumulated_pulses; /* 全局累计脉冲(有符号) */
#include "plsr_param.h" #include "plsr_param.h"


/** /**


+ 273
- 266
plsr/pulse_driver/plsr_pulse_driver.c
文件差异内容过多而无法显示
查看文件


+ 4
- 4
plsr/pulse_driver/plsr_pulse_driver.h 查看文件

@@ -35,10 +35,10 @@ extern TIM_HandleTypeDef htim11;
extern TIM_HandleTypeDef htim13; extern TIM_HandleTypeDef htim13;


/* 驱动拥有的真实输出状态,run_control 直接读取,不再保存第二份。 */ /* 驱动拥有的真实输出状态,run_control 直接读取,不再保存第二份。 */
extern volatile uint32_t g_plsr_output_freq_hz;
extern volatile uint8_t g_plsr_pwm_running;
extern uint8_t g_plsr_direction_forward;
extern uint8_t g_plsr_direction_valid;/*方向脚有效*/
extern volatile uint32_t g_plsr_output_freq_hz; /* 当前输出频率 Hz */
extern volatile uint8_t g_plsr_pwm_running; /* 1=PWM 正在跑 */
extern uint8_t g_plsr_direction_forward; /* 1=正转方向语义 */
extern uint8_t g_plsr_direction_valid; /* 1=方向脚有效写出 */


/** /**
* @brief 初始化三路脉冲 TIM + 方向 GPIO * @brief 初始化三路脉冲 TIM + 方向 GPIO


+ 682
- 647
plsr/run_control/plsr_run_control.c
文件差异内容过多而无法显示
查看文件


+ 37
- 26
plsr/signal_io/plsr_signal_io.c 查看文件

@@ -164,19 +164,20 @@ static void PlsrSignalIoTim5Init(void)
{ {
__HAL_RCC_TIM5_CLK_ENABLE(); __HAL_RCC_TIM5_CLK_ENABLE();


TIM5->CR1 = 0U;//定时器停止、向上计数、关闭单脉冲、普通边沿对齐
TIM5->DIER = 0U;//DMA/中断使能寄存器
TIM5->SR = 0U;//状态寄存器,清除所有中断标志位
TIM5->PSC = PLSR_TIM5_PSC_100US;//8399,1Mhz
TIM5->ARR = 0xFFFFFFFFUL;//自动重装载寄存器
TIM5->CNT = 0U;//计数值清零
TIM5->EGR = TIM_EGR_UG;//事件产生寄存器,软件产生一次中断,不产生中断写的psc不会生效
TIM5->SR = 0U;//EGR 的 UG 动作会把SR.UIF置 1,这里再次清零中断标志
TIM5->CR1 = 0U; /* 停表:向上计、关 OPM */
TIM5->DIER = 0U; /* 关 UPDATE 中断 */
TIM5->SR = 0U; /* 清状态标志 */
TIM5->PSC = PLSR_TIM5_PSC_100US; /* PSC=8399 → 10kHz(100µs/格),非 1MHz */
TIM5->ARR = 0xFFFFFFFFUL; /* 预装最大 ARR,真正延时在 Schedule 重写 */
TIM5->CNT = 0U;
TIM5->EGR = TIM_EGR_UG; /* UG:PSC 立刻生效(会置 UIF) */
TIM5->SR = 0U; /* 清 UG 带来的 UIF */


HAL_NVIC_SetPriority(TIM5_IRQn, 7, 0); HAL_NVIC_SetPriority(TIM5_IRQn, 7, 0);
HAL_NVIC_EnableIRQ(TIM5_IRQn); HAL_NVIC_EnableIRQ(TIM5_IRQn);
} }


/** @brief 信号 IO 初始化:消抖状态 + EXTI + TIM5 */
void PlsrSignalIoInit(void) void PlsrSignalIoInit(void)
{ {
s_delay_armed = 0U; s_delay_armed = 0U;
@@ -197,8 +198,7 @@ void PlsrSignalIoInit(void)


PlsrSignalIoGpioExtiInit(); PlsrSignalIoGpioExtiInit();
PlsrSignalIoTim5Init(); PlsrSignalIoTim5Init();
//中断初始化时可能会进入中断,读取时需要结构体合法
//为了防止初始化终端后意外触发,需要再次清除标志位
/* 配完 NVIC 后再清一次,避免配置期误沿 */
__HAL_GPIO_EXTI_CLEAR_IT(PLSR_X4_PIN); __HAL_GPIO_EXTI_CLEAR_IT(PLSR_X4_PIN);
__HAL_GPIO_EXTI_CLEAR_IT(PLSR_X5_PIN); __HAL_GPIO_EXTI_CLEAR_IT(PLSR_X5_PIN);
s_debounce_x4.fell = 0U; s_debounce_x4.fell = 0U;
@@ -207,6 +207,7 @@ void PlsrSignalIoInit(void)
s_debounce_x5.pending = 0U; s_debounce_x5.pending = 0U;
} }


/** @brief 装 TIM5 单次延时(ms),OPM 到期进 OnTim5Irq */
void PlsrSignalIoScheduleDelayMs(uint32_t delay_ms) void PlsrSignalIoScheduleDelayMs(uint32_t delay_ms)
{ {
uint32_t ticks; uint32_t ticks;
@@ -221,22 +222,23 @@ void PlsrSignalIoScheduleDelayMs(uint32_t delay_ms)
} }


/* N ms → N×10 个 100µs 格;OPM 计满一次 UPDATE 即到期 */ /* N ms → N×10 个 100µs 格;OPM 计满一次 UPDATE 即到期 */
ticks = delay_ms * PLSR_TIM5_TICKS_PER_MS;//乘10得到us
TIM5->CR1 = 0U;//控制寄存器 1 清零
TIM5->DIER = 0U;//DMA / 中断使能寄存器清零
TIM5->SR = 0U;//状态寄存器清零
TIM5->PSC = PLSR_TIM5_PSC_100US;//8399得到10KHZ即100us
TIM5->ARR = ticks - 1U;//自动重装载寄存器
TIM5->CR1 = TIM_CR1_URS;//仅更新事件产生更新中断
TIM5->EGR = TIM_EGR_UG;//软件生成更新事件写 UG=1:立刻把CNT寄存器加载 ARR 影子寄存器的值;PSC 预分频值生效
TIM5->SR = 0U;//再次清除状态寄存器,清除 UG 带来的各种标志。
TIM5->CNT = 0U;//计数器清零,从 0 开始计数。
TIM5->DIER = TIM_DIER_UIE;//使能更新中断。
ticks = delay_ms * PLSR_TIM5_TICKS_PER_MS;
TIM5->CR1 = 0U;
TIM5->DIER = 0U;
TIM5->SR = 0U;
TIM5->PSC = PLSR_TIM5_PSC_100US;
TIM5->ARR = ticks - 1U;
TIM5->CR1 = TIM_CR1_URS; /* 仅溢出产生 UPDATE */
TIM5->EGR = TIM_EGR_UG; /* PSC/ARR 立刻生效 */
TIM5->SR = 0U; /* 清 UG 带来的 UIF */
TIM5->CNT = 0U;
TIM5->DIER = TIM_DIER_UIE;
s_delay_armed = 1U; s_delay_armed = 1U;
TIM5->CR1 = (uint32_t)(TIM_CR1_CEN | TIM_CR1_OPM | TIM_CR1_URS);
TIM5->CR1 = (uint32_t)(TIM_CR1_CEN | TIM_CR1_OPM | TIM_CR1_URS); /* 开表单次 */
} }


/** @brief 取消 TIM5 延时并清武装 */
void PlsrSignalIoCancelDelay(void) void PlsrSignalIoCancelDelay(void)
{ {
TIM5->CR1 = 0U; TIM5->CR1 = 0U;
@@ -245,6 +247,7 @@ void PlsrSignalIoCancelDelay(void)
s_delay_armed = 0U; s_delay_armed = 0U;
} }


/** @brief 查询 TIM5 剩余延时 ms(未武装或已停返回 0) */
uint32_t PlsrSignalIoDelayRemainMs(void) uint32_t PlsrSignalIoDelayRemainMs(void)
{ {
uint32_t arr; uint32_t arr;
@@ -272,12 +275,14 @@ uint32_t PlsrSignalIoDelayRemainMs(void)
return left_ticks / PLSR_TIM5_TICKS_PER_MS; return left_ticks / PLSR_TIM5_TICKS_PER_MS;
} }


/** @brief OS 节拍消抖:确认 X4/X5 有效下降沿 */
void PlsrSignalIoDebouncePoll(void) void PlsrSignalIoDebouncePoll(void)
{ {
PlsrSignalIoDebounceConfirm(&s_debounce_x4); PlsrSignalIoDebounceConfirm(&s_debounce_x4);
PlsrSignalIoDebounceConfirm(&s_debounce_x5); PlsrSignalIoDebounceConfirm(&s_debounce_x5);
} }


/** @brief 丢弃两侧沿与 pending(EXT 段开跑前) */
void PlsrSignalIoClearEdges(void) void PlsrSignalIoClearEdges(void)
{ {
s_debounce_x4.fell = 0U; s_debounce_x4.fell = 0U;
@@ -288,6 +293,7 @@ void PlsrSignalIoClearEdges(void)
s_debounce_x5.stamp_ok = 0U; s_debounce_x5.stamp_ok = 0U;
} }


/** @brief 仅清 pending,保留已确认 fell(纯 EXT 段末) */
void PlsrSignalIoClearPending(void) void PlsrSignalIoClearPending(void)
{ {
s_debounce_x4.pending = 0U; s_debounce_x4.pending = 0U;
@@ -296,9 +302,10 @@ void PlsrSignalIoClearPending(void)
s_debounce_x5.stamp_ok = 0U; s_debounce_x5.stamp_ok = 0U;
} }


/** @brief 取 WAIT 口有效下降沿(读后清) */
uint8_t PlsrSignalIoTakeWaitFalling(void) uint8_t PlsrSignalIoTakeWaitFalling(void)
{ {
/* wait_x_sel:0 代表 X4,1 代表 X5。读取后立即清掉该下降沿。 */
/* wait_x_sel:0=X4,1=X5 */
if (g_plsr_config.wait_x_sel == 0U) if (g_plsr_config.wait_x_sel == 0U)
{ {
if (s_debounce_x4.fell != 0U) if (s_debounce_x4.fell != 0U)
@@ -315,9 +322,10 @@ uint8_t PlsrSignalIoTakeWaitFalling(void)
return 0U; return 0U;
} }


/** @brief 取 EXT 口有效下降沿(读后清) */
uint8_t PlsrSignalIoTakeExtFalling(void) uint8_t PlsrSignalIoTakeExtFalling(void)
{ {
/* ext_x_sel:0 代表 X4,1 代表 X5。读取后立即清掉该下降沿。 */
/* ext_x_sel:0=X4,1=X5 */
if (g_plsr_config.ext_x_sel == 0U) if (g_plsr_config.ext_x_sel == 0U)
{ {
if (s_debounce_x4.fell != 0U) if (s_debounce_x4.fell != 0U)
@@ -334,6 +342,7 @@ uint8_t PlsrSignalIoTakeExtFalling(void)
return 0U; return 0U;
} }


/** @brief TIM5 UPDATE:到期回调 run_control */
void PlsrSignalIoOnTim5Irq(void) void PlsrSignalIoOnTim5Irq(void)
{ {
if ((TIM5->SR & TIM_SR_UIF) != 0U) if ((TIM5->SR & TIM_SR_UIF) != 0U)
@@ -344,11 +353,12 @@ void PlsrSignalIoOnTim5Irq(void)
if (s_delay_armed != 0U) if (s_delay_armed != 0U)
{ {
s_delay_armed = 0U; s_delay_armed = 0U;
PlsrRunControlOnDelayTimer();
PlsrRunControlOnDelayTimer(); /* 方向/WAIT/ACT 到期 */
} }
} }
} }


/** @brief EXTI9_5:X4 下降沿 → pending */
void PlsrSignalIoOnExti9_5(void) void PlsrSignalIoOnExti9_5(void)
{ {
if (__HAL_GPIO_EXTI_GET_IT(PLSR_X4_PIN) != 0U) if (__HAL_GPIO_EXTI_GET_IT(PLSR_X4_PIN) != 0U)
@@ -358,6 +368,7 @@ void PlsrSignalIoOnExti9_5(void)
} }
} }


/** @brief EXTI15_10:X5 下降沿 → pending */
void PlsrSignalIoOnExti15_10(void) void PlsrSignalIoOnExti15_10(void)
{ {
if (__HAL_GPIO_EXTI_GET_IT(PLSR_X5_PIN) != 0U) if (__HAL_GPIO_EXTI_GET_IT(PLSR_X5_PIN) != 0U)


正在加载...
取消
保存