网上的寻迹小车代码千奇百怪,多数代码功能不全或是逻辑不清晰。为方便大家更快上手寻迹小车, 我找了一篇逻辑相对清晰的基础循迹代码,并自己加了些注释供大家参考。
【此代码不能完全契合每个人的小车,不能优秀的完成180°转向或是多元赛道等题目。仅给大家提供一个相对清晰的代码编写思路。想要完成所有赛题还需在此基础上补充完善】
#include<reg52.h>
typedef unsigned int u16;
typedef unsigned char u8;
/******************************/
此处六个端口对应L298N的六条信号线
/******************************/
sbit ENA = P2^0; //右点机使能,输出pwm
sbit IN1 = P2^1; //为0右轮反转
sbit IN2 = P2^2; //为0右轮正转
sbit IN3 = P2^3; //为0左轮正转
sbit IN4 = P2^4; //为0左轮反转
sbit ENB = P2^5; //左电机使能,输出pwm
/*******************************/
此处四个端口对应循迹模块的四条信号线
/*******************************/
sbit left1 = P1^3;
sbit left2 = P1^2;
sbit right1 = P1^1;
sbit right2 = P1^0;
u8 PWMCnt1 = 0;
u8 PWMCnt2 = 0;
u8 cntPWM1 = 0;
u8 cntPWM2 = 0;
void Timer0Init();
void XunJi();
void main()
{
Timer0Init(); //定时器0初始化
while(1)
{
XunJi(); 主循环持续循迹
}
}
/*******************************/
延时函数(备用)本代码暂时没用到
/*******************************/
// i = 1时, 大概延时10us(最大65535)
//void delay(u16 i)
//{
// while (i--);
//}
void Timer0Init()//定时器初始化函数,直接复制不用看懂
{
TH0 = 0xFF;
TL0 = 0xA3;
TMOD &= 0xF0;
TMOD |= 0x01;
EA = 1;
ET0 = 1;
TR0 = 1;
}
void TurnRight1() //右转
{
IN1 = 0; //右轮反转
IN2 = 1;
IN3 = 0; //左轮正转
IN4 = 1;
cntPWM1 = 70;//pwm设置用于调节转速(下边代码同理)
cntPWM2 = 55;
}
void TurnRight2() //右转
{
IN1 = 0; //右轮反转
IN2 = 1;
IN3 = 0; //左轮正转
IN4 = 1;
cntPWM1 = 50;
cntPWM2 = 40;
}
void TurnLeft1() //左转
{
IN1 = 1;
IN2 = 0; //右轮正转
IN3 = 1;
IN4 = 0; //左轮反转
cntPWM1 = 55;
cntPWM2 = 70;
}
void TurnLeft2() //左转
{
IN1 = 1;
IN2 = 0; //右轮正转
IN3 = 1;
IN4 = 0; //左轮反转
cntPWM1 = 40;
cntPWM2 = 50;
}
void Forward() //前进
{
IN1 = 1;
IN2 = 0; //右轮正转
IN3 = 0; //左轮正转
IN4 = 1;
cntPWM1 = 40;
cntPWM2 = 40;
}
//void Backward() //后退
//{
// IN1 = 0; //右轮反转
// IN2 = 1;
//
// IN3 = 1;
// IN4 = 0; //左轮反转
// cntPWM1 = 30;
// cntPWM2 = 30;
//}
void Stop() //停止
{
IN1 = 0;
IN2 = 0;
IN3 = 0;
IN4 = 0;
}
void XunJi()//此处代码是需要重点理解的,内涵循迹逻辑,根据实际情况自行增补
{
unsigned char flag = 0;
//flag变量用于存储小车行进状态(行进状态由对四路传感器妆台的判断而来)
if((left1 == 0)&&(left2 == 0)&&(right1 == 0)&&(right2 == 0)) //四路传感器状态:0 0 0 0
flag = 0;
if((left1 == 0)&&(left2 == 0)&&(right1 == 0)&&(right2 == 1)) //0 0 0 1
flag = 1;
if((left1 == 0)&&(left2 == 0)&&(right1 == 1)&&(right2 == 0)) //0 0 1 0
flag = 0;
if((left1 == 0)&&(left2 == 0)&&(right1 == 1)&&(right2 == 1)) //0 0 1 1
flag = 1;
if((left1 == 0)&&(left2 == 1)&&(right1 == 0)&&(right2 == 0)) //0 1 0 0
flag = 0;
if((left1 == 0)&&(left2 == 1)&&(right1 == 0)&&(right2 == 1)) //0 1 0 1
flag = 4;
if((left1 == 0)&&(left2 == 1)&&(right1 == 1)&&(right2 == 0)) //0 1 1 0
flag = 0;
if((left1 == 0)&&(left2 == 1)&&(right1 == 1)&&(right2 == 1)) //0 1 1 1
flag = 1;
if((left1 == 1)&&(left2 == 0)&&(right1 == 0)&&(right2 == 0)) //1 0 0 0
flag = 3;
if((left1 == 1)&&(left2 == 0)&&(right1 == 0)&&(right2 == 1)) //1 0 0 1
flag = 0;
if((left1 == 1)&&(left2 == 0)&&(right1 == 1)&&(right2 == 0)) //1 0 1 0
flag = 2;
// ?
if((left1 == 1)&&(left2 == 0)&&(right1 == 1)&&(right2 == 1)) //1 0 1 1
flag = 0;
if((left1 == 1)&&(left2 == 1)&&(right1 == 0)&&(right2 == 0)) //1 1 0 0
flag = 3;
//?
if((left1 == 1)&&(left2 == 1)&&(right1 == 0)&&(right2 == 1)) //1 1 0 1
flag = 0;
if((left1 == 1)&&(left2 == 1)&&(right1 == 1)&&(right2 == 0)) //1 1 1 0
flag = 3;
if((left1 == 1)&&(left2 == 1)&&(right1 == 1)&&(right2 == 1)) //1 1 1 1
flag = 5;
switch(flag)//根据“状态flag”改变小车行进模式
{
case 0:Forward();break;
case 1:TurnRight1();break;
case 2:TurnRight2();break;
case 3:TurnLeft1();break;
case 4:TurnLeft2();break;
default:Stop();break;
}
}
void InterruptTime0() interrupt 1//定时器相关函数(不用读懂直接粘贴)
{
PWMCnt1++;
PWMCnt2++;
if(PWMCnt1 >= 200)
{
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;
TL0 = (65536 - 50)%256;
}
【 附加讲解】
如果想要根据赛道调试小车,主要需要从两方面着手修改代码逻辑:
1、修改或增加TurnRight1()、TurnRight2()、TurnLeft1()、TurnLeft2()等控制行进模式的代码,调节里边的点机正反转逻辑或者左右速度差(pwm参数)
2、着重修改XunJi()函数,适当增加对各种情况判断语句,各种适应赛题的要求。
最后祝大家小车比赛顺利,起飞!!!
---TZ