STM32驱动步进电机(最全的版本寄存器+HAL库实现)

1 简介

1.1 什么是步进电机

步进电机是一种将电脉冲信号转换成相应角位移或线位移的电动机。每输入一个脉冲信号,转子就转动一个角度或前进一步,其输出的角位移或线位移与输入的脉冲数成正比,转速与脉冲频率成正比。因此,步进电动机又称脉冲电动机
详见百度百科:点击

1.2 步进电机和直流电机区别

种类直流电机步进电机
性质将直流电能转换为机械能的电动机将电脉冲信号转变为角位移或线位移的开环控制电机
原理当直流电源通过电刷向电枢绕组供电时,电枢表面的N极下导体可以流过相同方向的电流,根据左手定则导体将受到逆时针方向的力矩作用;电枢表面S极下部分导体也流过相同方向的电流,同样根据左手定则导体也将受到逆时针方向的力矩作用通常电机的转子为永磁体,当电流流过定子绕组时,定子绕组产生一矢量磁场。该磁场会带动转子旋转一角度,使得转子的一对磁场方向与定子的磁场方向一致。当定子的矢量磁场旋转一个角度。转子也随着该磁场转一个角度
主要不同直流电机内部有随电机转动而自动换向的绕组转换zhi机构步进电机的内部是没有绕组换向机构的

1.3 器材与配置

1.3.1 步进电机

在这里插入图片描述

1.3.2 驱动器

在这里插入图片描述

1.3.3 引脚

功能引脚
TIM3 _ch2PB5
按键PA0 \PC13
灯泡PB0

2 定时器的

3 驱动代码

本设计是采用TIM3->CH2通道 PB5 ,通过改变PB5的频率 从而达到变速设置。两个按键一个是加速、一个是减速。
注!!!!
1.步进电机通电后不会转
2.步进电机驱动器有一个保护就是速度过大会自动停止电机
3.如果发出怪声音是频率问题
4.步进电机是改变频率不是改变占空比调速
所以调速就改变计时器的输出频率就ok了
5.此版本是测试版本,只是简单实现了加速和减速功能,后续会优化加速减速功能,比如缓冲停车,加速分档等等

3.1 初始化

下面展示一些 寄存器初始化

void TIM3_Configuration( void)
{
	
	RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
	RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
	AFIO->MAPR = AFIO_MAPR_TIM3_REMAP_1; //部分映像
	GPIOB->CRL = (GPIOB->CRL & 0XFF0FFFF0) | 0XB00003;
	TIM3->ARR = 9;
	TIM3->PSC =71;
	TIM3->RCR = 1;
	TIM3->CR1 = TIM_CR1_CKD& 0X0000;
	TIM3->CR1 &=~TIM_CR1_DIR;
	TIM3->CCMR1 |= TIM_CCMR1_OC2M |( TIM_CCMR1_CC2S&0x0000)| TIM_CCMR1_OC2PE;
	TIM3->CR1 |= TIM_CR1_ARPE;
	TIM3->CCR2 = 9/2;
	TIM3->CCER |= TIM_CCER_CC2P | TIM_CCER_CC2E;
	TIM3->EGR |= TIM_EGR_UG;
	TIM3->CR1 |= TIM_CR1_CEN;
	TIM3->BDTR |= TIM_BDTR_MOE;
	//电机
	GPIOB->CRH = (GPIOB->CRH & 0X0FFFFFFF) | 0X30000000;
	
}

3.2 控制

下面展示一些 内联代码片

// An highlighted block
int main()

{
	RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_AFIOEN | RCC_APB2ENR_IOPCEN;
	GPIOA->CRL |= (GPIOA->CRL & 0XFFFFFFF0) | 0X4;
	GPIOC->CRH |= (GPIOC->CRH & 0XFF0FFFFF) | 0X400000;
	TIM3_Configuration();
	int i = 1;
	GPIOB->ODR |= GPIO_ODR_ODR0;
	while(1)
	{
		
		int i; 
		for(i = 0; i < 60; i++)
		{
			delay_ms(10);
			TIM2->CCR3 = i*5;
		}
		for(i = 60; i> 0; i--)
		{
			delay_ms(10);
			TIM2->CCR3 = i*5;
		}
		//减速
		if(GPIOA->IDR & GPIO_IDR_IDR0)
		{
			delay_ms(1000);
			GPIOB->ODR &=~GPIO_ODR_ODR0;
	
			if(GPIOA->IDR & GPIO_IDR_IDR0)
			{
				delay_ms(1000);
				i++;
				TIM3->ARR = i*50;
	
			}
		}
		//加速
		if(GPIOC->IDR & GPIO_IDR_IDR13)
		{
			delay_ms(1000);
			GPIOB->ODR |= GPIO_ODR_ODR0;
			if(GPIOA->IDR & GPIO_IDR_IDR13)
			{
				delay_ms(1000);
				i--;
				TIM3->ARR = i*5;
			}
		}
		if(i > 10 || i <= 1)
			i = 1;
	}

}

4. HAL库版本

4.1 源码

HAL库的初始化笔者直接在STM32Cube.mx中生成的,这里给出生成的代码,和控制代码

main.c

// An highlighted block
#include <stm32f1xx.h>
#include <stdio.h>
UART_HandleTypeDef huart1;
TIM_HandleTypeDef timhandle;
TIM_OC_InitTypeDef timoc;
void Error_Handler(void);
int i = 79;
void led_init()
{
	GPIO_InitTypeDef gpio = {0};
	gpio.Mode = GPIO_MODE_OUTPUT_PP;
	gpio.Pin = GPIO_PIN_1 |GPIO_PIN_0;
	gpio.Pull = GPIO_NOPULL;
	gpio.Speed = GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(GPIOB, &gpio);
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1| GPIO_PIN_0 ,GPIO_PIN_RESET);
	
}
void pwm_init()
{
	/*PB5*/
	GPIO_InitTypeDef gpio = {0};
	gpio.Mode = GPIO_MODE_AF_PP;
	gpio.Pin = GPIO_PIN_5;
	gpio.Speed = GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(GPIOB, &gpio);
	
	/*TIM3 CH2*/
	__HAL_RCC_TIM3_CLK_ENABLE();
	__HAL_RCC_AFIO_CLK_ENABLE();
	__HAL_AFIO_REMAP_TIM3_PARTIAL();

	timhandle.Init.Period = i;
	timhandle.Init.Prescaler = 25;
	timhandle.Init.CounterMode = TIM_COUNTERMODE_UP;
	timhandle.Instance=TIM3;
	HAL_TIM_PWM_Init(&timhandle);

	timoc.Pulse = 4;
	timoc.OCMode = TIM_OCMODE_PWM2;
	HAL_TIM_PWM_ConfigChannel(&timhandle,&timoc,TIM_CHANNEL_2);//配置TIM3通道2    
	HAL_TIM_PWM_Start(&timhandle,TIM_CHANNEL_2);//开启PWM通道2


}
/**
* @brief UART MSP Initialization
* This function configures the hardware resources used in this example
* @param huart: UART handle pointer
* @retval None
*/
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(huart->Instance==USART1)
  {
  /* USER CODE BEGIN USART1_MspInit 0 */

  /* USER CODE END USART1_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_USART1_CLK_ENABLE();
  
    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**USART1 GPIO Configuration    
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* USER CODE BEGIN USART1_MspInit 1 */

  /* USER CODE END USART1_MspInit 1 */
  }

}
/**
* @brief UART MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param huart: UART handle pointer
* @retval None
*/
void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
{
  if(huart->Instance==USART1)
  {
  /* USER CODE BEGIN USART1_MspDeInit 0 */

  /* USER CODE END USART1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_USART1_CLK_DISABLE();
  
    /**USART1 GPIO Configuration    
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX 
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);

  /* USER CODE BEGIN USART1_MspDeInit 1 */

  /* USER CODE END USART1_MspDeInit 1 */
  }

}
/**
  * @brief USART1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART1_UART_Init(void)
{

  /* USER CODE BEGIN USART1_Init 0 */

  /* USER CODE END USART1_Init 0 */

  /* USER CODE BEGIN USART1_Init 1 */

  /* USER CODE END USART1_Init 1 */
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_MultiProcessor_Init(&huart1, 0, UART_WAKEUPMETHOD_IDLELINE) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART1_Init 2 */

  /* USER CODE END USART1_Init 2 */

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();


  /*Configure GPIO pin : PC13 */
  GPIO_InitStruct.Pin = GPIO_PIN_13;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /*Configure GPIO pin : PA0 */
  GPIO_InitStruct.Pin = GPIO_PIN_0;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  /* EXTI interrupt init*/
  HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 1);
  HAL_NVIC_EnableIRQ(EXTI0_IRQn);

  HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0, 1);
  HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);

}


/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

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

  /* USER CODE END Error_Handler_Debug */
}
int main(void)
{

	HAL_Init();
	HAL_UART_MspDeInit(&huart1);
	MX_USART1_UART_Init();
	MX_GPIO_Init();
	__HAL_RCC_GPIOB_CLK_ENABLE();
	__HAL_RCC_USART1_CLK_ENABLE();
	led_init();
	pwm_init();
	
	while(1){
	if(i <20  && i > 7199)
		i = 500;
	
	}
}


void EXTI0_IRQHandler(void)
{
	i -= 20;
//	timhandle.Init.Period = i*10;
	TIM3->ARR = 500;
  /* USER CODE BEGIN EXTI0_IRQn 0 */
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);
  /* USER CODE END EXTI0_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
  /* USER CODE BEGIN EXTI0_IRQn 1 */

  /* USER CODE END EXTI0_IRQn 1 */
}

void EXTI15_10_IRQHandler(void)
{
	i += 100;
//	timhandle.Init.Period = i*10;
  /* USER CODE BEGIN EXTI15_10_IRQn 0 */
	TIM3->ARR = 10;
  /* USER CODE END EXTI15_10_IRQn 0 */
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
  /* USER CODE BEGIN EXTI15_10_IRQn 1 */

  /* USER CODE END EXTI15_10_IRQn 1 */
}

工程源码

1.csdn:点击
2.在微信搜索:MeiXiangDao2020 关注公众号:媒想到叭。 然后回复: 步进电机

STM32HAL库中,我们可以使用步进电机驱动器来控制步进电机的转角。步进电机是一种将输入脉冲信号转换为旋转角度的设备。在执行旋转时,步进电机有两种常见的工作方式:全步进和半步进。 在全步进模式下,步进电机按照每个输入脉冲将旋转角度分成几个均匀的步进。例如,如果我们将全步进设置为360度,那么每个脉冲将使步进电机旋转1度。使用STM32HAL库,我们可以通过配置相关的寄存器和定时器来生成精确的脉冲信号,并控制步进电机的转角。 另一种常见的工作模式是半步进模式。在这种模式下,步进电机旋转的角度会更精确,因为每个脉冲将使步进电机旋转更小的角度。例如,在半步进模式下,两个连续的脉冲将使步进电机旋转0.9度。使用STM32HAL库,我们可以配置相关的寄存器和定时器来生成正确的脉冲序列,从而控制步进电机的转角。 要控制步进电机的转角,我们可以设置相关的寄存器来指定步进电机每个输入脉冲的角度。例如,对于全步进模式,我们可以设置一个变量来存储每个脉冲对应的角度值,并在定时器中断中更新该变量。对于半步进模式,我们可以设置一个数组来存储每个脉冲对应的角度值,并在定时器中断中选择正确的角度。 总之,使用STM32HAL库,我们可以轻松地控制步进电机的转角。无论是全步进模式还是半步进模式,通过正确配置相关的寄存器和定时器,我们可以生成精确的脉冲信号,并控制步进电机旋转到所需的角度。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sf9090

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值