蓝牙遥控小车

功能简介

通过蓝牙发送命令控制小车移动

代码


#include<reg52.h>
#include<intrins.h>
#include<math.h>		//内涵abs函数
#include<string.h>
#define uchar unsigned char
#define uint unsigned int
#define FOSC 11059200     //System frequency
#define BAUD 9600       //UART baudrate
#define P_OUT P1

bit flag_execute = 0;
bit flag_TRX = 0;
bit flag_A5 = 1;

uint HighTimer0Value = 10000;//定时器T0高电平预装值
uint LowTimer0Value = 10000;//定时器T0低电平预装值
uint HighTimer1Value = 10000;//定时器T2高电平预装值
uint LowTimer1Value = 10000;//定时器T2低电平预装值
static uchar Receive[7]=0,Transmit[7]="0000000";
							//		 0.........包头
							//	      123......数据位
							//		   	 4.....状态位
							//			  5....校验位
							//			   6...尾字节
							//			

//把字符串赋值给数组时会在数组末尾加一个空字符\0
//单独定义数组时不会在末尾加入空字符
								  //0123456789
//四个轮子的速度(PWM占空比),范围1~99
char RightFrontSpeed = 20;
char LeftFrontSpeed = 20;
//uchar RightBackSpeed = 20;
//uchar LeftBackSpeed = 20;	  



//--定义使用的IO口--//

sbit RightFrontPwm = P1^6;  
sbit RightFrontDir = P1^7;  
sbit LeftFrontPwm = P1^0;  
sbit LeftFrontDir = P1^1; 
sbit RightBackPwm = P1^4;  
sbit RightBackDir = P1^5;  
sbit LeftBackPwm = P1^2;  
sbit LeftBackDir = P1^3; 


void CtrlSpeed();

char receive(char *s,char num);
void send(char *s,char num);
char analysis(char *R,char *T);
void Init_Uart(void);
void execute(void);
void CountDutyCycle(bit dir);


void main()
{
	Init_Uart();
	//T0用作PWM发生器0
	TMOD &= 0xF0;
	TMOD |= 0x01;
	TH0=(uchar)(HighTimer0Value>>8);
	TL0=(uchar)HighTimer0Value;
	ET0 = 0;	//关闭T0中断
    //T1用作PWM发生器1
	TMOD &= 0x0F;
	TMOD |= 0x10;
	TH1=(uchar)(HighTimer1Value>>8);
	TL1=(uchar)HighTimer1Value;
	ET1 = 0;	 //关闭T1中断
	PCON = 0X00;		//SMOD=0
	TR1 = 1;			//T1计时器开启
	TR0 = 1;			//T0计时器开启	
	EA = 1;


	while(1)
	{
		if (flag_execute) //如果执行标识开启
		{
			execute();  //对命令进行执行
			flag_execute = 0;	//清除标志位
		}
	}

}
//初始化串口
void Init_Uart(void)
{
	//T2用于波特率 9600
	T2CON = 0x34;
	TL2 = RCAP2L =(65536-(FOSC/32/BAUD)); //Set auto-reload vaule
  	TH2 = RCAP2H =(65536-(FOSC/32/BAUD)) >> 8;
	TH2 = 0xFF;
	TL2 = 0xC3;
	TR2 = 1;
	SCON = 0x50;
	ES = 1;
}


void T0_Interrupt()		interrupt 1		//生成PWM波
{
	if(RightFrontPwm==0)
	{
		TH0=(uchar)(HighTimer0Value>>8);
		TL0=(uchar)HighTimer0Value;
		RightFrontPwm = 1;
		RightBackPwm = 1;
	}
	else if(RightFrontPwm==1)
	{
		TH0=(uchar)(LowTimer0Value>>8);
		TL0=(uchar)LowTimer0Value;
		RightFrontPwm = 0;
		RightBackPwm = 0;
	}
}
void T1_Interrupt()		interrupt 3		//生成PWM波
{

	if(LeftFrontPwm==0)
	{
		TH1=(uchar)(HighTimer1Value>>8);
		TL1=(uchar)HighTimer1Value;
		LeftFrontPwm = 1;
		LeftBackPwm = 1;
	}
	else if(LeftFrontPwm==1)
	{
		TH1=(uchar)(LowTimer1Value>>8);
		TL1=(uchar)LowTimer1Value;
		LeftFrontPwm = 0;
		LeftBackPwm = 0;
	}
}


//命令执行函数,配置dir口方向,并调用占空比计算函数
void execute(void)
{
	bit flag_dir;		//flag_move;
	char y_spd = Receive[1];
	if(y_spd==0)
	{
		P_OUT = 0XFF;	//停止
//		flag_move = 0;
		ET0 = 0;
		ET1 = 0;	  //关闭中断,禁止修改P1口
	}
	else
	{
//		flag_move = 1;
		if(y_spd>0)
		{
			P_OUT = 0X00;	//前进
			flag_dir = 0;
		}
		else if(y_spd<0)
		{
			P_OUT = 0XFF;	//后退
			flag_dir = 1;
		}
		CountDutyCycle(flag_dir); //计算占空比,重载预装值
	} 

}
//占空比计算函数,并调用了预装值重载函数
void CountDutyCycle(bit dir)
{
	char y_spd = Receive[1];	//前进分量,提供前进程度(-99~99)
	char x_tur = Receive[2];	//转向分量,提供转向程度(-99~99)
	char speed = Receive[3];	//基础速度,提供基础占空比(1~99)

	speed = speed*abs(y_spd)/100;	//为speed加入前进分量

	RightFrontSpeed = speed;
	LeftFrontSpeed = speed;	
	
	if(x_tur > 0)	//向右转向
	{
		RightFrontSpeed = RightFrontSpeed*(100-abs(x_tur))/100;
	}
	else if(x_tur<0)	//向左转向		
	{	
		LeftFrontSpeed = RightFrontSpeed*(100-abs(x_tur))/100;
	}

	if(dir==1)		//后退则占空比取反
	{
		RightFrontSpeed = 100-RightFrontSpeed;
		LeftFrontSpeed = 100-LeftFrontSpeed;				
	}
	CtrlSpeed();
}

//控制小车速度的函数
//(通过控制定时器预装值,控制PWM的占空比)
//(无法控制PWM引脚的电平和T0计时器的开关)
void CtrlSpeed()
{
	static uint freq = 100;	  	//PWM频率为100Hz

	HighTimer0Value=65535 - 11059200/12/freq*RightFrontSpeed/100;
	LowTimer0Value=65535 - 11059200/12/freq*(100-RightFrontSpeed)/100;
	HighTimer1Value=65535 - 11059200/12/freq*LeftFrontSpeed/100;
	LowTimer1Value=65535 - 11059200/12/freq*(100-LeftFrontSpeed)/100;
	ET0 = 1;
	ET1 = 1;
}
void Bluetooth() interrupt 4	
{


	if(RI)				 //接收后服务程序
	{		
	 	RI = 0;

		if(receive(Receive,7))	//接收完一组数据
		{	
		 	if(analysis(Receive,Transmit))//对接收数据进行分析并写入发送数组
			{		
				flag_execute = 1;//插个旗,到主函数去执行算法							
				
			}
			flag_TRX = 1;
			TI = 1;	//发送数组Transmit	
		}
    }
	if(TI)				//发送后服务程序
	{	
		TI = 0;
		if(flag_TRX)
			send(Transmit,7);
	}
}
//接收数据分析函数,判断接收数据是否合法
//如果合法则将数据赋给发送数组,并在发送数组末尾写66
//如果有不合法数据,则将0赋给发送数组,并在发送数组末尾写0
//参数:接收数组,发送数组
//返回:0:有非法数据   1:无非法数据
char analysis(char *R,char *T) 
{
	char i,j,check;
	bit flag = 0;
	for(i=0;i<7;i++)  //第七位是空字符	
	{
		if((i==0)|(i==6))
		{
		   *(T+i)=*(R+i);  //复制包头 包尾
		}
		else if(i<4)		 //3位数据位
		{
			*(T+i)=*(R+i); 
			if((*(R+i)<-99)&(*(R+i)>99))	  //读取Y轴速度/x轴差速
			{
				 flag = 1;	//错误标志	//Y轴速度/x轴差速正常,无动作
			}
		}
		else if(i==4)  //1 位状态位
		{
			if(flag==0)
			{
				*(T+i) = 1;	
			}
			else
			{
				*(T+i) = 0;
			}
		}
		else if(i==5)	//1位校验位
		{
			check=0;
			for(j=1;j<i;j++)
				check+=*(T+j);	
			*(T+i)=check;
		}

	}
	if(flag==0)
		return 1;
	else
		flag=0;	
	return 0;

}
//串口接收函数
//参数:
//地址S,选择接收数组的首地址
//长度L,选择一次接收的字节个数
//返回值:
//未接收到足够的字节,返回0
//已接收到足够的字节,返回1
char receive(char *s,char num)
{
	static char i=0;


	*(s+i)=SBUF;	//此处应添加包头检测语句
		i++;

	if(i==num)
	{
		i=0;
		flag_A5 = 0;
		return 1;
	}
	else
	return 0;
}
//串口发送函数
//参数:
//地址S,选择要发送数组的首地址
void send(char *s,char num)	
{
	static char i=0;
	if(i<num)
	{
		SBUF=*(s+i);
		i++;
	}
	else 	   //当一个字符串发送完毕后会进入这里
	{
		flag_TRX = 0;
		i=0;
	}			 	
}



实物

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值