避障小车程序实现功能:
1.蓝牙控制,重力感应,通过串口通讯实现手机和蓝牙之间的连接控制用到hc-06模块
2.循迹壁障,遇见障碍能够及时躲避,通过舵机带动hc-sr04超声波模块的左右转动来测量前左右的障碍
3.跟踪,可以追踪一个物体,物进车进,物退车退
4.走黑线,不同颜色的物体对光的反射不同
4.pwm速度快慢调速,通过pwm调节l298n产生脉宽调制
5.开灯,通过手机控制单片机的io口输出高低电频实现
6.喇叭,高低电频产生震荡
********************************************************************************/
/********************************************************************************
避障小车出现的问题:
1.主要是定时器优先级别问题,解决办法调节定时器优先级别,第一次掌握了定时器二的用法,这是52特有的
2.切记,定时器0不能和定时器1互换,因为定时器1优先级没有0高,互换会导致超声波测距模块接受不到数据
3.出现模块从谍,的问题,解决办法用标记把可能出问题模块一个一个标记;最后发现原来是延时函数名字相同
4.字符串不能直接比较需要用if(strcmp(字符串,字符串2)==0)如果一样就返回一个0,如果一比二大就返回
一个正数否则返回负数记住需要包含#include<string.h>头文件
5.舵机不能两个地方同时出现归中,刚开始以为是定时器优先级别的问题,打开定时器1串口通讯就会制动打开
所以我在串口函数里设了点亮led灯来测试串口中断是否自己打开,然后我先是注释ET1发现程序正常,
后面又注释掉中断3发现程序正常,说明不是定时器设置问题, 注释掉中断三里的内容发现也正常说明不是中断引起的
然后注释掉舵机pwm调速,发现也正常说明不是小车档位pwm的问题最后注释掉小车快慢pwm调速,发现舵机函数有问题
然后注释掉舵机pwm调速里的eles发现不正常,之后尝试了改pwm输出口的名字以及io口发现都没用,最后拔掉舵机信号线
发现有用,说明舵机初始化有问题,最后把初始化里的归中14,该成0,发现能正常运作,最后把初始化该成14,注释掉
超声波次主函数的归中发现能正常运作,说明两个归中只能要一个。
结论;一点要细致认真,勤于思考,碰到问题要迎难而上因为编程本来就是个改错的过程别碰到问题就想着
问别人,因为自己的程序只有自己最了解,写代码一定要规范,免得到时后乱起来连自己都看不懂。
11月13日,吴才成
下面是制作的避障小车的实物图:
51单片机避障小车源程序如下:
- #include<AT89X52.H>
- #include<string.h> //字符串比较头文件
- #include <intrins.h> //nop的头文件
- #define Left_moto_go {P3_1=1,P3_2=0,P3_3=1,P3_4=0;} //左边两个电机向前走
- #define Left_moto_back {P3_1=0,P3_2=1,P3_3=0,P3_4=1;} //左边两个电机向后转
- #define Left_moto_Stop {P3_1=0,P3_2=0,P3_3=0,P3_4=0;} //左边两个电机停转
- #define Right_moto_go {P1_4=1,P1_5=0,P1_6=1,P1_7=0 ;} //右边两个电机向前走
- #define Right_moto_back {P1_4=0,P1_5=1,P1_6=0,P1_7=1;} //右边两个电机向前走
- #define Right_moto_Stop {P1_4=0,P1_5=0,P1_6=0,P1_7=0;} //右边两个电机停转 */
- /***************************************************************/
- //蓝牙的设置
- /*****************************************************************/
- void zxddc (); //转向灯 后退 刹车指示灯
- void zxdzz (); //转向灯左转
- void zxdyz (); //转向灯右转
- void zxdgd (); //转向灯关灯
- sbit LEDHZ = P3^5; //转向灯左边
- sbit LEDHY = P3^6; //转向灯右边
- sbit LED1 = P1^0 ; //左方向灯
- sbit LED2 = P1^1 ; //右方向灯
- sbit fmq = P1^2 ; //喇叭,蜂鸣器
- int pwmjishu = 0 ; //pwm调速
- int pushjishu = 0 ; //pwm调速
- sbit ena1 = P2^7;
- sbit enb1 = P2^6; //l298npwm调速引脚
- sbit ena2 = P2^5;
- sbit enb2 = P2^4;
- unsigned char data table[4]={ 0,0,0,};//用来装串口发送过来的字符串,不包括0
- /***************************************************************/
- //超声波的设置
- /*********************************************************/
- #define CSBPWM P2_2 //接舵机信号端输入PWM信号调节速度
- #define ECHO P2_0 //超声波接口定义
- #define TRIG P2_1 //超声波接口定义
- unsigned char disdat[4]={ 0,0,0,0,};
- unsigned char pwm_val_left = 0;//变量定义
- unsigned char push_val_left =0;//14;//舵机归中,产生约,1.5MS 信号
- unsigned long S=0;
- unsigned long S1=0;
- unsigned long S2=0;
- unsigned long S3=0;
- unsigned long S4=0;
- unsigned int time=0; //时间变量
- unsigned int timer=0; //延时基准变量
- unsigned char timer1=0; //扫描时间变量
- void qianj(void) //前进
- {
- Left_moto_go ; //左电机往前走
- Right_moto_go ; //右电机往前走
- }
- /************************************************************************/
- //全速后退
- void hout(void) //后退
- {
- Left_moto_back ; //左电机往前走
- Right_moto_back ; //右电机往前走
- zxddc (); //后退指示灯
- }
- /********************* ***************************************************/
- //左转 //左转
- void zuoz(void)
- {
- Left_moto_back ; //左电机往前走
- Right_moto_go ; //右电机往前走
- zxdzz (); //左转指示灯
- }
- /************************************************************************/
- //右转
- void youz(void) //右转
- {
- Left_moto_go ; //左电机往前走
- Right_moto_back ; //右电机往前走
- zxdyz (); //右转指示灯
- }
- /************************************************************************/
- //STOP
- void tingz(void) //停止
- {
- Left_moto_Stop ; //左电机停走
- Right_moto_Stop ; //右电机停走
- zxdgd (); //车子停止指示灯关闭
- }
- /************************************************************************/
- /************************************************************************/
- void delay1(unsigned int k) //延时函数
- {
- unsigned int x,y;
- for(x=0;x<k;x++)
- for(y=0;y<2000;y++);
- }
- /******************************//*******************************************/
- void delay_50us(unsigned int z) //延时函数
- {
- unsigned int x,y;
-
- for(x=z;x>0;x--)
- for(y=110;y>0;y--);
-
- }
- /*************************************************/
- void StartModule() //启动测距信号
- {
- TRIG=1; //给10us以上的高电频
- _nop_(); //_nop_()一个机器周期,1us
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- TRIG=0;
- }
- /***************************************************/
- /**************************************************/
- void Conut(void) //计算距离
- {
- while(!ECHO); //当RX为零时等待
- TR0=1; //开启计数
- while(ECHO); //当RX为1计数并等待
- TR0=0; //关闭计数
- time=TH0*256+TL0; //读取脉宽长度
- TH0=0;
- TL0=0;
- S=(time*1.7)/100; //算出来是CM
- }
- void COMM( void ) //方向计算
- {
- push_val_left=5; //舵机向左转90度
- timer=0;
- while(timer<=4000); //延时400MS让舵机转到其位置
- StartModule(); //启动超声波测距
- Conut(); //计算距离
- S2=S;
-
- push_val_left=23; //舵机向右转90度
- timer=0;
- while(timer<=4000); //延时400MS让舵机转到其位置
- StartModule(); //启动超声波测距
- Conut(); //计算距离
- S4=S;
- push_val_left=14; //舵机归中
- timer=0;
- while(timer<=4000); //延时400MS让舵机转到其位置
- StartModule(); //启动超声波测距
- Conut(); //计算距离
- S1=S;
- if((S2<20)||(S4<20)) //只要左右各有距离小于20CM小车后退
- {
- hout(); //后退
- timer=0;
- while(timer<=4000);
- }
- if(S2>S4)
- {
- youz(); //车的左边比车的右边距离小 右转
- timer=0;
- while(timer<=4000);
- }
- else
- {
- zuoz(); //车的左边比车的右边距离大 左转
- timer=0;
- while(timer<=4000);
- }
- }
- /**********************************************************************************
- 舵机pwm调速,和小车换挡调速共用一个定时器
- ***********************************************************************************/
- void pwm_Servomoto()
- {
-
- if(pwm_val_left<=push_val_left)
- CSBPWM=1;
- else
- CSBPWM=0;
- if(pwm_val_left>=200)
- pwm_val_left=0;
- }
- /************************************************************/
- void Delay(unsigned int i)
- {
- char j;
- for(i; i > 0; i--)
- for(j = 200; j > 0; j--);
- }
- /*****************************************************************/
- void fangx() //方向函数
- {
- if(strcmp(table,"ONA")==0) qianj();//前进
- else if(strcmp(table,"ONB")==0) hout();//后退
- else if(strcmp(table,"ONC")==0) zuoz();//左转
-
- else if(strcmp(table,"OND")==0) youz ();//右转
- else tingz();//停止
-
- // if((a[0]=='O')&&(a[1]='N')&&(a[2]=='A')&&(a[3]==0)) qianj();
- /*if(a=="ONA")qianj();//前进 总结字符串不能用==比较需要调用内部库函数
- else if(a=="ONB") hout();//后退
- else if(a=="ONC") zuoz();//左转
-
- else if(a=="OND") youz();//右转
-
- else tingz();//停止 */
- }
- /*****************************************************************************/
- void dangwei() //档位函数
- {
- if (strcmp(table,"ON1") ==0 )
- pushjishu=0;
- if (strcmp(table,"ON2") ==0 ) //判断是否按下按键
- {
- //pushjishu=pushjishu+10;
- pushjishu+=10; //x+=y;相当与x=x+y;这样使程序更精炼
- while (strcmp(table,"ON2") ==0 ); //当按键按下的时候进入while循环执行分号空语句,
- //当按键是释放跳出while循环,很好的使按键按下一次执行一次,不会跑飞
- }
- if (strcmp(table,"ON3") ==0 )
- {
- //pushjishu=pushjishu-10;
- pushjishu-=10;
- while (strcmp(table,"ON3") ==0 );
- }
- /* if (strcmp(table,"ON4") ==0 )
- pushjishu=105;
- /*if(strcmp(table,"ON5")==0)
- pushjishu=160;
- if(strcmp(table,"ON6")==0)
- pushjishu=200; */
- }
- /**************************************************************************/
- void zxddc () //转向灯 后退 刹车指示灯 。函数需要在前面声明,因为电机函数定义在此函数前面,在电机函数调用此函数会出现错误
- {
- LEDHZ = 0;
- LEDHY = 0;
- }
- void zxdzz () //转向灯左转
- {
- LEDHZ = 0;
- LEDHY = 1;
- }
- void zxdyz () //转向灯右转
- {
- LEDHZ = 1;
- LEDHY = 0;
- }
- void zxdgd () //转向灯关灯
- {
- LEDHZ = 1;
- LEDHY = 1;
- }
- /***************************************************************************/
- void kaideng() //开前大灯灯函数
- {
- if ( strcmp(table,"ON7") == 0 ) //开灯
- {
- LED1=0;
- LED2=0;
- }
- if ( strcmp(table,"ON8") == 0 )//关灯
- {
- LED1=1;
- LED2=1;
- }
- }
- /*************************************************************************/
- void laba()
- {
- if(strcmp(table,"ON9")==0)
- {
- fmq = 1; //给高电平
- Delay(5); //延时
- fmq = 0; //给低电平
- Delay(5);
- }
- }
- /**********************************************************/
- void pwm(void)//小车快慢pwm调速,是通过l298n完成的
- {
- if(pwmjishu<=pushjishu)
- {
- ena1 = 0;
- enb1 = 0;
- ena2 = 0;
- enb2 = 0; //l298n,实现pwm调速,当给高电频的时候io引脚有效,给低电平时无效
- }
- else
- {
- ena1 = 1 ;
- enb1 = 1 ;
- ena2 = 1 ;
- enb2 = 1 ;
- }
- if(pwmjishu >= 200)
- pwmjishu = 0;
- }
- /*******************************************************************************
- 超声波魔术手程序
- *******************************************************************************/
- void moss ()
- {
- Delay (100);
- push_val_left=14; //舵机归中
- while(1) /*无限循环*/
- {
- dangwei();//档位
- if(strcmp(table,"ON6")==0) //判断按键 是否按下如果按下就退出csbmian函数,return结束函数
- return;
- if(timer>=1000) //100MS检测启动检测一次
- {
- timer=0;
- StartModule(); //启动检测
- Conut(); //计算距离
- if(S<10) //距离小于20CM
- hout(); //小车停止
- if(20>S&&S>10) //距离小于20CM
- tingz();
- if(30>S&&S>20) //距离大于,30CM往前走
- qianj();
- else
- if(S>35)
- tingz();
- }
- }
- }
- /****************************************
- 超声波壁障主函数
- /***************************************************************/
- /* delay_50us(500);
- TMOD=0X11;
- TH1=(65536-100)/256; //100US定时
- TL1=(65536-100)%256;
- TH0=0;
- TL0=0;
- TR1= 1;
- ET1= 1;
- ET0= 1;
- EA = 1; */
- void csbmian ()
- {
- timer=0;
- push_val_left=14; /*舵机归中,在初始化的时候归要不在这归中,如果两个地方贵在程序就会出现毛病 两个地方
- 同时归中串口中断无缘无辜的会打开,导致车子不能串口通讯, */
- delay1(50);
- while(1) //无限循环//
- {
- dangwei();//档位
- kaideng(); //开灯函数
- laba(); //鸣笛函数
-
- if(strcmp(table,"ON6")==0) //判断按键 是否按下如果按下就退出csbmian函数,return结束函数
- return;
-
- if(timer>=1000) //100MS检测启动检测一次
- {
- timer=0;
- StartModule(); //启动检测
- Conut(); //计算距离
- if(S<45) //距离小于20CM
- {
- hout();
- hout(); //刹车
- hout();
- tingz(); //小车停止
- COMM(); //方向函数
- }
- else
- if(S>45) //距离大于,30CM往前走
- qianj();
- }
- }
- }
-
- /**********************************************************/
- void main()
- {
- T2CON=0x30; //设置定时器二为串口波特率模式
- SCON=0x50; //设置串口方式为1
- RCAP2H=0xff;
- RCAP2L=0xdc; //定时器二自动装初值16位
- TH2=0xff;
- TL2=0xdc; //定时器二
- TR2=1; //启动定时器2
- ES=1; //打开串口中断
- PS=1; //串口优先级设置为最高
- TMOD=0X11; //打开定时器0和定时器1,工作做方式一
- TH1=(65536-100)/256; //100US定时
- TL1=(65536-100)%256;
- ET1=1 ; //打开定时器一中断
- TR1=1 ; //启动定时器一
- TH0=0; //定时器0初始化
- TL0=0; //切记定时器0不能和定时器一互换,因为定时器0优先级比1高,如果换了以后就不能接收超声波了
- ET0=1; //打开定时器0中断
- EA=1; //打开总中断
-
-
-
- /* T2CON=0x30;
- SCON=0x50; //设置串口方式为1
- RCAP2H=0xff;
- RCAP2L=0xdc;
- TH2=0xff;
- TL2=0xdc;
- TMOD=0X11; //打开定时器0和定时器1,工作做方式一
- TH1=(65536-100)/256; //100US定时
- TL1=(65536-100)%256;
- TH0=0; //定时器0初始化
- TL0=0;
- ET1=1 ;
- ET0= 1; //打开定时器0中断
- TR2=1;
- ES=1;
- PS=1;
- EA=1;
- /*******************************************/
- /* TMOD=0X11;
- TH1=(65536-100)/256; //100US定时
- TL1=(65536-100)%256;
- TH0=0;
- TL0=0;
- TR1= 1;
- ET1= 1;
- ET0= 1;
- EA=1; //总开关
- /******************************************/
- //单独蓝牙的串口设置
- /******************************************/
- /*TMOD=0x21;//定时器1工作方式2,8位自动重装
- TH0=(65536-100)/256; //100US定时
- TL0=(65536-100)%256;
- TH1=0xFd; //11.0592M晶振,9600波特率
- TL1=0xFd;
- PS=1;
- ET0=1 ;
- TR0=1 ;
- TR1=1 ;//打开定时器1
- SM0=0 ;//串口方式1 SM0 SM1 01 允许接收
- SM1=1 ;//SMOD=0 16分频
- REN=1 ;
- ES=1 ;//打开串口中断
- EA=1;//开总中断 */
- //以上跟串口通信初始化有关
- while(1)
- {
- dangwei();//档位
- fangx(); //方向函数
- kaideng(); //开灯函数
- laba(); //鸣笛函数
- if(strcmp(table,"ON5")==0)//判断是否按下第五个按键,按下则启动超声波模式
- csbmian (); //超声波模块的主函数
- if(strcmp(table,"ON4")==0)//判断是否按下第四个按键,按下则启动超声波魔术手
- moss (); //超声波魔术手模块的主函数
- }
- }
- /***************************************************/
- ///*TIMER1中断服务子函数产生PWM信号*/
- void pwmdins()interrupt 3 //定时器一,优先级别最低
- {
- TH1=(65536-100)/256; //100US定时
- TL1=(65536-100)%256;
- pwmjishu++; // 小车快慢的pwm调速
- pwm(); //小车快慢的pwm函数
- timer++; //超声波的基准 定时器100US为准。在这个基础上延时
- pwm_val_left++; //舵机的pwm调速基准时间
- pwm_Servomoto(); //舵机pwm调速函数
- }
- /***************************************************/
- ///*TIMER0中断服务子函数产生PWM信号*/
- void timer0()interrupt 1 //因为串口优先级别变最高所以定时器0位第二高
- {
- }
- /***************************************************/
- void serial() interrupt 4 //中断子函数 //ps=1;使之优先级最高
- {
- int i;
- ES=0; //关闭串口中断,其实不关也没影响
- table[i++]=SBUF; //数组下标加一,把字符串变成字符字单个取出存入数组,使之成为一元素
- if(i==3) //字符串有三个字符,不包括标志位0
- i=0; //使之清零以便下次从收
- RI=0; //串口标志位硬件制一,手动清零
- ES=1; //打开串口
- …………
- …………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
原理图: 无
仿真: 无
代码:
宝马自动驾驶.zip
(53.9 KB, 下载次数: 508)
|