1
完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
51单片机实现步进电机(39BYG316/28BYJ48)的启停,圈数设定,正反转,速率调整,LCD1602显示等调节 一、方案设计 方案1:采用89C51+ULN2003+28BYJ48,28BYJ48是一种常见的四相五线步进减速电机,其减速比为1/64,步进角1.8°,即如果采用四相四拍运行,若使步进电机转一周则需要64*(360/1.8)个脉冲;如果采用四相八拍运行,若使步进电机转一周则需要64*(360/0.9)个脉冲; 方案2:采用89C51+ULN2003+39BYG316,39BYG316是一种常见的四相五线步进电机,步进角1.8°,即如果采用四相四拍运行,若使步进电机转一周则需要6360/1.8个脉冲;如果采用四相八拍运行,若使步进电机转一周则需要360/0.9个脉冲; 二、硬件设计 硬件设计分为MCU模块、LCD和按键模块、电源模块、驱动模块共四大模块。 MCU模块采用较为常见的STC89C52RC,一般的淘宝店都能买到,设计时要特别注意P0口需要配置上拉电阻,晶振选取11.0592M的。 LCD和按键模块,四个按键的功能分别是K1启停,K2设定圈数,K3方向转换,K4速率调整,LCD选取LCD1602。 电源模块的设计比较简单,测试用的输入为7.2V电源,因此仅采用一稳压芯片AMS1117-5.0即可得到所需要的单片机供电电压,并添加了一个自锁开关方便及时断电,电源指示灯用于指示电源状态。 驱动模块采用最最常用的达林顿管驱动器ULN2003,并在输出端口设置四路LED显示当前驱动状态。 另外,步进电机的接线较为麻烦易错,28BYJ48在淘宝上有现成的解决办法,结合ULN2003驱动很容易接线;39BYG316电机也是在淘宝上买的,4.5元一个,接线仿照28BYJ48也很容易解决。 二、软件设计 首先,为了步进电机更好的运行,采用八拍的运行方式,给出四相八拍正反转表,如下: //为了简便的宏定义 #define uchar unsigned char #define uint unsigned int //四相八拍反转表 uchar code FFW[8]={0x08,0x0c,0x04,0x06,0x02,0x03,0x01,0x09}; //四相八拍正转表 uchar code REV[8]={0x09,0x01,0x03,0x02,0x06,0x04,0x0c,0x08}; 然后,按照硬件设计编写软件连接 ***it K1 = P3^2; // 启停 ***it K2 = P3^3; // 设定圈数 ***it K3 = P3^4; // 方向调整 ***it K4 = P3^5; // 速率调整 ***it LCD_RS = P2^6; // LCD连接 ***it LCD_RW = P2^5; // LCD连接 ***it LCD_EN = P2^7; // LCD连接 设置必须用的延时函数,为后面按键消抖,LCD1602通信等所使用 //空指令延时函数 #define delayNOP(); {_nop_();_nop_();_nop_();_nop_();}; /********************************************************/ /*延时 t ms函数 /********************************************************/ void delay(uint t) { uchar k; while(t--) { for(k=0; k<125; k++) {} } } 再然后设置LCD1602的通信 /********************************************************/ /* 检查LCD状态 /* lcd_busy=1 忙,等待 /* lcd_busy=0 闲,可写指令与数据 /********************************************************/ bit lcd_busy() { bit result; LCD_RS = 0; LCD_RW = 1; LCD_EN = 1; delayNOP(); result = (bit)(P0&0x80); LCD_EN = 0; return(result); } /********************************************************/ /* 写指令到LCD /* RS=L , RW=L, E=高脉冲, D0-D7= 指令码 /* /********************************************************/ void lcd_wcmd(uchar cmd) { while(lcd_busy()); LCD_RS = 0; LCD_RW = 0; LCD_EN = 0; P0 = cmd; delay(1); LCD_EN = 1; delay(5); LCD_EN = 0; } /********************************************************/ /* 写显示数据到LCD /* RS=H , RW=L, E=高脉冲, D0-D7= 数据 /* /********************************************************/ void lcd_wdat(uchar dat) { while(lcd_busy()); LCD_RS = 1; LCD_RW = 0; LCD_EN = 0; P0 = dat; delay(1); LCD_EN = 1; delay(5); LCD_EN = 0; } /********************************************************/ /* LCD 初始化 /* /********************************************************/ void lcd_init() { lcd_wcmd(0x38); lcd_wcmd(0x0c); lcd_wcmd(0x06); lcd_wcmd(0x01); lcd_wcmd(0x80); } /********************************************************/ /* 设定显示位置 /* /********************************************************/ void lcd_pos(uchar pos) { lcd_wcmd(pos | 0x80); // 数据指针 = 80 + 地址变量 } 然后设置LCD1602的初始化 //LCD1602 显示的状态数据 uchar code cdis1[ ] = {" STEPPING MOTOR "}; uchar code cdis2[ ] = {"CONTROL PROCESS"}; uchar code cdis3[ ] = {" STOP "}; uchar code cdis4[ ] = {"NUM: RATE:"}; uchar code cdis5[ ] = {" RUNNING "}; /********************************************************/ /* LCD1602 初始化 /* /********************************************************/ void LCD_init_DIS() { delay(10); lcd_init(); // 初始化 LCD lcd_pos(0); // 设置为第一行第一位 m = 0; while(cdis1[m] != ' |