1、 综合课程设计报告题目: 迷宫电脑鼠的设计 二级学院 计算机科学与工程学院 专 业 计算机科学与技术 班 级 学生姓名 学号 指导教师 时 间 2015 01 17 II重庆理工大学综合课程设计报告 III目 录目 录I摘 要II1、课程设计的目的及要求11.1 课程设计目的11.2课程设计要求12、题目分析12.1 功能分析12.2 性能需求分析12.3 算法分析13、系统设计23.1系统整体设计23.2硬件设计33.2.1 硬件结构设计33.2.2 传感器组设计43.2.3 电机驱动电路设计73.3软件设计83.3.1 电脑鼠正常行走程序设计83.3.2 电脑鼠找终点程序设计113.3.3
2、 程序设计124 总结274.1 所遇问题及解决办法274.2 心得体会28摘 要“电脑鼠”是使用单片机微控制器,传感器和机电运动部件构成的一种智能行走装置。一只电脑鼠是具有机电知识整合的基本构架,本身就像是一个智能的机器人。要在指定的迷宫中比赛,就像是一个人置身竞赛中一样,必须要靠自己的判断力,敏捷动作及正确探查周边坏境。一般来说一只电脑鼠具备有以下两个基本能力:拥有稳定且快速的行走能力;正确判断能力。 重庆理工大学综合课程设计报告 1、课程设计的目的及要求1.1 课程设计目的(1)了解并熟悉电子元器件焊接技术与方法。(2)了解并熟悉电子元器件工作原理和功能特性。(3)掌握单片机对编码电机的
3、控制与红外发射与接收的控制。(4)熟练运用keil软件进行单片机的C语言编程。1.2课程设计要求走有一定弯度、曲折度、路线单一的迷宫。2、题目分析2.1 功能分析(1)迷宫电脑鼠能够在迷宫中随意穿行。由于迷宫中有很多挡板,要使电脑鼠能够在迷宫中随意穿行,就要让电脑鼠遇到挡板的时候能够转弯找到一条可通行的路,所以就要用到用来检测挡板的传感器。还要电脑鼠能够左转、右转和前进,所以必须要写出这四个功能函数,不然电脑鼠就不能在迷宫中行走。2.2 性能需求分析1、迷宫电脑鼠外形合理,符合88迷宫场地需求。2、迷宫电脑鼠运行稳定,能够正常在迷宫中随意穿行。2.3 算法分析此次迷宫电脑鼠主要用到了这几个算法
4、:左手法则、右手法则和车头方向、转弯算法、修正算法。转弯算法:当遇到障碍物向左转90度或者右转90度或者向后转。修正算法:当在迷宫中走偏后能够自动修正方向。左手法则:小车在搜过程中有两个以上的搜索方向时,优先选择向左转,其次是向前行进,最后才考虑向右转弯。右手法则:小车在搜过程中有两个以上的搜索方向时,优先选择向右转,其次是向前行进,最后才考虑向左转弯。车头方向:迷宫机器鼠的车头有绝对方向和相对方向之分。绝对方向:以小车刚开始运行的时候车头面向的方向作为“上”,其它方向类推。相对方向:顾名思义,相对于当前小车所朝向的方向的方向。机器鼠转弯时要修整方向为绝对方向。用数字0,1,2,3分别表示上,
5、右,下,左,修正公式为:转弯后的绝对方向=(转弯前的绝对方向+转弯数值)% 4,如图所示。绝对方向转弯前的方向转弯方向转弯后的方向0(上方)向左(+3)向左(0+3)%4 = 30(上方)向右(+1)向右(0+1)%4 = 10(上方)向后(+2)向后(0+2)%4 = 21(右方)向左(+3)向上(1+3)%4 = 01(右方)向右(+1)向下(1+1)%4 = 21(右方)向后(+2)向左(1+2)%4 = 32(下方)向左(+3)向右(2+3)%4 = 12(下方)向右(+1)向左(2+1)%4 = 32(下方)向后(+2)向上(2+2)%4 = 03(左方)向左(+3)向下(3+3)
6、%4 = 23(左方)向右(+1)向上(3+1)%4 = 03(左方)向后(+2)向右(3+2) %4 = 13、系统设计3.1系统整体设计系统的功能函数:延时函数功能:延时电机驱动函数功能:启动和停止左右电机电机初始化函数功能:初始化电机中断函数功能:T0、T1用来计数左右电机的脉冲数;T2用来产生红外信号系统初始化函数功能:初始化整个系统红外传感器函数功能:当遇到障碍物时点亮LED灯转弯函数1功能:左转和右转任意角度转弯函数2功能:左转90度,右转90度,向后转前进一步函数功能:电脑鼠在迷宫前进一个方格距离主程序流程图:3.2硬件设计3.2.1 硬件结构设计硬件电路部分主要由单片机最小系统
7、电路、传感器电路、电机驱动电路构成。如图所示,是硬件电路部分结构框图。单片机传感器组5传感器组4传感器组3传感器组2传感器组138KHz载波发生器3-8译码选择器显示器蜂鸣器电机1电机2驱动电路1驱动电路2操作按键1、微控制器微控制器是电脑鼠的核心,可以选择单片机,若RAM需求量大或者算法复杂或者性能要求高时,需要使用ARM等高性能的微处理器。2、传感器传感器的作用是用来感知环境,探测电脑鼠的左、前、右是否有路可走。本设计中采用的是红外线方式,发射和接收分别受微控制器控制。由硬件电路部分结构框图可知,在电脑鼠的前、左、右、左前、右前方共有5组,其中左、右、前三组传感器是用于探测电脑鼠在当前迷宫
8、格左、右、前三个方向上是否有支路的,左前、右前两组传感器呈45度安装,用于电脑鼠行进过程中进行姿态矫正,防止电脑鼠走偏而撞到迷宫墙。3、显示器显示器是用来显示当前位置等相关信息的,是电脑鼠的可选部分。4、电源电源用来为单片机供电,选择哪种电池,这也将影响电路的设计。5、蜂鸣器当电脑鼠到底终点、或是返回到起点,可以用蜂鸣器来提示,是电脑鼠的可选部分。3.2.2 传感器组设计(1)传感器的选择电脑鼠有5组传感器。这5组传感器分别安装于电脑鼠的左、左前、前、右前、右5个不同的方向,其中左、右、前三组传感器是用于探测电脑鼠在当前迷宫格左右前三个方向上是否有支路的,左前、右前两组传感器呈45度安装,用于
9、电脑鼠行进过程中进行姿态矫正,防止走偏而撞到迷宫墙。如图所示,是用于电脑鼠环境感知的传感器组电路。传感器组电路由红外发射LED和红外一体化接收头HS0038构成,红外LED由前面载波发生器产生的CLOCK信号驱动产生38KHz红外调制光。RP1为可调电阻,通过调节RP1来调节红外LED发光强度,从而调整传感器组检测迷宫墙障碍物的距离,RP1电阻越大,检测距离越近,电阻越小,检测距离越远。irT1用于控制该组传感器是否工作,连接到3-8译码选择电路。红外调制光经障碍物反射由HS0038红外一体化接收头接收,进行放大滤波、解调等处理后由irR1输出,单片机通过识别irR1位的高低电平来判断传感器前
10、面是否有障碍物。这里只给出了一组传感器,另外四组传感器也与该组传感器相同的。电脑鼠通过对这五组传感器信息的融合,实现环境感知功能。(2)74HC138译码器74HC138译码器可接受3位二进制加权地址输入(A0, A1和A2),并当使能时,提供8个互斥的低有效输出(Y0至Y7)。74HC138特有3个使能输入端:两个低有效(E1和E2)和一个高有效(E3)。除非E1和E2置低且E3置高,否则74HC138将保持所有输出为高。1、74HC138的引脚如图所示:2、74HC138的译码/真值表如下表所示:译码/真值表应用:例如A0A1A2地址为000时,74HC138输出Y0有效,从而使第一组传感
11、器工作,而其他组传感器处于没有工作的状态。这样就可以实现单片机的3个引脚控制5个或者更多的传感器组。如图所示,是硬件电路部分3-8译码选择器电路。(3)载波发生器传感器组是由38KHz的红外一体化接收头和红外发射管构成的障碍感测器。为了能够让传感器组正常工作,红外发射管需要一个38KHz的方波来驱动,使红外发射管发射出调制频率与接收头接收频率匹配的红外光。如图所示,是产生38KHz方波的载波发生器电路。(4)传感器的调试(主要写每组传感器如何进行调试。)1、左右两边的传感器检测是否有墙壁。2、左前和右前45角的两组传感器用于电脑鼠在行走过程中的微调。3、传感器上标的1、2、3、4、5对应led
12、的1、2、3、4、5(里面往前数)。4、传感器的测距是通过条对应的可调电阻来实现的,可调电阻顺时针转动调近,逆时针调远传感器的测试距离。3.2.3 电机驱动电路设计如图所示,是用来驱动电脑鼠伺服电机的驱动电路。由于单片机I/O口电流输出能力有限,不能直接驱动电机转动。为了能让单片机控制电机运转,需要使用电机驱动电路,将单片机I/O口弱电流放大到足以驱动电机的电流。1、L9110器件的管脚图如图所示。2、 管脚定义如下:3、通过L9110驱动芯片IA、IB输入的逻辑值的组合,不同高低电平的输入输出,控制电机正转、反转、停转。L9110的逻辑关系表如下表所示:L9110逻辑关系IAIBOAOBHL
13、HL正转LHLH反转LLLL停止HHLL停止3.3软件设计3.3.1 电脑鼠正常行走程序设计电脑鼠正常行走包括直走、左转弯、右转弯和向后转弯四个功能函数。这四个功能函数中要用到T0、T1定时/计数器;所以函数中首先初始化T0、T1。T0初始化:打开总开关EA=1;开T0中断ET0=1;设定T0模式2,8位自动重装值定时计数器TMOD&=0xf6; TMOD|=0x06; 设定T0计数初值,定义中断脉冲数TH0=256-ICP;TL0=256-ICP; /启动T0计数TR0=1;T1初始化也是一样的。为了使左右电机的转速尽可能相同,我们可以设定一个值,在这个值内,如果T0的脉冲数Count0大于
14、T1的脉冲数Count1,就停止左电机,转动右电机;当Count0Count1时,停止右电机,反转左电机;当Count0Count1时,停止右电机,正转左电机;当Count0Count1时,停止右电机,正转左电机;当Count0前左后。规定电脑鼠起点车头方向为北,顺时针依次为北、东、南、西,分别用0、1、2、3代表;在左转右转和后转中,每转一次向就更新一次当前的绝对方向,然后向前行进一步并更新当前坐标,然后将当前坐标与终点坐标比较,若当前坐标为终点坐标,则蜂鸣器响一声表示已到达终点坐标;否则继续用右手法则探路直到到达终点坐标为止。右手法则:3.3.3 程序设计1.头文件#include #de
15、fine ICP 35/位定义左右电机sbit ML1=P20;sbit ML2=P21;sbit MR1=P22;sbit MR2=P23;/指示灯接口定义sbit LED1=P00;sbit LED2=P01;sbit LED3=P02;sbit LED4=P03;sbit LED5=P04;sbit LED6=P05;sbit LED7=P06;sbit LED8=P07;/红外地址接口定义(74HC138译码器sbit A0=P12;sbit A1=P13;sbit A2=P14;/红外传感器接口定义sbit irR1=P25;/左外sbit irR2=P26;/中sbit irR3=
16、P27;/右外sbit irR4=P36;/左sbit irR5=P37;/右/按键接口定义sbit key=P10;/蜂鸣器接口定义sbit SPEAK=P24;2.符号定义#includehys.hbit irL,irR,irZ,irZL,irZR; /依次为左、右、前、左前、右前unsigned char endX,endY,X,Y,exchangeX,exchangeY,Count0,Count1; unsigned char now_direct; /绝对方向unsigned char arrived; /定义到达终点坐标时要用到的的一个符号3.延时函数代码/在24M晶振下,延时1m
17、s,12M倍频void delay(unsigned char ms)unsigned char X;while(ms-)X=250;while(-X);/延时250us X=250;while(-X);/延时250usX=250;while(-X);/延时250us X=250;while(-X);/延时250us4.驱动配置代码/*电机驱动函数*/左电机停止void STOPML()ML1=0;ML2=0;/右电机停止void STOPMR()MR1=0;MR2=0;/启动左电机void RUNML(bit i)if(i)ML1=1;ML2=0;elseML1=0;ML2=1;/启动右电机
18、void RUNMR(bit i)if(i)MR1=1;MR2=0;elseMR1=0;MR2=1;/*电机初始化函数*/void init_motor()ML1=0;ML2=0;MR1=0;MR2=0;5.中断函数代码/T2中断周期设定函数,最大30msvoid set_Timer2(unsigned int m)TH2=RCAP2H=(65535-m)/256;TL2=RCAP2L=(65535-m)%256;/设定T2自动重装载寄存器和计数器初值void init_Timer2(unsigned int m)/中断定时获取 传感器返回的值EA=1;ET2=1;TH2=RCAP2H=(65
19、535-m)/256;TL2=RCAP2L=(65535-m)%256;/设定T2自动重装载寄存器和计数器初值/捕捉/自动重载寄存器TR2=1;/*中断函数*/T0中断函数/右电机void timer0() interrupt 1/外部中断1/工作模式2.自动重装初值Count0+;/T1中断函数/左电机void timer1() interrupt 3 /外部中断2/工作模式2.自动重装初值Count1+;/T2中断函数void Timer2() interrupt 5static unsigned char intC=1,irNo=1;TF2=0;/软件清除溢出中断标志位/中断服务代码if
20、(intC=1)switch(irNo)case 1:A0=0;A1=0;A2=0;intC=1;set_Timer2(2000);/发射2usbreak;case 2:if(irR1) /如果irR1为高电平irZL=0; /没有障碍物 置低电平0LED1=1; /熄灭LED灯else /如果irR1低电平irZL=1; /有障碍物 置高电平1LED1=0; /点亮LED灯A0=1;A1=0;A2=0;intC=1;set_Timer2(2000);break;case 3:if(irR2)irZ=0;LED2=1;else irZ=1;LED2=0;A0=0;A1=1;A2=0;intC=
21、1;set_Timer2(2000);break;case 4:if(irR3)irZR=0;LED3=1;else irZR=1;LED3=0;A0=1;A1=1;A2=0;intC=1;set_Timer2(2000);break;case 5:if(irR4)irL=0;LED4=1;else irL=1;LED4=0;A0=0;A1=0;A2=1;intC=1;set_Timer2(2000);break;case 6:if(irR5)irR=0;LED5=1;else irR=1;LED5=0;A0=1;A1=1;A2=1;intC=2;set_Timer2(20000);break
22、;if(irNo6)irNo+;else irNo=1;elseintC-;6.系统初始化函数代码/*/系统初始化函数void init_system()/起点坐标初始化X=0;Y=0;/设置终点坐标endX=7;endY=7;/小车的当前方向初始化now_direct=0;/变量初始化Count0=0;Count1=0;init_motor();/初始化T2,自动传感器采样init_Timer2(2000);arrived=0;key=0;7.红外传感器void ir_Test()if(irZL)LED1=0;elseLED1=1;if(irL)LED4=0;elseLED4=1;if(ir
23、Z)LED2=0;elseLED2=1;if(irZR)LED3=0;elseLED3=1;if(irR)LED5=0;elseLED5=1;/delay(100);8.转弯函数/*向左转函数(转的角度通过参数控制)*/void left(unsigned char m)/T0初始化EA=1;/打开总开关ET0=1;/开T0中断TMOD&=0xf6;TMOD|=0x06;/设定T0模式2,8位自动重装值定时计数器TH0=256-ICP;TL0=256-ICP;/设定T0计数初值,定义中断脉冲数TR0=1;/启动T0计数/T1初始化EA=1;/打开总开关ET1=1;/开T1中断TMOD&=0x6
24、f;TMOD|=0x60;/设定T1模式2,8位自动重装值定时计数器TH1=256-ICP;TL1=256-ICP;/设定T1计数初值,定义中断脉冲数TR1=1;/启动T1计数Count0=0;Count1=0;while(Count0m)|(Count1m)if(Count0Count1)STOPML();/左轮停止RUNMR(1);/右轮正转else STOPMR();/右轮停止RUNML(0);/左轮反转STOPML();STOPMR();/*向右转函数(转的角度通过参数控制)*/void right(unsigned char m)/T0初始化EA=1;/打开总开关ET0=1;/开T0
25、中断TMOD&=0xf6;TMOD|=0x06;/设定T0模式2,8位自动重装值定时计数器TH0=256-ICP;TL0=256-ICP;/设定T0计数初值,定义中断脉冲数TR0=1;/启动T0计数/T1初始化EA=1;/打开总开关ET1=1;/开T1中断TMOD&=0x6f;TMOD|=0x60;/设定T1模式2,8位自动重装值定时计数器TH1=256-ICP;TL1=256-ICP;/设定T1计数初值,定义中断脉冲数TR1=1;/启动T1计数Count0=0;Count1=0;while(Count0m)|(Count1m)if(Count0Count1) STOPML();/左轮停止RU
26、NMR(0);/右轮反转else STOPMR();/右轮停止RUNML(1);/左轮正转STOPML();STOPMR();/*向左转、右转、转身*/void turnleft()/左转90度并更新当前绝对方向left(35);now_direct=(now_direct+3)%4;/修正当前方向为绝对方向void turnright()/右转90度并更新当前绝对方向 right(35);now_direct=(now_direct+1)%4;/修正当前方向为绝对方向void turnback()/向后转更并新当前绝对方向left(72);now_direct=(now_direct+2)%
27、4; /修正当前方向为绝对方向9.前进一步函数/*走一步函数(每走一步就判断是否到达终点)*/void Go_one_step()unsigned char tmp0,tmp1;/T0初始化EA=1;/打开总开关ET0=1;/开T0中断TMOD&=0xf6;TMOD|=0x06;/设定T0模式2,8位自动重装值定时计数器TH0=256-ICP;TL0=256-ICP;/设定T0计数初值,定义中断脉冲数TR0=1;/启动T0计数/T1初始化EA=1;/打开总开关ET1=1;/开T1中断TMOD&=0x6f;TMOD|=0x60;/设定T1模式2,8位自动重装值定时计数器TH1=256-ICP;T
28、L1=256-ICP;/设定T1计数初值,定义中断脉冲数TR1=1;/启动T1计数Count0=0;Count1=0;while(Count086)|(Count1Count1)STOPMR();/右轮停止RUNML(1);/正转左轮elseSTOPML();/左轮停止RUNMR(1);/正转右轮xy_repair(); /更新当前坐标arrive(); /判断是否到达指定坐标 init_motor();/初始化电机10.右手法则/*右手法则*/void righthand()switch(now_direct)case 0: / 当前方向向北if(!irR) /如果右边没有障碍turnrig
29、ht(); /先向右转并更新绝对方向Go_one_step();/再前进一步并且更新坐标并判断是否到达指定坐标break;if(!irZ) /如果前方没有障碍Go_one_step();/向前走一步并且更新坐标并判断是否到达指定坐标break;if(!irL) /如果左方没有障碍物turnleft(); /先左转并更新绝对方向Go_one_step(); /再前进一步并且更新坐标并判断是否到达指定坐标break;else /如果左、右、前方都有障碍物turnback();/先向后转并更新绝对方向Go_one_step();/再前进一步并且更新坐标并判断是否到达指定坐标break;case 1:
30、/当前方向向东if(!irR)turnright();Go_one_step();break;if(!irZ)Go_one_step();break;if(!irL)turnleft();Go_one_step();break;elseturnback();Go_one_step();break;case 2:/当前方向向南if(!irR)turnright();Go_one_step();break;if(!irZ)Go_one_step();break;if(!irL)turnleft();Go_one_step();break;elseturnback();Go_one_step();b
31、reak;case 3: /当前方向向西if(!irR)turnright();Go_one_step();break;if(!irZ)Go_one_step();break;if(!irL)turnleft();Go_one_step();break;elseturnback();Go_one_step();break;11.主函数void main()char s1=key;/按键开关init_system();/初始化系统if(s1)/按下开关键delay(500);while(1)/ir_Test();/可以不调用这个函数righthand(); /右手法则寻路if(arrived=1) /到达终点arrived=0;turnba