ULN2003芯片简介
-
C51单片机的I/O口:输出能力很弱。每个引脚最大只能输出几个毫安的电流(通常 sink current 在10-20mA左右),电压是5V。
-
许多外部设备:如继电器、小型直流电机、步进电机、电磁阀等,需要的工作电流远大于几十毫安,工作电压也可能是12V甚至24V。
结论:单片机是"大脑",但它"手无缚鸡之力",无法直接驱动这些"重体力"设备。ULN2003就是连接在"大脑"和"设备"之间的"肌肉"或"开关",专门负责大电流、高电压的切换。
ULN2003芯片内部结构和工作原理
ULN2003内部是7个达林顿晶体管阵列。你可以把它想象成7个用三极管构成的、能力超强的电子开关。
-
**输入(1B - 7B):**对应单片机的I/O口(如P1.0, P1.1...)。ULN2003是电流吸收型驱动,意思是当单片机I/O口输出高电平(5V) 时,这个开关会"闭合";输出低电平(0V) 时,开关"断开"。
-
**输出(1C - 7C):**连接你要驱动的设备(如继电器线圈的一端)。设备的另一端接所需的外接电源(如12V)。
-
**COM引脚:**这是一个非常关键的引脚。它内部连接了每个输出口的续流二极管。
当驱动感性负载(如继电器、电机)时,在断电瞬间会产生一个很高的反向电动势(可以理解为反向高压),这个高压会损坏ULN2003和电路中的其他元件。COM引脚接至外接电源的正极(如12V),这些二极管就为反向电动势提供了泄放回路,从而保护芯片。如果驱动的是灯、LED等阻性负载,COM引脚可以悬空,但为了安全,习惯上都会接上电源。

步进电机静态参数
- **相数:**产生不同对极 N、S 磁场的激磁线圈对数,也可以理解为步进电机中线圈的组数,其中两相步进电机步距角为 1.8°,三相的步进电机步角为1.5°,相数越多的步进电机,其步距角就越小。
- **拍数:**完成一个磁场周期性变化所需脉冲数或导电状态用 n 表示,或指电机转过一个齿距角所需脉冲数,以四相电机为例,有四相四拍运行方式即AB-BC-CD-DA-AB,四相八拍运行方式即 A-AB-B-BC-C-CD-D-DA-A。
- **步距角:**一个脉冲信号所对应的电机转动的角度,可以简单理解为一个脉冲信号驱动的角度,电机上都有写,一般 42 步进电机的步距角为 1.8°。
- **定位转矩:**电机在不通电状态下,电机转子自身的锁定力矩(由磁场齿形的谐波以及机械误差造成的)。 静转矩:电机在额定静态电压作用下,电机不作旋转运动时,电机转轴的锁定力矩。此力矩是衡量电机体积的标准,与驱动电压及驱动电源等无关。
28BYJ-48步进电机简介
28BYJ48 步进电机自带减速器,为四相无线步进电机,直径为 28mm。


28BYJ-48步进电机旋转驱动方式如下表:

硬件电路

示例代码
/**************************************************************************************
实验名称:步进电机实验
接线说明:
实验现象:下载程序后,当按下 KEY1 键可调节电机旋转方向;当按下 KEY2 键,电机加速;当按下 KEY3 键,电机减速
注意事项:将步进电机红色线对接到"步进电机模块"输出端子 J47 的 5V 上,其它相序依次接入。
***************************************************************************************/
#include "reg52.h"
typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;
//定义 ULN2003 控制步进电机管脚
sbit IN1_A=P1^0;
sbit IN2_B=P1^1;
sbit IN3_C=P1^2;
sbit IN4_D=P1^3;
//定义独立按键控制脚
sbit KEY1=P3^1;
sbit KEY2=P3^0;
sbit KEY3=P3^2;
sbit KEY4=P3^3;
//使用宏定义独立按键按下的键值
#define KEY1_PRESS 1
#define KEY2_PRESS 2
#define KEY3_PRESS 3
#define KEY4_PRESS 4
#define KEY_UNPRESS 0
// 定义步进电机速度,值越小,速度越快
// 最小不能小于 1
#define STEPMOTOR_MAXSPEED 1
#define STEPMOTOR_MINSPEED 5
/*******************************************************************************
* 函 数 名 : delay_10us
* 函数功能 : 延时函数,ten_us=1 时,大约延时 10us
* 输 入 : ten_us
* 输 出 : 无
*******************************************************************************/
void delay_10us(u16 ten_us)
{
while(ten_us--);
}
/*******************************************************************************
* 函 数 名 : delay_ms
* 函数功能 : ms 延时函数,ms=1 时,大约延时 1ms
* 输 入 : ten_us
* 输 出 : 无
*******************************************************************************/
void delay_ms(u16 ms)
{
u16 i,j;
for(i=ms;i>0;i--)
for(j=110;j>0;j--);
}
/*******************************************************************************
* 函 数 名 : step_motor_28BYJ48_send_pulse
* 函数功能 : 输出一个数据给 ULN2003 从而实现向步进电机发送一个脉冲
* 输 入 :
step:指定步进序号,可选值 0~7
dir:方向选择,1:顺时针,0:逆时针
* 输 出 : 无
*******************************************************************************/
void step_motor_28BYJ48_send_pulse(u8 step,u8 dir)
{
u8 temp=step;
if(dir==0) //如果为逆时针旋转
temp=7-step;//调换节拍信号
switch(temp)//8 个节拍控制:A->AB->B->BC->C->CD->D->DA
{
case 0: IN1_A=1;IN2_B=0;IN3_C=0;IN4_D=0;break;
case 1: IN1_A=1;IN2_B=1;IN3_C=0;IN4_D=0;break;
case 2: IN1_A=0;IN2_B=1;IN3_C=0;IN4_D=0;break;
case 3: IN1_A=0;IN2_B=1;IN3_C=1;IN4_D=0;break;
case 4: IN1_A=0;IN2_B=0;IN3_C=1;IN4_D=0;break;
case 5: IN1_A=0;IN2_B=0;IN3_C=1;IN4_D=1;break;
case 6: IN1_A=0;IN2_B=0;IN3_C=0;IN4_D=1;break;
case 7: IN1_A=1;IN2_B=0;IN3_C=0;IN4_D=1;break;
}
}
/*******************************************************************************
* 函 数 名 : key_scan
* 函数功能 : 检测独立按键是否按下,按下则返回对应键值
* 输 入 :
mode=0:单次扫描按键
mode=1:连续扫描按键
* 输 出 :
KEY1_PRESS:K1 按下
KEY2_PRESS:K2 按下
KEY3_PRESS:K3 按下
KEY4_PRESS:K4 按下
KEY_UNPRESS:未有按键按下
*******************************************************************************/
u8 key_scan(u8 mode)
{
static u8 key=1;
if(mode)key=1;//连续扫描按键
if(key==1&&(KEY1==0||KEY2==0||KEY3==0||KEY4==0))//任意按键按下
{
delay_10us(1000);//消抖
key=0;
if(KEY1==0)
return KEY1_PRESS;
else if(KEY2==0)
return KEY2_PRESS;
else if(KEY3==0)
return KEY3_PRESS;
else if(KEY4==0)
return KEY4_PRESS;
}
else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1) //无按键按下
{
key=1;
}
return KEY_UNPRESS;
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
u8 key=0;
u8 dir=0;//默认逆时针方向
u8 speed=STEPMOTOR_MAXSPEED;//默认最大速度旋转
u8 step=0;
while(1)
{
key=key_scan(0);
if(key==KEY1_PRESS)//换向
{
dir=!dir;
}
else if(key==KEY2_PRESS)//加速
{
if(speed>STEPMOTOR_MAXSPEED)
speed-=1;
}
else if(key==KEY3_PRESS)//减速
{
if(speed<STEPMOTOR_MINSPEED)
speed+=1;
}
step_motor_28BYJ48_send_pulse(step++,dir);
if(step==8)step=0;
delay_ms(speed);
}
}
完结,撒花~~~