/**************************************************************************************
* 红外遥控小车 *
实现现象:下载程序后,可以对小车状态进行红外遥控
注意事项: 红外遥控头要对准小车上的红外接收头
***************************************************************************************/
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
sbit IRIN=P3^2;
sbit P1_0=P0^0; //电机A控制输出口A+
sbit P1_1=P0^1; //电机A控制输出口A-
sbit P1_2=P0^2; //电机B控制输出口B+
sbit P1_3=P0^3; //电机B控制输出口B-
u8 ucMotorStep=0; //被触发的电机动作编号
sbit ENA=P0^4; //电机A使能端
sbit ENB=P0^5; //电机B使能端
u16 speed;
u16 T;
u8 IrValue[6];
u8 Time;
/*******************************************************************************
* 函 数 名 : delay
* 函数功能 : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(u16 i)
{
while(i--);
}
/*******************************************************************************
* 函数名 : IrInit()
* 函数功能 : 初始化红外线接收
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void IrInit()
{
IT0=1;//下降沿触发
EX0=1;//打开中断0允许
EA=1; //打开总中断
IRIN=1;//初始化端口
}
/*******************************************************************************
* 函数名 : detectorIR()
* 函数功能 : 判断红外线接收键值
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void detectorIR()
{
if(IrValue[2]==0x10) ucMotorStep=0; /*停止*/
else if(IrValue[2]==0x12) ucMotorStep=1;/*前进*/
else if(IrValue[2]==0x18) ucMotorStep=2;/*后退*/
else if(IrValue[2]==0x14) ucMotorStep=3;/*左转*/
else if(IrValue[2]==0x16) ucMotorStep=4;/*右转*/
else if(IrValue[2]==0x17) ucMotorStep=5;/*左自转*/
else if(IrValue[2]==0x19) ucMotorStep=6;/*右自转*/
else if(IrValue[2]==0x00) speed=400;
else if(IrValue[2]==0x03) speed=800;
else if(IrValue[2]==0x02) speed=1200;
else if(IrValue[2]==0x01) speed=T;
//else ucMotorStep=7;
}
/*******************************************************************************
* 函数名 : motorRun()
* 函数功能 : 控制电机运动状态
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void motorRun()
{
switch(ucMotorStep)
{
case 0: /*停止*/
P1_0=0;
P1_1=0;
P1_2=0;
P1_3=0;
break;
case 1: /*前进*/
P1_0=0;
P1_1=1;
P1_2=0;
P1_3=1;
break;
case 2: /*后退*/
P1_0=1;
P1_1=0;
P1_2=1;
P1_3=0;
break;
case 3: /*左转*/
P1_0=0;
P1_1=0;
P1_2=0;
P1_3=1;
break;
case 4: /*右转*/
P1_0=0;
P1_1=1;
P1_2=0;
P1_3=0;
break;
case 5: /*左自转*/
P1_0=1;
P1_1=0;
P1_2=0;
P1_3=1;
break;
case 6: /*右自转*/
P1_0=0;
P1_1=1;
P1_2=1;
P1_3=0;
break;
}
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
IrInit();
ENA=0;
ENB=0;
T=2048;
speed=400;//数字越大速度越快 390对应人脸追踪正好
ENA=1;
ENB=1;
while(1)
{
detectorIR();
motorRun();
if(speed!=T)
{
ENA=0;
ENB=0;
delay(T-speed);
ENA=1;
ENB=1;
delay(speed);
}
}
}
/*******************************************************************************
* 函数名 : ReadIr()
* 函数功能 : 读取红外数值的中断函数
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void ReadIr() interrupt 0
{
u8 j,k;
u16 err;
Time=0;
delay(700); //7ms
if(IRIN==0) //确认是否真的接收到正确的信号
{
err=1000; //1000*10us=10ms,超过说明接收到错误的信号
/*当两个条件都为真是循环,如果有一个条件为假的时候跳出循环,免得程序出错的时
侯,程序死在这里*/
while((IRIN==0)&&(err>0)) //等待前面9ms的低电平过去
{
delay(1);
err--;
}
if(IRIN==1) //如果正确等到9ms低电平
{
err=500;
while((IRIN==1)&&(err>0)) //等待4.5ms的起始高电平过去
{
delay(1);
err--;
}
for(k=0;k<4;k++) //共有4组数据
{
for(j=0;j<8;j++) //接收一组数据
{
err=60;
while((IRIN==0)&&(err>0))//等待信号前面的560us低电平过去
{
delay(1);
err--;
}
err=500;
while((IRIN==1)&&(err>0)) //计算高电平的时间长度。
{
delay(10); //0.1ms
Time++;
err--;
if(Time>30)
{
return;
}
}
IrValue[k]>>=1; //k表示第几组数据
if(Time>=8) //如果高电平出现大于565us,那么是1
{
IrValue[k]|=0x80;
}
Time=0; //用完时间要重新赋值
}
}
}
if(IrValue[2]!=~IrValue[3])
{
return;
}
}
}