/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : machine.c * @brief : LK540 Machine Stepper Motor Control Implementation * 步进电机控制模块实现 ****************************************************************************** * @attention * * Copyright (c) 2026 STMicroelectronics. * All rights reserved. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "machine.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* 步进脉冲时序参数(微秒) */ #define STEP_PULSE_HIGH_TIME_US 10 /* 脉冲高电平时间 */ #define STEP_PULSE_LOW_TIME_US 10 /* 脉冲低电平时间 */ /* 移动相关参数 */ #define MAX_STEPS_TO_ORIGIN 50000 /* 移动到原点的最大步数(防止无限循环) */ #define STEP_DELAY_US 100 /* 每步之间的延时(微秒) */ /* 各料位相对于原点的距离(mm) */ #define DISTANCE_TO_MATERIAL1 22.6f /* 215.0 - 192.4 = 22.6mm (向左) */ #define DISTANCE_TO_MATERIAL2 149.6f /* 215.0 - 65.4 = 149.6mm (向左) */ #define DISTANCE_TO_MATERIAL3 153.4f /* 215.0 - 61.6 = 153.4mm (向右) */ #define DISTANCE_TO_MATERIAL4 26.4f /* 215.0 - 188.6 = 26.4mm (向右) */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ /* USER CODE BEGIN PFP */ static void DelayUs(uint32_t us); static uint32_t Machine_MmToSteps(float mm); static uint8_t Machine_MoveSteps(Motor_DirectionTypeDef dir, uint32_t steps); /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /** * @brief 微秒级延时函数 * @param us: 延时时间(微秒) * @note 基于系统时钟的简单延时,72MHz系统时钟下 * 考虑循环开销,使用约60个周期/微秒 * @retval None */ static void DelayUs(uint32_t us) { uint32_t i; /* 72MHz时钟,考虑循环开销,约60个周期/微秒 */ for (i = 0; i < us * 60; i++) { __NOP(); } } /** * @brief 将毫米距离转换为步数 * @param mm: 距离(毫米) * @retval 步数 */ static uint32_t Machine_MmToSteps(float mm) { /* 每毫米5.33个脉冲,向上取整 */ return (uint32_t)(mm * MOTOR_PULSE_PER_MM + 0.5f); } /** * @brief 步进电机移动指定步数 * @param dir: 移动方向 * @param steps: 移动步数 * @retval 0: 成功, 1: 失败(到达限位点) */ static uint8_t Machine_MoveSteps(Motor_DirectionTypeDef dir, uint32_t steps) { uint32_t i; /* 设置方向 */ Machine_SetDirection(dir); DelayUs(STEP_DELAY_US); /* 移动指定步数 */ for (i = 0; i < steps; i++) { /* 检查限位传感器 */ if (Machine_IsAtLimit()) { return 1; /* 到达限位点,返回错误 */ } /* 移动一步 */ Machine_Step(); DelayUs(STEP_DELAY_US); } return 0; /* 成功 */ } /* USER CODE END 0 */ /* Exported functions --------------------------------------------------------*/ /** * @brief 检测步进电机是否在原点 * @note PB3状态为0表示检测到步进电机在原点 * @retval 1: 在原点, 0: 不在原点 */ uint8_t Machine_IsAtOrigin(void) { GPIO_PinState pinState; /* 读取PB3引脚状态 */ pinState = HAL_GPIO_ReadPin(MOTOR_ORIGIN_PIN_PORT, MOTOR_ORIGIN_PIN); /* PB3为0表示在原点 */ return (pinState == GPIO_PIN_RESET) ? 1 : 0; } /** * @brief 检测步进电机是否在临界点(限位传感器) * @note PG15状态为0表示检测到步进电机到达临界点,不能再前进了 * @retval 1: 在临界点, 0: 不在临界点 */ uint8_t Machine_IsAtLimit(void) { GPIO_PinState pinState; /* 读取PG15引脚状态 */ pinState = HAL_GPIO_ReadPin(MOTOR_LIMIT_PIN_PORT, MOTOR_LIMIT_PIN); /* PG15为0表示在临界点 */ return (pinState == GPIO_PIN_RESET) ? 1 : 0; } /** * @brief 设置步进电机方向 * @param dir: 方向 * MOTOR_DIR_CW (0): 向左移动 (CW - Clockwise) * MOTOR_DIR_CCW (1): 向右移动 (CCW - Counter Clockwise) * @note PD7为0表示向左,1表示向右 * @retval None */ void Machine_SetDirection(Motor_DirectionTypeDef dir) { GPIO_PinState pinState; /* 根据方向设置PD7引脚状态 */ /* CW(0) = 向左 = GPIO_PIN_RESET, CCW(1) = 向右 = GPIO_PIN_SET */ pinState = (dir == MOTOR_DIR_CW) ? GPIO_PIN_RESET : GPIO_PIN_SET; /* 设置方向引脚 */ HAL_GPIO_WritePin(MOTOR_DIR_PIN_PORT, MOTOR_DIR_PIN, pinState); } /** * @brief 步进电机移动一步 * @note 产生一个脉冲信号,电机移动一步 * 移动1mm需要5.33个脉冲,所以一步约等于1/5.33 mm * 脉冲时序:低->高->低 * @retval None */ void Machine_Step(void) { /* 确保步进引脚初始为低电平 */ HAL_GPIO_WritePin(MOTOR_STEP_PIN_PORT, MOTOR_STEP_PIN, GPIO_PIN_RESET); DelayUs(STEP_PULSE_LOW_TIME_US); /* 产生高电平脉冲 */ HAL_GPIO_WritePin(MOTOR_STEP_PIN_PORT, MOTOR_STEP_PIN, GPIO_PIN_SET); DelayUs(STEP_PULSE_HIGH_TIME_US); /* 恢复低电平 */ HAL_GPIO_WritePin(MOTOR_STEP_PIN_PORT, MOTOR_STEP_PIN, GPIO_PIN_RESET); DelayUs(STEP_PULSE_LOW_TIME_US); } /** * @brief 步进电机移动到原点 * @note 一直向左移动直到检测到原点传感器(PB3为0) * 如果检测到限位传感器(PG15为0),则停止并返回错误 * @retval 0: 成功到达原点, 1: 到达限位点(错误) */ uint8_t Machine_MoveToOrigin(void) { uint32_t stepCount = 0; /* 设置方向为向左(CW) */ Machine_SetDirection(MOTOR_DIR_CW); DelayUs(STEP_DELAY_US); /* 如果已经在原点,直接返回 */ if (Machine_IsAtOrigin()) { return 0; } /* 一直向左移动直到检测到原点 */ while (!Machine_IsAtOrigin()) { /* 检查限位传感器 */ if (Machine_IsAtLimit()) { return 1; /* 到达限位点,返回错误 */ } /* 防止无限循环 */ if (stepCount++ > MAX_STEPS_TO_ORIGIN) { return 1; /* 超时,返回错误 */ } /* 移动一步 */ Machine_Step(); DelayUs(STEP_DELAY_US); } return 0; /* 成功到达原点 */ } /** * @brief 步进电机从原点移动到中心点 * @note 从原点(传感器位置)向右移动215.0mm到达中心点 * @retval 0: 成功, 1: 失败(到达限位点) */ uint8_t Machine_MoveToCenter(void) { uint32_t steps; /* 计算需要的步数:215.0mm */ steps = Machine_MmToSteps(MOTOR_ORIGIN_DISTANCE); /* 向右移动 */ return Machine_MoveSteps(MOTOR_DIR_CCW, steps); } /** * @brief 步进电机从中心点移动到1#料位置 * @note 从原点(215.0mm)向左移动22.6mm到达1#料(192.4mm) * @retval 0: 成功, 1: 失败(到达限位点) */ uint8_t Machine_MoveToMaterial1(void) { uint32_t steps; /* 计算需要的步数 */ steps = Machine_MmToSteps(DISTANCE_TO_MATERIAL1); /* 向左移动 */ return Machine_MoveSteps(MOTOR_DIR_CW, steps); } /** * @brief 步进电机从中心点移动到2#料位置 * @note 从原点(215.0mm)向左移动149.6mm到达2#料(65.4mm) * @retval 0: 成功, 1: 失败(到达限位点) */ uint8_t Machine_MoveToMaterial2(void) { uint32_t steps; /* 计算需要的步数 */ steps = Machine_MmToSteps(DISTANCE_TO_MATERIAL2); /* 向左移动 */ return Machine_MoveSteps(MOTOR_DIR_CW, steps); } /** * @brief 步进电机从中心点移动到3#料位置 * @note 从原点(215.0mm)向右移动153.4mm到达3#料(61.6mm) * @retval 0: 成功, 1: 失败(到达限位点) */ uint8_t Machine_MoveToMaterial3(void) { uint32_t steps; /* 计算需要的步数 */ steps = Machine_MmToSteps(DISTANCE_TO_MATERIAL3); /* 向右移动 */ return Machine_MoveSteps(MOTOR_DIR_CCW, steps); } /** * @brief 步进电机从中心点移动到4#料位置 * @note 从原点(215.0mm)向右移动26.4mm到达4#料(188.6mm) * @retval 0: 成功, 1: 失败(到达限位点) */ uint8_t Machine_MoveToMaterial4(void) { uint32_t steps; /* 计算需要的步数 */ steps = Machine_MmToSteps(DISTANCE_TO_MATERIAL4); /* 向右移动 */ return Machine_MoveSteps(MOTOR_DIR_CCW, steps); } /* USER CODE BEGIN 1 */ /* USER CODE END 1 */