STM32F407 控制28BYJ-48步进电机可定角理论上0.0879°,只使用一个定时器,可以精确正反转角度,并且实时LCD显示当前角度。

        代码如下,亲测可以,起始角度固定了,才能可以精确正反转角度哈,代码有注释

1.步进电机引脚配置

代码如下(示例):

#ifndef __REG52_H
#define __REG52_H
#include "sys.h"

//IN1-PB6
#define IN1_GPIO_PORT     GPIOB
#define IN1_GPIO_CLK      RCC_AHB1Periph_GPIOB
#define IN1_GPIO_PIN      GPIO_Pin_6

//IN2-PB7
#define IN2_GPIO_PORT     GPIOB
#define IN2_GPIO_CLK      RCC_AHB1Periph_GPIOB
#define IN2_GPIO_PIN      GPIO_Pin_7

//IN3-PB10
#define IN3_GPIO_PORT     GPIOB
#define IN3_GPIO_CLK      RCC_AHB1Periph_GPIOB
#define IN3_GPIO_PIN      GPIO_Pin_10

//IN1-PB11
#define IN4_GPIO_PORT     GPIOB
#define IN4_GPIO_CLK      RCC_AHB1Periph_GPIOB
#define IN4_GPIO_PIN      GPIO_Pin_11


#define digitalHi(p,i)	{p->BSRRL=i;}
#define digitalLi(p,i)	{p->BSRRH=i;}

#define	IN1_HIGH	digitalHi(IN1_GPIO_PORT,IN1_GPIO_PIN)
#define IN1_LOW		digitalLi(IN1_GPIO_PORT,IN1_GPIO_PIN)

#define	IN2_HIGH	digitalHi(IN2_GPIO_PORT,IN2_GPIO_PIN)
#define IN2_LOW		digitalLi(IN2_GPIO_PORT,IN2_GPIO_PIN)

#define	IN3_HIGH	digitalHi(IN3_GPIO_PORT,IN3_GPIO_PIN)
#define IN3_LOW		digitalLi(IN3_GPIO_PORT,IN3_GPIO_PIN)

#define	IN4_HIGH	digitalHi(IN4_GPIO_PORT,IN4_GPIO_PIN)
#define IN4_LOW		digitalLi(IN4_GPIO_PORT,IN4_GPIO_PIN)

/*
*单相绕组通电
*/
#define Coil_A {IN1_HIGH;IN2_LOW;IN3_LOW;IN4_LOW;}
#define Coil_B {IN1_LOW;IN2_HIGH;IN3_LOW;IN4_LOW;}
#define Coil_C {IN1_LOW;IN2_LOW;IN3_HIGH;IN4_LOW;}
#define Coil_D {IN1_LOW;IN2_LOW;IN3_LOW;IN4_HIGH;}
#define Stop   {IN1_LOW;IN2_LOW;IN3_LOW;IN4_LOW;}

/*
*双相绕组通电
*/
#define Coil_1 {IN1_HIGH;IN2_LOW;IN3_LOW;IN4_HIGH;}
#define Coil_2 {IN1_HIGH;IN2_HIGH;IN3_LOW;IN4_LOW;}
#define Coil_3 {IN1_LOW;IN2_HIGH;IN3_HIGH;IN4_LOW;}
#define Coil_4 {IN1_LOW;IN2_LOW;IN3_HIGH;IN4_HIGH;}

/*
*正反转表格
*/
//uint16_t F_Rotating[4] = {0x0840 , 0x00c0, 0x0480, 0x0c00};
//uint16_t B_Rotating[4] = {0x0c00 , 0x0480, 0x00c0 ,0x0840};

#define Clockwise   1
#define UnClockwise 0
#define One_cir		4096

void GPIO_STEP_CONFIG(void);
	
#endif


#include "reg52.h"
/*
*一圈 == 4086个脉冲
*一个脉冲 == 0.08810573°
*45°=512个脉冲		90°=1024个脉冲
*/

void GPIO_STEP_CONFIG(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

	GPIO_InitStructure.GPIO_Pin = IN1_GPIO_PIN|IN2_GPIO_PIN|IN3_GPIO_PIN|IN4_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
		
}






2.步进电机驱动程序

代码如下(示例):

//定时器4初始化
void Timer4_Init(u16 arr,u16 psc)
{		 					 
	
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);     
	
	TIM_TimeBaseStructure.TIM_Prescaler = psc;   
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  
	TIM_TimeBaseStructure.TIM_Period = arr;  
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; 
	
	TIM_TimeBaseInit(TIM4,&TIM_TimeBaseStructure);
	
	TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);  
	
    TIM_Cmd(TIM4,ENABLE );   

    NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;   
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;   
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;   
	NVIC_Init(&NVIC_InitStructure);   
	
}  
/*
*28BYJ-48
*步进电机驱动程序
*/
struct step
{   
    uint16_t angle;//记录旋转结束后角度
}stepper;

#define CLIP_ROT(V,MIN,MAX) ( ( V>MAX?MIN:(V<MIN?MAX:V) ) )
uint16_t Rotating[8] = {0x0040, 0x00c0, 0x0080, 0x0480, 0x0400, 0x0c00, 0x0800, 0x0840};//配置的引脚不同,旋转序列也不同欧
extern uint8_t rotate_dir_flg;
extern uint16_t pulse_number;
extern uint16_t angle_circle;
extern float Current_Position ;
int Rot = 0;
float cir_finish = 0;//步进电机旋转结束

void rotate_angle_dir(uint16_t angle,uint16_t circle,uint16_t dir)
{
	if(cir_finish == 0)//旋转已经结束
	{
		cir_finish = 1;
		if(dir == UnClockwise)     //如果是反转
		rotate_dir_flg = UnClockwise;
	    else if(dir == Clockwise)    //如果是正转
		rotate_dir_flg = Clockwise;
		angle = CLIP_ROT(angle,0.0,360);//限制形参旋转角度范围
	    angle_circle = One_cir*circle + One_cir*angle/360;//由角度换算成,需要输出的脉冲个数
		TIM_Cmd(TIM4,ENABLE);
	}

}

void TIM4_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM4,TIM_IT_Update) == SET)   
	{
		TIM_ClearITPendingBit(TIM4,TIM_IT_Update);
		cir_finish = 1;//进行旋转中
		if(rotate_dir_flg == Clockwise)
		{
			Rot++;
			Current_Position = (stepper.angle + ((pulse_number + 1) * 360/One_cir))%360;
		}
		else if(rotate_dir_flg == UnClockwise)
		{
			Rot--;
			Current_Position =(stepper.angle + 360 - ((pulse_number + 1) * 360/One_cir))%360;//上次旋转角度 + 现在要旋转角度 = 计算当前位置
		}
		Rot = CLIP_ROT(Rot,0,7);
		GPIOB->BSRRL = Rotating[Rot];
		GPIOB->BSRRH = 0x0cc0 - Rotating[Rot];
		
		if(++pulse_number > angle_circle-1)  //单片机按Rotating[Rot]输出的脉冲个数已到
		{
			TIM_Cmd(TIM4,DISABLE);//关闭定时器4
			Stop;//四个引脚输出低电平,避免不用时发热
			pulse_number = 0;//脉冲计数数清零
			cir_finish = 0;//旋转结束
			stepper.angle = Current_Position;//记录当前旋转角度
		}
	
		LED0 = !LED0;
	}
	
}

 主函数如下:

uint8_t rotate_dir_flg = Clockwise;
uint16_t pulse_number = 0;
uint16_t angle_circle;
float Current_Position = 0.0;
uint8_t buf[50];

#define CLIP_ww(V,MIN,MAX) ( ( V>MAX?MIN:(V<MIN?MAX:V) ) )

int main(void)
{ 
	delay_init(168);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	uart_init(115200);
	Timer4_Init(840-1,100-1);
	LED_Init();
	LCD_Init();
	KEY_Init();           
	GPIO_STEP_CONFIG();
	POINT_COLOR = RED;

	while(1)
	{
		delay_ms(150);
		if(KEY_Scan(0) ==KEY0)
		{
			rotate_angle_dir(90,0,UnClockwise);
		}
		else if(KEY_Scan(0) ==KEY1)
		{
			rotate_angle_dir(90,0,Clockwise);
		}
			sprintf((char *)buf,"curent angle: %.0f   \r\n",Current_Position);
			LCD_ShowString(20,200,200,16,16,buf);//显示当前角度
		
	}
}

总结

额,不知道写啥,主要是方便自己后面需要代码了,程序找不到了,嘻嘻

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值