硬件驱动

  • 初始化
    拿到蓝牙模块先将其串口与电脑连接,波特率一般默认为9600,由于我用的是12M的晶阵,产生9600的波特率精度不行所以用4800的波特率。通过电脑串口调式助手发送AT指令修改蓝牙模块的波特率为4800,这些指令在资料里应该都有。(指令之后还有个回车)
AT+BAUD3
  • 然后接贴下面代码烧到单片机上去观察相应输出IO的电平看是否正确完事,再按照备注上的说明搭建小车就完美执行(电机驱动用的L289N)
#include "reg52.h"			 
#include<intrins.h>

//控制四轮的小车IO
#define control P0

typedef unsigned int u16;
typedef unsigned char u8;

//车灯控制,为0时亮
sbit LED = P2^4;

//电机驱动使能控制IO
//前面(俯视)
//motor1   motor2
//motor3   motor4

//control  11 11 11 11
//         m1 m2 m3 m4
//所有的都是01向前,10向后
sbit motor1=P2^0;
sbit motor2=P2^1;
sbit motor3=P2^2;
sbit motor4=P2^3;



//保存串口接收到的数据
u8 recv[50];
u8 count=0,length=0;

//速度调节
u16 time=0;
u16 speed=50;

//小车状态
u8 state=4;

//延迟10us
void delay(u16 i)	
{
	while(i--);	
}




//初始化
void init()
{
	//发送AT指令初始化蓝牙模块和客户端对应,客户端的UUID就是这个,还有蓝牙的名称为hardy
	char *a="at+namehardy\r\n";
   char *b="at+UUID0xFFE0\r\n";
	char *c="at+char0xFFE1\r\n";
	TMOD = 0x21;	  //T1工作方式2,T0工作方式2
	//设置波特率为4800
	SCON = 0x50;
	PCON = 0X80;	//波特率加倍
	TL1 = 0XF3;
	TH1 = 0XF3;	
	TR1 = 1;   //打开定时器

	//T0定时器初始化  100us
	TH0 = 0x0FF;
    TL0 = 0x0A4;
    ET0 = 1;
    TR0 = 1;
	
	IT0=1;	//设置外部中断0的触发方式为下降沿
	EX0=1;	//开启外部中断0

	EA = 1;	 //允许总中断
	ES = 0;  
	delay(50000);  //适当延迟给模块反应时间
    while(*a!='\0')
    {
        SBUF=*a;   
        while(!TI);  
        TI=0;        
        a++;
    }
	delay(50000);
    while(*b!='\0')
    {
		SBUF=*b;  
        while(!TI);  
        TI=0;
        b++;
    }
	delay(50000);
    while(*c!='\0')
    {
		SBUF=*c;  
        while(!TI);
        TI=0;
        c++;
    }
	ES = 1;
}


//输出PWM控制车速
void PWM(){
	if(time>100)  //PWM周期为100*100us
		{
			time=0;
		}
	if(time <speed)	  
		{
			motor1=1;
			motor2=1;
			motor3=1;
			motor4=1;
		}
	else
		{
			motor1=0;
			motor2=0;
			motor3=0;
			motor4=0;
	 	}

}


//通过串口发送字符串,发送到手机客户端用于提示
void send(char *str)  
{                
    ES=0;  //发送时先将串口接收中断关掉发送完成再打开
     while(*str!='\0') 
    {                      
        SBUF=*str;
        while(!TI);
        TI=0;    
        str++;
    }
    ES=1; 
}

//获取速度用以传入客户端显示
char* getspeed(){
	if(speed<20){
		return (char*)"speed:1";
	}
	if(speed>=20&&speed<40){
		return (char*)"speed:2";
	}
	if(speed>=40&&speed<60){
		return (char*)"speed:3";
	}
	if(speed>=60&&speed<80){
		return (char*)"speed:4";
	}
	if(speed>=80){
		return (char*)"speed:5";
	}
	return "error";
}

//获取小车状态用以传入客户端显示
char* getstate(){
	if(state==0){
		return (char*)"go";
	}
	if(state==1){
		return (char*)"back";
	}
	if(state==2){
		return (char*)"trun left";
	}
	if(state==3){
		return (char*)"trun right";
	}
	if(state==4){
		return (char*)"stop";
	}
	if(state==5){
		return (char*)"speed:5";
	}
	if(state==6){
		return (char*)"speed:5";
	}
	return "error";
}


//前进
void forword(){
	motor1=1;
	motor2=1;
	motor3=1;
	motor4=1;
	//对应01010101
	control=0x55;
	state = 0;
	send(getstate());
}
//后退
void back(){
	motor1=1;
	motor2=1;
	motor3=1;
	motor4=1;
	//对应10101010
	control=0xAA;
	state = 1;
	send(getstate());
}
//左转
void trunLeft(){
	//只有电机2前进,其他停止
	motor1=0;
	motor2=1;
	motor3=0;
	motor4=1;
	//对应xx01xxxx
	control=0x55;
	state = 2;
	send(getstate());
}
//右转
void trunRight(){
	//只有电机1前进,其他停止
	motor1=1;
	motor2=0;
	motor3=3;
	motor4=0;
	//对应01xxxxxx
	control=0x55;
	state = 3;
	send(getstate());
}
//停止
void stop(){
	 //全部电机使能停止
	motor1=0;
	motor2=0;
	motor3=0;
	motor4=0;
	state = 4;
	LED=1;
	send(getstate());
}
//开灯
void trunOnLight(){
	char *error = "light on";
	send(error);
	LED = 0;
	_nop_(); 
	_nop_(); 
	_nop_();
	LED = 1; 
}
//加速
void acce(){
	if(speed<100){
		speed = speed+10;
	}
	send(getspeed());
}
//减速
void slow(){
	if(speed>0){
		speed = speed-10;
	}
	send(getspeed());
}
//其他
void other(){
	char *error = "error";
	send(error);
}

void main()
{	
	init();
	 //初始化全部电机使能停止
	motor1=0;
	motor2=0;
	motor3=0;
	motor4=0;
	control=0xff;
	LED = 1;
	P1=0xFF;
	while(1)
	{
		//客户端发出指令
		if(length != 0){
			switch(recv[0]){
				//前进指令
				case 'f': forword();break;
				//后退指令
				case 'b': back();break;
				//左转指令
				case 'l': trunLeft();break;
				//右转指令
				case 'r': trunRight();break;
				//停止指令
				case 's': stop();break;
				//开灯指令
				case 'o':trunOnLight();break;
				//加速指令
				case 'c':acce();break;
				//减速指令
				case 'w':slow();break;
				//未知指令
				default:other(); break;
			}
			length=0;
		}
		//如果前进或者后退则speed速度有效,转弯全速
		if(state==0||state==1){
			PWM();
		}
	}		
}


//外部中断0触发时,读取P0中的控制数据
//这个用于另外单片机互动的,由于这个单片机只有两个定时器用完了,超声波模块需要用没有了
void ex0() interrupt 0 
{
	//外部信号拉低,对电机进行控制
	if(P1 != 0xFF){
		if(P1 == 0xFE){
			forword();
		}
		if(P1 == 0xFD){
			back();
		}
		if(P1 == 0xFB){
			trunLeft();
		}
		if(P1 == 0xF7){
			trunRight();
		}
		if(P1 == 0xEF){
			stop();
		}
		P1 = 0xFF;	
	}
}

//计数做PWM的产生
void Time0(void) interrupt 1   
{
	TH0 = 0x0FF;
    TL0 = 0x0A4;
	time++; 
}

//串口接收中断接收蓝牙模块发来的数据
void rev() interrupt 4
{
	//接收数据并且手动清空标志位
	char res;
	res=SBUF;
	RI = 0;
	//将字符串在符号$和符号#之间的保存到数组中 ,并记录长度,用$#两个符号包围数据防止干扰这里接收到的是数据的ASCII,比如客户端发送$过来接收到的ASCII码是35
	if(res == 35){
		length=count;
		count = 0;
	}
	else{
		if(res == 36){
			length=0;
			count = 0;
		}
		else{
			recv[count]=res;
			count++;
		}
	}
}

手机客户端——微信小程序

  • 客户端需要很麻烦的蓝牙连接过程,已经全部写好了直接调用接收和发送函数就可以了。代码上千行就不帖了,Gitee地址https://gitee.com/eedui/xiaoche