目录
1. 红外壁障模块分析编辑
2. 跟随小车的原理
3. 跟随小车开发和调试代码
4. 超声波模块介绍
5. 摇头测距小车开发和调试代码
1. 红外壁障模块分析
 
原理和循迹是一样的,循迹红外观朝下,跟随朝前
- TCRT5000传感器的红外发射二极管不断发射红外线
- 当发射出的红外线没有被反射回来或被反射回来但强度不够大时
- 红外接收管一直处于关断状态,此时模块的输出端为高电平,指示二极管一直处于熄灭状态
- 被检测物体出现在检测范围内时,红外线被反射回来且强度足够大,红外接收管饱和
- 此时模块的输出端为低电平,指示二极管被点亮
- 总结就是一句话,没反射回来,D0输出高电平,灭灯
2. 跟随小车的原理
- 左边跟随模块能返回红外,输出低电平,右边不能返回,输出高电平,说明物体在左边,需要左转
- 右边跟随模块能返回红外,输出低电平,左边不能返回,输出高电平,说明物体在右边,需要右转
3. 跟随小车开发和调试代码
//main.c
#include "motor.h"
#include "delay.h"
#include "reg52.h"
//sbit leftSensor = P2^7;
//sbit rightSensor = P2^6;
sbit leftSensor = P2^5;
sbit rightSensor = P2^4;
void main()
{
	while(1){
		if(leftSensor == 0 && rightSensor == 0){
			goForward();
		}
		if(leftSensor == 1 && rightSensor == 0){
			goRight();
		}
		
		if(leftSensor == 0 && rightSensor == 1){
			
			goLeft();
		}
		
		if(leftSensor == 1 && rightSensor == 1){
			//停
			stop();
		}
	}
}
//motor.c
#include "reg52.h"
sbit RightCon1A = P3^2;
sbit RightCon1B = P3^3;
sbit LeftCon1A = P3^4;
sbit LeftCon1B = P3^5;
void goForward()
{
	LeftCon1A = 0;
	LeftCon1B = 1;
	
	RightCon1A = 0;
	RightCon1B = 1;
}
void goRight()
{
	LeftCon1A = 0;
	LeftCon1B = 1;
	
	RightCon1A = 0;
	RightCon1B = 0;
}
void goLeft()
{
	LeftCon1A = 0;
	LeftCon1B = 0;
	
	RightCon1A = 0;
	RightCon1B = 1;
}
void goBack()
{
	LeftCon1A = 1;
	LeftCon1B = 0;
	
	RightCon1A = 1;
	RightCon1B = 0;
}
void stop()
{
	LeftCon1A = 0;
	LeftCon1B = 0;
	
	RightCon1A = 0;
	RightCon1B = 0;
}
//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);
}
4. 超声波模块介绍
使用超声波模块,型号:HC-SR04

- 怎么让它发送波 Trig ,给Trig端口至少10us的高电平
- 怎么知道它开始发了 Echo信号,由低电平跳转到高电平,表示开始发送波
- 怎么知道接收了返回波 Echo,由高电平跳转回低电平,表示波回来了
- 怎么算时间 Echo引脚维持高电平的时间! 波发出去的那一下,开始启动定时器 波回来的拿一下,我们开始停止定时器,计算出中间经过多少时间
- 怎么算距离 距离 = 速度 (340m/s)* 时间/2
时序图:

5. 摇头测距小车开发和调试代码
//main.c
#include "reg52.h"
#include "hc04.h"
#include "delay.h"
#include "sg90.h"
#include "motor.h"
#define MIDDLE 0
#define LEFT 1
#define RIGHT 2
void main()
{
	char dir;
	
	double disMiddle;
	double disLeft;
	double disRight;
	
	Time0Init();
	Time1Init();
	//舵机的初始位置
	sgMiddle();
	Delay300ms();
	Delay300ms();
	dir = MIDDLE;
	
	while(1){
		
		if(dir != MIDDLE){
			sgMiddle();
			dir = MIDDLE;
			Delay300ms();
		}
		disMiddle = get_distance();
		
		if(disMiddle > 35){
			//前进
			goForward();
		}else if(disMiddle < 10){
			goBack();
			
		}else
		{
			//停止
			stop();
			//测左边距离
			sgLeft();
			Delay300ms();
			disLeft = get_distance();
			
			sgMiddle();
			Delay300ms();
			
			sgRight();
			dir = RIGHT;
			Delay300ms();
			disRight = get_distance();
			
			if(disLeft < disRight){
				goRight();
				Delay150ms();
				stop();
			}
			if(disRight < disLeft){
				goLeft();
				Delay150ms();
				stop();
			}
		}
		
	}
}
//hc04.c
#include "reg52.h"
#include "delay.h"
sbit Trig     = P2^3;
sbit Echo     = P2^2;
void Time1Init()
{	
	TMOD &= 0x0F;		//设置定时器模式
	TMOD |= 0x10;
	TH1 = 0;
	TL1 = 0;
	//设置定时器0工作模式1,初始值设定0开始数数,不着急启动定时器
}
void startHC()
{
	Trig = 0;
	Trig = 1;
	Delay10us();
	Trig = 0;
}
double get_distance()
{
		double time;
		//定时器数据清零,以便下一次测距
		TH1 = 0;
		TL1 = 0;
	//1. Trig ,给Trig端口至少10us的高电平
		startHC();
		//2. echo由低电平跳转到高电平,表示开始发送波
		while(Echo == 0);
		//波发出去的那一下,开始启动定时器
		TR1 = 1;
		//3. 由高电平跳转回低电平,表示波回来了
		while(Echo == 1);
		//波回来的那一下,我们开始停止定时器
		TR1 = 0;
		//4. 计算出中间经过多少时间
		time = (TH1 * 256 + TL1)*1.085;//us为单位
		//5. 距离 = 速度 (340m/s)* 时间/2
		return  (time * 0.017);
}
//delay.c
#include "intrins.h"
void Delay2000ms()		//@11.0592MHz
{
	unsigned char i, j, k;
	i = 15;
	j = 2;
	k = 235;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}
void Delay10us()		//@11.0592MHz
{
	unsigned char i;
	i = 2;
	while (--i);
}
void Delay300ms()		//@11.0592MHz
{
	unsigned char i, j, k;
	_nop_();
	i = 3;
	j = 26;
	k = 223;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}
void Delay150ms()		//@11.0592MHz
{
	unsigned char i, j, k;
	i = 2;
	j = 13;
	k = 237;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}
void Delay450ms()		//@11.0592MHz
{
	unsigned char i, j, k;
	_nop_();
	i = 4;
	j = 39;
	k = 209;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}
//sg90.c
#include "reg52.h"
#include "delay.h"
sbit sg90_con = P1^1;
int jd;
int cnt = 0;
void Time0Init()
{
	//1. 配置定时器0工作模式位16位计时
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;
	//2. 给初值,定一个0.5出来
	TL0=0x33;
	TH0=0xFE;
	//3. 开始计时
	TR0 = 1;
	TF0 = 0;
	//4. 打开定时器0中断
	ET0 = 1;
	//5. 打开总中断EA
	EA = 1;
}
void sgMiddle()
{
	//中间位置
	jd = 3; //90度 1.5ms高电平
	cnt = 0;
}
void sgLeft()
{
	//左边位置
	jd = 5; //135度 1.5ms高电平
	cnt = 0;
}
void sgRight()
{
	//右边位置
	jd = 1; //0度
	cnt = 0;
}
void Time0Handler() interrupt 1
{
	cnt++;  //统计爆表的次数. cnt=1的时候,报表了1
	//重新给初值
	TL0=0x33;
	TH0=0xFE;
	
	//控制PWM波
	if(cnt < jd){
		sg90_con = 1;
	}else{
		sg90_con = 0;
	}
	
	if(cnt == 40){//爆表40次,经过了20ms
		cnt = 0;  //当100次表示1s,重新让cnt从0开始,计算下一次的1s
		sg90_con = 1;
	}
		
}
//motor.c
#include "reg52.h"
sbit RightCon1A = P3^2;
sbit RightCon1B = P3^3;
sbit LeftCon1A = P3^4;
sbit LeftCon1B = P3^5;
void goForward()
{
	LeftCon1A = 0;
	LeftCon1B = 1;
	
	RightCon1A = 0;
	RightCon1B = 1;
}
void goRight()
{
	LeftCon1A = 0;
	LeftCon1B = 1;
	
	RightCon1A = 0;
	RightCon1B = 0;
}
void goLeft()
{
	LeftCon1A = 0;
	LeftCon1B = 0;
	
	RightCon1A = 0;
	RightCon1B = 1;
}
void goBack()
{
	LeftCon1A = 1;
	LeftCon1B = 0;
	
	RightCon1A = 1;
	RightCon1B = 0;
}
void stop()
{
	LeftCon1A = 0;
	LeftCon1B = 0;
	
	RightCon1A = 0;
	RightCon1B = 0;
}



















