STM32+TMC2209控制步进电机正反转。

avatar
作者
猴君
阅读量:0

STM32F103ZET6+TMC2209控制步进电机正反转

1. 步进电机介绍

  • 本实验采用2项步进电机,电机只有2项,A+\A-\B+\B-。
  • 电机步距角1.8°
    在这里插入图片描述

2 驱动器TMC2209介绍

2.1 引脚图及其功能

在这里插入图片描述
在这里插入图片描述

2.2 细分介绍

在这里插入图片描述

  • 8细分控制精度=1.8°/8=0.225°,电机转一周需要1600个脉冲。
  • 16细分控制精度=1.8°/16=0.1125°,电机转一周需要3200个脉冲。
  • 32细分控制精度=1.8°/32=0.05625°,电机转一周需要6400个脉冲。
  • 64细分控制精度=1.8°/64=0.0140625°,电机转一周需要12800个脉冲。
    满足绝大多数精度场景,如低精度机床、家电、3D打印等。

2.3 TMC控制驱动器接法

这里只需要使用13个引脚
EN:控制器使能引脚,接GND, 电机才能工作。
DIR:控制方向,这个引脚的高\低电平分别控制正\反转
VM:给电机的电压(4.75—>28VDC),可以选择24V电源供电,没24V直流电源可以在网上买一个。电机电压5V可能导致电机丢步,尽量选择24V的直流电源。
GND:VM的GND
STEP: 控制脉冲,一个占空比为50%高电平、一个占空比50%的低电平为一个脉冲。
MS1\MS2: 控制细分,参考2.2节
VDD: 给TMC2209供电,供+5V供电。
GND: VDD的GND
A1\A2\B1\B2: 参考第1节的电机。

3 控制器介绍

  • STM32F103ZET6(正点原子V3)

3.1 确定控制引脚

  • 将下面的引脚与2.3的引脚连接,具体位置如下图红圈位置。
    DIR: PF12/FSMC_A6
    STEP: PG1/FSMC_A11
    EN: PF14/FSMC_A8
    MS1: PF15/FSMC_A9
    MS2: PG0/FSMC_VA10
    VDD: 见下图红圈位置
    GND: 见下图红圈位置
    在这里插入图片描述

3.2 UBEMX配置

3.2.1 GPIO配置

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.2.2 NVIC配置

在这里插入图片描述在这里插入图片描述

3.2.3 RCC配置

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.2.4 SYS配置

  • 用的ST-link V2的仿真器,选择下面这个:
    在这里插入图片描述

3.2.5 USRAT2配置(PS:没用上可以跳过)

在这里插入图片描述

3.2.6 保存并生成工程

在这里插入图片描述

4 代码部分

主要修改main.c,其他的不用管。

/* USER CODE BEGIN Header */ /**   ******************************************************************************   * @file           : main.c   * @brief          : Main program body   ******************************************************************************   * @attention   *   * Copyright (c) 2024 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 "usart.h" #include "gpio.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 ---------------------------------------------------------*/ // UART_HandleTypeDef huart2a; /* USER CODE BEGIN PV */  /* USER CODE END PV */  /* Private function prototypes -----------------------------------------------*/ // static void MX_GPIO_Init(void); // static void MX_USART2_UART_Init(void); void SystemClock_Config(void); /* USER CODE BEGIN PFP */  /* USER CODE END PFP */  /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ void SubdivisionSet(uint8_t i);												//细分设置 void MoveStep(uint8_t DIR_Flag,uint32_t Step);				//电机移动多少步 /* 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();   MX_USART2_UART_Init();   /* USER CODE BEGIN 2 */ 	SubdivisionSet(64);													//细分设置为64 	HAL_GPIO_WritePin(GPIOG,STEP_Pin, GPIO_PIN_SET); 																							//STEP设置为高    /* USER CODE END 2 */    /* Infinite loop */   /* USER CODE BEGIN WHILE */   while (1)   {     /* USER CODE END WHILE */ 		MoveStep(1,12800*10);													//正转一圈 		HAL_Delay(2000);														//延时2S 		MoveStep(0,12800*10);													//反转一圈 		HAL_Delay(2000);														//延时2S     /* USER CODE BEGIN 3 */   }   /* USER CODE END 3 */ }  /**   * @brief SubdivisionSet 	* 细分设置   * @retval None   */ void SubdivisionSet(uint8_t i) { 	if(i==8) 	{ 		HAL_GPIO_WritePin(GPIOG,MS2_Pin, GPIO_PIN_RESET); 		HAL_GPIO_WritePin(GPIOF,MS1_Pin, GPIO_PIN_RESET); 	} 	else 	if(i==32) 	{ 		HAL_GPIO_WritePin(GPIOG,MS2_Pin, GPIO_PIN_RESET); 		HAL_GPIO_WritePin(GPIOF,MS1_Pin, GPIO_PIN_SET); 	} 	else 	if(i==64) 	{ 		HAL_GPIO_WritePin(GPIOG,MS2_Pin, GPIO_PIN_SET); 		HAL_GPIO_WritePin(GPIOF,MS1_Pin, GPIO_PIN_RESET); 	} 	else 	{ 		HAL_GPIO_WritePin(GPIOG,MS2_Pin, GPIO_PIN_SET); 		HAL_GPIO_WritePin(GPIOF,MS1_Pin, GPIO_PIN_SET); 	} } /**   * @brief DelayNop 	* 延时   * @retval None   */ void DelayNop(uint8_t i) { 	uint32_t 	j; 	do 	{ 		for(j=0;j<100;j++){;} 	}while(i--); } /**   * @brief MoveStep 	* 电机移动多少步   * @retval None   */ void MoveStep(uint8_t DIR_Flag,uint32_t Step) { 	//uint8_t		j=200; 	uint32_t		j=1; 	uint32_t 	i; 	 	//电机使能 	HAL_GPIO_WritePin(GPIOF,EN_Pin, GPIO_PIN_RESET); 	 	if(DIR_Flag) 	{ 		//正转 		HAL_GPIO_WritePin(GPIOF,DIR_Pin, GPIO_PIN_SET); 	} 	else 	{ 		//反转 		HAL_GPIO_WritePin(GPIOF,DIR_Pin, GPIO_PIN_RESET); 	} 	 	for(i=0;i<Step;i++) 	{ 		//发送脉冲 		HAL_GPIO_WritePin(GPIOG,STEP_Pin, GPIO_PIN_RESET); 		 		//if(j>1)	j--; 		//else;		 		DelayNop(j); 		HAL_GPIO_WritePin(GPIOG,STEP_Pin, GPIO_PIN_SET); 		DelayNop(j); 	} 	 	HAL_Delay(10); 	//电机非使能 	HAL_GPIO_WritePin(GPIOF,EN_Pin, GPIO_PIN_SET); } /**   * @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_HSI;   RCC_OscInitStruct.HSIState = RCC_HSI_ON;   RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2;   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_1) != HAL_OK)   {     Error_Handler();   } }  /* USER CODE BEGIN 4 */ /**   * @brief USART2 Initialization Function   * @param None   * @retval None   */ //void MX_USART2_UART_Init(void) //{  //  /* USER CODE BEGIN USART2_Init 0 */  //  /* USER CODE END USART2_Init 0 */  //  /* USER CODE BEGIN USART2_Init 1 */  //  /* USER CODE END USART2_Init 1 */ //  huart2a.Instance = USART2; //  huart2a.Init.BaudRate = 115200; //  huart2a.Init.WordLength = UART_WORDLENGTH_8B; //  huart2a.Init.StopBits = UART_STOPBITS_1; //  huart2a.Init.Parity = UART_PARITY_NONE; //  huart2a.Init.Mode = UART_MODE_TX_RX; //  huart2a.Init.HwFlowCtl = UART_HWCONTROL_NONE; //  huart2a.Init.OverSampling = UART_OVERSAMPLING_16; //  if (HAL_UART_Init(&huart2a) != HAL_OK) //  { //    Error_Handler(); //  }   /* USER CODE BEGIN USART2_Init 2 */    /* USER CODE END USART2_Init 2 */  //}  /**   * @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 */  
  • 这边的代码是选择64细分,正转10圈-等待2S-反转10圈-等待2S。
    在这里插入图片描述
  • 编译代码烧录到单板
    仿真器配置参考link中13节。
    在这里插入图片描述
  • 这样,就可以控制电机正反转啦。
    ps: 正点原子STM32战舰版V3的板子每次烧录需要摁红色reset按钮,烧录才能生效。

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!