目录
一、循迹模块使用
二、接线方式
三、循迹小车原理
四、代码实现
一、循迹模块使用
1、TCRT5000传感器的红外发射二极管不断发射红外线,当发出的红外线没有被反射回来或被反射回来但强度不太够时,红外接收管一直处于关断状态,此时模块的输出为高电平,指示二极管一直处于熄灭状态,被检测物体出现在检测范围内时,红外线被反射回来且强度足够大,红外接收管饱和,此时模块的输出端为低电平,指示二极管被点亮
总之一句话:没反射回来,D0输出高电平,灭灯
二、接线方式
VCC:接上官一号正极(3-5V)
GND:接上官一号负极
D0:TTL开关信号输出0、1
A0:模拟信号输出(不同距离输出不同的电压,此脚一般可以不接)
三、循迹小车原理
由于黑色具有较强的吸收能力,当循迹模块发射的红外线照射到黑线时,红外线将会被黑线吸收,导致循迹模块上光敏二
0.极管处于关闭状态,此时模块上一个LED熄灭,在没有检测到黑线时,模块上两个LED常亮
总结就是一句话:有感应到黑线,D0输出高电平,灭灯
循迹模块安装在小车车头两侧
下方小车两个模块都能反射回来红外,输出低电平,灯亮,直走
上方小车左循迹模块遇到黑线,红外被吸收,左模块输出高电平,右模块输出低电平,左转,反之右转
总结:两个小绿灯都亮,那左右两边的车轮就都转动,只亮一个小绿灯的说明这侧遇到了黑线,红外被吸收,红外没有被反射回来,输出高电平,所以就不转动了。
四、代码实现
main.c
#include "motor.h"
#include "delay.h"
#include "uart.h"
#include "time.h"
#include "reg52.h"
extern char speedLeft; //此变量/函数是在别处定义的,要在此处引用
extern char speedRight;
sbit leftSensor = P2^7;
sbit rightSensor = P2^6;
void main()
{
Time0Init(); //定时器0初始化
Time1Init(); //定时器1初始化
UartInit(); //串口初始化
while(1){
if(leftSensor == 0 && rightSensor == 0 ){
//直走
speedLeft = 40;
speedRight = 40;
}
if(leftSensor == 1 && rightSensor == 0 ){
//左转
speedLeft = 10;
speedRight = 40;
}
if(leftSensor == 0 && rightSensor == 1 ){
//右转
speedLeft = 40;
speedRight = 10;
}
if(leftSensor == 1 && rightSensor == 1){
//停止
speedLeft = 0;
speedRight = 0;
}
}
}
motor.c
#include "reg52.h"
sbit RightCon1A = P3^2;
sbit RightCon1B = P3^3;
sbit LeftCon1A = P3^4;
sbit LeftCon1B = P3^5;
void goForWardLeft(){ //小车左前进
LeftCon1A = 1;
LeftCon1B = 0;
}
void goForWardRight(){ //小车右前进
RightCon1A = 1;
RightCon1B = 0;
}
void stopLeft(){ //小车左停止
LeftCon1A = 0;
LeftCon1B = 0;
}
void stopRight(){ //小车右停止
RightCon1A = 0;
RightCon1B = 0;
}
void goForWard(){ //小车前转
LeftCon1A = 1;
LeftCon1B = 0;
RightCon1A = 1;
RightCon1B = 0;
}
void goBack(){ //小车后转
LeftCon1A = 0;
LeftCon1B = 1;
RightCon1A = 0;
RightCon1B = 1;
}
void goLeft(){ //小车左转
LeftCon1A = 0;
LeftCon1B = 0;
RightCon1A = 1;
RightCon1B = 0;
}
void goRight(){ //小车右转
LeftCon1A = 1;
LeftCon1B = 0;
RightCon1A = 0;
RightCon1B = 0;
}
void stop(){ //小车停止
LeftCon1A = 0;
LeftCon1B = 0;
RightCon1A = 0;
RightCon1B = 0;
}
motor.h
void goForWard();
void goBack();
void goLeft();
void goRight();
void stop();
void goForWardLeft();
void goForWardRight();
void stopLeft();
void stopRight();
delay.c
#include "intrins.h"
void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 8;
j = 1;
k = 243;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay10ms() //@11.0592MHz
{
unsigned char i, j;
i = 18;
j = 235;
do
{
while (--j);
} while (--i);
}
delay.h
void Delay1000ms();
void Delay10ms();
uart.c------串口初始化文件
#include "reg52.h"
#include "motor.h"
#include "string.h"
#include "delay.h"
#define SIZE 12
sfr AUXR = 0x8E;
char cmd;
char buffer[SIZE];
void UartInit(void) //9600bps@11.0592MHz
{
AUXR = 0x01; //降低时钟对外界的辐射
SCON = 0x50; //串行口寄存器工作模式选择方式1,RNE=1,为串行允许接收状态
TMOD &= 0x0F; //定时器1工作方式位8位自动重装
TMOD |= 0x20;
TH1 = 0xFD;
TL1 = 0xFD; //9600波特率的初值
TR1 = 1; //启动定时器
EA = 1; //总中断寄存器,开启总中断
ES = 1; //开启串口中断
}
void Uart_Handler() interrupt 4
{
char tmp;
static int i = 0; //静态变量,被初始化一次
if(RI == 1){ //中断处理函数中,对于接收中断的响应
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) {
i = 0;
memset(buffer,'\0',SIZE);
}
}
}
uart.h
void UartInit(void);
time.c------初始化定时器及定时器开启中断文件
#include "motor.h"
#include "reg52.h"
char speedLeft;
char cntLeft = 0;
char speedRight;
char cntRight = 0;
void Time1Init(){
//1、配置定时器0工作模式位16位计时
TMOD &= 0x0F;
TMOD |= 0x1 << 4;
//2、给定时器一个初值,每个周期都等于0.5ms
TL1 = 0x33;
TH1 = 0xFE;
//3、定时器开始计时
TR1 = 1;
TF1 = 0;
//4、打开中断定时器1
ET1 = 1;
//5、设置总中断定时器
EA = 1;
}
void Time0Init(){
//1、配置定时器0工作模式位16位计时
TMOD = 0x01;
//2、给定时器一个初值,每个周期都等于0.5ms
TL0 = 0x33;
TH0 = 0xFE;
//3、定时器开始计时
TR0 = 1;
TF0 = 0;
//4、打开中断定时器
ET0 = 1;
//5、设置总中断定时器
EA = 1;
}
void Time1Handler() interrupt 3 //定时器0的中断号为 interrupt 1
{
cntRight ++; //统计爆表的次数
//给定时器重新定义初值,每个周期都等于0.5ms
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 //定时器0的中断号为 interrupt 1
{
cntLeft ++; //统计爆表的次数
//给定时器重新定义初值,每个周期都等于0.5ms
TL0 = 0x33;
TH0 = 0xFE;
//控制PWM波形
if(cntLeft < speedLeft){
//左前进
goForWardLeft();
}else{
//左停止
stopLeft();
}
if(cntLeft == 40){ //要爆表40次,经过了20ms
cntLeft = 0; //当100次表示1s,重新让cnt从0开始,计算下一次的1s
}
}
time.h
void Time0Init();
void Time1Init();