初学C51时,制作的蓝牙控制寻迹避障跟踪小车

小车制作时间2019年10月,当时我刚刚开始接触51单片机,参加了学校的电子设计比赛,我主要负责代码书写,刚刚开始学51的我,制作一个小车还是很有难度。现在把当时的代码分享到博客上希望对学习者有所帮助。

一、难点

1.51单片机的定时器只有两个,用51写蓝牙控制的循迹避障小车中,蓝牙、超声波避障、PWM调制都需要定时器,这样定时器是不够使用的,当时我在这里纠结了很久,最后避障有红外做的。
2.当时用51单片机书写这种功能的成熟代码,没有好的参考。

二、小车代码

1.程序

/*

功能:寻迹,跟踪,避障,由蓝牙控制
1).寻迹:在正常轨迹上时,前进;单边出线时,调整;双边出线时,停止
2).跟踪:跟着白色物体走
3).避障:躲避障碍物
4).调速:P2^5控制加速,P2^0控制减速
注:相关引脚定义,见小车头文件

*/
#include <reg52.h>    //51头文件
#include <CAR51.h>    //小车头文件

//宏定义常量
#define ZKB_left  69   //左轮占空比定义0~255
#define ZKB_right 64   //右轮占空比定义0~255
#define ZKB_max   255  //占空比最大值
//#define GaoSu     70
//#define DiSu      54

//PWM左右占空比等相关定义
uchar pwm_t;                    //pwm周期
uchar push_left = ZKB_left;     //左轮占空比赋值
uchar push_right = ZKB_right;   //右轮占空比赋值
uchar push_max = ZKB_max;       //占空比最大值, 此时速度最慢

uchar flag = 's';               //功能切换标志
uchar flag1 = '0';              //持续返回标志
uint  flag_a = 0;
uint  flag2 = 0;

void Tinit();               //定时器初始化
void XunJi();               //红外寻迹
void XunJi_l();             //左转寻迹
void XunJi_r();             //右转寻迹
void XunJi_A();             //寻迹避人
void GenZong();             //红外跟踪
void Avoid();               //红外避障
void CK_Tinit();            //初始化串口

//主函数
void main()
{
	uchar i;
	stop();                 //保证小车开始处于停止状态
	Tinit();                //定时器初始化
	CK_Tinit();             //初始化串口
	
	while(1)
	{
		//TiaoSu();
		flag  = SBUF;
		RI = 0;
		switch(flag)
		{	
			case 'f': forward();    flag = 'f'; break; //前进
			case 'b': backward();   flag = 'b'; break; //后退
			case 'l': left_run();   flag = 'l'; break; //左转
			case 'r': right_run();  flag = 'r'; break; //右转
			case 's': stop();       flag = 's'; break; //停止
			case 'x': XunJi();      flag = 'x'; break; //循迹	
			case 'y': XunJi_A();    flag = 'y'; break; //循迹避障          
			case 'g': GenZong();    flag = 'g'; break; //跟踪
			case 'a': Avoid();      flag = 'a'; break; //避障
			default:                flag = 's'; 
		}
		//返回数据,表示串口正常运行
		if(flag != flag1)
			for(i = 0; i < 36; i++)
			{
				SBUF = flag;   
				while(!TI); 
				flag1 = flag;         
				TI = 0;			
			}
		flag2 = 0;
	}
}


//寻迹
void XunJi()
{
	//左右红外探头必须大于等于黑线长度
	if(left_led1 == 0 && right_led1 == 0)  //左右寻迹探头识别到白线
		forward();                         //前进
	if(left_led1 == 1 && right_led1 == 0)  //小车右边出线,左转修正
		left_run();                        //左转
	if(left_led1 == 0 && right_led1 == 1)  //小车左边出线,右转修正
		right_run();                       //右转
	if(left_led1 == 1 && right_led1 == 1)  //左右寻迹探头识别到黑线
	{
		left_run();
		delay(17);
		if(left_led1 == 0 && right_led1 == 0)  //左右寻迹探头识别到白线
			forward();                         //前进
		else
			right_run();                        //左转
	}
	//push_left = ZKB_left;     //左轮占空比赋值
	//push_right = ZKB_right;    //右轮占空比赋值	
}


//寻迹避人
void XunJi_A()
{
	//左右红外探头必须大于等于黑线长度
	if(left_led1 == 0 && right_led1 == 0)  //左右寻迹探头识别到白线
    {
        if((left_led2 == 0) || (mid_led2 == 0) || (right_led2 == 0))
        {    
            backward();
            delay(20);
            stop();
            delay(20);
        }
        else
            forward();                     //前进
    }        
	if(left_led1 == 1 && right_led1 == 0)  //小车右边出线,左转修正
    {
        if((left_led2 == 0) || (mid_led2 == 0) || (right_led2 == 0))
        {    
            backward();
            delay(20);
            stop();
            delay(20);
        }  
        else
            left_run();                        //左转
    }
	if(left_led1 == 0 && right_led1 == 1)  //小车左边出线,右转修正
    {
        if((left_led2 == 0) || (mid_led2 == 0) || (right_led2 == 0))
        {    
            backward();
            delay(20);
            stop();
            delay(20);
        }   
        else
            right_run();                       //右转
    }
	if(left_led1 == 1 && right_led1 == 1)  //左右寻迹探头识别到黑线
		stop();

}


//红外跟踪
void GenZong()
{
	if((left_led2 == 0) && (right_led2 == 0))  //左右寻迹探头识别到白板
		forward();                             //前进
	if((left_led2 == 0) && (right_led2 == 1))  //小车右边出轨迹,左转修正
		left_run();                            //左转
	if((left_led2 == 1) && (right_led2 == 0))  //小车左边出轨迹,右转修正
		right_run();                           //右转
	if((left_led2 == 1) && (right_led2 == 1))  //左右寻迹探头没识别到白板
		stop();                                //停止
	
}

void Avoid()
{
	
	if((left_led2 == 0) && (mid_led2 == 0) && (right_led2 == 0))
	{
		delay(2);
		if((left_led2 == 0) && (mid_led2 == 0) && (right_led2 == 0))
		{
			backward();
			delay(20);	
			left_run();              //左转
			delay(40);
		}
	}
	if((left_led2 == 1) && (mid_led2 == 0) && (right_led2 == 0))
	{
		delay(2);
		if((left_led2 == 1) && (mid_led2 == 0) && (right_led2 == 0))
		{
			backward();
			delay(20);	
			left_run();              //左转
			delay(40);
		}
	}
	if((left_led2 == 0) && (mid_led2 == 0) && (right_led2 == 1))
	{
		delay(2);
		if((left_led2 == 0) && (mid_led2 == 0) && (right_led2 == 1))
		{
			backward();
			delay(20);	
			right_run();              //右转
			delay(40);
		}
	}
	if((left_led2 == 1) && (mid_led2 == 0) && (right_led2 == 1))
	{
		delay(2);
		if((left_led2 == 1) && (mid_led2 == 0) && (right_led2 == 1))
		{
			backward();
			delay(20);	
			right_run();              //右转
			delay(40);
		}
	}
	if((left_led2 == 0) && (mid_led2 == 1) && (right_led2 == 0))  //左右寻迹探头识别到白板
	{
		delay(2);
		if((left_led2 == 0) && (mid_led2 == 1) && (right_led2 == 0))  //左右寻迹探头识别到白板
			backward();
	}
	if((left_led2 == 0) && (mid_led2 == 1) && (right_led2 == 1))  //小车右边出轨迹,左转修正
	{
		delay(2);
		if((left_led2 == 0) && (mid_led2 == 1) && (right_led2 == 1))  //小车右边出轨迹,左转修正
		{
			backward();
			delay(20);	
			right_run();              //右转
			delay(40);
		}
	}
	if((left_led2 == 1) && (mid_led2 == 1) && (right_led2 == 0))  //小车左边出轨迹,右转修正
	{
		delay(2);
		if((left_led2 == 1) && (mid_led2 == 1) && (right_led2 == 0))  //小车左边出轨迹,右转修正
		{
			backward();
			delay(20);	
			left_run();              //左转
			delay(40);
		}
	}
	if((left_led2 == 1) && (mid_led2 == 1) && (right_led2 == 1))  //左右寻迹探头没识别到白板
	{
		delay(2);
		if((left_led2 == 1) && (mid_led2 == 1) && (right_led2 == 1))  //左右寻迹探头没识别到白板
			forward();                                //停止
	}

}



//定时器初始化
void Tinit()
{
	TMOD |= 0x01;   //8位自动重装模块
	TH0 = 0xff;
	TL0 = 0xff;     //1us定时
    TR0 = 1;
    ET0 = 1;
	EA = 1;         //开总中断
}

//初始化串口
void CK_Tinit()
{        
	SCON = 0X50;                        
	TMOD |= 0X20;                        
	PCON = 0X80;                        
	TH1 = 0Xfa;                  
	TL1 = 0Xfa;
	TR1 = 1;
	REN = 1;
	SM0 = 0;
	SM1 = 1;
	ES = 1;         
	EA = 1;      
}

/******************pwm控制start******************/

//控制pwm的中断函数
void timer0() interrupt 1
{
	TH0 = 0xff;
	TL0 = 0xff;     //1us定时
	pwm_t++;
	if(pwm_t == push_max)
		pwm_t = 0;
	if(push_left > pwm_t)
		ENB = 1;
	else
		ENB = 0;
	if(push_right > pwm_t)
		ENA = 1;
	else
		ENA = 0;

}

/*******************pwm控制end*******************/

/*

void TiaoSu()
{
	if(key_s1 == 0)         //实时检测S1按键是否被按下
	{
		stop();
		delay(3);           //软件消抖
		if(key_s1 == 0)     //再检测S1是否被按下
		{
			stop();
			flag2 = 1;
			while(!key_s1); //松手检测
		}
	}
	if(key_s2 == 0)         //实时检测S1按键是否被按下
	{
		stop();
		delay(3);           //软件消抖
		if(key_s2 == 0)     //再检测S1是否被按下
		{
			stop();
			flag = 2;
			while(!key_s2); //松手检测
		}
	}
	switch(flag2)
	{
		case 1: push_right += 10; push_left += 10;   break;
		case 2: push_right -= 10; push_left -= 10; break;
		default: stop();
	}
}

*/

2.头文件CAR51.h

#ifndef __CAR51_H__
#define __CAR51_H__

//L298N定义
sbit ENA = P1^2;//右电机使能
sbit IN1 = P1^3;//为1,右轮反转
sbit IN2 = P1^4;//为1,右轮正转
sbit IN3 = P1^5;//为1,左轮反转
sbit IN4 = P1^6;//为1,左轮正转
sbit ENB = P1^7;//左电机使能

//寻迹信号定义
sbit left_led1 = P3^2; //左寻迹信号 为0 没有识别到黑线 为1识别到黑线
sbit right_led1 = P3^3;//右寻迹信号	为0 没有识别到黑线 为1识别到黑线

//跟踪寻迹信号定义
sbit left_led2 = P3^4; //左跟踪寻迹信号 为0 跟踪
sbit right_led2 = P3^5;//右跟踪寻迹信号	为0 跟踪
sbit mid_led2 = P2^2;  //中间避障信号

//按键定义
sbit key_s1 = P2^5;
sbit key_s2 = P2^0;

//小车车轮正反转定义
#define right_f IN1 = 0;IN2 = 1//右轮正转
#define right_b IN1 = 1;IN2 = 0//右轮反转
#define right_s IN1 = 0;IN2 = 0//右轮停止
#define left_f  IN3 = 0;IN4 = 1//左轮正转
#define left_b  IN3 = 1;IN4 = 0//左轮反转
#define left_s  IN3 = 0;IN4 = 0//左轮停止

//毫秒延时函数xms
void delay(uint xms)
{
	uint x, y;
	for(x = xms; x > 0; x--)
		for(y = 111; y > 0 ; y--);
}

/******************小车运动情况start******************/
///*
//小车前进
void forward()
{
	left_f;
	right_f;
}

//小车后退
void backward()
{
	left_b;
	right_b;
}

//小车左转
void left_run()
{	
	right_f;
	left_b;
}

//小车右转
void right_run()
{
	right_b;
	left_f;
}
//*/
//小车停止
void stop()
{
	left_s;
	right_s;
}

/*******************小车运动情况end*******************/


#endif

三、启示

当时写程序没考虑后续使用,将程序都写到了主函数,看起来会用有点吃力,望见谅!
希望更多的大佬一起交流学习,一起进步!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值