基于51单片机的步进电机驱动,亲测无误
文章目录
- 前言
- 一、我们该如何实现电机驱动?
- 二、驱动实现
- 1.硬件准备
- 2.软件编写
- 3.实物
- 总结
前言
这一次要分享的项目是最近接单做的一个小玩意儿,基于51单片机的步进电机驱动。最近积压了两个月的小项目会在后面陆续发出,好了回归正题。本次步进电机驱动的话主要实现的功能就是实现:
步进电机的加速和减速,正转反转和开启或者停止工作。用LCD1602显示当前工作转速及正反转状态,可通过按键控制电机的开启和关闭。
一、我们该如何实现电机驱动?
目前步进电机的驱动系统已经非常完善了,总结下来你只需要准备这几个信号即可:
脉冲信号:步进电机是脉冲驱动型,拿最常见的42步进电机来说,普通状态下它的步距角为1.8°。这个步距角的含义指的是,你给电机一个脉冲信号,步进电机就转动1.8°,而很明显我们转动一圈需要360°,也就是说我们给步进电机200个脉冲信号,就能够让步进电机转一圈。因此只需要单片机内部发出脉冲信号,根据你自己的需求,比如你想使步进电机转动速度变快,相应的增加脉冲的频率即可,在相同的时间内发出的脉冲数越多,你就可以转动的越快。
方向信号:顾名思义,你给高电平或者低电平,对应的步进电机转动的方向就为正方向或者反方向。你只需要设置好IO口输出状态,51单片机不用管,32单片机推挽输出即可。
脱机信号:这玩意儿我的评价是,暂时用不到,悬空就行。
其他的就是供电电源之类的准备,其实搞懂这些,就可以实现对步进电机的驱动了
二、驱动实现
1.硬件准备
- 主要的硬件清单
1、AT89C51最小系统套件,兼容即可
2、LCD1602液晶显示屏
3、LM2596S-5.0稳压芯片
4、步进电机驱动器+42步进电机(我买的是一体式的)
5、供电电源(我用的是XH_2接口的12V电池接入
- 接线说明
P1口的0-4号引脚均接入按键中,实现不同的功能
P3^7为正反转的控制位
P3^4为脉冲的输出位
- 电路图
- PCB
2.软件编写
- 关键点
在代码中总共用到了两个定时器:
其中定时器一主要是为了刷新界面,每隔2s对界面进行刷新,注意此处是在步进电机不细分的情况下,对应的pulse_speed参量是每秒钟的脉冲总数
定时器二主要是对脉冲输出进行控制,work_degree为步进电机的档位,根据不同的档位选择不同的定时时间,也就是脉冲的频率,档位越高,定时器的时间就越短,相对应的频率也就越高,在此处还定义了一个flag变量,定义此变量的意义在于每执行一次定时器,输出电平就会反转。相当于输出脉冲的频率是此定时器的1/2,快乐加倍。
至于其他地方代码都是比较简洁明了的,也有相对应的注释。
- 代码
main.c
#include<reg51.h>
#include"lcd.h"
#define uchar unsigned char
#define uint unsigned int
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
void DelayMs(unsigned int );
/*******************************************************************************
* 函数名 : 变量定义
* 函数功能 : 新的变量
* 输入 : 无
* 输出 : 无
*******************************************************************************/
unsigned char num[4]; //显示每分钟多少转
unsigned char dangwei[1]; //档位的显示
unsigned int pulse_speed=100; //每分钟多少转
unsigned int pulse_speed1=0; //每分钟多少转
unsigned char code wenzi1[16]={"now_V: r/min"};
unsigned char code wenzi2[16]={"status: "};
unsigned char code zheng1[5]={"zheng"};
unsigned char code fan1[5]={"fan "};
//占空比输出
uint flag=1; //计时增加值
u16 duty=1; //占空比
u16 work_degree=1; //步进电机工作等级
u16 work_status=0; //工作状态,为0的时候不工作,为1的时候工作
//电机控制
sbit status=P3^7; //正反转控制位
sbit out=P3^4; //脉冲输出位
//按键控制
sbit add=P1^0; //加速
sbit reduce=P1^1; //减速
sbit zheng=P1^2; //正转
sbit fan=P1^3; //反转
sbit start=P1^4; //开始或者停止工作/*******************************************************************************
* 函 数 名 : delay
* 函数功能 : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(u16 i)
{while(i--);
}
/*******************************************************************************
* 函 数 名 : keypros
* 函数功能 : 按键处理函数,判断按键K1是否按下
*******************************************************************************/
void keypros()
{if(add==0) //检测按键K1是否按下{ delay(1000); //消除抖动 一般大约10msif(add==0) //再次判断按键是否按下{work_degree+=1;if(work_degree==8)work_degree=7;}while(!add); //检测按键是否松开} if(reduce==0) //检测按键K1是否按下{ delay(1000); //消除抖动 一般大约10msif(reduce==0) //再次判断按键是否按下{work_degree-=1;if(work_degree==0)work_degree=1;}while(!reduce); //检测按键是否松开}if(zheng==0) //检测按键K1是否按下{ delay(1000); //消除抖动 一般大约10msif(zheng==0) //再次判断按键是否按下{status=1;}while(!zheng); //检测按键是否松开}if(fan==0) //检测按键K1是否按下{ delay(1000); //消除抖动 一般大约10msif(fan==0) //再次判断按键是否按下{status=0;}while(!fan); //检测按键是否松开}if(start==0) //检测按键K1是否按下{ delay(1000); //消除抖动 一般大约10msif(start==0) //再次判断按键是否按下{work_status+=1;if(work_status>=2)work_status=0;}while(!start); //检测按键是否松开}
}
/*******************************************************************************
* 函 数 名 : Timer0Init
* 函数功能 : 定时器0初始化
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Timer0Init()
{TMOD|=0X11;//选择为定时器0模式,工作方式1,仅用TR0打开启动。TH0=0XD8; //给定时器赋初值,定时1msTL0=0XF1; ET0=1;//打开定时器0中断允许EA=1;//打开总中断TR0=1;//打开定时器
}
/*******************************************************************************
* 函 数 名 : Timer1Init
* 函数功能 : 定时器1初始化
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Timer1Init()
{TMOD|=0X11;//选择为定时器1模式,工作方式1,仅用TR1打开启动。TH1=0X3C; //给定时器赋初值,定时50msTL1=0XB1; ET1=1;//打开定时器1中断允许EA=1;//打开总中断TR1=1;//打开定时器
}
/*******************************************************************************
* 函数名 : main
* 函数功能 : 主函数
* 输入 : 无
* 输出 : 无
*******************************************************************************/void main()
{unsigned char i;Timer0Init(); //定时器0初始化Timer1Init(); //定时器1初始化LcdInit();LcdWriteCom(0x80);for(i=0;i<16;i++){LcdWriteData(wenzi1[i]); }LcdWriteCom(0x80+0x40);for(i=0;i<16;i++){LcdWriteData(wenzi2[i]); }while(1){//按键处理keypros();//显示转速
// pulse_speed=;num[0]=pulse_speed/1000;num[1]=pulse_speed%1000/100;num[2]=pulse_speed%100/10;num[3]=pulse_speed%10;dangwei[0]=work_degree;if(num[0]>9){LcdWriteCom(0x80+0x06); //设置显示位置LcdWriteData(0x37+num[0]); //将数值转换为该显示的ASCII码}else{LcdWriteCom(0x80+0x06);LcdWriteData(num[0]+0x30); //将数值转换为该显示的ASCII码}if(num[1]>9){LcdWriteCom(0x80+0x07);LcdWriteData(num[1]+0x37); //将数值转换为该显示的ASCII码}else{LcdWriteCom(0x80+0x07);LcdWriteData(num[1]+0x30); //将数值转换为该显示的ASCII码} if(num[2]>9){LcdWriteCom(0x80+0x08);LcdWriteData(num[2]+0x37); //将数值转换为该显示的ASCII码}else{LcdWriteCom(0x80+0x08);LcdWriteData(num[2]+0x30); //将数值转换为该显示的ASCII码} if(num[3]>9){LcdWriteCom(0x80+0x09);LcdWriteData(num[3]+0x37); //将数值转换为该显示的ASCII码}else{LcdWriteCom(0x80+0x09);LcdWriteData(num[3]+0x30); //将数值转换为该显示的ASCII码} //显示正反转if(status==1){LcdWriteCom(0x80+0x47);for(i=0;i<5;i++){LcdWriteData(zheng1[i]); }}else{LcdWriteCom(0x80+0x47);for(i=0;i<5;i++){LcdWriteData(fan1[i]); }}//显示当前档位if(dangwei[0]>9){LcdWriteCom(0x80+0x4F);LcdWriteData(dangwei[0]+0x37); //将数值转换为该显示的ASCII码}else{LcdWriteCom(0x80+0x4F);LcdWriteData(dangwei[0]+0x30); //将数值转换为该显示的ASCII码} }
}
/*******************************************************************************
* 函 数 名 : void Timer0() interrupt 1
* 函数功能 : 定时器0中断函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Timer0() interrupt 1
{static u16 i;TH0=0Xdc; //给定时器赋初值,定时10msTL0=0X00;i++;if(i==200){if(work_degree==1)pulse_speed=50;else if(work_degree==2)pulse_speed=100;else if(work_degree==3)pulse_speed=200;else if(work_degree==4)pulse_speed=500;else if(work_degree==5)pulse_speed=1000;else if(work_degree==6)pulse_speed=2000;else if(work_degree==7)pulse_speed=4000;i=0;}
}
/*******************************************************************************
* 函 数 名 : void Timer1() interrupt 3
* 函数功能 : 定时器0中断函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Timer1() interrupt 3
{if(work_degree==1)TH1=0xD8,TL1=0xF1;//定时10mselse if(work_degree==2)TH1=0xEC,TL1=0x79;//定时5mselse if(work_degree==3)TH1=0xF6,TL1=0x3D;//定时2.5mselse if(work_degree==4)TH1=0xFC,TL1=0x19;//定时1mselse if(work_degree==5)TH1=0xFE,TL1=0x0D;//定时500uselse if(work_degree==6)TH1=0xFF,TL1=0x07;//定时250uselse if(work_degree==7)TH1=0xFF,TL1=0x84;//定时125usflag++;if(flag>1){flag=0;} if(work_status==1){if(flag<duty){out=1;}else{out=0;}}else{out=0;}
}
Lcd.c
#include"lcd.h"
/*******************************************************************************
* 函 数 名 : Lcd1602_Delay1ms
* 函数功能 : 延时函数,延时1ms
* 输 入 : c
* 输 出 : 无
* 说 名 : 该函数是在12MHZ晶振下,12分频单片机的延时。
*******************************************************************************/void Lcd1602_Delay1ms(uint c) //误差 0us
{uchar a,b;for (; c>0; c--){for (b=199;b>0;b--){for(a=1;a>0;a--);} }}/*******************************************************************************
* 函 数 名 : LcdWriteCom
* 函数功能 : 向LCD写入一个字节的命令
* 输 入 : com
* 输 出 : 无
*******************************************************************************/
#ifndef LCD1602_4PINS //当没有定义这个LCD1602_4PINS时
void LcdWriteCom(uchar com) //写入命令
{LCD1602_E = 0; //使能LCD1602_RS = 0; //选择发送命令LCD1602_RW = 0; //选择写入LCD1602_DATAPINS = com; //放入命令Lcd1602_Delay1ms(1); //等待数据稳定LCD1602_E = 1; //写入时序Lcd1602_Delay1ms(5); //保持时间LCD1602_E = 0;
}
#else
void LcdWriteCom(uchar com) //写入命令
{LCD1602_E = 0; //使能清零LCD1602_RS = 0; //选择写入命令LCD1602_RW = 0; //选择写入LCD1602_DATAPINS = com; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改Lcd1602_Delay1ms(1);LCD1602_E = 1; //写入时序Lcd1602_Delay1ms(5);LCD1602_E = 0;// Lcd1602_Delay1ms(1);LCD1602_DATAPINS = com << 4; //发送低四位Lcd1602_Delay1ms(1);LCD1602_E = 1; //写入时序Lcd1602_Delay1ms(5);LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 数 名 : LcdWriteData
* 函数功能 : 向LCD写入一个字节的数据
* 输 入 : dat
* 输 出 : 无
*******************************************************************************/
#ifndef LCD1602_4PINS
void LcdWriteData(uchar dat) //写入数据
{LCD1602_E = 0; //使能清零LCD1602_RS = 1; //选择输入数据LCD1602_RW = 0; //选择写入LCD1602_DATAPINS = dat; //写入数据Lcd1602_Delay1ms(1);LCD1602_E = 1; //写入时序Lcd1602_Delay1ms(5); //保持时间LCD1602_E = 0;
}
#else
void LcdWriteData(uchar dat) //写入数据
{LCD1602_E = 0; //使能清零LCD1602_RS = 1; //选择写入数据LCD1602_RW = 0; //选择写入LCD1602_DATAPINS = dat; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改Lcd1602_Delay1ms(1);LCD1602_E = 1; //写入时序Lcd1602_Delay1ms(5);LCD1602_E = 0;LCD1602_DATAPINS = dat << 4; //写入低四位Lcd1602_Delay1ms(1);LCD1602_E = 1; //写入时序Lcd1602_Delay1ms(5);LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 数 名 : LcdInit()
* 函数功能 : 初始化LCD屏
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
#ifndef LCD1602_4PINS
void LcdInit() //LCD初始化子程序
{LcdWriteCom(0x38); //开显示LcdWriteCom(0x0c); //开显示不显示光标LcdWriteCom(0x06); //写一个指针加1LcdWriteCom(0x01); //清屏LcdWriteCom(0x80); //设置数据指针起点
}
#else
void LcdInit() //LCD初始化子程序
{LcdWriteCom(0x32); //将8位总线转为4位总线LcdWriteCom(0x28); //在四位线下的初始化LcdWriteCom(0x0c); //开显示不显示光标LcdWriteCom(0x06); //写一个指针加1LcdWriteCom(0x01); //清屏LcdWriteCom(0x80); //设置数据指针起点
}
#endif
lcd.h
#ifndef __LCD_H_
#define __LCD_H_
/**********************************
当使用的是4位数据传输的时候定义,
使用8位取消这个定义
**********************************/
//#define LCD1602_4PINS/**********************************
包含头文件
**********************************/
#include<reg51.h>//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif#ifndef uint
#define uint unsigned int
#endif/**********************************
PIN口定义
**********************************/
#define LCD1602_DATAPINS P0
sbit LCD1602_E=P2^5;
sbit LCD1602_RW=P2^6;
sbit LCD1602_RS=P2^7;/**********************************
函数声明
**********************************/
/*在51单片机12MHZ时钟下的延时函数*/
void Lcd1602_Delay1ms(uint c); //误差 0us
/*LCD1602写入8位命令子函数*/
void LcdWriteCom(uchar com);
/*LCD1602写入8位数据子函数*/
void LcdWriteData(uchar dat) ;
/*LCD1602初始化子程序*/
void LcdInit(); #endif
需要注意的是,虽然lcd的代码是基于普中科技的实验例程修正过来的,但是对于RS\RW\EN三个接口的引脚有所更改,建议复制粘贴我的lcd代码
3.实物
实物视频请移步我的个人主页视频去看
总结
冲冲冲,步进电机驱动很简单,大家可以在此基础上结合其他模块玩一些好玩的东西,稍后代码和资料会发布到我的资源中
基于51单片机的步进电机驱动,亲测无误相关推荐
- (毕业设计资料)基于51单片机脉搏心率智能检测测速系统设计
基于51单片机跑步机系统脉搏检测红外测速设计 本设计由STC89C52单片机电路+脉搏/心率传感器电路+LM393比较器电路+霍尔测速电路+电机控制电路+LCD1602显示电路+电源电路组成. 1.通 ...
- 基于51单片机出租车计价器(霍尔测速)
具体实现功能 系统由AT89C52单片机+霍尔传感器模块+LCD1602液晶屏+DS1302时钟模块+AT24C02掉电存储模块+直流电机+按键模块+电源构成. 具体功能: 1.无乘客模式:显示当前时 ...
- 基于51单片机和霍尔传感器的测速
项目代码: 链接:https://pan.baidu.com/s/1vK3i5r0wnks7lWC4yUP8Jg 提取码:vwu0 1. 小项目简介 主要采用stc89c51/52单片机作为主控,由霍 ...
- 基于STM32单片机闭环步进电机驱动调速仿真(仿真+源码+全套资料)
资料编号:081 (1) 基本功能:本任务通过输出脉冲控制步进电机的停止.运动.方向.使用 两个按键分别控制步进电机的正转和反转,再次按下这两个按键,步进电机停止, 同时 LCD 显示电机状态信息. ...
- 基于51单片机的红外非接触测温仪阈值报警方案原理图设计
系统的功能分析 (附文件) 系统功能分析 本设计由STC89C52单片机电路+1602液晶显示电路+MLX90614ESF红外非接触温度检测电路+按键电路+蜂鸣器报警电路. 1.液晶实时显示MLX90 ...
- 基于51单片机的直流电机调速测速正反转控制(仿真+源程序+原理图+PCB)
资料编号:206 1.本设计采用STC89C51/52(与AT89S51/52.AT89C51/52通用,可任选)51单片机作为主控制器 2.采用霍尔传感器非接触式测电机转速 3.LCD1602液晶显 ...
- 基于51单片机的八路多路温度测控系统proteus仿真原理图PCB
功能介绍: 0.本系统采用STC89C52作为单片机 1.LCD1602液晶实时滚动显示8路温度传感器检测的温度值及设定温度值 2.当8路平均温度超过设定温度阈值范围,蜂鸣器报警,同时启动加热或降温装 ...
- 基于51单片机的公交车安全智能检测系统、基于51单片机的金属探测仪控制设计、基于单片机的智能电子密码锁系统设计、基于51单片机酒精浓度检测仪设计【资料转发分享】
630基于51单片机的公交车安全智能检测系统-设计资料 本资料是基于单片机的公交车安全监测系统 具有如下功能: 1.监测环境的温度,超标报警.可以设置上下限 2.监测是否有火灾以及有毒气体,超标报警, ...
- 2022-4-9 基于51单片机驱动直流电机(L293D)(公众号:风吹摇铃 奔赴星海)
基于51单片机的直流电机驱动 仿真软件为Proteus8.10 编程软件为keil4 系统组成:单片机最小系统.四位共阳极数码管.三个独立按键.直流电机.L293D芯片. 系统功能:又三个按键控制 ...
最新文章
- selenium 文件下载
- CentOS6.5最小化安装+自定义安装包
- Excel酷炫技能,批量修改工作表名称,让你的工作事半功倍
- this关键字+super关键字
- 算法—实现排列 A(n,m)
- 北师大计算机组成原理答案,计算机组成原理(白中英)本科生试题库整理附答案[共21页].doc...
- 易到追债贾跃亭 乐视回应:对方无耻甩锅
- UI实用素材|播放器界面模板
- 车rc陀螺仪测试软件,利用加速度计和陀螺仪测量车辆运动
- visual studio 编译器在辨异 C/C++ 程序时的注意事项
- ASP.NET底层架构 22
- Big Data 导论HadoopHDFS
- 基于iPhone 上的运动协处理器M7判断用户当前的运动(姿态)类型
- 【STM32】HAL库-备份寄存器(BKP)
- 安卓手机屏幕投射电脑 手机投屏到win7
- 单片机蓝牙模块的使用,以及配置控制舵机的源码
- 力扣刷题pdf(java版本,内含暗黑版和光明版),都在这里了
- 【转】Subsonic的添加和更新、删除操作
- 猿创征文|前端进阶必备——WebSockt实现聊天室(附源码)
- 我,一个走在创业路上人的自白——贝勒爷
热门文章
- windows winrar 指令_Windows上WinRAR.exe命令行参数说明
- 全国地区车牌字母对应的地区
- android锁屏退场动画,锁屏十秒超时,锁屏界面退出动画流程,FLAG_KEEP_SCREEN_ON亮屏...
- 拟录取之后需要关注的几件事,千万别大意!
- 独家|陆金所IPO幕后事:内部高管看空、P2P存量难消、兑付方案未果
- 引用Geoip实现由IP地址获取国家城市等信息
- VTK8.2.0安装步骤
- 云课堂智慧职教答案python_智慧职教云课堂Python程序设计答案
- 青岛跻身互联网+智慧城市全国十强
- HP LaserJet M1536dnf MFP 在win11上无法安装 HP SCAN