stm32通过输出脉冲个数精确控制电机旋转角度

一、硬件准备

57步进电机在市面上还是挺常见的,每一款都大同小异。而市面上最为常用的为两相四线制的步进电机。两相即AB相,四线即步进电机引出来的四根线。

HTS-884A步进电机驱动器 

 

步进电机实际上是按着一定的频率,分别去给线圈上电,最后使其转起来,但我们有了驱动器就不需要考虑这么多了,里面已经帮我们把所需的电路集成好了,这里我们只需要会连线就行了。

 

其中还有的VCC接购买的步进电机所需的电压值

其中ENA,DIR,PUL的接线有两种,一种是共阳,另一种是共阴接法,共阳即将ENA+,DIR+,PUL+都接3.3V的口,而共阴接法则由上表格所示。

ENA为使电机脱机状态控制端子
若按上述接线,当ENA+赋予高电平时,电机处于脱机状态,手可以转动转轴,电流撤去。故一般工作情况,ENA+要赋予低电平。

DIR为控制步进电机正反转的控制端子
按上述接线,当DIR+赋予低电平时,默认为反转,DIR+赋予高电平时,默认为正转,可以通过控制这个端子去控制步进电机按照指定方向运作

PUL为脉冲控制端子
PUL为控制步进电机最为关键的端子。而在介绍PUL前,还需要介绍一个步进电机的基础知识,即细分和步距角。

步距角:输入一个电脉冲信号,步进电动机转子相应的角位移。
即说明,给一个PWM波,步进电机转子转过的角度。对于1.8°步距角的步进电机来说,转一圈则需要360/1.8=200个脉冲

步进电机细分技术:细分通俗易懂的说就是将上面所说的需要200个脉冲转一圈变成需要更多的脉冲才能转一圈了,如果是二细分,则为400个脉冲转一圈。

其中脉冲信号我们从PUL+中输入,而细分,则由驱动器上的说明设置

二、代码部分

main.c

#include "system.h"
#include "led.h"
#include "SysTIck.h"
#include "usart.h"
#include "key.h"
#include "motor1.h"


int main()
{
	
	//u16 period = 500;
	
	
	int j;
	SysTick_Init(72);//ϵͳ³õʼ»¯£¬Ñ¡ÔñʱÖÓÀ´Ô´£¬ÏµÍ³Ê±ÖÓԭΪ72£¬µ÷ÓÃÑÓʱº¯Êý
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	LED_Init();
	KEY_Init();
	//MY_EXIT_Init();
	USART1_Init(9600);
	//MOTOR_Init();
	//MOTOR_PWM_Init(period,12-1);//per,֨װֵ£¬¿ØÖÆÖÜÆÚ£¬12-1¿ØÖÆÆµÂÊ
	//TIM_SetCompare2(TIM3,period/2);//Õ¼¿Õ±ÈÒ»¶¨£¬£¨1/2£©µÄ֨װֵÊä³ö·½²¨
	Motor_Pin_Init();

	
	
	while(1)
	{
		j++;
		if(j%20==0)
		{
			led2=!led2;
		}
		if (KEY_SCAN(0) == KEY_UP)
		{
			led1=0;
			delay_ms(1000);
			delay_ms(1000);
			led1=1;
			MOTOR_DIR_CCW;//¸Ä±äDIR¸ßµÍµçƽ£¬¼´¸Ä±äתÏò
			Step_90_Degrees();
			
		}
		if (KEY_SCAN(0) == KEY_DOWN)
		{
			led3=0;
			delay_ms(1000);
			delay_ms(1000);
			led3=1;
			MOTOR_DIR_CW;
			Step_90_Degrees();
		}
  }
}

motor1.c

#include "motor1.h"
#include "led.h"
int i = 0;

void Motor_Pin_Init(){
	
		GPIO_InitTypeDef GPIO_InitStructure;
		RCC_APB2PeriphClockCmd(MOTOR_DIR_CLK | MOTOR_PUL_CLK | MOTOR_ENA_CLK, ENABLE);
	
	/*PE5¶ÔÓ¦DIR,ĬÈÏ˳ʱÕëÐýת*/
		
		GPIO_InitStructure.GPIO_Pin=MOTOR_DIR_PIN;  
		GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;	 //ÉèÖÃΪ¸´ÓÃÍÆÍìÊä³ö
		GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;	 
		GPIO_Init(MOTOR_DIR_PORT,&GPIO_InitStructure); 	  
		GPIO_ResetBits(MOTOR_DIR_PORT,MOTOR_DIR_PIN);
	
		/*PE6¶ÔÓ¦ENA,ĬÈÏΪ¸ßµçƽ£¬²»»áʹÄÜ*/
		GPIO_InitStructure.GPIO_Pin=MOTOR_ENA_PIN;  
		GPIO_Init(MOTOR_ENA_PORT,&GPIO_InitStructure); 	  
		GPIO_ResetBits(MOTOR_ENA_PORT,MOTOR_ENA_PIN); 


		GPIO_InitStructure.GPIO_Pin = MOTOR_PUL_PIN;
		GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;	 //ÉèÖÃΪ¸´ÓÃÍÆÍìÊä³ö
		GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;	
    GPIO_Init(MOTOR_PUL_PORT, &GPIO_InitStructure);
    GPIO_ResetBits(MOTOR_PUL_PORT, MOTOR_PUL_PIN);

}
void Delay(__IO uint32_t nCount){
	for (; nCount != 0; nCount--)
		;
};

void Step_90_Degrees(){
	// NC = 1600, 800 toggles means 90 degree motor rotation
	for (i=0; i < 3200; i++)
	{	
		MOTOR_PUL_Toggle;//
		// The delay time determines the motor speed
		Delay(0xfff);
		
	}
	i=0;
}

motor1.h

#ifndef __motor1_H
#define __motor1_H

#include "system.h"


#define MOTOR_DIR_PORT      GPIOE
#define MOTOR_DIR_PIN       GPIO_Pin_5//DIR+¶ÔÓ¦PE5
#define MOTOR_DIR_CLK       RCC_APB2Periph_GPIOE

#define MOTOR_PUL_PORT      GPIOA
#define MOTOR_PUL_PIN       GPIO_Pin_7//PUL+¶ÔÓ¦PA7
#define MOTOR_PUL_CLK       RCC_APB2Periph_GPIOA

#define MOTOR_ENA_PORT      GPIOE
#define MOTOR_ENA_PIN       GPIO_Pin_4//ENA+¶ÔÓ¦PE4
#define MOTOR_ENA_CLK       RCC_APB2Periph_GPIOE

#define digitalHi(p,i) 			{p->BSRR=i;}
#define digitalLo(p,i) 			{p->BRR=i;}
#define digitalToggle(p,i) 	{p->ODR ^= i;}

#define MOTOR_ENA_Toggle    digitalToggle(MOTOR_ENA_PORT, MOTOR_ENA_PIN)
#define MOTOR_ON 	    			digitalHi(MOTOR_ENA_PORT, MOTOR_ENA_PIN)
#define MOTOR_OFF	    			digitalLo(MOTOR_ENA_PORT, MOTOR_ENA_PIN)

#define MOTOR_PUL_Toggle    digitalToggle(MOTOR_PUL_PORT, MOTOR_PUL_PIN)//ʹ¸ÃÒý½Å¸ßµÍµçƿת»»Ò»´Î£¬¼´Êä³öÒ»¸öÂö³å
#define MOTOR_PUL_ON 	    	digitalHi(MOTOR_PUL_PORT, MOTOR_PUL_PIN)
#define MOTOR_PUL_OFF 	    digitalLo(MOTOR_PUL_PORT, MOTOR_PUL_PIN)

#define MOTOR_DIR_Toggle    digitalToggle(MOTOR_DIR_PORT, MOTOR_DIR_PIN)
#define MOTOR_DIR_CCW    		digitalHi(MOTOR_DIR_PORT, MOTOR_DIR_PIN)
#define MOTOR_DIR_CW   			digitalLo(MOTOR_DIR_PORT, MOTOR_DIR_PIN)

void Motor_Pin_Init(void);
void Delay(__IO uint32_t nCount);

void Step_90_Degrees(void);
#endif

### 使用PWM控制步进电机转动指定角度 为了使步进电机能够按照特定的角度旋转,通常需要结合PWM信号与具体的步数计算方法。通过调整PWM占空比可以改变电机的速度,而要实现精确的位置控制,则需根据目标角度转换成相应的步数并逐步执行。 对于Arduino平台而言,`analogWrite()`函数可用于生成PWM信号来调节电机速度[^1]: ```cpp // 定义PWM引脚和参数 const int speedPin = 9; // PWM输出引脚 int stepsPerRevolution = 200; // 步进电机每圈所需步数(具体数值取决于所使用的电机) void setup() { pinMode(speedPin, OUTPUT); } void loop() { // 计算对应于期望角位移的总步数 float targetAngle = 180.0; // 设定的目标角度 long totalSteps = round(targetAngle / 360 * stepsPerRevolution); // 设置合适的PWM值以获得所需的转速 analogWrite(speedPin, 128); // 中间值作为初始测试 // 执行相应数量的步进来完成定位移动... } ``` 上述代码片段展示了基本思路,但在实际操作中还需要考虑更多细节,比如如何发送脉冲序列给电机驱动器以便让其前进或后退指定数目个步距。这可能涉及到额外的I/O线用于方向指示以及更复杂的定时机制确保平稳运行。 当采用STM32控制器时,可以通过调用专门设计好的API来进行更加精细的操作[^2]: ```c #include "StepMotorControl.h" int main(void) { InitializeMotorDriver(); // 初始化电机控制系统 SetRotationAngle(180); // 配置希望达到的角度位置 SetSpeed(10); // 指定运动过程中的平均速率 StartRotation(); // 开始执行动作直到到达设定点 while (1) {} // 主循环等待任务结束 } ``` 此段C语言程序说明了利用预定义接口简化开发流程的方式,在这里不再依赖简单的PWM配置而是借助高级别的抽象层处理整个过程。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值