普中51单片机学习笔记-ULN2003芯片驱动步进电机

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);
	}
}

完结,撒花~~~

相关推荐
伯明翰java4 小时前
Redis学习笔记-List列表(2)
redis·笔记·学习
云帆小二4 小时前
从开发语言出发如何选择学习考试系统
开发语言·学习
Elias不吃糖4 小时前
总结我的小项目里现在用到的Redis
c++·redis·学习
就是蠢啊4 小时前
51单片机——数码管
单片机·嵌入式硬件·51单片机
BullSmall4 小时前
《道德经》第六十三章
学习
AA陈超5 小时前
使用UnrealEngine引擎,实现鼠标点击移动
c++·笔记·学习·ue5·虚幻引擎
BullSmall5 小时前
《道德经》第六十二章
学习
Knox_Lai6 小时前
数据结构与算法学习(0)-常见数据结构和算法
c语言·数据结构·学习·算法
IMPYLH6 小时前
Lua 的 assert 函数
开发语言·笔记·junit·单元测试·lua
离离茶7 小时前
【笔记1-8】Qt bug记录:QListWidget窗口的浏览模式切换为ListMode后,滚轮滚动速度变慢
笔记·qt·bug