51单片机:直流电机与步进电机

小白向单片机笔记七:电机

  • 前言
  • 一、电机驱动
    • 电机
    • 单极性步进电机原理图
    • ULN2003D驱动芯片
  • 二、代码
    • 1.直流电机
      • 中断初始化函数 interrupt_utils.h
      • 主函数
    • 2.步进电机
      • 时延函数delay.h
      • 中断初始化函数interrupt_utils.h
      • 电机控制相关函数step_utils.h
      • 主函数


前言

ULN2003D芯片,直流电机的驱动,步进电机控制

一、电机驱动

电机

直流电机: 将直流电能转化为机械能,将机械能转化为直流电的旋转电机
直流电机特点: 无正负之分,加直流电即可工作
步进电机: 将电脉冲信号转变为角位移或线位移的开环控制元件
步进电机特点: 给一个脉冲信号,电机则转过一个步距角。只有周期性误差,无累计误差。角位移和输入的脉冲数成正比,转速和脉冲频率成正比,改变绕组通电顺序会反转

单极性步进电机原理图

51单片机:直流电机与步进电机_第1张图片
51单片机:直流电机与步进电机_第2张图片
28BYJ48步进电机,当通电顺序为: A–>B–>C–>D时可产生旋转;当通电顺序为:D–>C–>B–>A时产生反向旋转。此时电机为4步旋转,当通电顺序为:A–>AB–>B–>BC–>C–>CD–>D–>DA时为8步旋转,反向旋转同理。

  1. 8步与4步的区别在于:8步控制更精准和顺畅,如果驱动器细分能力更强,可以细分为更多的步。不过细分更多步要更强的驱动芯片。
  2. 在实际编程中,如果只执行一次从A–>D或D—>A的通电顺序,电机并不是只转一圈,而是不旋转只产生震动。
  3. 在实际编程中,电机的通电顺序不能跳步通电,例如从A–>B–>C–>D直接跳为A–>D或A–>C–>D之类的,不然也不能正常工作。
  4. 由于转速和脉冲频率成正比,在通电过程中加入时延函数就能控制电机的转速。A-->delay-->B-->delay-->C-->delay--->D。在测试过程中发现,最小时延大致为 900us才能正常工作
  5. 这个型号的步进电机转速本身就很慢,属于正常现象,直流电机更快。

ULN2003D驱动芯片

51单片机:直流电机与步进电机_第3张图片
ULN2003D为电机的驱动芯片,其中输入与输出一 一对应,例如 I N 1 IN1 IN1对应 O U T 1 OUT1 OUT1。ULN2003D相当于一个非门电路,输入高电平,对应引脚则输出低电平。输入低电平,对应引脚则输出高电平。

二、代码

1.直流电机

将直流电机引脚接到电机模块的5V和01引脚即可,顺序随便
功能:通过外部中断0,即独立按键K3来控制电机的转动。长按K3转动,不按停止

中断初始化函数 interrupt_utils.h

#ifndef _INTERRUPT_H_
#define _INTERRUPT_H_
#include "reg52.h"
/*中断初始化*/

/*外部中断0*/
void Int0_Init(const unsigned char *mode){//外部中断0的触发方式,0低电平触发,1下降沿触发
	EA=1;//总中断允许位
	EX0=1;//外部中断0允许位
	IT0=*mode;	
}
/*外部中断1*/
void Int1_Init(const unsigned char *mode){//外部中断1的触发方式,0低电平触发,1下降沿触发
	EA=1;//总中断允许位
	EX1=1;//外部中断0允许位
	IT1=*mode;	
}

void Timer0_Init(const unsigned char *mode ,const unsigned char *HighVal , const unsigned char *LowVal ){
	EA=1;//打开中断总允许位
	ET0=1;//打开T0中断允许位
	TR0=1;//定时/计数器中断0开始工作
	TMOD |= *mode;//设置T0工作模式
	TH0 = *HighVal; //高八位寄存器初值
	TL0 = *LowVal;  //第八位寄存器初值
} 

void Timer1_Init(const unsigned char *mode ,const unsigned char *HighVal , const unsigned char *LowVal ){
	EA=1;//打开中断总允许位
	ET1=1;//打开T0中断允许位
	TR1=1;//定时/计数器中断0开始工作
	TMOD |= *mode;//设置T0工作模式
	TH1 = *HighVal; //高八位寄存器初值
	TL1 = *LowVal;  //第八位寄存器初值
} 
#endif

主函数

#include "reg52.h"
#include "interrupt_utils.h"
sbit P10=P1^0;
sbit K3 = P3^2;
void main(){	
	Int0_Init(0);
	P10=0;
	while(1){
	}
}
void Int0_Routine(void) interrupt 0{
	 while(!K3){
	 	P10=1;
	 }
	 P10=0;
}

2.步进电机

将步进电机的5个引脚插入电机模块,红线对应5V引脚
功能:

  1. 长按K3转动
  2. 长按K4逆向转动
  3. 短按K2加速一级,长按K2减速
  4. 数码管显示当前速度。

时延函数delay.h

#ifndef _DELAY_H__
#define _DELAY_H__
/*10us=1,时延为10us*/
void delay_10us(unsigned int _10us){
	while(_10us--){}
}

/*1ms=1,时延为1ms*/
void delay_1ms(unsigned int _1ms){
	 _1ms*=110;
	 while(_1ms--){
	 }
}
#endif

中断初始化函数interrupt_utils.h

同直流电机中的函数,略。

电机控制相关函数step_utils.h

#ifndef _STEP_UTILS_H_
#define _STEP_UTILS_H_
#include "reg52.h"
#include "delay.h"
static unsigned char Speed=1;
/*步进电机引脚*/
sbit P10 = P1^0;
sbit P11 = P1^1;
sbit P12 = P1^2;
sbit P13 = P1^3;

/*按键引脚:
	默认不转
	K3功能:长按按前进
	K4功能:  长按后退
	K2功能:短按加速一级,长按减速
*/
sbit K3 = P3^2;	//外部中断0
sbit K4 = P3^3;	//外部中断1
sbit K2 = P3^0;	//按键检测
/*选择通电引脚*/
void Set_Step(unsigned char Step , unsigned char direct ){
	if(direct) Step = 7-Step;//*direct为0正转,1逆转
	switch(Step){
		case 0: P10=1,P11=0,P12=0,P13=0;break;//A
		case 1: P10=1,P11=1,P12=0,P13=0;break;//AB
		case 2: P10=0,P11=1,P12=0,P13=0;break;//B
		case 3: P10=0,P11=1,P12=1,P13=0;break;//BC
		case 4: P10=0,P11=0,P12=1,P13=0;break;//C
		case 5: P10=0,P11=0,P12=1,P13=1;break;//CD
		case 6: P10=0,P11=0,P12=0,P13=1;break;//D
		case 7: P10=1,P11=0,P12=0,P13=1;break;//DA
		default: break;
	}	
}

/*检测K2按键*/
void Speed_Update(){
	if(!K2){
		delay_1ms(100);//消抖并监测长按,长按阈值100ms
		if(!K2){//长按减速
			if(Speed<6) ++Speed;
		}else{
			if(Speed>1) --Speed;
		} 		
	}
}
#endif

主函数

#include "reg52.h"
#include "delay.h"
#include "interrupt_utils.h"
#include "step_utils.h"

void main(){
	unsigned char display[] = {0x00,0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
				  0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
	Int0_Init(0);
	Int1_Init(0);
	while(1){
		Speed_Update();
		P0 = display[Speed+1]; //显示速度,显示数字越小,速度越大
	}
}
void Int0_Routine(void) interrupt 0{
	while(!K3){
		/*正转*/
		unsigned char i;
		for(i=0 ; i<8;++i){
			Set_Step(i,0);
			delay_1ms(Speed);
		}
	}
}
void Int1_Routine(void) interrupt 2{
	while(!K4){
			/*逆转*/
			unsigned char i;
			for(i=0 ; i<8;++i){
				Set_Step(i,1);
				delay_1ms(Speed);
			}	
	}
}

你可能感兴趣的:(51单片机学习笔记,单片机,51单片机)