//****************** 说明:必看------仅仅提供给本实验室217-2使用,代码不成熟,不要外传。不要外传。
/*
1、本程序是用stc89C52RC或者stc89C51类普通的12T的单片机;如果用stc15系列增强版单片机,
需要调节波特率的函数以及定时的初值的计算;
2、本程序,利用定时器0产生PWM,以及延时使用;利用定时器1,产生蓝牙小车的波特率9600;定时器1不能挪作它用,已经使用了。
3、本程序,可以在定时器0里面,添加代码,比如定时1s,然后设置一个标记位,计算外部中断的次数,从而计算电机的速度或者行程
(这个部分自己添加);显示数据部分,自己学习我的视频,LCD1602的内容,完成;
4、本程序,利用四个循迹传感器,四个传感器一定要和实际的比赛场地,进行合理布局,建议中间两个夹着黑线,外面的和中间的稍微疏远
一点,不要等间距,自己调试过之后,进行合理布局;
5、四个循迹传感器,必须要在实际的场地进行调试一下,不同光照情况,碰到黑线、白线的表现都不一样,需要用螺丝刀调节一个个调试
可以将循迹传感器,划过黑线,划过白线,对比指示灯,进行调试;
6、每个人的车上的负载不一样,因此电机速度也不一样,需要根据自己的小车进行多次调试;
比如直走,左转弯,右转弯,大转弯,调头等等;
转弯的时候,可以采取速度差的方法,或者一边后退,一边前进的方法,具体速度自己调试。在0-200范围内就可以。
7、调头的动作,调头是采取一边后退,一边前进的方法,然后延时一定时间,实现。这个时间需要根据设定的速度进行多次调试,
保证可以实现180度调头;
8、如果两边电机的方向不一样,需要根据实际情况进行更改线,或者更改对换程序的接口,一般改线不方便,那么就改程序的接口,对调。
如,如果下面的接线不对,
sbit IN1 = P1^4; //为0左轮反转
sbit IN2= P1^3; //为0左轮正转
可以更改为
sbit IN1 = P1^3; //为0左轮反转
sbit IN2= P1^4; //为0左轮正转
右轮也一样。
9、蓝牙模块和下载器,都用同一个串口,因此,如果想下载程序,需要把蓝牙模块的电源拔掉断掉,不然不能下载程序;
下载程序之后,再插上蓝牙模块的电源线;
10、实验室黄色的TT电机,最大电压只能调节到6.5V,黑色电机,最大可以到7.4V。不要超过电压。
本例子使用的是7.4V黑色电机,电机传动比是1:48;给电机的电压是7.4V;其他地形需要自己调试电压和转弯的速度差等数据;
11、蓝牙模块控制命令
首先,最好是用HC05模块,不用BLE蓝牙模块。
利用实验室网上的资料软件,编辑界面(实验室自编讲义有介绍);
命令
发送3个字符,0和9是帧头和帧尾,是为了保证数据的有效性,接收三个数据,头和尾巴都相等,才判断第二个功能码。
0f9,前进
0l9,左转,这个l是小写的L;
0r9是,右转;
0b9是后退;
0x9是循迹模式
*/
#include<reg52.h>
typedef unsigned int u16;
typedef unsigned char u8;
sbit ENA = P1^2; //左电机使能PWM
sbit IN1 = P1^4; //左轮
sbit IN2= P1^3; //左轮
sbit IN3 = P1^5; //右电机PMM
sbit IN4= P1^6; //右轮
sbit ENB = P1^7; //
//sbit BEEP=P1^0;
sbit KEY_Start=P3^7;
//left1,left2,right1,right2
//P20 P21 P22 P23
//四路循迹模块 接线
sbit left1 = P2^0;
sbit left2 = P2^1;
sbit right1 = P2^2;
sbit right2 = P2^3;
u8 PWMCnt1 = 0;//占空比的动态点,一个定时周期加1,小于设定值,就PWM=1,高电平时间,决定占空比;当大于设定值且小于200那么就PWMIO口=0,输出低电平
u8 PWMCnt2 = 0;//占空比的动态点,一个定时周期加1,小于设定值,就PWM=1,高电平时间,决定占空比;当大于设定值且小于200那么就PWMIO口=0,输出低电平
u8 cntPWM1 = 0;//PWM的设定值,程序修改,完成占空比的设置,完成电机速度的控制
u8 cntPWM2 = 0;//PWM的设定值,程序修改,完成占空比的设置,完成电机速度的控制
u8 timeflag=0;//定时时间标记位,不用的时候是0,使用的时候,等待定时程序中定时时间到,就等于1,后面记得手动程序清0
u8 XunJiFlag=0;//循迹标记位,通按键或者蓝牙进行置1或者清0使用,=1,就是循迹模式。
//定时器0产生PWM,并且测速,测位移,定时器1,产生波特率
void Timer0Init();//定时器0产生PWM
void XunJi();
void TurnRight1() ; //右转,左轮速度快,速度差这里设置70-55
void TurnRight2() ; //右转
void TurnLeft1(); //左转
void TurnLeft2(); //左转
void Backward(); //后退
void Stop(); //停止
void Forward();
void delayms(unsigned int tms)
{
unsigned int i,j;
for(i=0;i<100;i++)
{
for(j=0;j<tms;j++);
}
}
/********************************************************/
/* 串口配置函数,baud-通信波特率 */
void ConfigUART(unsigned int baud)
{
SCON = 0x50; //配置串口为模式1
TMOD &= 0x0F; //清零T1的控制位
TMOD |= 0x20; //配置T1为模式2
TH1 = 256 - (11059200/12/32)/baud; //计算T1重载值
TL1 = TH1; //初值等于重载值
ET1 = 0; //禁止T1中断
ES = 1; //使能串口中断
TR1 = 1; //启动T1
}
//定时50us
void Timer0Init()
{
TH0 = (65536 - 50)/256;//50us
TL0 = (65536 - 50)%256;
TMOD &= 0xF0;
TMOD |= 0x01;
ET0 = 1;
TR0 = 1;
}
//**********************************主函数
void main()
{
Timer0Init();
ConfigUART(9600);
EA = 1;
while(1)
{
//用开发板的P37的按键,控制启动,也可以通过蓝牙模块控制启动
if(KEY_Start==0)
{
delayms(10);
if(KEY_Start==0)
{
if(XunJiFlag==0)
{
delayms(2000);//按下,等两秒,再启动
XunJiFlag=1;
}
else if(XunJiFlag==1)
{
XunJiFlag=0;
Stop();
}
}
}
if(XunJiFlag==1)
{
XunJi();
}
}
}
void TurnRight1() //右转,左轮速度快,速度差这里设置70-55
{
IN1 = 0;
IN2 = 1;//
IN3 = 1;
IN4 =0;
cntPWM1 = 150;
cntPWM2 = 60;
}
void TurnRight2() //右转
{
IN1 = 0; //
IN2 = 1;
IN3 = 1; //
IN4 = 0;
cntPWM1 = 195;
cntPWM2 = 120;
delayms(10);
}
void TurnLeft1() //左转
{
IN1 = 1;
IN2 = 0;
IN3 = 0;
IN4 = 1;
cntPWM1 = 60;
cntPWM2 = 150;
}
void TurnLeft2() //左转
{
IN1 =1;
IN2 =0;
IN3 = 0;
IN4 = 1;
cntPWM1 = 120;
cntPWM2 = 195;
delayms(10);
}
void Forward() //前进
{
IN1 = 0;
IN2 = 1; //右轮正转
IN3 = 0; //左轮正转
IN4 = 1;
cntPWM1 = 45;
cntPWM2 = 45;
}
void Backward() //后退
{
IN1 =1; //右轮反转
IN2 =0;
IN3 = 1;
IN4 = 0; //左轮反转
cntPWM1 = 60;
cntPWM2 = 60;
}
void Stop() //停止
{
IN1 = 0;
IN2 = 0;
IN3 = 0;
IN4 = 0;
}
void XunJi()
{
u8 flag = 0;
if((left1 == 0)&&(left2 == 0)&&(right1 == 0)&&(right2 == 0)) //0 0 0 0
flag = 0;
else if((left1 == 0)&&(left2 == 0)&&(right1 == 0)&&(right2 == 1)) //0 0 0 1
flag = 1;
else if((left1 == 0)&&(left2 == 0)&&(right1 == 1)&&(right2 == 0)) //0 0 1 0
flag = 2;
else if((left1 == 0)&&(left2 == 1)&&(right1 == 0)&&(right2 == 0)) //0 1 0 0
flag = 3;
else if((left1 == 1)&&(left2 == 0)&&(right1 == 0)&&(right2 == 0)) //1 0 0 0
flag = 4;
else if((left1 == 0)&&(left2 == 0)&&(right1 == 1)&&(right2 == 1)) //0 0 1 1 zuo转90° 倒7路口
flag = 5;
else if((left1 == 0)&&(left2 == 1)&&(right1 == 1)&&(right2 == 1)) //0 1 1 0 //0 0 1 1 倒7路口,右转90°
flag = 5;
else if((left1 == 1)&&(left2 == 1)&&(right1 == 0)&&(right2 ==0)) //0 1 1 1左转90°
flag = 6;
else if((left1 == 1)&&(left2 == 1)&&(right1 == 1)&&(right2 ==0)) //0 1 1 1左转90°
flag = 6;
else if((left1 == 1)&&(left2 == 1)&&(right1 == 1)&&(right2 == 1)) //1 1 1 1 掉头
flag = 7;
switch(flag)
{
case 0:
Forward();
break;
case 1://0001
TurnRight2();break;
case 2:
TurnRight1();break;
case 3:
TurnLeft1();break;
case 4:
TurnLeft2();break;
case 5://0011 0111
TurnRight2();break;
break;
case 6://1100 1110
TurnLeft2();break;
break;
case 7://调头
Forward();//前进
while(timeflag==0);
timeflag=0;//前进一小段时间
while(timeflag==0);
timeflag=0;//前进一小段时间
Stop();
while(timeflag==0);
timeflag=0;//前进一小段时间
while(timeflag==0);
timeflag=0;//前进一小段时间
/// TurnRight2();//右转这么多时间,必须经过多次调试转弯的时间,确保不会大于270度。
IN1 = 0; //
IN2 = 1;
IN3 = 1; //
IN4 = 0;
cntPWM1 = 130;
cntPWM2 = 130;
while(timeflag==0);
timeflag=0;//前进一小段时间
while(timeflag==0);
timeflag=0;//前进一小段时间
while(timeflag==0);
timeflag=0;//前进一小段时间
while(timeflag==0);
timeflag=0;//前进一小段时间
break;
default:break;//Stop();
}
}
void timer0inter() interrupt 1
{
static unsigned int ttms;
ttms++;
if(ttms>=2000)//
{
ttms=0;
timeflag=1;
}
PWMCnt1++;
PWMCnt2++;
if(PWMCnt1 >= 200)//50us*200=10 000us=10ms
{
PWMCnt1 = 0;
}
if(PWMCnt1 <= cntPWM1)
{
ENA = 1;
}
else
{
ENA = 0;
}
if(PWMCnt2 >= 200)
{
PWMCnt2 = 0;
}
if(PWMCnt2 <= cntPWM2)
{
ENB = 1;
}
else
{
ENB = 0;
}
TH0 = (65536 - 50)/256;//50us
TL0 = (65536 - 50)%256;
}
/*----------------------------
UART 中断服务程序,蓝牙控制
-----------------------------*/
void Uart1() interrupt 4 using 1
{
static unsigned char RecSbuf[3];
static unsigned char recNum=0;
if (RI) //接收到新字节
{
RI = 0; //清零接收中断标志位,软件清零
//接收到的数据保存在 SBUF 里面,只能放一个字节;
if(recNum==0)//第一个字节
{
RecSbuf[0]=SBUF;//将数据放在 RecSbuf 中
if(RecSbuf[0]=='0')
//接头暗号正确,才进行后续数据的接收判断
{
recNum=1;
//LED=!LED;
}
}
else if(recNum==1)//第 2 个字节
{
RecSbuf[1]=SBUF;//将数据放在 RecSbuf 中
recNum=2; //接收第3个数据
}
else if(recNum==2)
{
RecSbuf[2]=SBUF;//
recNum=0; //第三个接收到了,就运行接收新的。
if( RecSbuf[2]=='9')//判断帧尾是不是等于约定的‘9’
{
//*******************************************************
if(RecSbuf[1]=='x') //动作1
{
//LED0=!LED0;
//小车循迹模式 按一次进行循迹,再按一次,就停止循迹
if(XunJiFlag==0)
{
XunJiFlag=1;
}
else if(XunJiFlag==1)
{
XunJiFlag=0;
Stop();
}
}
//*******************************************************
if(RecSbuf[1]=='f') //动作2
{
//LED1=!LED1;
//小车直行模式
Forward();//前进
}
//*******************************************************
if(RecSbuf[1]=='l') //动作3
{
//LED0=!LED0;
//小车转90度,左转
TurnLeft1();
}
//*******************************************************
if(RecSbuf[1]=='r') //动作4
{
//LED1=!LED1;
//小车转90度,右转
TurnRight1();
}
//*******************************************************
if(RecSbuf[1]=='b') //动作4
{
//LED1=!LED1;
//小车调头
Forward();//前进
while(timeflag==0);
timeflag=0;//前进一小段时间
while(timeflag==0);
timeflag=0;//前进一小段时间
Stop();
while(timeflag==0);
timeflag=0;//前进一小段时间
while(timeflag==0);
timeflag=0;//前进一小段时间
/// TurnRight2();//右转这么多时间,必须经过多次调试转弯的时间,确保不会大于270度。
IN1 = 0; //
IN2 = 1;
IN3 = 1; //
IN4 = 0;
cntPWM1 = 130;
cntPWM2 = 130;
while(timeflag==0);
timeflag=0;//前进一小段时间
while(timeflag==0);
timeflag=0;//前进一小段时间
while(timeflag==0);
timeflag=0;//前进一小段时间
while(timeflag==0);
timeflag=0;//前进一小段时间
}
//*******************************************************
if(RecSbuf[1]=='s') //停止
{
//LED1=!LED1;
//停止
Stop();
}
if(RecSbuf[1]=='t') //后退
{
//LED1=!LED1;
//停止
Backward();
}
}
}
}
if (TI) //字节发送完毕
{
TI = 0; //清零发送中断标志位
}
}
stc89c52---循------车代码
最新推荐文章于 2023-11-07 21:55:27 发布