1 前言

本实验是基于STM32103芯片和ULN2003进行对步进电机的控制。

2 ULN2003的基本介绍

2.1 ULN2003的概述

ULN2003是高耐压、大电流复合晶体管阵列,由七个硅NPN 复合晶体管组成。一般采用DIP—16SOP—16 塑料封装。

ULN2003的主要特点:

  • ULN2003 的每一对达林顿都串联一个2.7K 的基极电阻,在5V 的工作电压下它能与TTL 和CMOS 电路直接相连,可以直接处理原先需要标准逻辑缓冲器来处理的数据。
  • ULN2003 工作电压高,工作电流大,灌电流可达500mA,并且能够在关态时承受50V 的电压,输出还可以在高负载电流并行运行。

2.2 ULN2003的作用

ULN2003是大电流驱动阵列,多用于单片机、智能仪表、PLC、数字量输出卡等控制电路中,可直接驱动继电器等负载输入5VTTL电平,输出可达500mA/50V。

简单地说,ULN2003其实就是用来放大电流的,增加驱动能力。比如说单片机输出引脚一般输出就几mA,是无法驱动电机、继电器或者电磁阀的,像要让直流电机转需要500mA,而用ULN2003放大后,可以通过单片机的输出引脚直接控制这些设备。而我们文章的目的是使用ULN2003芯片来增大单片机的输出电流使得单片机的输出电流可以驱动步进电机。

2.3 ULN2003的引脚图和功能

STM32通过ULN2003对步进电机进行控制_嵌入式开发

  • 引脚1:CPU脉冲输入端,端口对应一个信号输出端;
  • 引脚2:CPU脉冲输入端;
  • 引脚3:CPU脉冲输入端;
    引脚4:CPU脉冲输入端;
  • 引脚5:CPU脉冲输入端;
    引脚6:CPU脉冲输入端;
  • 引脚7:CPU脉冲输入端;
  • 引脚8:接地;
    引脚9:该脚是内部7个续流二极管负极的公共端,各二极管的正极分别接各达林顿管的集电极。用于感性负载时,该脚接负载电源正极,实现续流作用。如果该脚接地,实际上就是达林顿管的集电极对地接通;
  • 引脚10:脉冲信号输出端,对应7脚信号输入端;
  • 引脚11:脉冲信号输出端,对应6脚信号输入端;
  • 引脚12:脉冲信号输出端,对应5脚信号输入端;
  • 引脚13:脉冲信号输出端,对应4脚信号输入端;
  • 引脚14:脉冲信号输出端,对应3脚信号输入端;
  • 引脚15:脉冲信号输出端,对应2脚信号输入端;
  • 引脚16:脉冲信号输出端,对应1脚信号输入端。

2.4 ULN2003工作原理驱动应用电路

ULN2003是高耐压、大电流复合晶体管阵列,由七个硅NPN 复合晶体管组成,每一对达林顿都串联一个2.7K 的基极电阻,在5V 的工作电压下它能与TTL 和CMOS 电路直接相连,可以直接处理原先需要标准逻辑缓冲器来处理的数据。

LN2003也是一个7路反向器电路,即当输入端为高电平时,ULN2003输出端为低电平;当输入端为低电平时,ULN2003输出端为高电平。

ULN2003是一个非门电路,包含7个单元,单独每个单元驱动电流最大可达500mA,9脚可以悬空。比如1脚输入,16脚输出,你的负载接在VCC与16脚之间,不用9脚。

根据上面的原理,ULN2003的驱动应用电路的基本示例图,各个引脚的功能都标注在上面:

STM32通过ULN2003对步进电机进行控制_步进电机_02

这里需要注意的是:尽管按照官方文献要求,控制电压输入需要在5V,其实只需要超过2.5V的电平信号基本都能够算作是高电平。也就是说,3.3V的单片机的IO口的高电平输出就能够直接来进行ULN2003的控制输入了。

再介绍一个实际例程的ULN2003的驱动应用电路:

STM32通过ULN2003对步进电机进行控制_C语言_03

3 28BYJ48型步进电机

3.1 步进电机简介

28BYJ48型步进电机是四相八拍电机,电压为DC5V~DC12V。当对步进电机按一定顺序施加一系列连续不断的控制脉冲时,它可以连续不断地转动。每一个脉冲信号使得步进电机的某一相或两相绕组的通电状态改变一次,也就对应转子转过一定的角度。当通电状态的改变完成一个循环时,转子转过一个齿距。四相步进电机可以在不同的通电方式下运行。

  • 单(单相绕组通电)四拍(A-B-C-D-A……)
  • 双(双相绕组通电)四拍(AB-BC-CD-DA-AB……)
  • 四相八拍(A-AB-B-BC-C-CD-D-DA-A……)。

所以说,要想启动步进电机只需要依次给各个相输入高电平信号就可以了。注意,当给某一相输入信号的时候,其他相要重新置0。也就是说,同一时刻只能保持有一个相。

3.2 步进电机参数

STM32通过ULN2003对步进电机进行控制_单片机_04

STM32通过ULN2003对步进电机进行控制_嵌入式开发_05

4 STM32控制程序

步进电机是一种将电脉冲转化为角位移的执行设备。通俗一点讲:当步进驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动一个固定的角度(即步进角)。我们可以通过控制脉冲个数来控制角位移量,从而达到准确定位的目的;同时我们可以通过控制脉冲频率来控制电机转动的速度和加速度,从而达到调速的目的。

4.1 硬件配置

  • 单片机:STM32103C8T6
  • 步进电机:28BYJ-48
  • 驱动电路:ULN2003芯片的驱动板
  • 引脚连接:IN1 ----- PB6
    IN2 ----- PB7
    IN3 ----- PB8
    IN4 ----- PB9
    OUT1:步进电机4、OUT2:步进电机3、OUT3:步进电机2、OUT4:步进电机1、步进电机5:
    VCC电源正极(5V)、GND:共地、COM:VCC电源正极(5V)。
  • 5V直流电源:STM32F103ZET6开发板上的5V电压引脚(下图中的VCC)。

STM32通过ULN2003对步进电机进行控制_单片机_06

4.2 控制代码

motor.h

/***************************************************************************************
$ @ Copyright    : 
$ @ Author       : Krone
$ @ Data         : Do not edit
$ @ LastEditor   : 
$ @ LastData     : 
$ @ Describe     : 
*****************************************************************************************/
#ifndef MOTOR_H__
#define MOTOR_H__
#include <stdio.h>
#include <string.h>

#define  MOTOR_CLK               (RCC_APB2Periph_GPIOB)
#define  MOTOR_PORT              (GPIOB)
#define  MOTOR_IN1_PIN           (GPIO_Pin_6)
#define  MOTOR_IN2_PIN           (GPIO_Pin_7)
#define  MOTOR_IN3_PIN           (GPIO_Pin_8)
#define  MOTOR_IN4_PIN           (GPIO_Pin_9)

void Moto_Init(void);
void Motor_Forward_Ration(void);  //反转
void Motor_Reverse_Rotation(void);  //正转
void MotorStop(void); //停止
void Motor_Ctrl_Direction_Angle(int direction, int angle);//控制电机正转还是反转某个角度

#endif

motor.c

/***************************************************************************************
$ @ Copyright    : 
$ @ Author       : Krone
$ @ Data         : Do not edit
$ @ LastEditor   : 
$ @ LastData     : 
$ @ Describe     : 
*****************************************************************************************/
#include "motor.h"
#include "delay.h"

uint16_t phasecw[4] ={0x0200,0x0100,0x0080,0x0040}; /*   D-C-B-A  反转 */
uint16_t phaseccw[4]={0x0040,0x0080,0x0100,0x0200}; /*	 A-B-C-D   正转 */
/*---------------------------------电机模块与单片机连接引脚---------------------------------------------------*/
/* IN4: PB9  d */
/* IN3: PB8  c */
/* IN2: PB7  b */ 
/* IN1: PB6  a */

void Moto_Init(void)
{
	 GPIO_InitTypeDef GPIO_InitStructure;
	 RCC_APB2PeriphClockCmd(MOTOR_CLK,ENABLE);

	 GPIO_InitStructure.GPIO_Pin = MOTOR_IN1_PIN | MOTOR_IN2_PIN | MOTOR_IN3_PIN | MOTOR_IN4_PIN ;//引脚按着INT1顺序接就行了
	 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	 GPIO_Init(GPIOB,&GPIO_InitStructure);
	 GPIO_ResetBits(MOTOR_PORT, MOTOR_IN1_PIN | MOTOR_IN2_PIN |MOTOR_IN3_PIN |MOTOR_IN4_PIN );
}
// 正转
void Motor_Forward_Ration(void)  
{  
    int i;  
    for(i=0;i<4;i++)  
    {  
        GPIO_Write(MOTOR_PORT, phaseccw[i]);  
        delay_ms(1);  
    }  
}
// 反转
void Motor_Reverse_Rotation(void)  
{  
	uint8_t i;  
    for(i=0;i<4;i++)  
    {  
        GPIO_Write(MOTOR_PORT, phasecw[i]);  
        delay_ms(1);  
    }  
}
//停止
void MotorStop(void) 
{  
    GPIO_Write(MOTOR_PORT, 0x0000);  
}

//控制电机正转还是反转某个角度
//direction方向,1为正转,0为反转
//angle角度,可为0-360具有实际意义
void Motor_Ctrl_Direction_Angle(int direction, int angle)
{
	uint16_t i;

	if(direction == 1)
	{								
		for(i = 0; i < 64*angle/45; i++) 
		{
			/* 正转 */
			Motor_Forward_Ration();
		}
		MotorStop();//停止
  	}
	else
	{
		for(i = 0; i < 64*angle/45; i++) 
		{
			/* 反转 */
			Motor_Reverse_Rotation(); 
		}
		 MotorStop();//停止
	}
}