- #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
- }
复制代码 |