标题:
昨天发的多功能小车程序
[打印本页]
作者:
LGX123
时间:
2018-5-29 08:30
标题:
昨天发的多功能小车程序
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
#define u8 unsigned char
#define u16 unsigned int
uchar num;
unsigned char irtime; //红外用全局变量
unsigned char IRcord[4]; //红外按键对应码值选对应功能的数组
unsigned char irdata[33]; //存储电平持续的时间的数组
u16 EchoCnt;
bit irpro_ok,irok; //位定义,用于判断操作是否完成
sbit in1=P1^0; //电机引脚定义
sbit in2=P1^1;
sbit in3=P1^2;
sbit in4=P1^3;
sbit IR=P3^2; //将IR位定义为P3.2引脚红外模块引脚
sbit XUNJI0 =P2^2; //循迹模块
sbit XUNJI1 =P2^3;
sbit Trig = P3^6; //超声波模块
sbit Echo = P3^7;
sbit XUNGUANG0 = P2^0; // 红外寻光接口定义
sbit XUNGUANG1 = P2^1;
typedef enum
{
FORWARD=0,
BACKUP,
LEFT,
RIGHT,
STOP,
ZHUANHUAN,
XUNJI,
BIZHANG,
XUNGUANG,
}MOTOR_DIR;
void qianjin();
void houtui();
void zuozhuan();
void youzhuan();
void tingzhi();
void DelayMs(u16 t); //延时函数
void DelayUs(u16 i);
void DcMotorContorl(MOTOR_DIR dir, u8 speed); // 小车直流电机控制,dir为方向,speed为速度
void TIM0init(); //定时器0初始化
void Ircordpro();
void Ir_work();
void HC04_Init();
void HC04_Loop();
void hongwaiyaokong(); //红外遥控函数
void lanya(); //蓝牙遥控函数
void xunji(); //循迹函数
void bizhang(); //壁障函数
void xunguang(); //寻光函数
void init_t1() //初始化函数
{
TMOD=0x20; //设置定时器1为工作方式2
TH1=0xfd; //波特率初始值
TL1=0xfd;
TR1=1; //定时器打开
REN=1; //允许串行接受
SM0=0; //串行口工作方式设置为1
SM1=1;
EA=1; //打开总中断
ES=1;
}
void main() //主函数
{
init_t1();
while(1)
{
lanya();
}
}
void EX0init(void) // 外部中断初始化
{
IT0 = 1; //指定外部中断0下降沿触发,INT0 (P3.2)
EX0 = 1; //允许外部中断0
EA = 1; //开总中断
}
void ex0_isr (void) interrupt 0 using 0 //外部中断0服务函数
{
static unsigned char i; //接收红外信号处理
static bit startflag; //是否开始处理标志位
if(startflag)
{
if(irtime<63&&irtime>=33)//引导码 TC9012的头码,9ms低电平+4.5ms高电平
i=0;
irdata[i]=irtime;//存储每个电平的持续时间,用于以后判断是0还是1
irtime=0;
i++;
if(i==33)
{
irok=1;
i=0;
}
}
else
{irtime=0;
startflag=1;
}
}
void tim0_isr (void) interrupt 1 using 1//定时器0中断服务函数
{
irtime++; //用于计数2个下降沿之间的时间
}
void TIM0init(void)//定时器0初始化
{
TMOD=0x02;//定时器0工作方式2,TH0是重装值,TL0是初值
TH0=0x00; //重载值
TL0=0x00; //初始化值
ET0=1; //开中断允许位
TR0=1; //开启定时器功能
}
void t1() interrupt 4//中断服务函数
{
if(RI)
{
RI=0;
num=SBUF-48; //将接收到的码值转换为十进制整数以选择对应功能
}
}
void HC04_Init(void) //初始化超声波模块
{
Trig = 0;
Echo = 0;
TMOD &=0X0f;
TMOD |=0X10; //使用模式1,16位定时器1;
TH1=0; //装初值
TL1=0;
EA=1; //开总中断
ET1=1; //开定时器1中断
TR1=0; //定时器1
}
void HC04_Loop(void) //数据处理函数计算前方物体和小车的距离
{
Trig = 1;
DelayUs(20);
Trig = 0;
while(Echo == 0);
TH1=0;
TL1=0;
TR1=1;
while(Echo == 1);
EchoCnt = (TH1*256 + TL1)*1.7/100;
}
void lanya()
{
while(1)
{
switch(num)
{
case 1: qianjin();break; //前进
case 2: zuozhuan();break; //左转
case 3: tingzhi();break; //停止
case 4: youzhuan();break; //右转
case 5: houtui();break; //后退
case 6: hongwaiyaokong();break; //启动红外遥控
case 7: xunji();break; //启动循迹功能
case 8: bizhang();break; //启动壁障功能
case 9: xunguang();break; //启动寻光功能
default:break;
}
}
}
/*蓝牙遥控电机程序*/
void qianjin()
{
in1=1;
in2=0;
in3=1;
in4=0;
}
void houtui()
{
in1=0;
in2=1;
in3=0;
in4=1;
}
void zuozhuan()
{
in1=1;
in2=0;
in3=0;
in4=0;
}
void youzhuan()
{
in1=0;
in2=0;
in3=1;
in4=0;
}
void tingzhi()
{
in1=0;
in2=0;
in3=0;
in4=0;
}
void hongwaiyaokong() // 红外遥控函数
{
TIM0init();
EX0init();
while(1)
{
if(irok) //如果接收好了进行红外处理 红外解码
{
Ircordpro();
irok=0;
}
if(irpro_ok) //如果处理好后进行工作处理,执行对应功能
{
Ir_work();
}
}
}
void xunji() // 循迹函数
{
DelayMs(1000); // 默认延时,等待系统稳定
while(1)
{
DcMotorContorl(FORWARD, 10);
if((XUNJI0 == 1) && (XUNJI1 == 0)) // 寻迹右边红外检测到黑线
{
DcMotorContorl(RIGHT, 14); // 小车往右边走
}
else if((XUNJI0 == 0) && (XUNJI1 == 1)) // 小车左边红外检测到黑线
{
DcMotorContorl(LEFT, 14); // 小车往左边走
}
else if((XUNJI0 == 0) && (XUNJI1 == 0)) // 小车左右都没有检测到黑线
{
DcMotorContorl(FORWARD, 10); // 小车直走
}
}
}
void bizhang(void) //壁障函数
{
HC04_Init();
while(1)
{
HC04_Loop(); //调用数据处理函数
if(EchoCnt < 25) // 距离小于25CM
{
DcMotorContorl(STOP, 20); // 小车停止
DcMotorContorl(RIGHT, 20); //小车右转
DelayUs(1500);
if(EchoCnt < 25)
{
DcMotorContorl(STOP, 20); // 小车停止
DcMotorContorl(RIGHT, 25); //小车右转
}
else
{
DcMotorContorl(FORWARD, 20); // 小车前进
}
}
else
{
DcMotorContorl(FORWARD, 20); // 小车前进
}
}
}
void xunguang(void) //寻光函数
{
DelayMs(1000); // 延时,等待系统稳定
while(1)
{
if((XUNGUANG0 == 1) && (XUNGUANG1 == 0)) // 寻光右边红外检测到光线
{
DcMotorContorl(RIGHT, 15); // 小车往右边走
}
else if((XUNGUANG0 == 0) && (XUNGUANG1 == 1)) // 小车左边红外检测到光线
{
DcMotorContorl(LEFT, 15); // 小车往左边走
}
else if((XUNGUANG0 == 0) && (XUNGUANG1 == 0)) // 小车左右都有检测到光线
{
DcMotorContorl(FORWARD, 20); // 小车直走
}
}
}
/*红外遥控电机程序*/
void DcMotorContorl(MOTOR_DIR dir,u8 speed)
{
switch(dir)
{
case FORWARD: // 前进
in1 = 1;
in2 = 0;
in3 = 1;
in4 = 0;
break;
case BACKUP: // 后退
in1 = 0;
in2 = 1;
in3 = 0;
in4 = 1;
break;
case LEFT: // 左转
in1 = 0;
in2 = 1;
in3 = 1;
in4 = 0;
break;
case RIGHT: // 右转
in1 = 1;
in2 = 0;
in3 = 0;
in4 = 1;
break;
case STOP: // 停止
in1 = 0;
in2 = 0;
in3 = 0;
in4 = 0;
break;
case ZHUANHUAN: //转换功能
lanya();
break;
case XUNJI: //循迹功能
xunji();
break;
case BIZHANG: //壁障功能
bizhang();
break;
case XUNGUANG: //寻光功能
xunguang();
break;
default: // 其他
in1 = 0;
in2 = 0;
in3 = 0;
in4 = 0;
break;
}
DelayMs(speed); // speed的值越大,速度越快
in1 = 1;
in2 = 1;
in3 = 1;
in4 = 1;
DelayMs(25 - speed); // speed的值越大,延时时间越短,速度越快
}
void DelayMs(u16 t)
{
u16 i,j;
for(i=0; i<t; i++)
for(j=0; j<120; j++);
}
void DelayUs(u16 i)
{
while(--i);
}
void Ir_work(void) //红外键值处理,红外键值转程序
{
switch(IRcord[2]) //判断第三个数码值
{
case 0x0c: // 数字1 //转换为蓝牙
DcMotorContorl(ZHUANHUAN, 0);
break;
case 0x18: // 数字2
DcMotorContorl(FORWARD, 20); // 小车直行
break;
case 0x5e: // 数字3
DcMotorContorl(XUNJI, 0); //循迹功能
break;
case 0x08: // 数字4
DcMotorContorl(LEFT, 20); // 小车左转
break;
case 0x1c: // 数字5
DcMotorContorl(STOP, 20); // 小车停止
break;
case 0x5a: // 数字6
DcMotorContorl(RIGHT, 20); // 小车右转
break;
case 0x42: // 数字7
DcMotorContorl(BIZHANG, 0); //壁障功能
break;
case 0x52: // 数字8
DcMotorContorl(BACKUP, 20); // 小车后退
break;
case 0x4a: // 数字9
DcMotorContorl(XUNGUANG, 0); //寻光功能
break;
case 0x16: // 数字0
break;
case 0x46: // Mode
DcMotorContorl(FORWARD, 20); // 小车直行
break;
case 0x40: // <-
DcMotorContorl(STOP, 20); // 小车停止
break;
case 0x44: // >||
DcMotorContorl(LEFT, 20); // 小车左转
break;
case 0x43: //->
DcMotorContorl(RIGHT, 20); // 小车右转
break;
case 0x15: // VOL-
DcMotorContorl(BACKUP, 20); // 小车后退
break;
default:
break;
}
//irpro_ok=0;//处理完成标志
}
void Ircordpro(void) //红外解码码值处理函数
{
unsigned char i, j, k;
unsigned char cord,value;
k=1;
for(i=0;i<4;i++) //处理4个字节
{
for(j=1;j<=8;j++) //处理1个字节8位
{
cord=irdata[k];
if(cord>7) //大于某值为1,这个和晶振有绝对关系,此值可以有一定误差
{
value=value|0x80;
}
else
{
value=value;
}
if(j<8)
{
value=value>>1;
}
k++;
}
IRcord[i]=value;
value=0;
}
irpro_ok=1; //处理完毕标志位置1
}
复制代码
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1