|
下载:
智能小车资料.zip
(89.07 KB, 下载次数: 231)
一些问题:
问:
大神请教个问题,我用keil给51单片机写的程序能运行在其中设备上吗?因为我是有一个打算就是用我的单片机作试验,再把程序写到自己设计的电路中去,我需要用到什么芯片才能执行这个程序
答:
我就是用的KEIL+51单片机,你可以在自己的开发板上做实验,只要单品机是一样的就完全可以,即使不完全一样,也仅仅需要改改IO口等
是用的两个红外,两个红外之间距离远点,另外我这个直走和转弯是两个不同的PWM速度,转弯大概是直走的2倍左右,效果好点.
下面是智能小车外形图:
小车是用的慧静4WD小车,程序是自己写的.
遥控子程序:
- #include <reg52.h>
- #include "SmartCar.h"
- //#include "Dianji.h"
- #include "RTX51TNY.H"
- #define Imax 14000 //此处为晶振为11.0592时的取值,
- #define Imin 8000 //如用其它频率的晶振时,
- #define Inum1 1450 //要改变相应的取值。
- #define Inum2 700
- #define Inum3 3000
- unsigned char f=0; //找到起始码时置1
- unsigned char Im[4]={0x00,0x00,0x00,0x00}; //分别存储,客户码1,客户码2,操作码,操作码反码
- unsigned int Tc = 0; //Tc时间间隔
- unsigned char m = 0; //m往Im存数时计数用
- unsigned char IrOK = 0; //提取成功后置1
- unsigned char ImOld=0; //储存旧命令,用于加减速控制
- //unsigned char const discode[] ={ 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xBF,0xff/*-*/};
- //unsigned char const positon[3]={ 0xfe,0xfd,0xfb};
- //sbit FM = P2^6; //test
- /************************************************************************/
- //遥控
- void YaoKong (void)
- {
- if(IrOK==1)
- {
- // FM=0;
- switch(Im[2])
- {
- case 0x18: //前进
- {
- ucFlagControl=FLAG_GO;
- }
- break;
- case 0x52: //后退
- {
- ucFlagControl=FLAG_BACK;
- }
- break;
- case 0x1C: //停止
- {
- ucFlagControl=FLAG_STOP;
- }
- break;
- case 0x08: //左转
- {
- ucFlagControl=FLAG_TURNLEFT;
- }
- break;
- case 0x5A: //右转
- {
- ucFlagControl=FLAG_TURNRIGHT;
- }
- break;
- case 0x15: //加速
- {
- if(++ucPwm>10)
- {
- ucPwm=10;
- }
- }
- break;
- case 0x07: //减速
- {
- if(--ucPwm==0)
- {
- ucPwm=1; //Pwm至少为1
- }
- }
- break;
- case 0x0C: //遥控模式
- {
- ucFlagState = FLAG_YAOKONG;
- }
- break;
- case 0x5E: //循迹模式
- {
- ucFlagState = FLAG_XUNJI;
- }
- break;
- case 0x42: //跟随模式
- {
- ucFlagState = FLAG_GENSUI;
- }
- break;
- case 0x4A: //避障模式
- {
- ucFlagState = FLAG_BIZHANG;
- ucFlagChangeState=YES;
- }
- break;
- default:
- break;
- }
- IrOK=0; //将成功标记位置位
- }
- }
- //外部中断解码程序
- void intersvr1() interrupt 2
- {
- Tc=TH1*256+TL1; //提取中断时间间隔时长,两次下降沿之间的时间间隔
- TH1=0;
- TL1=0; //定时中断重新置零
- if((Tc>Imin)&&(Tc<Imax))
- {
- m=0;
- f=1;
- return;
- }
- if(f==1) //找到启始码
- {
- if(Tc>Inum1&&Tc<Inum3)
- {
- Im[m/8]=Im[m/8]>>1|0x80; m++;
- }
- if(Tc>Inum2&&Tc<Inum1)
- {
- Im[m/8]=Im[m/8]>>1; m++; //取码
- }
- if(m==32)
- {
- m=0;
- f=0;
- if(Im[2]==~Im[3])
- {
- IrOK=1;
- }
- else IrOK=0; //取码完成后判断读码是否正确
- }
- }
- }
-
复制代码
电机子程序:
主程序:
- /*******************************************************
- * 项目名称:循迹避障小车
- * 单 片 机: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;
- }
- //初始化区
- void initial_myself(void)//第一区 初始化单片机
- {
- unsigned char i;
- for(i=0;i<NUM_TASK_REFRESH;i++)uc_delay_task_cnt[i]=0;//初始化让所有任务就绪
- TMOD=0X11; //定时器0、1为16位不自动重装
- TH0=255-TIME_CLOCK/TIME_PER_SEC/12/256;
- TL0=255-TIME_CLOCK/TIME_PER_SEC/12%256;
- TH1=0;
- TL1=0;
- TH2=0;
- TL2=0;
- DUOJI=0; //防止舵机转动,同时不情愿的开启了第四个数码管的显示
- }
- void initial_peripheral(void) //第二区 初始化外围
- {
- EA=1; //开总中断
- ET0=1; //允许定时器中断
- IT1=1; //下降沿触发
- EX1=1; //允许外部1中断
- TR0=1; //启动定时器0
- TR1=1; //启动定时器1
- }
- void delay100ms(void) //@11.0592MHz
- {
- unsigned char i, j, k;
- ;
- ;
- i = 5;
- j = 52;
- k = 195;
- do
- {
- do
- {
- while (--k);
- } while (--j);
- } while (--i);
- }
复制代码
|
|