增加读取寄存器状态和控制步进电机功能

This commit is contained in:
yankun
2026-02-06 17:12:14 +08:00
parent eaa1427f9f
commit 04936f22cf
4 changed files with 868 additions and 384 deletions

136
Core/Inc/machine.h Normal file
View File

@@ -0,0 +1,136 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : machine.h
* @brief : LK540 Machine Stepper Motor Control Header
* 步进电机控制模块头文件
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
******************************************************************************
*/
/* USER CODE END Header */
#ifndef __MACHINE_H
#define __MACHINE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Exported types ------------------------------------------------------------*/
/**
* @brief 步进电机方向枚举
*/
typedef enum
{
MOTOR_DIR_CWW = 0, /* 向左移动 (Counter Clockwise) */
MOTOR_DIR_CW = 1 /* 向右移动 (Clockwise) */
} Motor_DirectionTypeDef;
/* Exported constants --------------------------------------------------------*/
/* 电机参数定义 */
#define MOTOR_PULSE_PER_MM 5.33f /* 每毫米脉冲数 */
#define MOTOR_ORIGIN_DISTANCE 215.0f /* 原点距离 (mm) */
#define MOTOR_MATERIAL1_DISTANCE 192.4f /* 1#料距离 (mm) */
#define MOTOR_MATERIAL2_DISTANCE 65.4f /* 2#料距离 (mm) */
#define MOTOR_MATERIAL3_DISTANCE 61.6f /* 3#料距离 (mm) */
#define MOTOR_MATERIAL4_DISTANCE 188.6f /* 4#料距离 (mm) */
/* GPIO引脚定义 */
#define MOTOR_ORIGIN_PIN_PORT GPIOB
#define MOTOR_ORIGIN_PIN GPIO_PIN_3
#define MOTOR_LIMIT_PIN_PORT GPIOG
#define MOTOR_LIMIT_PIN GPIO_PIN_15
#define MOTOR_DIR_PIN_PORT GPIOD
#define MOTOR_DIR_PIN GPIO_PIN_7
#define MOTOR_STEP_PIN_PORT GPIOG
#define MOTOR_STEP_PIN GPIO_PIN_9
/* Exported macro ------------------------------------------------------------*/
/* Exported functions prototypes ---------------------------------------------*/
/**
* @brief 检测步进电机是否在原点
* @retval 1: 在原点, 0: 不在原点
*/
uint8_t Machine_IsAtOrigin(void);
/**
* @brief 检测步进电机是否在临界点(限位传感器)
* @retval 1: 在临界点, 0: 不在临界点
*/
uint8_t Machine_IsAtLimit(void);
/**
* @brief 设置步进电机方向
* @param dir: 方向 (MOTOR_DIR_CWW: 向左, MOTOR_DIR_CW: 向右)
* @retval None
*/
void Machine_SetDirection(Motor_DirectionTypeDef dir);
/**
* @brief 步进电机移动一步
* @note 产生一个脉冲信号电机移动一步1/5.33 mm
* @retval None
*/
void Machine_Step(void);
/**
* @brief 步进电机移动到原点
* @note 一直向左移动直到检测到原点传感器PB3为0
* 如果检测到限位传感器PG15为0则停止并返回错误
* @retval 0: 成功到达原点, 1: 到达限位点(错误)
*/
uint8_t Machine_MoveToOrigin(void);
/**
* @brief 步进电机从原点移动到中心点
* @note 中心点就是原点位置215.0mm处)
* 如果已经在原点,则不需要移动
* @retval 0: 成功, 1: 失败
*/
uint8_t Machine_MoveToCenter(void);
/**
* @brief 步进电机从中心点移动到1#料位置
* @note 从原点215.0mm向左移动22.6mm到达1#料192.4mm
* @retval 0: 成功, 1: 失败(到达限位点)
*/
uint8_t Machine_MoveToMaterial1(void);
/**
* @brief 步进电机从中心点移动到2#料位置
* @note 从原点215.0mm向左移动149.6mm到达2#料65.4mm
* @retval 0: 成功, 1: 失败(到达限位点)
*/
uint8_t Machine_MoveToMaterial2(void);
/**
* @brief 步进电机从中心点移动到3#料位置
* @note 从原点215.0mm向右移动153.4mm到达3#料61.6mm
* @retval 0: 成功, 1: 失败(到达限位点)
*/
uint8_t Machine_MoveToMaterial3(void);
/**
* @brief 步进电机从中心点移动到4#料位置
* @note 从原点215.0mm向右移动26.4mm到达4#料188.6mm
* @retval 0: 成功, 1: 失败(到达限位点)
*/
uint8_t Machine_MoveToMaterial4(void);
#ifdef __cplusplus
}
#endif
#endif /* __MACHINE_H */

View File

@@ -1,69 +1,69 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.h
* @brief : Header for main.c file.
* This file contains the common defines of the application.
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H
#define __MAIN_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx_hal.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
/* Exported functions prototypes ---------------------------------------------*/
void Error_Handler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
#ifdef __cplusplus
}
#endif
#endif /* __MAIN_H */
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.h
* @brief : Header for main.c file.
* This file contains the common defines of the application.
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H
#define __MAIN_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx_hal.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "machine.h"
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
/* Exported functions prototypes ---------------------------------------------*/
void Error_Handler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
#ifdef __cplusplus
}
#endif
#endif /* __MAIN_H */

332
Core/Src/machine.c Normal file
View File

@@ -0,0 +1,332 @@
/* 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_CWW (0): 向左移动 (CWW - Counter Clockwise)
* MOTOR_DIR_CW (1): 向右移动 (CW - Clockwise)
* @note PD7为0表示向左1表示向右
* @retval None
*/
void Machine_SetDirection(Motor_DirectionTypeDef dir)
{
GPIO_PinState pinState;
/* 根据方向设置PD7引脚状态 */
pinState = (dir == MOTOR_DIR_CWW) ? 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;
/* 设置方向为向左CWW */
Machine_SetDirection(MOTOR_DIR_CWW);
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)
{
/* 如果已经在原点(中心点),直接返回成功 */
if (Machine_IsAtOrigin())
{
return 0;
}
/* 否则移动到原点 */
return Machine_MoveToOrigin();
}
/**
* @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_CWW, 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_CWW, 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_CW, 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_CW, steps);
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

View File

@@ -1,315 +1,331 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "cmsis_os.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 */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* Definitions for motorTask */
osThreadId_t motorTaskHandle;
const osThreadAttr_t motorTask_attributes = {
.name = "motorTask",
.stack_size = 256 * 4,
.priority = (osPriority_t) osPriorityAboveNormal,
};
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
void StartMotorTask(void *argument);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Init scheduler */
osKernelInitialize();
/* USER CODE BEGIN RTOS_MUTEX */
/* add mutexes, ... */
/* USER CODE END RTOS_MUTEX */
/* USER CODE BEGIN RTOS_SEMAPHORES */
/* add semaphores, ... */
/* USER CODE END RTOS_SEMAPHORES */
/* USER CODE BEGIN RTOS_TIMERS */
/* start timers, add new ones, ... */
/* USER CODE END RTOS_TIMERS */
/* USER CODE BEGIN RTOS_QUEUES */
/* add queues, ... */
/* USER CODE END RTOS_QUEUES */
/* Create the thread(s) */
/* creation of motorTask */
motorTaskHandle = osThreadNew(StartMotorTask, NULL, &motorTask_attributes);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
/* USER CODE BEGIN RTOS_EVENTS */
/* add events, ... */
/* USER CODE END RTOS_EVENTS */
/* Start scheduler */
osKernelStart();
/* We should never get here as control is now taken by the scheduler */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_7, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_9, GPIO_PIN_RESET);
/*Configure GPIO pin : PD7 */
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/*Configure GPIO pin : PG9 */
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
/*Configure GPIO pin : PG15 */
GPIO_InitStruct.Pin = GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
/*Configure GPIO pin : PB3 */
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/* USER CODE BEGIN Header_StartMotorTask */
/**
* @brief Function implementing the motorTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartMotorTask */
void StartMotorTask(void *argument)
{
/* USER CODE BEGIN 5 */
/* Infinite loop */
for(;;)
{
osDelay(1);
}
/* USER CODE END 5 */
}
/**
* @brief Period elapsed callback in non blocking mode
* @note This function is called when TIM6 interrupt took place, inside
* HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
* a global variable "uwTick" used as application time base.
* @param htim : TIM handle
* @retval None
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* USER CODE BEGIN Callback 0 */
/* USER CODE END Callback 0 */
if (htim->Instance == TIM6)
{
HAL_IncTick();
}
/* USER CODE BEGIN Callback 1 */
/* USER CODE END Callback 1 */
}
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "cmsis_os.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 */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* Definitions for motorTask */
osThreadId_t motorTaskHandle;
const osThreadAttr_t motorTask_attributes = {
.name = "motorTask",
.stack_size = 256 * 4,
.priority = (osPriority_t) osPriorityAboveNormal,
};
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
void StartMotorTask(void *argument);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
/* 上电后步进电机初始化:从任何位置移动到原点 */
/* Power-on initialization: Move stepper motor to origin from any position */
if (Machine_MoveToOrigin() == 0)
{
/* 成功到达原点,移动到中心点(中心点就是原点位置) */
/* Successfully reached origin, move to center (center is the origin position) */
Machine_MoveToCenter();
}
else
{
/* 移动到原点失败,可能是到达限位点或超时 */
/* Failed to move to origin, may have reached limit or timeout */
/* 这里可以添加错误处理例如LED闪烁或蜂鸣器报警 */
/* Error handling can be added here, such as LED blinking or buzzer alarm */
}
/* USER CODE END 2 */
/* Init scheduler */
osKernelInitialize();
/* USER CODE BEGIN RTOS_MUTEX */
/* add mutexes, ... */
/* USER CODE END RTOS_MUTEX */
/* USER CODE BEGIN RTOS_SEMAPHORES */
/* add semaphores, ... */
/* USER CODE END RTOS_SEMAPHORES */
/* USER CODE BEGIN RTOS_TIMERS */
/* start timers, add new ones, ... */
/* USER CODE END RTOS_TIMERS */
/* USER CODE BEGIN RTOS_QUEUES */
/* add queues, ... */
/* USER CODE END RTOS_QUEUES */
/* Create the thread(s) */
/* creation of motorTask */
motorTaskHandle = osThreadNew(StartMotorTask, NULL, &motorTask_attributes);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
/* USER CODE BEGIN RTOS_EVENTS */
/* add events, ... */
/* USER CODE END RTOS_EVENTS */
/* Start scheduler */
osKernelStart();
/* We should never get here as control is now taken by the scheduler */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_7, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_9, GPIO_PIN_RESET);
/*Configure GPIO pin : PD7 */
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/*Configure GPIO pin : PG9 */
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
/*Configure GPIO pin : PG15 */
GPIO_InitStruct.Pin = GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
/*Configure GPIO pin : PB3 */
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/* USER CODE BEGIN Header_StartMotorTask */
/**
* @brief Function implementing the motorTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartMotorTask */
void StartMotorTask(void *argument)
{
/* USER CODE BEGIN 5 */
/* Infinite loop */
for(;;)
{
osDelay(1);
}
/* USER CODE END 5 */
}
/**
* @brief Period elapsed callback in non blocking mode
* @note This function is called when TIM6 interrupt took place, inside
* HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
* a global variable "uwTick" used as application time base.
* @param htim : TIM handle
* @retval None
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* USER CODE BEGIN Callback 0 */
/* USER CODE END Callback 0 */
if (htim->Instance == TIM6)
{
HAL_IncTick();
}
/* USER CODE BEGIN Callback 1 */
/* USER CODE END Callback 1 */
}
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */