基于8051控制步进电机并具有屏幕LCD12864可控菜单选项

基于8051系统控制步进电机28BYJ-48,并且通过LCD12864可选菜单选择步进电机运行模式

步进电机控制部分

28BYJ48.C

#include "28BYJ48.H"
#include "LCD12864.H"
unsigned char delay_ms(unsigned int ms, unsigned char Range)
{
    unsigned int i;
    unsigned char j, FSOC;

    for(i = ms; i > 0; i--)
    {
        for(FSOC = 12; FSOC > 0; FSOC--)
        {
            for(j = 96; j > 0; j--)
            {
                switch(Range)
                {
                    case 0: //Just Delay
                    {

                    } break;

                    case 1: //LimitSwitch
                    {
                        if(LimitSwitch == 0)
                        {
                            return 1;
                        }
                    }
                    break;

                    case 2://
                    {
                        if(!Start)
                        {
                            return 2;
                        }

                        if(!Back)
                        {
                            return 3;
                        }
                    }
                    break;
                }
            }
        }
    }

    return 0;
}

void step_motor_28BYJ48_send_pulse(unsigned char Step, bit Dir)
{


    if(Dir == 0) 	//如果为逆时针旋转
    {
        Step = 7 - Step; //调换节拍信号
    }

    switch(Step)//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;

        default:
            IN1_A = 0;
            IN2_B = 0;
            IN3_C = 0;
            IN4_D = 0;
            break;//停止相序
    }
}
//电机初始化
bit MOTOR28BYJ48Init(bit Dir)
{
    unsigned char step;
    unsigned char step1;

    while(1)
    {
        step_motor_28BYJ48_send_pulse(step++, Dir);

        if(step == 8)
        {
            step = 0;
            step1++;
            //转180度
            if(step1 == 255)
            {
                return 1;
            }
        }

        if(delay_ms(1, 1))
        {
            return 0;
        }
    }
}
28BYJ48.H

#include <STC8.H>
#ifndef __28BYJ48_H__
#define __28BYJ48_H__


//端口定义
sbit LimitSwitch = P4 ^ 3;

sbit IN1_A = P6 ^ 0;
sbit IN2_B = P6 ^ 1;
sbit IN3_C = P6 ^ 2;
sbit IN4_D = P6 ^ 3;
//端口定义

void step_motor_28BYJ48_send_pulse(unsigned char Step, bit Dir);
unsigned char delay_ms(unsigned int ms, unsigned char Range);
bit MOTOR28BYJ48Init(bit Dir);
#endif

 LCD12864实现部分,可以切换为Oled12864以及其他屏幕

LCD12864.C

#include "LCD12864.H"


void DelayLCD()
{
    unsigned char i, j;

    for(i = 0; i < 12; i++)
    {
        for(j = 0; j < 32; j++)
        {

        }
    }
}

//-->整数转换函数
char* itoa(int num, char* str, int radix)
{
    char index[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; //索引表
    char temp;//临时变量,交换两个值时用到
    unsigned unum;//存放要转换的整数的绝对值,转换的整数可能是负数
    int i = 0, j, k; //i用来指示设置字符串相应位,转换之后i其实就是字符串的长度;转换后顺序是逆序的,有正负的情况,k用来指示调整顺序的开始位置;j用来指示调整顺序时的交换。

    //获取要转换的整数的绝对值
    if(radix == 10 && num < 0) //要转换成十进制数并且是负数
    {
        unum = (unsigned) - num; //将num的绝对值赋给unum
        str[i++] = '-'; //在字符串最前面设置为'-'号,并且索引加1
    }
    else unum = (unsigned)num; //若是num为正,直接赋值给unum

    //转换部分,注意转换后是逆序的
    do
    {
        str[i++] = index[unum % (unsigned)radix]; //取unum的最后一位,并设置为str对应位,指示索引加1
        unum /= radix; //unum去掉最后一位

    }
    while(unum); //直至unum为0退出循环

    str[i] = '\0'; //在字符串最后添加'\0'字符,c语言字符串以'\0'结束。

    //将顺序调整过来
    if(str[0] == '-') k = 1; //如果是负数,符号不用调整,从符号后面开始调整
    else k = 0; //不是负数,全部都要调整

    for(j = k; j <= (i - 1) / 2; j++) //头尾一一对称交换,i其实就是字符串的长度,索引最大值比长度少1
    {
        temp = str[j]; //头部赋值给临时变量
        str[j] = str[i - 1 + k - j]; //尾部赋值给头部
        str[i - 1 + k - j] = temp; //将临时变量的值(其实就是之前的头部值)赋给尾部
    }

    return str;//返回转换后的字符串
}
//-->读忙函数
void CheckBusy(void)
{
    RS = 0;
    RW = 1;
    EN = 1;

    while((DataPort & 0x80) == 0x80);

    EN = 0;
}
//-->写指令
void WriteCmd(unsigned char CmdCode)
{
    CheckBusy();
    RS = 0;
    RW = 0;
    EN = 1;
    DataPort = CmdCode;
    DelayLCD();
    EN = 0;
}
//-->写数据
void WriteData(unsigned char DataCode)
{
    CheckBusy();
    RS = 1;
    RW = 0;
    EN = 1;
    DataPort = DataCode;
    DelayLCD();
    EN = 0;
}
//-->LCD12864初始化
void InitLCD(void)
{
    RSB = 1;
    RST = 0;
    DelayLCD();
    RST = 1;
    WriteCmd(0x30);

    WriteCmd(0x30);

    WriteCmd(0x0c);

    WriteCmd(0x02);

    WriteCmd(0x01);

    BLA = 0;

    LCD_String(0, 0, "显示器显示无误!!");
    LCD_String(0, 1, "显示器显示无误!!");
    LCD_String(0, 2, "显示器显示无误!!");
    LCD_String(0, 3, "显示器显示无误!!");
}

//-->发送字符串
void LCD_String(unsigned char x, unsigned char y, unsigned char  *Str)
{
    switch(y)
    {
        case 0:
            WriteCmd(0x80 + x);
            break;

        case 1:
            WriteCmd(0x90 + x);
            break;

        case 2:
            WriteCmd(0x88 + x);
            break;

        case 3:
            WriteCmd(0x98 + x);
            break;

        default:
            break;
    }

    while(*Str > 0)
    {
        WriteData(*Str);
        DelayLCD();
        Str++;
    }
}
LCD12864.H

#include <STC8.H>

#ifndef __LCD12864_H__
#define __LCD12864_H__

//端口定义
#define DataPort P7
sbit RS = P1 ^ 1;
sbit RW = P1 ^ 2;
sbit EN = P1 ^ 3;
sbit RSB = P4 ^ 4;
sbit NC  = P1 ^ 5;
sbit RST = P1 ^ 0;
sbit BLA = P1 ^ 4;

sbit LED1 = P5 ^ 5;
sbit LED2 = P4 ^ 1;
sbit BUZZ = P2 ^ 1;
sbit Start = P6 ^ 7;
sbit Back  = P6 ^ 6;
sbit Up    = P6 ^ 5;
sbit Down  = P6 ^ 4;
sbit Sure  = P4 ^ 3;
//端口定义

/********************
******函数定义******/
//-->整数转换函数
char* itoa(int num, char* str, int radix);
//-->读忙函数
void CheckBusy(void);
//-->写指令
void WriteCmd(unsigned char CmdCode);
//-->写数据
void WriteData(unsigned char DataCode);
//-->LCD12864初始化
void InitLCD(void);
//-->发送字符串
void LCD_String(unsigned char x, unsigned char y, unsigned char *s);
//-->用于稳定时序的延时
void DelayLCD();
/********************
******函数定义******/

#endif

主函数部分

#include <STC8.H>

#include "28BYJ48.H"
#include "LCD12864.H"

bit StartFlag = 0;

bit Laout2Flag = 0;

//储存模式
bit Laout3FlagA;
bit Laout3FlagB;
bit Laout3FlagC;
//储存角度
bit Laout4FlagA;
bit Laout4FlagB;
bit Laout4FlagC;
//储存速度
bit Laout5FlagA;
bit Laout5FlagB;
bit Laout5FlagC;

void UI(unsigned char Layout, unsigned char Mode)
{


    switch(Layout)
    {
        //开机界面
        case 0:
        {
            WriteCmd(0x01);
            LCD_String(0, 0, "->初始化未完成<0");
            LCD_String(0, 1, "显示器显示无误!!");
            LCD_String(0, 2, "限位开关检测异常");
            LCD_String(0, 3, "当前状态循环自检");
        }
        break;

        //自检完成待机界面
        case 1:
        {
            WriteCmd(0x01);
            LCD_String(0, 0, "->初始化已完成<1");
            LCD_String(0, 1, "长按启动按钮开启");
            LCD_String(0, 2, "限位开关检测无误");
            LCD_String(0, 3, "自检完毕等侯操作");

        }
        break;

        //选择模式开启电机
        case 2:
        {
            if(!Laout2Flag)
            {
                WriteCmd(0x01);
                WriteCmd(0x01);
                LCD_String(0, 0, "->选择模式开机<2");
                LCD_String(0, 1, "A>顺时针转动");
                LCD_String(0, 2, "B>逆时针转动");
                LCD_String(0, 3, "C>循环转动");
                Laout2Flag = 1;
            }

            switch(Mode)
            {
                case 0:
                {
                    LCD_String(0, 1, "+>顺时针转动");
                    LCD_String(0, 2, "B>");
                    LCD_String(0, 3, "C>");
                }
                break;

                case 1:
                {
                    LCD_String(0, 1, "A>");
                    LCD_String(0, 2, "+>逆时针转动");
                    LCD_String(0, 3, "C>");
                }
                break;

                case 2:
                {
                    LCD_String(0, 1, "A>");
                    LCD_String(0, 2, "B>");
                    LCD_String(0, 3, "+>循环转动");
                }
                break;
            }
        }
        break;

        //选择模式开启电机
        case 3:
        {
            if(!Laout2Flag)
            {
                WriteCmd(0x01);
                WriteCmd(0x01);
                LCD_String(0, 0, "->选择转动模式<3");
                LCD_String(0, 1, "->转动45度");
                LCD_String(0, 2, "->转动90度");
                LCD_String(0, 3, "->按下启动转动");
                Laout2Flag = 1;
            }

            switch(Mode)
            {
                case 0:
                {
                    LCD_String(0, 1, "+>");
                    LCD_String(0, 2, "->");
                    LCD_String(0, 3, "->");
                }
                break;

                case 1:
                {
                    LCD_String(0, 1, "->");
                    LCD_String(0, 2, "+>");
                    LCD_String(0, 3, "->");
                }
                break;

                case 2:
                {
                    LCD_String(0, 1, "->");
                    LCD_String(0, 2, "->");
                    LCD_String(0, 3, "+>");
                }
                break;
            }

        }
        break;

        //选择转速
        case 4:
        {
            if(!Laout2Flag)
            {
                WriteCmd(0x01);
                WriteCmd(0x01);
                LCD_String(0, 0, "->选择转动速度<4");
                LCD_String(0, 1, "->低速");
                LCD_String(0, 2, "->中速");
                LCD_String(0, 3, "->高速");
                Laout2Flag = 1;
            }

            switch(Mode)
            {
                case 0:
                {
                    LCD_String(0, 1, "+>");
                    LCD_String(0, 2, "->");
                    LCD_String(0, 3, "->");
                }
                break;

                case 1:
                {
                    LCD_String(0, 1, "->");
                    LCD_String(0, 2, "+>");
                    LCD_String(0, 3, "->");
                }
                break;

                case 2:
                {
                    LCD_String(0, 1, "->");
                    LCD_String(0, 2, "->");
                    LCD_String(0, 3, "+>");
                }
                break;
            }
        }
        break;

        case 5:
        {
            if(!Laout2Flag)
            {
                WriteCmd(0x01);
                WriteCmd(0x01);
                LCD_String(0, 0, "->按下启动开始<5");
                LCD_String(0, 1, "模式:");

                LCD_String(0, 2, "速度:");

                LCD_String(0, 3, "状态:");

                Laout2Flag = 1;
            }

            if(Laout3FlagA)
            {
                LCD_String(3, 1, "顺时");
            }

            if(Laout3FlagB)
            {
                LCD_String(3, 1, "逆时");
            }

            if(Laout3FlagC)
            {
                LCD_String(3, 1, "循环");
            }

            if(Laout4FlagA)
            {
                LCD_String(5, 1, "45度");
            }

            if(Laout4FlagB)
            {
                LCD_String(5, 1, "90度");
            }

            if(Laout4FlagC)
            {
                LCD_String(5, 1, "按键");
            }

            if(Laout5FlagA)
            {
                LCD_String(3, 2, "低速");
            }

            if(Laout5FlagB)
            {
                LCD_String(3, 2, "中速");
            }

            if(Laout5FlagC)
            {
                LCD_String(3, 2, "高速");
            }

            if(StartFlag)
            {
                LCD_String(3, 3, "开启");
            }
            else
            {
                LCD_String(3, 3, "关闭");
            }

        }
        break;
    }
}



void  main(void)
{

    unsigned char ModeFlag;
    unsigned char Mode, Angle, Speed;
    unsigned char Buff1, Buff2, Buff3;

    RSTCFG = 0X10;
    P1M0 = 0X1F;
    P1M1 = 0X00;
    P7M0 = 0XFF;
    P7M1 = 0XFF;

    InitLCD();

    //显示开机界面
    UI(0, ModeFlag);

    //等待限位开关
    //while(LimitSwitch);
    while(MOTOR28BYJ48Init(LED2))
    {
        LED2 = !LED2;
    }

    //显示自检完成待机界面
    UI(1, ModeFlag);

    //等待按下启动按钮
    while(Start);


Layout2:
    {
//*****************************************
//    Layout = 2;
        Laout2Flag = 0;
        //显示2菜单
        UI(2, ModeFlag);

        //等待确认
        ModeFlag = 0;


        while(Sure)
        {


            if(Up == 0)
            {
                while(!Up);

                ModeFlag++;
            }

            if(Down == 0)
            {
                while(!Down);

                ModeFlag--;
            }

            if(ModeFlag == 3)
            {
                ModeFlag = 0;
            }

            if(ModeFlag == 255)
            {
                ModeFlag = 2;
            }

            UI(2, ModeFlag);
        }

        //存储转动模式
        switch(ModeFlag)
        {
            case 0:
            {
                Laout3FlagA = 1;
                Laout3FlagB = 0;
                Laout3FlagC = 0;
            }
            break;

            case 1:
            {
                Laout3FlagA = 0;
                Laout3FlagB = 1;
                Laout3FlagC = 0;
            }
            break;

            case 2:
            {
                Laout3FlagA = 0;
                Laout3FlagB = 0;
                Laout3FlagC = 1;
            }
            break;
        }

    }
Layout3:
    {
//*****************************************
//    Layout = 3;
        Laout2Flag = 0;
        //等待确认
        ModeFlag = 0;

        UI(3, ModeFlag);

        while(!Sure);

        while(Sure)
        {
            if(Up == 0)
            {
                while(!Up);

                ModeFlag++;
            }

            if(Down == 0)
            {
                while(!Down);

                ModeFlag--;
            }

            if(Back == 0)
            {
                while(!Back);

                goto Layout2;
            }

            if(ModeFlag == 3)
            {
                ModeFlag = 0;
            }

            if(ModeFlag == 255)
            {
                ModeFlag = 2;
            }

            UI(3, ModeFlag);
        }

        //储存角度
        switch(ModeFlag)
        {
            case 0:
            {
                Laout4FlagA = 1;
                Laout4FlagB = 0;
                Laout4FlagC = 0;
            }
            break;

            case 1:
            {
                Laout4FlagA = 0;
                Laout4FlagB = 1;
                Laout4FlagC = 0;
            }
            break;

            case 2:
            {
                Laout4FlagA = 0;
                Laout4FlagB = 0;
                Laout4FlagC = 1;
            }
            break;
        }
    }
Layout4:
    {
//*****************************************
//    Layout = 4;
        Laout2Flag = 0;
        //等待确认
        ModeFlag = 0;

        UI(4, ModeFlag);

        while(!Sure);

        while(Sure)
        {
            if(Up == 0)
            {
                while(!Up);

                ModeFlag++;
            }

            if(Down == 0)
            {
                while(!Down);

                ModeFlag--;
            }

            if(Back == 0)
            {
                while(!Back);

                goto Layout3;
            }

            if(ModeFlag == 3)
            {
                ModeFlag = 0;
            }

            if(ModeFlag == 255)
            {
                ModeFlag = 2;
            }

            UI(4, ModeFlag);
        }

        //储存角度
        switch(ModeFlag)
        {
            case 0:
            {
                Laout5FlagA = 1;
                Laout5FlagB = 0;
                Laout5FlagC = 0;
            }
            break;

            case 1:
            {
                Laout5FlagA = 0;
                Laout5FlagB = 1;
                Laout5FlagC = 0;
            }
            break;

            case 2:
            {
                Laout5FlagA = 0;
                Laout5FlagB = 0;
                Laout5FlagC = 1;
            }
            break;
        }

    }
Layout5:
    {
//*****************************************
//    Layout = 5;
        Laout2Flag = 0;
        StartFlag = 0;
        //等待确认
        ModeFlag = 0;


        UI(5, ModeFlag);


        while(Start)
        {

            if(Back == 0)
            {
                while(!Back);

                goto Layout4;
            }
        }

        while(!Start);

        StartFlag = 1;

        UI(5, ModeFlag);
    }

//*****************************************

    while(1)
    {
        if(!Back)
        {
            while(!Back);

            goto Layout5;
        }

        if(!Start)
        {
            while(!Start);

            goto Layout5;
        }

Motor:



        Mode = Angle = Speed = 0;
        {
            if(Laout3FlagA)
                Mode = 1;

            if(Laout3FlagB)
                Mode = 2;

            if(Laout3FlagC)
                Mode = 3;

            //
            if(Laout4FlagA)
                Angle = 64;

            if(Laout4FlagB)
                Angle = 128;

            if(Laout4FlagC)
                Angle = 255;

            //
            if(Laout5FlagA)
                Speed  = 15;

            if(Laout5FlagB)
                Speed  = 10;

            if(Laout5FlagC)
                Speed  = 1;

            while(Start || Back)
            {
                if(!Back)
                {
                    while(!Back);

                    goto Layout4;
                }

                //step_motor_28BYJ48_send_pulse(Buff1++, Buff2 );

                if(Mode == 1)
                {
                    Buff2 = 0;
                }

                if(Mode == 2)
                {
                    Buff2 = 1;
                }

                if(Mode == 3)
                {
                    if(Buff1 == Angle)
                    {
                        Buff2 = !Buff2;
                        Buff1 = 0;
                    }
                }

                if(Angle == Buff1)
                {
                    Buff1 = 0;
                    goto Layout5;
                }

                if(Angle == 255)
                {
                    while(Sure)
                    {
                        if(!Start)
                        {
                            while(!Start);

                            break;
                        }

                        if(!Back)
                        {
                            while(!Back);

                            goto Layout4;
                        }
                    }
                }

                if(Buff3 == 8)
                {
                    Buff3 = 0;
                    Buff1++;
                }

                step_motor_28BYJ48_send_pulse(Buff3++, Buff2 );

                if(delay_ms(Speed, 2) == 2)
                {
                    while(!Start);

                    while(!Back);

                    goto Layout5;
                }

//                switch(delay_ms(Speed, 2)){
//                    case 2:
//                    {
//                        while(!Start);
//                        goto Motor;
//                    }break;
//                    case 3:
//                    {
//                        while(!Back);
//                        goto Layout5;
//                    }break;
//                }
            }
        }

    }
}

使用说明:

该代码为屎山代码,不保证移植能用,主函数与28BYJ48.C关联密切,其中按键未使用中断也能够快速跳出死循环代码段,具体实现详情看代码。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值