基于51单片机下通过蓝牙串口控制LCD1602屏幕显示步进电机正反转以及转速

通过蓝牙串口控制LCD1602屏幕显示正反转以及转速

简 述:

  • 通过蓝牙串口发送指定数据到STC89C52RC单片机,控制28BYJ-48步进电机正转或者反转或者速度的快中慢,然后51单片机,
    做相应的判断,在LCD1602屏幕上显示正反转状态 以及 转速

  • 演示视频放在了哔哩哔哩上: https://www.bilibili.com/video/av61543899

  • 完整程序的已经放在了文末

二.准备
1. 单片机 :个人嫌麻烦用的开发板,可以使用STM32或者其他类型;
2.	24BYJ-48步进电机:
			该步进电机为4相5线式
4.	LCD1602	有条件可以试试OLED12864之类
5.	HC-05	蓝牙模块

步进电机
LCD1602
蓝牙模块

三. 原理图

【还没画完,半成品,最近要忙着准备2019年的电赛了,所有顾不上但大概的东西都在这儿了】

原理图

四. 程序

1.说明
  • 已经将程序整体工程化,方便移植,比如STM32,STM8等单片机上
  • 思路:
    • 1.蓝牙串口发送特定字符给51单片机
    • 2.单片机接收到消息触发串口中断,进入串口中断服务函数
      注意服务函数不要写过多,中断服务函数应该尽量简短,一般是做一些标识,不要在中断中做延时之类的
      占用CPU很长时间的工作。----快进快出
    • 3.中断函数制作判断标志位,然后给到其他函数去做具体事例
    • 4.主函数中判断并做出相应的动作和屏幕显示
  • 有个问题:主函数判断不知道为什么不能用switch,无法判断出来,希望看完知道的大佬指教下!
2. LCD1602显示程序(lcd.c)
#include "lcd.h"
sbit E = P2 ^ 7;		//1602使能引脚
sbit RW = P2 ^ 6;		//1602读写引脚
sbit RS = P2 ^ 5;		//1602数据/命令选择引脚

/********************************************************************
* 名称 : bit Busy(void)
* 功能 : 这个是一个读状态函数,读出函数是否处在忙状态
* 输入 : 输入的命令值
* 输出 : 无
***********************************************************************/
bit Busy(void)
{
    bit busy_flag = 0;
    RS = 0;
    RW = 1;
    E = 1;
    delay3();
    busy_flag = (bit)(P0 & 0x80);
    E = 0;
    return busy_flag;
}


/********************************************************************
* 名称 : wcmd(uchar del)
* 功能 : 1602命令函数
* 输入 : 输入的命令值
* 输出 : 无
***********************************************************************/
void wcmd(uchar del)
{
    while(Busy());
    RS = 0;
    RW = 0;
    E = 0;
    delay3();
    P0 = del;
    delay3();
    E = 1;
    delay3();
    E = 0;
}

/********************************************************************
* 名称 : wdata(uchar del)
* 功能 : 1602写数据函数
* 输入 : 需要写入1602的数据
* 输出 : 无
***********************************************************************/

void wdata(uchar del)
{
    while(Busy());
    RS = 1;
    RW = 0;
    E = 0;
    delay3();
    P0 = del;
    delay3();
    E = 1;
    delay3();
    E = 0;
}


/********************************************************************
* 名称 : L1602_init()
* 功能 : 1602初始化,请参考1602的资料
* 输入 : 无
* 输出 : 无
***********************************************************************/
void L1602_init(void)
{
    wcmd(0x38);
    Delay(5);
    wcmd(0x38);
    Delay(5);
    wcmd(0x38);
    Delay(5);
    wcmd(0x38);
    wcmd(0x08);
    wcmd(0x0c);
    wcmd(0x04);
    wcmd(0x01);
}


//不用注释掉,防止报错未调用该函数  此处代码中未用到所以注释了
///********************************************************************
//* 名称 : L1602_char(uchar hang,uchar lie,char sign)
//* 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符显示"b" ,调用该函数如下
//		 L1602_char(1,5,'b')
//* 输入 : 行,列,需要输入1602的数据
//* 输出 : 无
//***********************************************************************/
//void L1602_char(uchar hang, uchar lie, char sign)
//{
//    uchar a;
//    if(hang == 1) a = 0x80;
//    if(hang == 2) a = 0xc0;
//    a = a + lie - 1;
//    wcmd(a);
//    wdata(sign);
//}


/********************************************************************
* 名称 : L1602_string(uchar hang,uchar lie,uchar *p)
* 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下
	 	 L1602_string(1,5,"ab cd ef;")
* 输入 : 行,列,需要输入1602的数据
* 输出 : 无
***********************************************************************/
void L1602_string(uchar hang, uchar lie, uchar *p)
{
    uchar a, b = 0;
    if(hang == 1) a = 0x80;
    if(hang == 2) a = 0xc0;
    a = a + lie - 1;
    while(1)
    {
        wcmd(a++);
        if((*p == '\0') || (b == 16)) break;
        b++;
        wdata(*p);
        p++;
    }
}

3.控制步进电机正反转(motor.c)
#include "motor.h"

int forward(uchar speed)		//控制正转
{
    uchar i;
    for(i = 0; i < 8; i++)
    {
        P1 = F_Rotation[i];		//顺时针转动
        Delay(speed);					//改变转速
    }
		return speed;
}


int back(uchar speed)		//控制反转
{
    uchar i;
    for(i = 0; i < 8; i++)
    {
        P1 = B_Rotation[i];	 //逆时针转动
        Delay(speed);							//改变转速
    }
			return speed;
}
4.开启串口定时器,且设置波特率为9600(Uart.c)
#include "Uart.h"

void UartInit()		//[email protected]
{
    SCON = 0x50; // SCON: 模式1, 8-bit UART, 使能接收
    TMOD |= 0x20;
    TH1 = 0xfd; //波特率9600 初值
    TL1 = 0xfd;
    TR1 = 1;
    EA = 1; //打开总中断
    ES = 1; //打开串口中断
}
5.main.c
#include "123.h"

main()
{
	L1602_init();
    Delay(100);
    UartInit();
    while(1)
    {
    	panduan();
    }
}

void panduan()
{
	if(flag == 0)		//判断正转
	{
		led = 0;	//状态灯灭
					
		forward(speed);		//电机执行正转且返回速度送给下面进行判断
					
		if(speed == 1)			//如果为1	则速度显示为快速
		{
			LCD_display("Mo Dir: Goto","Mo Spd: Fast ^_^");
		}
					
		else if(speed == 3)		//如果为3	则速度显示为中速
		{
			LCD_display("Mo Dir: Goto","Mo Spd: Norl ^_^");
		}
					
		else if(speed == 5)		//如果为5	则速度显示为慢速
		{
			LCD_display("Mo Dir: Goto","Mo Spd: Slow ^_^");
		}
	}


	if(flag == 1)			//判断反转
	{
  	  led = 1;			//状态灯亮
          
		back(speed);
		  
		if(speed == 1)			//电机执行正转且返回速度送给下面进行判断
		{
			LCD_display("Mo Dir: Back","Mo Spd: Fast ^_^");
		}
		else if(speed == 3)
		{
		 	LCD_display("Mo Dir: Back","Mo Spd: Norl ^_^");
		}
		else if(speed == 5)
		{
		 	LCD_display("Mo Dir: Back","Mo Spd: Slow ^_^");
		}
	}
}

void Usart() interrupt 4			//中断服务函数
{
    uchar n; //定义临时变量
//	led = 1;
    if(RI) //判断是接收中断产生
    {
        RI = 0; //标志位清零
        n = SBUF; //读入缓冲区的值
        switch(n)
        {
        case'0':		//控制正转
        	flag = 0;
        break;
				
        case'1':		//控制反转
        	flag = 1;
        break;
				
		case'2':		//控制速度为慢
			speed = 5;
		break;
				
		case'3':		//控制速度为中等
			speed = 3;
		break;
				
		case'4':		//控制速度为快
			speed = 1;
		break;
				
        }
        TI = 1;
        SBUF = n; //把接收到的值再发回
    }
   		if(TI) //如果是发送标志位,清零
        TI = 0;
}

五.源代码

完整程序的已经放在了github上:https://github.com/Long1373766226/LCD1602-display-in-the-motor

发布了13 篇原创文章 · 获赞 8 · 访问量 1724

猜你喜欢

转载自blog.csdn.net/qq_30722795/article/details/97822456