ULN2003D芯片,直流电机的驱动,步进电机控制
直流电机: 将直流电能转化为机械能,将机械能转化为直流电的旋转电机
直流电机特点: 无正负之分,加直流电即可工作
步进电机: 将电脉冲信号转变为角位移或线位移的开环控制元件
步进电机特点: 给一个脉冲信号,电机则转过一个步距角。只有周期性误差,无累计误差。角位移和输入的脉冲数成正比,转速和脉冲频率成正比,改变绕组通电顺序会反转
。
28BYJ48步进电机,当通电顺序为: A–>B–>C–>D时可产生旋转;当通电顺序为:D–>C–>B–>A时产生反向旋转。此时电机为4步旋转,当通电顺序为:A–>AB–>B–>BC–>C–>CD–>D–>DA时为8步旋转,反向旋转同理。
由于转速和脉冲频率成正比,在通电过程中加入时延函数就能控制电机的转速。A-->delay-->B-->delay-->C-->delay--->D。在测试过程中发现,最小时延大致为 900us才能正常工作
。
ULN2003D为电机的驱动芯片,其中输入与输出一 一对应,例如 I N 1 IN1 IN1对应 O U T 1 OUT1 OUT1。ULN2003D相当于一个非门电路
,输入高电平,对应引脚则输出低电平。输入低电平,对应引脚则输出高电平。
将直流电机引脚接到电机模块的5V和01引脚即可,顺序随便
。
功能:通过外部中断0,即独立按键K3来控制电机的转动。长按K3转动,不按停止
#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;
}
将步进电机的5个引脚插入电机模块,红线对应5V引脚
。
功能:
#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
同直流电机中的函数,略。
#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);
}
}
}