Pārlūkot izejas kodu

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

Signed-off-by: hanyongwei <2043702190@qq.com>
dev3
hanyongwei pirms 2 nedēļām
vecāks
revīzija
5bd7cb9c53
10 mainītis faili ar 1887 papildinājumiem un 1853 dzēšanām
  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
Failā izmaiņas netiks attēlotas, jo tās ir par lielu
Parādīt failu


+ 6
- 3
plsr/accel_curve/plsr_accel_curve.h Parādīt failu

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

/* 当前段唯一的曲线规划和逐拍状态,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) */
void PlsrAccelPrebuildFreqTables(const PlsrAccelPlan_t *plan);

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



+ 29
- 38
plsr/command/plsr_command.c Parādīt failu

@@ -30,9 +30,9 @@
* s_live_freq_req — 运行中写频请求标志,Poll 消费后清 0
* 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保持寄存器
@@ -57,9 +57,9 @@ static void PlsrCommandPublishMonitor(void)

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
{
@@ -118,18 +118,18 @@ void PlsrCommandInit(void)
*/
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;

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

freqency = (uint32_t)ReadHoldReg(start_addr) |
((uint32_t)ReadHoldReg((uint16_t)(start_addr + 1U)) << 16);
/* 运行中改频非法不改段表、不请求 ChangeFreq */
if ((freqency < 1U) || (freqency > 100000U))
{
PlsrCommandSetFault(PLSR_ERR_FREQ_ILLEGAL);
PlsrCommandSetFault(PLSR_ERR_FREQ_ILLEGAL); /* 非法:不改段表、不请求 */
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_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)
{
uint16_t ctrl = ReadHoldReg(PLSR_CTRL_REG);
uint8_t skip_monitor = 0U;
uint8_t skip_monitor = 0U; /* 精确等待时跳过本拍监控刷新 */

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

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

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

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

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

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

+ 41
- 39
plsr/param/plsr_param.c Parādīt failu

@@ -17,30 +17,30 @@
#include "modbus_rtu.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 volatile uint16_t s_expect_frames; /* 本批期望总帧数 = 5 + 段数 */
static volatile uint16_t s_recv_frames; /* 已收帧计数 */
static volatile uint8_t s_xfer_active; /* 1=正在接收一批分帧 */

/** @return 有效段数,须在[0, PLSR_SEG_MAX]之间 */
/** @return 有效段数,软钳到 [0, PLSR_SEG_MAX] */
uint16_t PlsrParamGetSegCount(void)
{
if (g_plsr_config.seg_count < 1U)
{
return 0U;
return 0U; /* 无有效段 */
}
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;
}

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

if (n < 1U)
{
return 1U;
return 1U; /* 无段时仍返回 1 */
}
if (g_plsr_config.start_seg < 1U)
{
@@ -56,7 +56,7 @@ uint16_t PlsrParamGetStartSeg(void)
}
if (g_plsr_config.start_seg > n)
{
return n;
return n; /* 超出则钳到末段 */
}
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_MAX_HZ 100000U

/** 速度 Hz 是否落在 [1, 100k](默认速度/段频非 0) */
static uint8_t PlsrParamIsSpeedHzValid(uint32_t hz)
{
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 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)
{
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)
{
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.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) ?
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.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);
g_plsr_config.seg_count = n;
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 ((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)
@@ -226,23 +227,23 @@ uint8_t PlsrParamBlockApplyFromHold(void)
g_plsr_config.default_speed = PlsrParamReadDWord(PLSR_REG_DEFAULT_SPD_L);
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)
{
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)
{
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))
{
@@ -253,32 +254,32 @@ uint8_t PlsrParamBlockApplyFromHold(void)
(int32_t)PlsrParamReadDWord((uint16_t)(base + PLSR_SEG_OFF_FREQ_L));
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 =
(int32_t)PlsrParamReadDWord((uint16_t)(base + PLSR_SEG_OFF_PULSE_L));
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 =
(PlsrWaitType_e)ReadHoldReg((uint16_t)(base + PLSR_SEG_OFF_WAIT));
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 =
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 =
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)
{
return 1U;
return 1U; /* 可落存 BKP */
}
return 0U;
}
@@ -301,32 +302,33 @@ void PlsrParamBlockOnHoldWrite(uint16_t start_addr, uint16_t quantity)
if ((start_addr == PLSR_REG_COMMON_F1_BASE) &&
(quantity >= PLSR_PARAM_COMMON_FRAME1_WORDS))
{
/* 公共帧 1:开新一批,期望 5+段数 */
uint16_t seg_n = ReadHoldReg(PLSR_REG_SEG_COUNT);
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_recv_frames = 1U;
s_xfer_active = 1U;
s_recv_frames = 1U; /* 帧 1 已计入 */
s_xfer_active = 1U; /* 开始收批 */
}
else if ((s_xfer_active != 0U) &&
((PlsrParamIsCommonTailFrameWrite(start_addr, quantity) != 0U) ||
(PlsrParamIsSegFrameWrite(start_addr, quantity) != 0U)))
{
s_recv_frames++;
s_recv_frames++; /* 公共帧 2~5 或段帧 +1 */
}
else
{
return;
return; /* 非本批帧 / 未开批 → 忽略 */
}

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)
{
(void)OSSemPost(s_param_sem);
(void)OSSemPost(s_param_sem); /* 唤醒 ParamBlockTask */
}
}
}


+ 1
- 1
plsr/plsr.c Parādīt failu

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

(void)pArg;



+ 3
- 3
plsr/plsr.h Parādīt failu

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

/* 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"

/**


+ 273
- 266
plsr/pulse_driver/plsr_pulse_driver.c
Failā izmaiņas netiks attēlotas, jo tās ir par lielu
Parādīt failu


+ 4
- 4
plsr/pulse_driver/plsr_pulse_driver.h Parādīt failu

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

/* 驱动拥有的真实输出状态,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


+ 682
- 647
plsr/run_control/plsr_run_control.c
Failā izmaiņas netiks attēlotas, jo tās ir par lielu
Parādīt failu


+ 37
- 26
plsr/signal_io/plsr_signal_io.c Parādīt failu

@@ -164,19 +164,20 @@ static void PlsrSignalIoTim5Init(void)
{
__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_EnableIRQ(TIM5_IRQn);
}

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

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

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

/* 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;
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)
{
TIM5->CR1 = 0U;
@@ -245,6 +247,7 @@ void PlsrSignalIoCancelDelay(void)
s_delay_armed = 0U;
}

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

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

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

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

/** @brief 取 WAIT 口有效下降沿(读后清) */
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 (s_debounce_x4.fell != 0U)
@@ -315,9 +322,10 @@ uint8_t PlsrSignalIoTakeWaitFalling(void)
return 0U;
}

/** @brief 取 EXT 口有效下降沿(读后清) */
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 (s_debounce_x4.fell != 0U)
@@ -334,6 +342,7 @@ uint8_t PlsrSignalIoTakeExtFalling(void)
return 0U;
}

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

/** @brief EXTI9_5:X4 下降沿 → pending */
void PlsrSignalIoOnExti9_5(void)
{
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)
{
if (__HAL_GPIO_EXTI_GET_IT(PLSR_X5_PIN) != 0U)


Notiek ielāde…
Atcelt
Saglabāt