Przeglądaj źródła

增加故障码判断

Signed-off-by: hanyongwei <2043702190@qq.com>
dev1
hanyongwei 3 tygodni temu
rodzic
commit
96fe4e6461
9 zmienionych plików z 220 dodań i 103 usunięć
  1. +3
    -0
      .gitignore
  2. +2
    -2
      app/main.c
  3. +4
    -4
      modbus/modbus_rtu.c
  4. +32
    -9
      plsr/command/plsr_command.c
  5. +28
    -1
      plsr/command/plsr_command.h
  6. +128
    -48
      plsr/param/plsr_param.c
  7. +9
    -14
      plsr/param/plsr_param.h
  8. +11
    -18
      plsr/plsr.c
  9. +3
    -7
      plsr/plsr.h

+ 3
- 0
.gitignore Wyświetl plik

@@ -21,3 +21,6 @@ build-plsr_host-Desktop_Qt_5_6_3_MinGW_32bit-Debug/
plsr/test/
tools/
.cursor/
PLSR测试大纲.html
_gen_outline_p1.py
run_control_full.txt

+ 2
- 2
app/main.c Wyświetl plik

@@ -97,7 +97,7 @@ int main(void)
OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR | OS_TASK_OPT_SAVE_FP);

/*
* 参数块任务:Pend → ApplyFromHold → SaveParamsFromHold → ExportToHold。
* 参数块任务:Pend → ApplyFromHold(校验)→ 通过则 SaveParamsFromHold。
* 分帧写完后由 OnHoldWrite Post;Save 落 BKP,Export 仅供读回钳位结果。
*/
OSTaskCreateExt(PlsrParamBlockTask,
@@ -118,7 +118,7 @@ int main(void)
}

/**
* @brief 系统时钟:HSE(12MHz) → PLL → 168MHz SYSCLK(APM32F407 / STM32F4 类)
* @brief 系统时钟:HSE(12MHz) → PLL → 168MHz SYSCLK
* @note 须与 OS_CPU_SysTickInit、pulse_driver 使用的主频常量一致
* @note PLLM 须等于晶振 MHz:12MHz 用 12;误用 8 会使 SYSCLK=252MHz,脉冲频率偏 1.5 倍
*/


+ 4
- 4
modbus/modbus_rtu.c Wyświetl plik

@@ -14,6 +14,7 @@
#include "gpio.h"
#include "plsr_param.h"
#include "plsr_command.h"
#include "plsr_persist.h"

static uint8_t g_modbus_proc_buf[MODBUS_RX_BUF_LEN];

@@ -68,12 +69,11 @@ void ModbusSlaveTask(void *pArg)
(void)pArg;

/*
* ModbusDataInit 会 memset 整个 g_hold_reg,冲掉 PlsrInit 里 PersistLoad/Export 的结果。
* 须立刻 Export:用已 Apply 的 s_cfg/s_seg 填回公共+段参数,供 FC03 读与后续 START。
* (监控区另由 PlsrPersistTickMonitor 每节拍从运行态回填。)
* ModbusDataInit 会清零 g_hold_reg;上电后仅从 BKP 恢复参数/监控到 hold,
* 不再把运行结构体 Export 回寄存器(非法参数保留在上位机写入值 + 0x2006)。
*/
ModbusDataInit();
PlsrParamBlockExportToHold();
PlsrPersistLoad();
ModbusPortInit();

while (1)


+ 32
- 9
plsr/command/plsr_command.c Wyświetl plik

@@ -79,6 +79,17 @@ uint16_t PlsrCommandGetFault(void)
return s_fault;
}

/** @brief 参数/重复启动类故障是否禁止 START(见 plsr_command.h) */
uint8_t PlsrCommandIsStartBlocked(void)
{
if ((s_fault >= PLSR_ERR_PARAM_BLOCK_MIN) &&
(s_fault <= PLSR_ERR_PARAM_BLOCK_MAX))
{
return 1U;
}
return 0U;
}

/** @brief 指令模块初始化(见 plsr_command.h) */
void PlsrCommandInit(void)
{
@@ -160,7 +171,7 @@ void PlsrCommandOnSegFreqHoldWrite(uint16_t start_addr, uint16_t quantity)
* 1. 读 ctrl 后立即写 0(避免重复触发)
* 2. STOP — 急停
* 3. CLR — 清累计 + ClearFault
* 4. START — 仅当无 STOP 位:Apply → ClearFault → Stop → Start
* 4. START — 忙则 0x0C;否则 Apply 校验 → 0x04~0x0C 门禁则拒启 → Stop+Start
* 动态改频在控制位之后、PublishMonitor 之前执行。
*/
void PlsrCommandPoll(void)
@@ -187,15 +198,27 @@ void PlsrCommandPoll(void)
if (((ctrl & PLSR_CTRL_BIT_START) != 0U) &&
((ctrl & PLSR_CTRL_BIT_STOP) == 0U))
{
(void)PlsrParamBlockApplyFromHold();
/* 启动视为正常入口:先写故障码 0,再 Stop+Start;非法频率由 Start 改写为 4 */
PlsrCommandClearFault();
PlsrStop();
(void)PlsrStart(PlsrParamGetStartSeg());
/* 已进换向/WAIT 精确等待:本周期勿再 PublishMonitor,尽快 Pend */
if (PlsrRunControlIsPreciseWait() != 0U)
if (PlsrIsBusy() != 0U)
{
/* 0x0C:运行中重复 START,启动无效 */
PlsrCommandSetFault(PLSR_ERR_DUP_START);
}
else if (PlsrParamBlockApplyFromHold() == 0U)
{
/* Apply 失败:故障码已由参数块写入 0x2006,不落 BKP */
}
else if (PlsrCommandIsStartBlocked() != 0U)
{
/* 0x04~0x0B 等门禁故障:禁止启动 */
}
else
{
skip_monitor = 1U;
PlsrStop();
(void)PlsrStart(PlsrParamGetStartSeg());
if (PlsrRunControlIsPreciseWait() != 0U)
{
skip_monitor = 1U;
}
}
}
}


+ 28
- 1
plsr/command/plsr_command.h Wyświetl plik

@@ -51,13 +51,34 @@
* 1 | PLSR_ERR_PULSE_CNT | 实际脉冲数与段目标不一致 | 告警 | 继续跑,不中断
* 2 | PLSR_ERR_FREQ_UNREACH | 规划峰值达不到设定目标(三角) | 告警 | 按压后规划继续
* 3 | PLSR_ERR_CURVE_MISMATCH | 加减速相内脉冲与规划预算不符 | 告警 | 继续跑
* 4 | PLSR_ERR_FREQ_ILLEGAL | 频率 ∉ [1, 100000] Hz | 门禁 | 禁止启动/改频
* 4 | PLSR_ERR_FREQ_ILLEGAL | 段频率 ∉ [1, 100000] Hz(非 0) | 门禁 | 禁止启动/改频
* 5 | PLSR_ERR_PULSE_RANGE | 脉冲个数 ∉ int32 合法范围 | 门禁 | 禁止启动
* 6 | PLSR_ERR_SEG_COUNT | 总段数 ∉ [1, 10] | 门禁 | 禁止启动
* 7 | PLSR_ERR_START_SEG | 起始段 ∉ [1, 总段数] | 门禁 | 禁止启动
* 8 | PLSR_ERR_START_END_SPD | 起/止速非0且 ∉ [1, 100000] Hz | 门禁 | 禁止启动(0=合法)
* 9 | PLSR_ERR_PULSE_Y | 脉冲端子 ∉ {Y0,Y1,Y2} | 门禁 | 禁止启动
* 10 | PLSR_ERR_DIR_Y | 方向端子 ≠ Y3 | 门禁 | 禁止启动
* 11 | PLSR_ERR_DEFAULT_SPD | 默认速度 ∉ [1, 100000] Hz | 门禁 | 禁止启动
* 12 | PLSR_ERR_DUP_START | 运行中重复 START | 告警 | 启动无效
*/
#define PLSR_ERR_NONE 0x00U
#define PLSR_ERR_PULSE_CNT 0x01U
#define PLSR_ERR_FREQ_UNREACH 0x02U
#define PLSR_ERR_CURVE_MISMATCH 0x03U
#define PLSR_ERR_FREQ_ILLEGAL 0x04U
#define PLSR_ERR_PULSE_RANGE 0x05U
#define PLSR_ERR_SEG_COUNT 0x06U
#define PLSR_ERR_START_SEG 0x07U
#define PLSR_ERR_START_END_SPD 0x08U
#define PLSR_ERR_PULSE_Y 0x09U
#define PLSR_ERR_DIR_Y 0x0AU
#define PLSR_ERR_DEFAULT_SPD 0x0BU
#define PLSR_ERR_DUP_START 0x0CU

/** 参数类门禁故障码下限(含) */
#define PLSR_ERR_PARAM_BLOCK_MIN PLSR_ERR_FREQ_ILLEGAL
/** 参数类门禁故障码上限(含 0x0C 重复启动) */
#define PLSR_ERR_PARAM_BLOCK_MAX PLSR_ERR_DUP_START

/**
* @brief 指令模块初始化
@@ -90,6 +111,12 @@ void PlsrCommandClearFault(void);
/** @return 当前故障码镜像(与 0x2006 一致) */
uint16_t PlsrCommandGetFault(void);

/**
* @brief 是否因参数/重复启动类故障禁止 START
* @return 1=0x2006 为 0x04~0x0C(门禁/重复启动);0=可尝试启动
*/
uint8_t PlsrCommandIsStartBlocked(void);

/**
* @brief FC10 写段频率双字后的钩子
* @param start_addr 写入起始保持寄存器地址


+ 128
- 48
plsr/param/plsr_param.c Wyświetl plik

@@ -15,11 +15,12 @@
*
* 与其它模块关系
* Modbus FC10 应答路径调用 OnHoldWrite;Command START 也会同步 ApplyFromHold;
* Persist:Apply 成功后 SaveParamsFromHold 整包落 BKP;运行中改频单独落频率双字
* ExportToHold 只把钳位后的结构体摊回 hold(读回 / 抗 ModbusDataInit 清零),不负责写 BKP
* Persist:校验全部通过才 SaveParamsFromHold;失败只写故障码,不落 BKP
* 非上电不再 ExportToHold(hold 保留上位机写入值,由故障码提示修正)
*/
#include "plsr_param.h"
#include "plsr_persist.h"
#include "plsr_command.h"
#include "modbus_rtu.h"
#include "ucos_ii.h"
#include <string.h>
@@ -194,37 +195,95 @@ static void PlsrParamSetXferStatus(uint16_t st, uint16_t fail_frame)
WriteHoldReg(PLSR_PARAM_XFER_RECV_REG, s_recv_frames);
}

/*============================================================================*/
/* 参数校验辅助 */
/*============================================================================*/

#define PLSR_PARAM_SPD_MIN_HZ 1U
#define PLSR_PARAM_SPD_MAX_HZ 100000U

/** 记录「最后一个」故障码(校验顺序决定多错时保留末项) */
static void PlsrParamFaultLast(uint16_t *fault, uint16_t code)
{
*fault = code;
}

static uint8_t PlsrParamIsSpeedHzValid(uint32_t hz)
{
return ((hz >= PLSR_PARAM_SPD_MIN_HZ) && (hz <= PLSR_PARAM_SPD_MAX_HZ)) ? 1U : 0U;
}

/**
* 起速/止速:0 合法(运行层 ResolveStartHz / ResolveEndHz 处理);
* 非 0 须在 1~100kHz。
*/
static uint8_t PlsrParamIsStartEndSpeedValid(uint32_t hz)
{
if (hz == 0U)
{
return 1U;
}
return PlsrParamIsSpeedHzValid(hz);
}

/** 段频率:0=用默认速度;非 0 须在 1~100kHz */
static uint8_t PlsrParamIsSegFreqValid(int32_t freq_hz)
{
if (freq_hz == 0)
{
return 1U;
}
if (freq_hz < 0)
{
return 0U;
}
return PlsrParamIsSpeedHzValid((uint32_t)freq_hz);
}

/** 脉冲个数 SDW:须在 int32 有符号范围内 */
static uint8_t PlsrParamIsPulseCntValid(int32_t pulse_cnt)
{
if (pulse_cnt < (int32_t)(-2147483647L - 1L))
{
return 0U;
}
if (pulse_cnt > (int32_t)2147483647L)
{
return 0U;
}
return 1U;
}

/*============================================================================*/
/* 分帧导入 / 导出 */
/*============================================================================*/

/**
* @brief 保持寄存器 → 运行映像(见 plsr_param.h)
* @brief 保持寄存器 → 运行映像,边拷贝边校验(见 plsr_param.h)
*
* 字段裁剪策略(当前不做故障码,仅钳制到合法枚举/范围):
* pulse_y>2 → 0;dir 强制 3;accel_mode>2 → LINEAR;seg_count 上限 10;
* start_seg 钳到 [1,n];wait_type>4 → TIME。
* 频率合法性由 run_control 启动/开段时查 0x04,此处不拒绝写入。
* @details 校验失败时仍完成拷贝(保留上位机原始值),故障码写入 0x2006;
* 多项非法时仅保留校验过程中「最后一个」故障码。
* @return 1=全部通过;0=存在门禁故障(不落 BKP)
*/
uint8_t PlsrParamBlockApplyFromHold(void)
{
uint16_t i;
uint16_t n;
uint16_t base;
uint16_t m;
uint16_t fault = PLSR_ERR_NONE;
PlsrSeg_t *seg;

/*
* 从保持寄存器组装运行映像。
* TODO:段数/频率/脉冲/端子冲突/跳转非法 → 故障码(当前仅裁剪)
*/
s_cfg.pulse_y = ReadHoldReg(PLSR_REG_PULSE_Y);
if (s_cfg.pulse_y > 2U)
{
s_cfg.pulse_y = 0U;
PlsrParamFaultLast(&fault, PLSR_ERR_PULSE_Y);
}

s_cfg.dir_y = ReadHoldReg(PLSR_REG_DIR_Y);
if (s_cfg.dir_y != 3U)
{
PlsrParamFaultLast(&fault, PLSR_ERR_DIR_Y);
}
s_cfg.dir_y = 3U; /* 方向固定 Y3,忽略上位机其它值 */
WriteHoldReg(PLSR_REG_DIR_Y, 3U);

s_cfg.wait_x_sel = ReadHoldReg(PLSR_REG_WAIT_X) ? 1U : 0U;
s_cfg.ext_x_sel = ReadHoldReg(PLSR_REG_EXT_X) ? 1U : 0U;
@@ -232,59 +291,83 @@ uint8_t PlsrParamBlockApplyFromHold(void)
s_cfg.dir_delay_ms = ReadHoldReg(PLSR_REG_DIR_DELAY);
s_cfg.dir_logic = (ReadHoldReg(PLSR_REG_DIR_LOGIC) != 0U) ?
PLSR_DIR_LOGIC_NEG : PLSR_DIR_LOGIC_POS;

m = ReadHoldReg(PLSR_REG_ACCEL_MODE);
if (m > (uint16_t)PLSR_ACCEL_SINE)
{
m = (uint16_t)PLSR_ACCEL_LINEAR;
}
s_cfg.accel_mode = (PlsrAccelMode_e)m;
s_cfg.accel_mode = (PlsrAccelMode_e)ReadHoldReg(PLSR_REG_ACCEL_MODE);
s_cfg.run_mode = (ReadHoldReg(PLSR_REG_RUN_MODE) != 0U) ?
PLSR_POS_ABSOLUTE : PLSR_POS_RELATIVE;

n = ReadHoldReg(PLSR_REG_SEG_COUNT);
if (n > PLSR_SEG_MAX)
s_cfg.seg_count = n;
if ((n < 1U) || (n > PLSR_SEG_MAX))
{
n = (uint16_t)PLSR_SEG_MAX;
PlsrParamFaultLast(&fault, PLSR_ERR_SEG_COUNT);
}
s_cfg.seg_count = n;

s_cfg.start_seg = ReadHoldReg(PLSR_REG_START_SEG);
if (s_cfg.start_seg < 1U)
if ((n >= 1U) && (n <= PLSR_SEG_MAX))
{
s_cfg.start_seg = 1U;
if ((s_cfg.start_seg < 1U) || (s_cfg.start_seg > n))
{
PlsrParamFaultLast(&fault, PLSR_ERR_START_SEG);
}
}
if ((n >= 1U) && (s_cfg.start_seg > n))
else if (s_cfg.start_seg < 1U)
{
s_cfg.start_seg = n;
PlsrParamFaultLast(&fault, PLSR_ERR_START_SEG);
}

s_cfg.default_speed = PlsrParamReadDWord(PLSR_REG_DEFAULT_SPD_L);
if (PlsrParamIsSpeedHzValid(s_cfg.default_speed) == 0U)
{
PlsrParamFaultLast(&fault, PLSR_ERR_DEFAULT_SPD);
}

s_cfg.start_speed = PlsrParamReadDWord(PLSR_REG_START_SPD_L);
if (PlsrParamIsStartEndSpeedValid(s_cfg.start_speed) == 0U)
{
PlsrParamFaultLast(&fault, PLSR_ERR_START_END_SPD);
}

s_cfg.end_speed = PlsrParamReadDWord(PLSR_REG_END_SPD_L);
if (PlsrParamIsStartEndSpeedValid(s_cfg.end_speed) == 0U)
{
PlsrParamFaultLast(&fault, PLSR_ERR_START_END_SPD);
}

s_cfg.accel_ms = ReadHoldReg(PLSR_REG_ACCEL_MS);
s_cfg.decel_ms = ReadHoldReg(PLSR_REG_DECEL_MS);

for (i = 0U; i < n; i++)
if ((n >= 1U) && (n <= PLSR_SEG_MAX))
{
seg = &s_seg[i];
base = (uint16_t)(PLSR_REG_SEG1_BASE + i * PLSR_SEG_STRIDE);
seg->freq_hz = PlsrParamReadSignedDWord((uint16_t)(base + PLSR_SEG_OFF_FREQ_L));
seg->pulse_cnt = PlsrParamReadSignedDWord((uint16_t)(base + PLSR_SEG_OFF_PULSE_L));
for (i = 0U; i < n; i++)
{
uint16_t w = ReadHoldReg((uint16_t)(base + PLSR_SEG_OFF_WAIT));
if (w > 4U)
seg = &s_seg[i];
base = (uint16_t)(PLSR_REG_SEG1_BASE + i * PLSR_SEG_STRIDE);
seg->freq_hz = PlsrParamReadSignedDWord((uint16_t)(base + PLSR_SEG_OFF_FREQ_L));
if (PlsrParamIsSegFreqValid(seg->freq_hz) == 0U)
{
w = 0U;
PlsrParamFaultLast(&fault, PLSR_ERR_FREQ_ILLEGAL);
}
seg->wait_type = (PlsrWaitType_e)w;

seg->pulse_cnt = PlsrParamReadSignedDWord((uint16_t)(base + PLSR_SEG_OFF_PULSE_L));
if (PlsrParamIsPulseCntValid(seg->pulse_cnt) == 0U)
{
PlsrParamFaultLast(&fault, PLSR_ERR_PULSE_RANGE);
}

seg->wait_type = (PlsrWaitType_e)ReadHoldReg((uint16_t)(base + PLSR_SEG_OFF_WAIT));
seg->wait_ms = ReadHoldReg((uint16_t)(base + PLSR_SEG_OFF_WAIT_MS));
seg->act_ms = ReadHoldReg((uint16_t)(base + PLSR_SEG_OFF_ACT_MS));
seg->jump_seg = ReadHoldReg((uint16_t)(base + PLSR_SEG_OFF_JUMP));
}
seg->wait_ms = ReadHoldReg((uint16_t)(base + PLSR_SEG_OFF_WAIT_MS));
seg->act_ms = ReadHoldReg((uint16_t)(base + PLSR_SEG_OFF_ACT_MS));
seg->jump_seg = ReadHoldReg((uint16_t)(base + PLSR_SEG_OFF_JUMP));
}

return 1U;
PlsrCommandSetFault(fault);

if (fault == PLSR_ERR_NONE)
{
return 1U;
}
return 0U;
}

/**
@@ -412,10 +495,8 @@ void PlsrParamBlockInit(void)
/**
* @brief 参数块任务(见 plsr_param.h)
*
* for(;;) 为 uC/OS 任务标准死循环:
* OSSemPend → ApplyFromHold → SaveParamsFromHold → ExportToHold
* Save 用 hold 中上位机刚写入的值落 BKP;Export 仅把钳位结果摊回 hold 供读回。
* Apply 失败则写 XFER_FAIL 与当前 recv 帧号。
* for(;;):OSSemPend → ApplyFromHold(校验+写 0x2006)→ 通过则 SaveParamsFromHold。
* 校验失败:不落 BKP,hold 保留上位机原值,由故障码提示修正。
*/
void PlsrParamBlockTask(void *pArg)
{
@@ -434,8 +515,7 @@ void PlsrParamBlockTask(void *pArg)
if (PlsrParamBlockApplyFromHold() != 0U)
{
PlsrParamSetXferStatus(PLSR_PARAM_XFER_OK, 0U);
PlsrPersistSaveParamsFromHold(); /* hold 原值 → BKP(不依赖 Export) */
PlsrParamBlockExportToHold(); /* 钳位后映像 → hold,供 Modbus 读回 */
PlsrPersistSaveParamsFromHold(); /* 仅全部校验通过才落 BKP */
}
else
{


+ 9
- 14
plsr/param/plsr_param.h Wyświetl plik

@@ -6,7 +6,7 @@
* 1. 定义公共参数区 0x1000~0x1013、段表区 0x1100+i*0x10 的地址与字段语义;
* 2. 维护运行侧唯一映像 s_cfg / s_seg[](运动规划只读此映像,不直接啃寄存器);
* 3. 支持上位机「1 公共帧 + N 段帧」分帧 FC10 写入:收齐后 ApplyFromHold;
* 4. 支持 ExportToHold:上电默认或读回时把映像摊到保持寄存器
* 4. 上电由 PersistLoad 填 hold;ExportToHold 仅保留作调试接口
*
* 与其它模块关系
* - modbus_rtu / modbus_data :ReadHoldReg / WriteHoldReg
@@ -18,9 +18,8 @@
* 关键数据流
* 上位机写公共帧@0x1000 → OnHoldWrite 开传输 expect=1+N
* 上位机写段帧@0x1100+ → recv++;收齐 → OSSemPost
* ParamBlockTask → ApplyFromHold → SaveParamsFromHold → ExportToHold → 状态 OK
* 上电:PersistLoad → ApplyFromHold → … ModbusDataInit 清 hold …
* → ExportToHold(填回参数)+ TickMonitor(填回监控)
* ParamBlockTask → ApplyFromHold(校验)→ 通过则 SaveParamsFromHold → 状态 OK/FAIL
* 上电:PersistLoad(BKP→hold) → ApplyFromHold(hold→结构体)
*
* 协议概要
* - 公共帧:0x1000~0x1013(20 字),0x1009=段数 N,预期总帧=1+N
@@ -195,7 +194,8 @@ uint16_t PlsrParamGetStartSeg(void);
void PlsrParamBlockInit(void);

/**
* @brief 参数块任务:阻塞等信号量 → ApplyFromHold → SaveParamsFromHold → ExportToHold
/**
* @brief 参数块任务:阻塞等信号量 → ApplyFromHold(校验)→ 通过则 SaveParamsFromHold
* @param pArg 未使用
* @note for(;;) 死循环为 RTOS 任务常态;空循环体是错觉(花括号内有 Pend/Apply)
*/
@@ -210,19 +210,14 @@ void PlsrParamBlockTask(void *pArg);
void PlsrParamBlockOnHoldWrite(uint16_t start_addr, uint16_t quantity);

/**
* @brief 保持寄存器 → s_cfg / s_seg
* @return 1=成功(当前恒为 1;完整校验/故障码待扩展)
* @note 成功后由 ParamBlockTask 调用 SaveParamsFromHold 整包落 BKP
* @brief 保持寄存器 → s_cfg / s_seg,边拷贝边校验
* @return 1=全部通过(写 0x2006=0);0=存在门禁故障(写对应码,不落 BKP)
*/
uint8_t PlsrParamBlockApplyFromHold(void);

/**
* @brief s_cfg / s_seg → 保持寄存器(供 FC03 读回 / START 前 hold 有效)
* @note 调用时机:
* - ParamBlockTask:Apply+Save 之后,把钳位结果摊回 hold
* - ModbusDataInit 清 hold 之后立刻 Export
* - PlsrTask 首次延时后再 Export(双保险)
* @note 本函数不写 BKP;落盘用 SaveParamsFromHold
* @brief s_cfg / s_seg → 保持寄存器(调试/特殊用途;正常运行路径不再调用)
* @note 上电参数由 BKP→hold(PersistLoad);非法参数保留 hold 原值供上位机读回修正
*/
void PlsrParamBlockExportToHold(void);



+ 11
- 18
plsr/plsr.c Wyświetl plik

@@ -10,10 +10,8 @@
* 本文件仅依赖 plsr.h 及各子模块头文件,不被其它 plsr 模块反向引用。
*
* 关键数据流
* PlsrInit 顺序:PersistLoad(BKP→hold) → ApplyFromHold →
* PulseDriver → RunControl → RestoreRuntime → ExportToHold →
* CommandInit → RestoreMonitor → TickMonitor
* (随后 ModbusDataInit 可能清 hold,须再 Export + TickMonitor)
* PlsrInit 顺序:PersistLoad(BKP→hold) → ApplyFromHold(hold→结构体) → …
* ModbusDataInit 清 hold 后:再次 PersistLoad(BKP→hold),不再 ExportToHold
* PlsrTask 循环:TickMs → DebouncePoll → CommandPoll → TickMonitor → WakePend
*/
#include "plsr.h"
@@ -29,20 +27,18 @@
* @brief 子系统初始化(见 plsr.h)
*
* 顺序要点
* PersistLoad → Apply:BKP 进结构体;
* Export:先填 hold(随后 ModbusDataInit 仍可能清零,故任务里再 Export);
* RestoreRuntime / TickMonitor:累计脉冲进运行态并与 BKP 对齐。
* PersistLoad → Apply:BKP → hold → 结构体(BKP 内参数应已合法);
* 非上电不再把结构体 Export 回 hold;Modbus 清零后由 BKP 再填 hold。
*/
void PlsrInit(void)
{
//PlsrParamInitDefault();
PlsrPersistLoad(); /* BKPSRAM 稀疏映像 → g_hold_reg */
(void)PlsrParamBlockApplyFromHold(); /* hold → s_cfg / s_seg[] */
PlsrPersistLoad(); /* BKPSRAM → g_hold_reg */
(void)PlsrParamBlockApplyFromHold(); /* hold → s_cfg / s_seg[] + 校验 */
PlsrPulseDriverInit();
PlsrSignalIoInit();
PlsrRunControlInit();
PlsrPersistRestoreRuntime(); /* hold 0x2000 累计 → run_control(须在 DataInit 清 hold 前) */
PlsrParamBlockExportToHold(); /* 结构体 → hold;Modbus 清零后须再 Export */
PlsrPersistRestoreRuntime(); /* hold 0x2000 累计 → run_control */
PlsrCommandInit();
PlsrPersistRestoreMonitor(); /* 恢复故障码;0x3000/运行态强制空闲 */
PlsrPersistTickMonitor(); /* 监控区 hold+BKP 与运行态对齐 */
@@ -116,18 +112,15 @@ void PlsrTask(void *pArg)
while(1)
{
/*
* 首次进入:ModbusSlaveTask 启动时 ModbusDataInit 会 memset(g_hold_reg)。
* 延迟让出 CPU 后再次 Export:把已从 BKP Apply 的运行映像摊回 hold,
* 否则读 PLC 公共/段为 0,START 的 ApplyFromHold 也会用空 hold 覆盖结构体。
* TickMonitor:清 hold 后立刻把累计等监控量刷回 hold+BKP。
* 首次进入:ModbusSlaveTask 已 DataInit 清 hold 并 PersistLoad 填回 BKP 参数。
* 此处仅恢复监控/指令侧,不再 Export 结构体到 hold。
*/
if (s_booted == 0U)
{
OSTimeDly(3U); /* ~30ms @ 100Hz tick;让出 CPU 给 Modbus 完成 DataInit */
PlsrParamBlockExportToHold(); /* 参数区 hold ← s_cfg/s_seg */
OSTimeDly(3U); /* ~30ms @ 100Hz tick;让出 CPU 给 Modbus 完成初始化 */
PlsrCommandInit();
PlsrPersistRestoreMonitor();
PlsrPersistTickMonitor(); /* 监控区 hold+BKP ← 运行态 */
PlsrPersistTickMonitor();
s_booted = 1U;
}



+ 3
- 7
plsr/plsr.h Wyświetl plik

@@ -16,13 +16,9 @@
* - plsr_signal_io :WAIT/EXT 外部输入、TIM5 延时
*
* 关键数据流
* 上电:PlsrInit → PersistLoad(BKP→hold) → ApplyFromHold → 驱动/IO/RunControl
* → RestoreRuntime → ExportToHold → CommandInit → RestoreMonitor → TickMonitor
* →(ModbusDataInit 清 hold 后再次 Export + TickMonitor)
* 周期:PlsrTask → TickMs → Debounce → CommandPoll → TickMonitor → WakePend
* 脉冲:TIM UPDATE 中断 → PlsrOnPulseIsr → RunControl 计数 + 逐拍改频
* 启动:PlsrStart → RunControlStart → 段序/方向 + 曲线规划 + PWM 输出
* 写参:分帧收齐 → ParamBlockTask Apply → SaveParamsFromHold → ExportToHold
* 上电:PlsrInit → PersistLoad(BKP→hold) → ApplyFromHold → …
* →(ModbusDataInit 后再次 PersistLoad 填 hold)
* 写参:分帧收齐 → ParamBlockTask Apply(校验)→ 通过则 SaveParamsFromHold
*/
#ifndef PLSR_H
#define PLSR_H


Ładowanie…
Anuluj
Zapisz