文章目录

  • 前言
  • 一、我们该如何实现电机驱动?
  • 二、驱动实现
    • 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单片机的步进电机驱动,亲测无误相关推荐

  1. (毕业设计资料)基于51单片机脉搏心率智能检测测速系统设计

    基于51单片机跑步机系统脉搏检测红外测速设计 本设计由STC89C52单片机电路+脉搏/心率传感器电路+LM393比较器电路+霍尔测速电路+电机控制电路+LCD1602显示电路+电源电路组成. 1.通 ...

  2. 基于51单片机出租车计价器(霍尔测速)

    具体实现功能 系统由AT89C52单片机+霍尔传感器模块+LCD1602液晶屏+DS1302时钟模块+AT24C02掉电存储模块+直流电机+按键模块+电源构成. 具体功能: 1.无乘客模式:显示当前时 ...

  3. 基于51单片机和霍尔传感器的测速

    项目代码: 链接:https://pan.baidu.com/s/1vK3i5r0wnks7lWC4yUP8Jg 提取码:vwu0 1. 小项目简介 主要采用stc89c51/52单片机作为主控,由霍 ...

  4. 基于STM32单片机闭环步进电机驱动调速仿真(仿真+源码+全套资料)

    资料编号:081 (1) 基本功能:本任务通过输出脉冲控制步进电机的停止.运动.方向.使用 两个按键分别控制步进电机的正转和反转,再次按下这两个按键,步进电机停止, 同时 LCD 显示电机状态信息. ...

  5. 基于51单片机的红外非接触测温仪阈值报警方案原理图设计

    系统的功能分析 (附文件) 系统功能分析 本设计由STC89C52单片机电路+1602液晶显示电路+MLX90614ESF红外非接触温度检测电路+按键电路+蜂鸣器报警电路. 1.液晶实时显示MLX90 ...

  6. 基于51单片机的直流电机调速测速正反转控制(仿真+源程序+原理图+PCB)

    资料编号:206 1.本设计采用STC89C51/52(与AT89S51/52.AT89C51/52通用,可任选)51单片机作为主控制器 2.采用霍尔传感器非接触式测电机转速 3.LCD1602液晶显 ...

  7. 基于51单片机的八路多路温度测控系统proteus仿真原理图PCB

    功能介绍: 0.本系统采用STC89C52作为单片机 1.LCD1602液晶实时滚动显示8路温度传感器检测的温度值及设定温度值 2.当8路平均温度超过设定温度阈值范围,蜂鸣器报警,同时启动加热或降温装 ...

  8. 基于51单片机的公交车安全智能检测系统、基于51单片机的金属探测仪控制设计、基于单片机的智能电子密码锁系统设计、基于51单片机酒精浓度检测仪设计【资料转发分享】

    630基于51单片机的公交车安全智能检测系统-设计资料 本资料是基于单片机的公交车安全监测系统 具有如下功能: 1.监测环境的温度,超标报警.可以设置上下限 2.监测是否有火灾以及有毒气体,超标报警, ...

  9. 2022-4-9 基于51单片机驱动直流电机(L293D)(公众号:风吹摇铃 奔赴星海)

    基于51单片机的直流电机驱动 仿真软件为Proteus8.10   编程软件为keil4 系统组成:单片机最小系统.四位共阳极数码管.三个独立按键.直流电机.L293D芯片. 系统功能:又三个按键控制 ...

最新文章

  1. selenium 文件下载
  2. CentOS6.5最小化安装+自定义安装包
  3. Excel酷炫技能,批量修改工作表名称,让你的工作事半功倍
  4. this关键字+super关键字
  5. 算法—实现排列 A(n,m)
  6. 北师大计算机组成原理答案,计算机组成原理(白中英)本科生试题库整理附答案[共21页].doc...
  7. 易到追债贾跃亭 乐视回应:对方无耻甩锅
  8. UI实用素材|播放器界面模板
  9. 车rc陀螺仪测试软件,利用加速度计和陀螺仪测量车辆运动
  10. visual studio 编译器在辨异 C/C++ 程序时的注意事项
  11. ASP.NET底层架构 22
  12. Big Data 导论HadoopHDFS
  13. 基于iPhone 上的运动协处理器M7判断用户当前的运动(姿态)类型
  14. 【STM32】HAL库-备份寄存器(BKP)
  15. 安卓手机屏幕投射电脑 手机投屏到win7
  16. 单片机蓝牙模块的使用,以及配置控制舵机的源码
  17. 力扣刷题pdf(java版本,内含暗黑版和光明版),都在这里了
  18. 【转】Subsonic的添加和更新、删除操作
  19. 猿创征文|前端进阶必备——WebSockt实现聊天室(附源码)
  20. 我,一个走在创业路上人的自白——贝勒爷

热门文章

  1. windows winrar 指令_Windows上WinRAR.exe命令行参数说明
  2. 全国地区车牌字母对应的地区
  3. android锁屏退场动画,锁屏十秒超时,锁屏界面退出动画流程,FLAG_KEEP_SCREEN_ON亮屏...
  4. 拟录取之后需要关注的几件事,千万别大意!
  5. 独家|陆金所IPO幕后事:内部高管看空、P2P存量难消、兑付方案未果
  6. 引用Geoip实现由IP地址获取国家城市等信息
  7. VTK8.2.0安装步骤
  8. 云课堂智慧职教答案python_智慧职教云课堂Python程序设计答案
  9. 青岛跻身互联网+智慧城市全国十强
  10. HP LaserJet M1536dnf MFP 在win11上无法安装 HP SCAN