基于51开发板循迹小车(基础模型——简陋版)后续会改进
功能组成:
开发板:51
驱动模块:TT电机
循迹模块—>TCRT5000传感器
原理:循迹模块使用
TCRT5000传感器的红外发射二极管不断发射红外线,当发射出的红外线没有被反射回来或被反射回来但强度不够大时,红外接收管- -直处于关断状态,此时模块的输出端为高电平,指示二_极管-直处于熄灭状态,被检测物体出现在检测范围内时,红外线被反射回来且强度足够大,红外接收管饱和,此时模块的输出端为低电平,指示二极管被点亮。
代码:
main.c
#include "reg52.h"
#include "moto.h"
#include "Delay.h"
#include "uart.h"
#include "time.h"
extern char speedLeft;
extern char speedRight;
sbit leftSensor = P2^7;
sbit rightSensor = P2^6;
void main()
{
Time0Init();
Time1Init();
//UartInit();
while(1){
if(leftSensor == 0 && rightSensor == 0){
goForward();
speedLeft = 25;
speedRight = 25;
}
if(leftSensor == 1 && rightSensor == 0){
goLeft();
speedLeft = 15;
speedRight = 40;
}
if(leftSensor == 0 && rightSensor == 1){
goRight();
speedLeft = 40;
speedRight = 15;
}
if(leftSensor == 1 && rightSensor == 1){
//ͣ
speedLeft = 0;
speedRight = 0;
}
}
}
moto.c
#include "reg52.h"
#include <intrins.h>
sbit RightCon1A =P3^2;
sbit RightCon1B =P3^3;
sbit LeftCon1A =P3^4;
sbit LeftCon1B =P3^5;
void goForwardLeft()
{
LeftCon1A = 0;
LeftCon1B = 1;
}
void stopLeft()
{
LeftCon1A = 0;
LeftCon1B = 0;
}
void goForwardRight()
{
RightCon1A = 0;
RightCon1B = 1;
}
void stopRight()
{
RightCon1A = 0;
RightCon1B = 0;
}
void goForward()
{
LeftCon1A = 0;
LeftCon1B = 1;
RightCon1A = 0;
RightCon1B = 1;
}
void goBack()
{
LeftCon1A = 1;
LeftCon1B = 0;
RightCon1A = 1;
RightCon1B = 0;
}
void goLeft()
{
LeftCon1A = 0;
LeftCon1B = 1;
RightCon1A = 0;
RightCon1B = 0;
}
void goRight()
{
LeftCon1A = 0;
LeftCon1B = 0;
RightCon1A = 0;
RightCon1B = 1;
}
void stop()
{
LeftCon1A = 0;
LeftCon1B = 0;
RightCon1A = 0;
RightCon1B = 0;
}
uart.c
#include "reg52.h"
#include "moto.h"
#include "string.h"
#include "Delay.h"
sbit D5 = P3^7;
#define SIZE 12
sfr AUXR = 0x8E;
char buffer[SIZE];
void UartInit(void) //[email protected]
{
AUXR = 0x01;
SCON = 0x50; //配置串口工作方式1,REN使能接收
TMOD &= 0x0F;
TMOD |= 0x20;//定时器1工作方式位8位自动重装
TH1 = 0xFD;
TL1 = 0xFD;//9600波特率的初值
TR1 = 1;//启动定时器
EA = 1;//开启总中断
ES = 1;//开启串口中断
}
//M1qian M2 hou M3 zuo M4 you
void Uart_Handler() interrupt 4
{
static int i = 0;//静态变量,被初始化一次
char tmp;
if(RI)//中断处理函数中,对于接收中断的响应
{
RI = 0;//清除接收中断标志位
tmp = SBUF;
if(tmp == 'M'){
i = 0;
}
buffer[i++] = tmp;
//灯控指令
if(buffer[0] == 'M'){
switch(buffer[1]){
case '1':
goForward();
Delay10ms();
break;
case '2':
goBack();
Delay10ms();
break;
case '3':
goLeft();
Delay10ms();
break;
case '4':
goRight();
Delay10ms();
break;
default:
stop();
break;
}
}
if(i == 12) {
memset(buffer, '\0', SIZE);
i = 0;
}
}
}
time.c
#include "moto.h"
#include "reg52.h"
char speedLeft;
char cntLeft = 0;
char speedRight;
char cntRight = 0;
void Time1Init()
{
//1. 配置定时器1工作模式位16位计时
TMOD &= 0x0F;
TMOD |= 0x1 << 4;
//2. 给初值,定一个0.5出来
TL1=0x33;
TH1=0xFE;
//3. 开始计时
TR1 = 1;
TF1 = 0;
//4. 打开定时器1中断
ET1 = 1;
//5. 打开总中断EA
EA = 1;
}
void Time0Init()
{
//1. 配置定时器0工作模式位16位计时
TMOD = 0x01;
//2. 给初值,定一个0.5出来
TL0=0x33;
TH0=0xFE;
//3. 开始计时
TR0 = 1;
TF0 = 0;
//4. 打开定时器0中断
ET0 = 1;
//5. 打开总中断EA
EA = 1;
}
void Time1Handler() interrupt 3
{
cntRight++; //统计爆表的次数. cnt=1的时候,报表了1
//重新给初值
TL1=0x33;
TH1=0xFE;
//控制PWM波
if(cntRight < speedRight){
//右前进
goForwardRight();
}else{
//停止
stopRight();
}
if(cntRight == 40){
//爆表40次,经过了20ms
cntRight = 0; //当100次表示1s,重新让cnt从0开始,计算下一次的1s
}
}
void Time0Handler() interrupt 1
{
cntLeft++; //统计爆表的次数. cnt=1的时候,报表了1
//重新给初值
TL0=0x33;
TH0=0xFE;
//控制PWM波
if(cntLeft < speedLeft){
//左前进
goForwardLeft();
}else{
//停止
stopLeft();
}
if(cntLeft == 40){
//爆表40次,经过了20ms
cntLeft = 0; //当100次表示1s,重新让cnt从0开始,计算下一次的1s
}
}
moto.h
void goForward();
void goBack();
void goLeft();
void goRight();
void stop();
void goForwardLeft();
void stopLeft();
void goForwardRight();
void stopRight();
Delay.h
Delay2000ms();
Delay10ms();
uart.h
void UartInit(void);
time.h
void Time0Init();
; //当100次表示1s,重新让cnt从0开始,计算下一次的1s
}
}
moto.h
void goForward();
void goBack();
void goLeft();
void goRight();
void stop();
void goForwardLeft();
void stopLeft();
void goForwardRight();
void stopRight();
Delay.h
Delay2000ms();
Delay10ms();
uart.h
void UartInit(void);
time.h
void Time0Init();
void Time1Init();
QQ视频20230324223230