|
包含以下功能:1、人工操作(前进、后退、左转、右转)
2、超声波避障(包含距离的显示)
3、红外避障
源码:
/*******************************XB-4WD 智能小车参考程序****************************************
* 平台:XB-4WD + Keil4 + STC89C52
* 名称:小车超声波避障
* 日期:2014-5-18
* QQ : 61924336
**********************************************************************************************/
/**********************************************************************************************
** 智能小车接线说明
**********************************************************************************************/
/**********************************************************************************************
电池盒 XB-L293D驱动板上的电池输入端子(蓝色)
***********************************************************************************************
红线(+) ------------------------------- 蓝色输入端子(+)
黑线(-) ------------------------------- 蓝色输入端子(-)
***********************************************************************************************
/**********************************************************************************************
XB-L293D驱动板上的5V电源输出排针 XB-1A主板上的+5V电源输入排针
***********************************************************************************************
VCC ------------------------------- +5V
GND ------------------------------- GND
***********************************************************************************************
/**********************************************************************************************
XB-1A主板 XB-L293D驱动板(输入) * XB-L293D驱动板(输出) 电机
***********************************************************************************************
P1.0 --------- IN1 * OUT1 --------- 左上电机(+)
P1.1 --------- IN2 * OUT2 --------- 左上电机(-)
*********************************************************************************************** *
P1.2 --------- IN3 * OUT3 --------- 左下电机(+)
P1.3 --------- IN4 * OUT4 --------- 左下电机(-)
***********************************************************************************************
P1.4 --------- IN5 * OUT5 --------- 右上电机(+)
P1.5 --------- IN6 * OUT6 --------- 右上电机(-)
***********************************************************************************************
P1.6 --------- IN7 * OUT7 --------- 右下电机(+)
P1.7 --------- IN8 * OUT8 --------- 右下电机(-)
***********************************************************************************************/
/***********************************************************************************************
舵机模块 XB-1A主板
************************************************************************************************
红色线(电源正) -------------------------- JPW(+5V)
棕色线(电源负) -------------------------- JPW(GND)
橙色线(信号线) -------------------------- P2.7
************************************************************************************************
/***********************************************************************************************
超声波模块 XB-1A主板
************************************************************************************************
VCC -------------------------------------- JPW(+5V)
TRIG -------------------------------------- P2.1
ECHO -------------------------------------- P2.0
GND -------------------------------------- JPW(GND)
************************************************************************************************
/***********************************************************************************************
** 头文件
***********************************************************************************************/
#include<AT89x51.H>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
/**********************************************************************************************
** 舵机信号线(橙色)
**********************************************************************************************/
#define Sevro_moto_pwm P2_7
/**********************************************************************************************
** 超声波控制线
**********************************************************************************************/
#define ECHO P2_5 //超声波接口定义 P2.1
#define TRIG P2_6 //超声波接口定义 P2.0
#define Left_moto_pwm1 P2_0 //PWM信号端
#define Left_moto_pwm2 P2_1 //PWM信号端
#define Right_moto_pwm1 P2_2 //PWM信号端
#define Right_moto_pwm2 P2_3 //PWM信号端
#define Left_1_led P3_4 //左传感器
#define Right_1_led P3_5 //右传感器
/**********************************************************************************************
** 蜂鸣器接口定义
**********************************************************************************************/
sbit FM = P3^6; //蜂鸣器接口
sbit Speed=P3^7; //控制外部中断
/******************************************************************
** 接线定义
******************************************************************/
#define Left_moto_go {P1_0=1,P1_1=0,P1_2=1,P1_3=0;} //左边两个电机向前走
#define Left_moto_back {P1_0=0,P1_1=1,P1_2=0,P1_3=1;} //左边两个电机向后转
#define Left_moto_Stop {P1_0=0,P1_1=0,P1_2=0,P1_3=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;} //右边两个电机停转
/******************************************************************
** 红外遥控器的相关定义
******************************************************************/
#define Imax 14000 //此处为晶振为11.0592时的取值,
#define Imin 8000 //如用其它频率的晶振时,
#define Inum1 1450 //要改变相应的取值。
#define Inum2 700
#define Inum3 3000
/**********************************************************************************************
** 变量定义
**********************************************************************************************/
uchar disbuff[4] ={ 0,0,0,0,};
uchar posit=0;
uchar pwm_val_steering = 0; //变量定义
uchar push_val_steering =14; //舵机归中,产生约,1.5MS 信号
uchar pwm_val_left =0; //变量定义
uchar push_val_left =0; //左电机占空比N/20
uchar pwm_val_right =0;
uchar push_val_right=0; //右电机占空比N/20
bit Right_moto_stop=1;
bit Left_moto_stop =1;
ulong S=0;
ulong S1=0;
ulong S2=0;
ulong S3=0;
ulong S4=0;
uint time=0; //时间变量
uint timer=0; //延时基准变量
uchar timer1=0; //扫描时间变量
uint num = 3;
uchar f=0;
uchar Im[4]={0x00,0x00,0x00,0x00};
uchar show[2]={0,0};
ulong m,Tc;
uchar IrOK;
bit flag;
uint shu[9]={1,2,3,4,5,6, 7,8,9};
uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //0~9 共阳极数码管
uchar code chose[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //共阴极数码管
void ultrasonic( void ); //超声波避障
void artificial( void ); //人工操作小车
void control_menu(void ); //主控菜单
/**********************************************************************************************
** 延时函数
**********************************************************************************************/
void delay(unsigned int k) //延时函数
{
unsigned int x,y;
for(x=0;x<k;x++)
for(y=0;y<2000;y++);
}
void delayms(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=99;y>0;y--);
}
/**********************************************************************************************
** 启动测距信号
**********************************************************************************************/
void StartModule()
{
TRIG=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
TRIG=0;
}
/******************************************************************
** 小车前进
******************************************************************/
void run(void)
{
push_val_left=8;
push_val_right=8;
Left_moto_go ; //左电机往前走
Right_moto_go ; //右电机往前走
}
/******************************************************************
** 小车后退
******************************************************************/
void backrun(void)
{
push_val_left=8;
push_val_right=8;
Left_moto_back ; //左电机后退
Right_moto_back ; //右电机后退
}
/******************************************************************
** 小车左转
******************************************************************/
void leftrun(void)
{
push_val_left=8;
push_val_right=8;
Right_moto_back ; //右电机后退
Left_moto_go ; //左电机前进
}
/******************************************************************
** 小车右转
******************************************************************/
void rightrun(void)
{
push_val_left=8;
push_val_right=8;
Right_moto_go; //右电机前进
Left_moto_back ; //左电机停止
}
/******************************************************************
** 小车停走
******************************************************************/
void stoprun(void)
{
push_val_left=8;
push_val_right=8;
Left_moto_Stop
Right_moto_Stop;
}
/**********************************************************************************************
** 数码管显示
**********************************************************************************************/
/**********************************************************************************************
** 显示数据的转换
**********************************************************************************************/
void display()
{
P0=table[disbuff[1]];
P2_0 = 0;
delayms(5);
P2_0 = 1;
P0=table[disbuff[0]];
P2_1 = 0;
delayms(5);
P2_1 = 1;
P0=table[disbuff[1]];
P2_2 = 0;
delayms(5);
P2_2 = 1;
P0=table[disbuff[2]];
P2_3 = 0;
delayms(5);
P2_3 = 1;
}
/**********************************************************************************************
** 计算距离
**********************************************************************************************/
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
disbuff[0]=S%1000/100; //更新显示 百位
disbuff[1]=S%1000%100/10; //更新显示 十位
disbuff[2]=S%1000%10 %10; //更新显示 个位
}
/**********************************************************************************************
** 计算速度
**********************************************************************************************/
void speed(void)
{
TR1=1;
TH1=0;
TL1=0;
flag=0;
while(flag==0);
S=TH1*256+TL1;
disbuff[0]=S%1000/100; //更新显示 百位
disbuff[1]=S%1000%100/10; //更新显示 十位
disbuff[2]=S%1000%10 %10; //更新显示 个位
}
/**********************************************************************************************
** 判断小车该往哪边走
**********************************************************************************************/
void judge(void)
{
if((S2<40)||(S4<40)){ //只要左右各有距离小于,30CM小车后退
backrun(); //后退
timer=0;
while(timer<=1000);
}
if(S2>S4){
rightrun(); //车的左边比车的右边距离小 右转
timer=0;
while(timer<=800);
}else{
leftrun(); //车的左边比车的右边距离大 左转
timer=0;
while(timer<=800);
}
}
void judge1(void)
{
if((S2>S4)&&(S2 > 40)){
rightrun(); //车的左边比车的右边距离小 右转
timer=0;
while(timer<=800);
}else if((S2<=S4)&&(S4 > 40)){
leftrun(); //车的左边比车的右边距离大 左转
timer=0;
while(timer<=800);
}
}
/**********************************************************************************************
** 左右超声波检测距离
**********************************************************************************************/
void COMM( void )
{
push_val_steering=5; //舵机向右转90度
timer=0;
while(timer<=3500); //延时400MS让舵机转到其位置 4000
StartModule(); //启动超声波测距
Conut(); //计算距离
display(); //显示距离
S2=S;
push_val_steering=25; //舵机再向左转180度
timer=0;
while(timer<=3500); //延时400MS让舵机转到其位置
StartModule(); //启动超声波测距
Conut(); //计算距离
display(); //显示距离
S4=S;
push_val_steering=14; //舵机归中
timer=0;
while(timer<=3500); //延时400MS让舵机转到其位置
StartModule(); //启动超声波测距
Conut(); //计算距离
display(); //显示距离
S1=S;
judge();
}
/*********************************************************************************************/
/* PWM调制电机转速 */
/*********************************************************************************************/
/* 舵机电机调速 */
/* 调节steering_engine_left的值改变舵机转速,占空比 */
void pwm_Servomoto(void)
{
if(pwm_val_steering<=push_val_steering)
Sevro_moto_pwm=1;
else
Sevro_moto_pwm=0;
if(pwm_val_steering>=100)
pwm_val_steering=0;
}
/******************************************************************
** 左电机调速
******************************************************************/
void pwm_out_left_moto(void)
{
if(Left_moto_stop){
if(pwm_val_left<=push_val_left){
Left_moto_pwm1=1;
Left_moto_pwm2=1;
}else {
Left_moto_pwm1=0;
Left_moto_pwm2=0;
}
if(pwm_val_left>=20)
pwm_val_left=0;
}else{
Left_moto_pwm1=0;
Left_moto_pwm2=0;
}
}
/******************************************************************
** 右电机调速
******************************************************************/
void pwm_out_right_moto(void)
{
if(Right_moto_stop){
if(pwm_val_right<=push_val_right){
Right_moto_pwm1=1;
Right_moto_pwm2=1;
}else {
Right_moto_pwm1=0;
Right_moto_pwm2=0;
}
if(pwm_val_right>=20)
pwm_val_right=0;
}else {
Right_moto_pwm1=0;
Right_moto_pwm2=0;
}
}
/**********************************************************************************************
** TIMER1中断服务子函数产生PWM信号 **
**********************************************************************************************/
/******************************************************************
** 定时器0初始化
******************************************************************/
void timer0_Init(void)
{
TMOD=0X01;
TH0= 0XFc; //1ms定时
TL0= 0X18;
TR0= 1;
ET0= 1;
EA = 1; //开总中断
}
/******************************************************************
** 定时器0中断服务子程序
******************************************************************/
void timer0()interrupt 1 using 2
{
TH0=0XFc;
TL0=0X18;
time++;
pwm_val_left++;
pwm_val_right++;
pwm_out_left_moto();
pwm_out_right_moto();
}
/******************************************************************
** 定时器1中断服务子程序
******************************************************************/
void time1()interrupt 3 using 2
{
TH1=(65536-100)/256; //100US定时
TL1=(65536-100)%256;
timer++; //定时器100US为准。在这个基础上延时
pwm_val_steering++;
pwm_Servomoto();
timer1++; //2MS扫一次数码管
if(timer1>=20){
timer1=0;
}
}
/******************************************************************
** 外部中断解码程序
******************************************************************/
void intersvr0(void) interrupt 0 using 1
{
Tc=TH0*256+TL0; //提取中断时间间隔时长
TH0=0;
TL0=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; //取码完成后判断读码是否正确
}
} //准备读下一码
}
/******************************************************************
** 红外线避障
******************************************************************/
void Infrared(void)
{
timer0_Init();
while(1){
if(IrOK==1) {
stoprun();
switch(Im[2]) {
case 0x16:
control_menu(); //返回主控菜单
break;
default:
break;
}
IrOK=0;
}
if(Left_1_led==1&&Right_1_led==1) //左右边都检测不到红外,灯都是灭的
run(); //调用前进函数
else{
if(Left_1_led==1&&Right_1_led==0){ //右边边检测到红外,右边灯亮
leftrun(); //调用小车左转函数
}
if(Right_1_led==1&&Left_1_led==0){ //左边检测到红外,左边灯亮
rightrun(); //调用小车右转函数
}
if(Right_1_led == 0 && Left_1_led == 0){ //左右检测到红外,左右灯亮
backrun(); //小车后退
}
}
}
}
/**********************************************************************************************
** 超声波的避障代码
**********************************************************************************************/
void ultrasonic( void )
{ IrOK=0;
TMOD=0X11;
TH1=(65536-100)/256; //100US定时
TL1=(65536-100)%256;
TR1= 1;ET1= 1;
ET0= 1;TR0=1;
m=0;f=0;
IT0=1;EX0=1;
TH0=0;TL0=0;TR0=1;
EA=1;
delay(100);
push_val_steering=14; //舵机归中
while (1){
if(IrOK==1) {
stoprun();
switch(Im[2]) {
case 0x16:
control_menu(); //返回主控菜单
break;
default:
break;
}
IrOK=0;
}
if(timer>=200){ //80MS检测启动检测一次 800
timer=0;
StartModule(); //启动检测
Conut(); //计算距离
display();
if(S<=40) { //距离小于40CM
stoprun(); //小车停止
COMM(); //方向函数
} else
if(S>40){ //距离大于,40CM往前走
run();
}
}
}
}
/**********************************************************************************************
** 人工操控小车代码
**********************************************************************************************/
void artificial( void )
{
m=0;f=0;
IT0=1;EX0=1;
TMOD=0x11;
TH0=0;TL0=0;
TR0=1;
EA=1;
delay(100);
speed();
display();
while(1) { /*无限循环*/
if(IrOK==1) {
switch(Im[2]) {
case 0x18: run(); //前进
break;
case 0x52: backrun(); //后退
break;
case 0x08: leftrun(); //左转
break;
case 0x5A: rightrun(); //右转
break;
case 0x1C: stoprun(); //停止
break;
case 0x16: stoprun();
control_menu(); //返回主控菜单
break;
default:
break;
}
IrOK=0;
}
}
}
/**********************************************************************************************
** 小车主控菜单代码
**********************************************************************************************/
void control_menu(void )
{
m=0;f=0;
IT0=1;EX0=1;
TMOD=0x11;
TH0=0;TL0=0;
TR0=1;
EA=1;
delay(100);
while(1){
if(IrOK==1) {
switch(Im[2]) {
case 0x18: push_val_steering=14; //舵机归中
artificial(); //人工控制小车
break;
case 0x0C:
ultrasonic(); //超声波避障
break;
case 0x5E:
Infrared(); //红外线避障
break;
case 0x08: num = 4;
ultrasonic(); //超声波红外线避障
break;
default:
break;
}
IrOK=0;
}
}
}
/**********************************************************************************************
** 主函数
**********************************************************************************************/
void main(void)
{
while(1) { /*无限循环*/
control_menu(); //调用主控菜单
}
}
/**********************************************************************************************
** END FILE
**********************************************************************************************/
|
评分
-
查看全部评分
|