壁障小车
单片机源程序如下:
- /*******************************************************
- * 项目名称:循迹避障小车
- * 单 片 机:STC89C52RC
- * 功 能:循迹,红外遥控,超声波避障,舵机,PWM,跟踪
- * 作 者:刘琦
- * IO口定义:红外循迹 P3^4,P3^5
- * 红外避障 P3^6,P3^7
- * 电机 P1^0~P1^7
- * 超声波避障 P2^4~P2^5
- * 红外遥控 P3^3
- * 舵机 P2^3
- * 数码管段选 P0
- * 数码管位选 P2^0~P2^3
- * 遥 控 器:2 前进 (18)
- * 8 后退 (52)
- * 5 停止 (1C)
- * 4 左转 (08)
- * 6 右转 (5A)
- * 1 遥控模式 (0C)
- * 3 循迹模式 (5E)
- * 7 跟随模式 (42)
- * 9 避障模式 (4A)
- * + 加速 (15)
- * - 减速 (07)
- * 定 时 器:T0 PWM(电机、舵机),数码管(超声波测距)
- * T1 红外遥控计时
- * T2 超声波计时
- *******************************************************/
- /******************************头文件区***********************************************/
- #include <reg52.h>
- #include "Dianji.h"
- #include "Yaokong.h"
- #include "RTX51TNY.H"
- #include "Chaoshengbo.h"
- #include "Duoji.h"
- /******************************宏定义区***********************************************/
- //需要定时刷新的任务数,0YaoKong,1Display,2CSB
- #define NUM_TASK_REFRESH 3
- //刷新频率
- //#define TIME_PER_SEC 200 //每次进入中断的频率,200Hz,5ms
- #define TIME_PER_SEC 10000 //每次进入中断的频率,10000Hz,0.1ms
- #define TIME_CLOCK 11059200 //晶振频率
- #define TIME_YAOKONG_50HZ TIME_PER_SEC/50 //响应遥控命令频率,0.02s
- #define TIME_SUMA_300HZ TIME_PER_SEC/300 //超声波距离显示数码管刷新频率,0.003s
- #define TIME_CSB_5HZ TIME_PER_SEC/5 //超声波自动检测的频率,0.2s
- #define FLAG_YAOKONG 0
- #define FLAG_XUNJI 1
- #define FLAG_BIZHANG 2
- #define FLAG_GENSUI 3
-
- #define FLAG_GO 0
- #define FLAG_BACK 1
- #define FLAG_STOP 2
- #define FLAG_TURNLEFT 3
- #define FLAG_TURNRIGHT 4
- #define NO 0
- #define YES 1
- #define DELAYTURN 5000
- #define DELAYDUOJI 5000
- /******************************子函数声明区***********************************************/
- void initial_myself(void);
- void initial_peripheral(void);
- void delay100ms(void);
- /******************************IO口定义区***********************************************/
- sbit LEFT_XJ = P3^4; // 左循迹
- sbit RIGHT_XJ = P3^5; // 右循迹
- sbit LEFT_GS = P3^6; // 左跟随
- sbit RIGHT_GS = P3^7; // 右跟随
- //sbit LEFT_CS = P // 左测速
- //sbit RIGHT_CS = P // 右测速
- sbit KEY=P2^6; // 激活超声波测距,测试用,蜂鸣器也响;
- /******************************全局变量定义区***********************************************/
- unsigned char ucPwm = 4; //电机的PWM占空比,N/10
-
- unsigned int ucPwmCountDianJ = 0; //电机Pwm计数
- unsigned int ucPwmCountDuoJ = 0; //舵机Pwm计数
- unsigned char ucFlagState = FLAG_YAOKONG; //模式选择,遥控,循迹,避障
- unsigned char ucFlagControl = FLAG_STOP; //遥控模式下的控制选择,前进后退停止左转右转
- unsigned int uc_delay_task_cnt[NUM_TASK_REFRESH]; //任务刷新延迟
- unsigned char ucCSBCheck = NO; //用于判断是否需要停车检测
- unsigned int ucPwmDuoj = 6; //舵机归中,默认情况下先归中
- unsigned int ulS[4] = {0,0,0,0}; //储存距离数据,0°,180°,90°,后退时90°
- unsigned char ucDuoJiPosition[3]={11,2,6}; //舵机的0°,180°,90°对应的ucPwmDuoj数值
- unsigned char ucFlagTurning=NO; //在超声波避障模式中,判断是否正在转弯
- unsigned char ucFlagDuoJiPositon=0; //正在检测的舵机位置标示,0代表正在检测0°
- unsigned char ucLockCSBCheck=NO; //超声波检测过程中时,此为YES,锁住红外传感器的检测
- unsigned int uiDelayDuoJiMove=DELAYDUOJI; //舵机移动延迟结束
- unsigned char ucFlagDuoJiMove=NO; //舵机开始移动的标志,此标志为YES时uiDelayDuoJiMove开始减
- unsigned char ucFlagCSBBegin=NO; //超声波开始检测标志,当uiDelayDuoJiMove为0时,为YES
- unsigned char ucNumS=0; //ulS数组的第几位
- unsigned char ucNumCSB=0; //进入超声波检测的次数,用来控制什么时候结束检测,开始转弯
- unsigned int uiDelayTurn=DELAYTURN; //转弯结束,大概90°
- unsigned char ucFlagTurn=NO; //开始转动的标志,此标志为YES时uiDelayTurn开始减
- unsigned char ucFlagTurnOver=NO; //转弯结束标志,为YES时,退出转弯
- unsigned char ucFlagSMGLock=NO; //数码管锁,从检测到障碍,到转弯结束,这段时间锁上不显示
- unsigned char ucFlagGuiZhong=NO; //头一次进入避障模式先归中
- unsigned char ucFlagBegin=NO; //归中后此位为YES
- unsigned char ucFlagChangeState=NO; //改变状态标识,如果改变了,那么初始化避障模式的变量
- unsigned char ucFlagBackOK=NO; //后退OK标识,后退结束后,才开始转弯
- //unsigned char ucCSBDirection = 0; //用来记录并判断检测后行进方向
- //unsigned char ucCSBFlag = 0; //用来激活400ms计时
- //unsigned char ucFlagJumpoutPwm = 0; //Pwm跳出标示,1为跳出
- //unsigned char const discode[] ={ 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xBF,0xff/*-*/};
- //unsigned char const positon[3]={ 0xfe,0xfd,0xfb};
- /******************************主函数开始***********************************************/
- void main(void)
- {
- initial_myself();
- delay100ms();
- initial_peripheral();
- while(1)
- {
- if(ucFlagChangeState==YES) //每次改变状态,将避障模式的变量初始化
- {
- ucFlagTurning=NO; //在超声波避障模式中,判断是否正在转弯
- ucFlagDuoJiPositon=0; //正在检测的舵机位置标示,0代表正在检测0°
- ucLockCSBCheck=NO; //超声波检测过程中时,此为YES,锁住红外传感器的检测
- uiDelayDuoJiMove=DELAYDUOJI; //舵机移动延迟结束
- ucFlagDuoJiMove=NO; //舵机开始移动的标志,此标志为YES时uiDelayDuoJiMove开始减
- ucFlagCSBBegin=NO; //超声波开始检测标志,当uiDelayDuoJiMove为0时,为YES
- ucNumS=0; //ulS数组的第几位
- ucNumCSB=0; //进入超声波检测的次数,用来控制什么时候结束检测,开始转弯
- uiDelayTurn=DELAYTURN; //转弯结束,大概90°
- ucFlagTurn=NO; //开始转动的标志,此标志为YES时uiDelayTurn开始减
- ucFlagTurnOver=NO; //转弯结束标志,为YES时,退出转弯
- ucFlagSMGLock=NO; //数码管锁,从检测到障碍,到转弯结束,这段时间锁上不显示
- ucFlagGuiZhong=NO; //头一次进入避障模式先归中
- ucFlagBegin=NO; //归中后此位为YES
- ucFlagBackOK=NO; //后退OK标识,后退结束后,才开始转弯
- ucPwm=4;
- ucFlagChangeState=NO;
- }
- if(uc_delay_task_cnt[0]==0)
- {
- YaoKong();
- ET0=0;//在中断中也有可能变化的变量在更改前时先关闭中断
- uc_delay_task_cnt[0]=TIME_YAOKONG_50HZ;
- ET0=1;
- }
- //遥控模式
- if(ucFlagState==FLAG_YAOKONG)
- {
- switch(ucFlagControl)
- {
- case FLAG_GO:
- Go();
- break;
- case FLAG_STOP:
- Stop();
- break;
- case FLAG_BACK:
- Back();
- break;
- case FLAG_TURNLEFT:
- TurnLeft();
- break;
- case FLAG_TURNRIGHT:
- TurnRight();
- break;
- default:
- break;
- }
- }
- //循迹模式
- if(ucFlagState==FLAG_XUNJI)
- {
- if(LEFT_XJ==1&&RIGHT_XJ==1)
- {
- ucPwm=3;
- Go();
- }
- else if(RIGHT_XJ==0)
- {
- ucPwm=8;
- TurnRight();
- }
- else if(LEFT_XJ==0)
- {
- ucPwm=8;
- TurnLeft();
- }
-
- }
- //跟随模式
- if(ucFlagState==FLAG_GENSUI)
- {
- if(LEFT_GS==1&&RIGHT_GS==1) //左右都检测到物体
- {
- Stop();
- }
- else if(LEFT_GS==0&&RIGHT_GS==1) //左侧未检测到,右侧检测到
- {
- TurnRight();
- }
- else if(LEFT_GS==1&&RIGHT_GS==0) //右侧未检测到,左侧检测到
- {
- TurnLeft();
- }
- else //左右都未检测到
- {
- Go();
- }
- }
- //超声波+红外避障模式
- //ucFlagBegin=NO,
- if(ucFlagState==FLAG_BIZHANG)
- {
- if(ucFlagBegin==NO)
- {
- ucPwmDuoj=ucDuoJiPosition[2];
- ucFlagGuiZhong=YES;
- }
- else
- {
- // if(ucFlagSMGLock==NO&&uc_delay_task_cnt[1]==0) //数码管刷新
- if(uc_delay_task_cnt[1]==0) //数码管刷新
- {
- Display();
- ET0=0;//在中断中也有可能变化的变量在更改前时先关闭中断
- uc_delay_task_cnt[1]=TIME_SUMA_300HZ;
- ET0=1;
- }
-
- if(ucFlagTurning==NO) //没在转弯
- {
- if(ucLockCSBCheck==NO&&uc_delay_task_cnt[2]==0) //超声波自动检测
- {
- CSB ();
- ET0=0;//在中断中也有可能变化的变量在更改前时先关闭中断
- uc_delay_task_cnt[2]=TIME_CSB_5HZ;
- ET0=1;
- if(S<=40)
- {
- ucLockCSBCheck=YES;
- ucFlagSMGLock=YES;
- Stop();
- }
- }
-
- if(ucLockCSBCheck==NO)
- {
- Go();
- }
-
- if(ucLockCSBCheck==YES) //遇到障碍后超声波检测整个过程开始
- {
- if(ucFlagCSBBegin==NO) //超声波检测未开始
- {
- ucPwmDuoj=ucDuoJiPosition[ucFlagDuoJiPositon]; //正在检测的角度,随着ucFlagDuoJiPositon变化而变化
- ucFlagDuoJiMove=YES;
- }
- if(ucFlagCSBBegin==YES)
- {
- // if(ucFlagDuoJiPositon<2) //只在0°,180°进行超声波检测
- // {
- CSB ();
- CSB ();
- CSB ();
- ulS[ucNumS]=S; //将距离数据存起来
- // if(ucNumS<2)
- ucNumS++;
- // }
- if(++ucFlagDuoJiPositon>2)
- ucFlagDuoJiPositon=0;
- if(++ucNumCSB>=3)
- {
- ucFlagTurning=YES; //激活转弯
- ucLockCSBCheck=NO;
- ucNumCSB=0; //进入检测的次数清0
- ucNumS=0; //存储距离数据的位置清0
- }
- ucFlagCSBBegin=NO; //超声波检测结束
- }
-
- }
- }
- else //正在转弯
- {
- if(ucFlagBackOK==NO)
- {
- if( ulS[2]<30)
- {
- Back();
- CSB();
- ulS[3]=S;
- if(ulS[3]>=30)
- ucFlagBackOK=YES;
- }
- else
- ucFlagBackOK=YES;
- }
- else
- {
- if(ucFlagTurnOver==NO) //未转弯结束
- {
- ucFlagTurn=YES;
- if(ulS[0]>ulS[1]) //左侧>右侧
- TurnLeft();
- else
- TurnRight();
- }
- else
- {
- ucFlagTurning=NO;
- ucFlagTurnOver=NO;
- ucFlagSMGLock=NO;
- ucFlagBackOK=NO;
- }
- }
- }
- }
- }
- }
- }
- //中断函数
- void timer0(void) interrupt 1
- {
- unsigned char i;
- TR0=0;
- TH0=255-TIME_CLOCK/TIME_PER_SEC/12/256;
- TL0=255-TIME_CLOCK/TIME_PER_SEC/12%256;
- //task_delay[]减到0时,相应的函数准备就绪
- for(i=0;i<NUM_TASK_REFRESH;i++)
- {
- if(uc_delay_task_cnt[i]!=0)//延迟不为0时才减
- {uc_delay_task_cnt[i]--;};
- }
- ucPwmCountDianJ++;
- if(ucPwmCountDianJ >= 10)
- {
- ucPwmCountDianJ = 0;
- }
-
- //舵机转动距离控制
- if(ucFlagDuoJiMove==YES||ucFlagGuiZhong==YES)
- {
- ucPwmCountDuoJ++;
- if(ucPwmCountDuoJ>205) //0.5+20(ms),整个周期长度
- {
- ucPwmCountDuoJ=0;
- }
- PwmServomoto();
- }
- //舵机转动时间控制
- if(ucFlagDuoJiMove==YES)
- {
- if(uiDelayDuoJiMove!=0)
- uiDelayDuoJiMove--;
- else
- {
- uiDelayDuoJiMove=DELAYDUOJI;
- ucFlagDuoJiMove=NO;
- ucFlagCSBBegin=YES;
- }
- }
- //头一次进入避障模式的舵机归中
- if(ucFlagGuiZhong==YES)
- {
- if(uiDelayDuoJiMove!=0)
- uiDelayDuoJiMove--;
- else
- {
- uiDelayDuoJiMove=DELAYDUOJI;
- ucFlagGuiZhong=NO;
- ucFlagBegin=YES;
- }
- }
- //转弯延迟
- if(ucFlagTurn==YES)
- {
- if(uiDelayTurn!=0)
- uiDelayTurn--;
- else
- {
- uiDelayTurn=DELAYTURN;
- ucFlagTurn=NO;
- ucFlagTurnOver=YES;
- }
- }
- TR0=1;
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
8.6 No.1 超声波避障基本可以用,还不完善.zip
(90.83 KB, 下载次数: 12)
|