#include<reg52.h>
#include <intrins.h>
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;
sbit Sevro_moto_pwm = P2^6; //接舵机信号端输入PWM信号调节速度
sbit ECHO= P1^1; //超声波接口定义
sbit TRIG= P1^0; //超声波接口定义
sbit PWM1 = P2^5; //左电机高电平
sbit PWM2 = P2^4; //右电机高电平
sbit IN1 = P2^3;
sbit IN2 = P2^2; //左电机
sbit IN3 = P2^1;
sbit IN4 = P2^0; //右电机
sbit A1 = P1^4; //左红外避障模块
sbit A2 = P2^7; //右红外避障模块
//sbit A3 = P1^2; //左红外寻迹模块
//sbit A4 = P1^3; //右红外寻迹模块
sbit K1 = P3^2; //功能转换按键
sbit K2 = P3^3; //加速键
sbit K3 = P3^4; //减速键
u8 connt; //调速周期
u8 PWM_NO; //高电平时间
u8 a=0,c=0; //标志位
u8 COM;
u8 pwm_val_left = 0;//变量定义
u8 push_val_left ;//舵机归中,产生约,1.5MS 信号
u32 S=0; //距离变量定义
u32 S1=0;
u32 S2=0;
u32 S3=0;
u32 S4=0;
u16 time=0; //时间变量
u16 timer=0; //延时基准变量
u8 non=0,t=0;
u8 pon=3; //数码管显示
u8 code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f};//显示0~9的值
/************************************************************************/
void delay(u16 k) //延时函数
{
u16 x,y;
for(x=0;x<k;x++)
for(y=0;y<2000;y++);
}
void delay1(u16 j) //延时函数
{
u16 x,y;
for(x=0;x<j;x++)
for(y=0;y<120;y++);
}
/************************************************************************/
void Display(void) //扫描数码管
{
P0=smgduan[pon];
if(K2==0) // 加速
{
delay1(10);
if(K2==0)
{
pon++;
PWM_NO--;
}
while(!K2); //松键检测
}
if(K3==0) //减速
{
delay1(10);
if(K3==0)
{
pon--;
PWM_NO++;
}
while(!K3);
}
}
void SC() //刹车
{
IN1 = 0;
IN2 = 0;
IN3 = 0;
IN4 = 0;
}
void QJ() //前进
{
IN1 = 1;
IN2 = 0;
IN3 = 1;
IN4 = 0;
}
void HT() //后退
{
IN1 = 0;
IN2 = 1;
IN3 = 0;
IN4 = 1;
}
void ZZ1() //左大转
{
IN1 = 0;
IN2 = 1;
IN3 = 1;
IN4 = 0;
}
void YZ1() //右大转
{
IN1 = 1;
IN2 = 0;
IN3 = 0;
IN4 = 1;
}
/************************************************************************/
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 InitUART(void) //串口中断初始化函数
{
SCON=0x50; //设置为工作方式1
TMOD=0x20; //设置计数器工作方式2
PCON=0x00; //波特率不加倍
TH1=0xfd; //计数器初始值设置,注意波特率是9600的
TL1=0xfd;
ES=1; //打开接收中断
EA=1; //打开总中断
TR1=1; //打开计数器
}
/***************************************************/
void Conut(void) //计算距离
{
while(!ECHO); //当RX为零时等待
TR1=1; //开启计数
while(ECHO); //当RX为1计数并等待
TR1=0; //关闭计数
time=TH1*256+TL1; //读取脉宽长度
TH1=0;
TL1=0;
S=(time*1.7)/100; //算出来是CM
}
/************************************************************************/
void COMM( void )
{
push_val_left=23; //舵机向左转90度
timer=0;
while(timer<=4000); //延时400MS让舵机转到其位置 4000
StartModule(); //启动超声波测距
Conut(); //计算距离
S2=S;
push_val_left=5; //舵机向右转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)||(S1<20)) //只要左右各有距离小于,20CM小车后退
{
HT(); //后退
timer=0;
while(timer<=4000);
}
if((S2<20)&&(S4<20)&&(S1<20)) //只要左右各有距离小于,20CM小车后退
{
HT(); //后退
timer=0;
while(timer<=4000);
}
if(S2>S4)
{
ZZ1(); //车的左边比车的右边距离小 右转
timer=0;
while(timer<=4000);
}
else
{
YZ1(); //车的左边比车的右边距离大 左转
timer=0;
while(timer<=4000);
}
}
/************************************************************************/
/* PWM调制舵机转速 */
/************************************************************************/
/* 舵机调速 */
/*调节push_val_left的值改变电机转速,占空比 */
void pwm_Servomoto(void)
{
if(pwm_val_left <= push_val_left)
Sevro_moto_pwm=1;
else
Sevro_moto_pwm=0;
if(pwm_val_left>=100)
pwm_val_left=0;
}
void minm() //按钮控制功能转换
{
COM=0;
if(K1==0)
{
delay1(10);
if(K1==0)
{
COM++;
}
while(!K1);
}
if(COM==4)
COM=0;
}
/***************************************************/
///*TIMER1中断服务子函数产生PWM信号*/
void time0()interrupt 1
{
TH0=(65536-100)/256; //100US定时
TL0=(65536-100)%256;
timer++; //定时器100US为准。在这个基础上延时
pwm_val_left++;
pwm_Servomoto();
t++;
if(t==5) //PWM调制左右电机速度
{
t=0;
non++;
}
if( non == PWM_NO )
{
PWM1 = 1;
PWM2 = 1;
}
if( non == connt )
{
non = 0;
if( PWM_NO != 0)
{
PWM1 = 0;
PWM2 = 0;
}
}
}
void lin() //避障功能
{
if(timer>=1000) //100MS检测启动检测一次 1000
{
timer=0;
StartModule(); //启动检测
Conut(); //计算距离
if(S<=25) //距离小于30CM
{
SC(); //小车停止
COMM(); //方向函数
}
else
if(S>25) //距离大于,30CM往前走
QJ();
if(!A1)
{
SC();
delay1(20);
HT();
delay1(300);
SC();
COMM();
}
if(!A2)
{
SC();
delay1(20);
HT();
delay1(300);
SC();
COMM();
}
}
}
/***************************************************/
///*TIMER0中断服务子函数产生PWM信号*/
void timer0()interrupt 3
{
}
/***************************************************/
void UARTInterrupt(void) interrupt 4 //串口中断函数
{
unsigned char com;
if(a==1) //判断能否执行
{
if(RI==1)
com = SBUF; //暂存接收到的数据
RI=0;
}
P0=smgduan[pon];
switch(com) //接收到字符并要执行的功能
{
case 0: QJ();break;
case 1: SC();break;
case 2: ZZ1();break;
case 3: YZ1();break;
case 4: HT();break;
case 5: pon++;PWM_NO--;break;
case 6: pon--;PWM_NO++;break;
}
}
void main(void)
{
IP=0x10;
TMOD=0X11;
TH0=(65536-100)/256; //100US定时
TL0=(65536-100)%256;
TR0= 1;
ET0= 1;
EA = 1;
connt = 20; //PWM的一个周期
PWM_NO = 16; //调速,数值越大速度越慢
delay(100);
push_val_left=14;
while(1) /*无限循环*/
{
Display();
minm();
switch(COM) //接收到字符并要执行的功能
{
case 0:TH1=0;TL1=0;ET1= 1; lin();break;
case 1:SC();InitUART();ET1= 0;a=1;while(1);break;
default:break;
}
}
}
|