SelfLearnFinished=1
Motor_Init(从掉电保持区读取上次标定与运行状态,若可信且一致,则计算 Position_Up/Position_Down 和 Set_Position,返回 1 表示“可跳过自学习”;否则返回 0)
忙碌返回 :如果当前任务不空闲,则返回 1 ,表示请求未能发起
S0:请求读取电机状态
正常控制流程 (motor_ctrl & motor_set_position)
读取存储器 : ReadData_Cali = *(volatile uint64_t*)(MOTOR_CALI_DATA_ADDR); :从 MOTOR_CALI_DATA_ADDR 地址读取 64 位(8 字节)的校准数据。这个数据包含了校验魔数和 Position_Limite ReadData_St = *(volatile uint64_t*)(MOTOT_RUNNING_ST_ADDR); :从 MOTOT_RUNNING_ST_ADDR 地址读取 64 位(8 字节)的运行状态数据。这个数据包含了 MotorRunningSt 和 MotorRunningDir
真
请求发起失败
读取外部请求 : SPKMotionSysConReq_l= l_u8_rd_LI0_SPKMotionSysConReq_l(); 从 LIN 总线读取外部(如车身控制器)发送的控制指令(例如“向上”、“向下”)
动作映射 :Action == MOTOR_DIR_UP (通常为 1 ):将 Set_Position 设置为 Position_Up Action == MOTOR_DIR_DOWN (通常为 2 ):将 Set_Position 设置为 Position_Down Action == 0 (无请求):不改变 Set_Position
没到位
调用 motor_set_position(SPKMotionSysConReq_l) :根据外部指令更新电机的目标位置 Set_Positionif((SelfLearnFinished == 1) && (motor_ctrl_step == 0))(即只有当电机已完成自学习且当前控制状态机空闲时才执行)
S0-S1 :读取电机当前位置 Current_Position 比对目标 :如果 Current_Position 不等于 Set_Position ,则表示需要移动
解析数据 :Position_Limite = (uint16_t)((ReadData_Cali >> 32) & 0xFFFF); :从 ReadData_Cali 的高 16 位中提取 Position_Limite MotorRunningSt = (uint32_t)(ReadData_St & 0xFFFFFFFF); :从 ReadData_St 的低 32 位中提取 MotorRunningSt MotorRunningDir = (uint32_t)((ReadData_St >> 32) & 0xFFFFFFFF); :从 ReadData_St 的高 32 位中提取 MotorRunningDir
S11:等待 TX 完成
Motor_MainFuncion(在 main 循环中每 50ms 调用一次)
S10:发送“打到 60000”的指令(镜像时对应反向)
数据有效性校验 :if(((ReadData_Cali & 0xFFFFFFFF) == 0xDDCCBBAA) && (MotorRunningSt == 0) && ((MotorRunningDir == 1) || (MotorRunningDir == 2))) :检查校准数据是否包含正确的“魔数” ( 0xDDCCBBAA ),上次任务是否完成 ( MotorRunningSt == 0 ),以及上次运行方向是否有效
否
假
数据收齐且收到的第一位数据为0x02
S8-->S9:预约读取状态并等待完成
退出
返回结果 :返回 1 :表示成功从存储器加载有效数据,可以跳过自学习返回 0 :表示数据无效或范围不符,需要执行完整的自学习
S6:发送“设置当前位置为基准”的指令(若 FindMotorCaliData==1 则写入 Position_Up/Down;否则默认 0x2710=10000)
预约请求 :如果当前任务空闲,则:lin_id_list[0].task_type = TASK_TYPE_RX; :将 ID 0x02 的任务类型设置为“接收”g_lin_node.msg_list[2].task_type = TASK_TYPE_RX; :确保 LIN 协议栈的报文缓冲区也标记为接收任务g_timer2_flag = 1; :置位全局定时器标志,通知 main.c 中的 lin_loop 立即处理这个新的 LIN 任务返回 0 :表示请求成功发起
S12-->S13:预约读取状态并等待完成;从应答中解析 Position_Limite,并计算 Position_Up/Down 写入掉电保持区:固化 Position_Limite 到 MOTOR_CALI_DATA_ADDR 写“Job Finished/方向”到 MOTOT_RUNNING_ST_ADDRSet_Position 默认置为 Position_Down,SelfLearnFinished=1
motor_self_learn
S3:等待 TX 完成
左右电机区分 :通过 LI0_lin_configured_NAD 判断当前是右电机 ( 0x11 ) 还是左电机
S1:调用 Motor_Init
S2:准备发送“去零点”指令,把 data_goto_zero 复制到发送缓冲,标 TX,置 g_timer2_flag
左右电机适配与位置计算 :如果校验通过,会根据 MOTOR_DIR 宏和 LI0_lin_configured_NAD (LIN 节点地址)判断当前是左电机还是右电机在对应的分支中,会根据 Position_Limite 计算出 Position_Down 和 Position_Up 同时,会根据 MotorRunningDir (上次运行方向)设置 data_set_current_position 报文中的目标位置,并更新 Set_Position 如果 Position_Limite 在合理范围内,则设置 Ret = 1
S4-S5 :循环读取电机当前位置,直到 Current_Position 等于 Set_Position
Motor_Init 返回 0:FindMotorCaliData=0
S7:等待“置当前为基准”完成 如果 FindMotorCaliData==1:此处直接 SelfLearnFinished=1,结束状态机(break),后续按已存在标定继续运行 否则进入继续完整测量流程
S5:状态检查,确认电机到位(通过状态字某位)
所有节点都有回退和重试路径,避免异常卡死(多处将 motor_init_step 置 0 并清空任务标志
S2-S3 :将 Set_Position 打包到 data_goto_Set_Position 报文中,并标记为 TASK_TYPE_TX 发送给电机。同时,将当前任务状态和方向写入存储器
调用 motor_ctrl() :执行电机的正常位置控制状态机
忙碌检查 : if((TASK_TYPE_RX != lin_id_list[0].task_type) && (TASK_TYPE_TX != lin_id_list[0].task_type)) 。检查 LIN 任务列表中的第一个任务(通常是 ID 0x02)是否正在进行 RX 或 TX 操作
S4:再次预约读取状态(RX)
变量变化 : Set_Position 被更新为 Position_Up 或 Position_Down