#include <REGX52.H> //包含51单片机相关的头文件
#include <intrins.h>
sbit LeftIR=P3^5; //定义前方左侧红外探头端口
sbit RightIR=P3^4; //定义前方右侧红外探头端口
sbit IN1=P1^2; //定义左侧电机驱动A端
sbit IN2=P1^3; //定义左侧电机驱动B端
sbit IN3=P1^4; //定义右侧电机驱动A端
sbit IN4=P1^5;
sbit EN1=P1^6;
sbit EN2=P1^0;
sbit Beep=P2^3; //定义蜂鸣器端口
sbit IRIN=P3^3; //定义红外接收端口
sbit p00=P0^0; //LED
sbit p01=P0^1; //LED
sbit p02=P0^2; //LED
sbit p03=P0^3; //LED
sbit p04=P0^4; //LED
sbit p05=P0^5; //LED
sbit p06=P0^6; //LED
sbit p07=P0^7; //LED
sbit sda=P1^1;
sbit key=P3^2;
#define Left_moto_pwm P1_6 //PWM信号端
#define Right_moto_pwm P1_7 //PWM信号端
#define Left_moto_go {P1_2=1,P1_3=0;} //左电机向前走
#define Left_moto_back {P1_2=0,P1_3=1;} //左边电机向后转
#define Left_moto_Stop {P1_2=0,P1_3=0;} //左边电机停转
#define Right_moto_go {P1_4=1,P1_5=0;} //右边电机向前走
#define Right_moto_back {P1_4=0,P1_5=1;} //右边电机向后走
#define Right_moto_Stop {P1_4=0,P1_5=0;} //右边电机停转
unsigned char pwm_val_left =0;//变量定义
unsigned char push_val_left =0;// 左电机占空比N/20
unsigned char pwm_val_right =0;
unsigned char push_val_right=0;// 右电机占空比N/20
unsigned char code RecvData[]={0x19,0x18,0x52,0x5A,0x08,0x1C,0x16,0x45,0x46,0x47,0x0D,0x0E,0x00,0x0F};
unsigned char temp = 1;
unsigned char IRCOM[7];//接收数据缓冲区
unsigned int z;
bit Right_moto_stop=1;
bit Left_moto_stop =1;
unsigned int time3=0;
/*********************************************************************/
void tingzhi(void)
{
P1_2 = 0;
P1_3 = 0;
P1_4 = 0;
P1_5 = 0;
}
void qianjin(void)
{
push_val_left=3; //速度调节变量 0-20。。。0最小,20最大
push_val_right=3;
Left_moto_go ; //左电机往前走
Right_moto_go ; //右电机往前走
}
void houtui()
{
push_val_left=12; //速度调节变量 0-20。。。0最小,20最大
push_val_right=12;
Left_moto_back ; //左电机往前走
Right_moto_back ; //右电机往前走
}
void zuozhuan()
{
push_val_left=6;
push_val_right=12;
Right_moto_go ; //右电机往前走
Left_moto_back ; //左电机后走
}
void youzhuan()
{
push_val_left=12;
push_val_right=6;
Left_moto_go ; //左电机往前走
Right_moto_back ; //右电机往后走
}
/************************************************************************/
/* PWM调制电机转速 */
/************************************************************************/
/* 左电机调速 */
/*调节push_val_left的值改变电机转速,占空比 */
void pwm_out_left_moto(void)
{
if(Left_moto_stop)
{
if(pwm_val_left<=push_val_left)
{
Left_moto_pwm=1;
}
else
{
Left_moto_pwm=0;
}
if(pwm_val_left>=20)
pwm_val_left=0;
}
else
{
Left_moto_pwm=0;
}
}
/******************************************************************/
/* 右电机调速 */
void pwm_out_right_moto(void)
{
if(Right_moto_stop)
{
if(pwm_val_right<=push_val_right)
{
Right_moto_pwm=1;
}
else
{
Right_moto_pwm=0;
}
if(pwm_val_right>=20)
pwm_val_right=0;
}
else
{
Right_moto_pwm=0;
}
}
/***************************************************/
///*TIMER0中断服务子函数产生PWM信号*/
void timer0()interrupt 1 using 2
{
TH0=0xFc;
TL0=0X18;
time3++;
pwm_val_left++;
pwm_val_right++;
pwm_out_left_moto();
pwm_out_right_moto();
}
void Timer1Init() //50毫秒@11.0592MHz
{
// AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x10; //设置定时器模式
TL1 = 0x00; //设置定时初值
TH1 = 0x4C; //设置定时初值
TF1 = 0; //清除TF1标志
EA=1;
ET1=1;
TR1 = 1; //定时器1开始计时
}
void Timer1() interrupt 3//晶振频率是11.0592M
{
TH1=0X00; //给定时器赋初值,定时50ms
TL1=0x4C;
z++;
}
void Delay1ms(unsigned int i)
{
unsigned char j,k;
do{
j = 10;
do{
k = 50;
do{
_nop_();
}while(--k);
}while(--j);
}while(--i);
}
void delay_nus(unsigned int i) //延时:i>=12 ,i的最小延时单12 us
{
i=i/10;
while(--i);
}
void delay_nms(unsigned int n) //延时n ms
{
n=n+1;
while(--n)
delay_nus(900); //延时 1ms,同时进行补偿
}
void delayms(unsigned char x) //0.14mS延时程序
{
unsigned char i; //定义临时变量
while(x--) //延时时间循环
{
for (i = 0; i<13; i++) {} //14mS延时
}
}
void delay5(unsigned int i) //延时程序
{while(i--);}
void Delay1us ( int T )
{
while(T!=0)
{
_nop_();
T--;
}
}
void led_delay(void)
{
unsigned char i,j;
for(i=0;i<220;i++)
for(j=0;j<220;j++);
}
/*
void wudao(void)
{
Timer1Init();
while(1)
{
if(z>=3){
z=0;
tingzhi();
}
if(z>=60){
z=0;
qianjin();
}
if(z>=3){
z=0;
tingzhi();
}
if(z>=3){
z=0;
youzhuan();
}
if(z>=3){
z=0;
tingzhi();
}
if(z>=60){
z=0;
qianjin();
}
if(z>=3){
z=0;
tingzhi();
}
if(z>=3){
z=0;
youzhuan();
}
if(z>=3){
z=0;
tingzhi();
}
if(z>=60){
z=0;
qianjin();
}
if(z>=3){
z=0;
tingzhi();
}
if(z>=3){
z=0;
youzhuan();
}
if(z>=3){
z=0;
tingzhi();
}
if(z>=3){
z=0;
qianjin();
}
tingzhi();
}
}
*/
void wudao(void)
{
Timer1Init();//定时器1初始化
while(1)
{
tingzhi();
TR1=1;
while(z!=3);
TR1=0;
z=0;
qianjin();
TR1=1;
while(z!=60);
TR1=0;
z=0;
tingzhi();
TR1=1;
while(z!=3);
TR1=0;
z=0;
youzhuan();
TR1=1;
while(z!=3);
TR1=0;
z=0;
tingzhi();
TR1=1;
while(z!=3);
TR1=0;
z=0;
qianjin();
TR1=1;
while(z!=6);
TR1=0;
z=0;
tingzhi();
TR1=1;
while(z!=3);
TR1=0;
z=0;
youzhuan();
TR1=1;
while(z!=3);
TR1=0;
z=0;
tingzhi();
TR1=1;
while(z!=3);
TR1=0;
z=0;
qianjin();
TR1=1;
while(z!=60);
TR1=0;
z=0;
tingzhi();
TR1=1;
while(z!=3);
TR1=0;
z=0;
youzhuan();
TR1=1;
while(z!=3);
TR1=0;
z=0;
tingzhi();
TR1=1;
while(z!=3);
TR1=0;
z=0;
qianjin();
TR1=1;
while(z!=60);
TR1=0;
z=0;
tingzhi();
}
}
void forward(void)//两边
{
P0=0x7e;
led_delay();
P0=0xbd;
led_delay();
P0=0xdb;
led_delay();
P0=0xe7;
led_delay();
P0=0xe7;
led_delay();
P0=0xdb;
led_delay();
P0=0xbd;
led_delay();
P0=0x7e;
led_delay();
}
void Alter(void)//交替
{
P0=0xaa;
led_delay();
P0=0x55;
led_delay();
}
void backward(void)
{
P0=0x7f;
led_delay();
P0=0xbf;
led_delay();
P0=0xdf;
led_delay();
P0=0xef;
led_delay();
P0=0xf7;
led_delay();
P0=0xfb;
led_delay();
P0=0xfd;
led_delay();
P0=0xfe;
led_delay();
}
void blink(void)
{
P0=0xff;
led_delay();
P0=0x00;
led_delay();
}
void deng1() //流水灯
{p00=0;
p01=0;
delay5(5000);
p02=0;
p03=0;
delay5(5000);
p04=0;
p05=0;
delay5(5000);
p06=0;
p07=0;
delay5(5000);
p07=1;
p06=1;
delay5(5000);
p05=1;
p04=1;
delay5(5000);
p03=1;
p02=1;
delay5(5000);
p01=1;
p00=1;
delay5(5000);}
void deng2() //流水灯
{p00=0;
p01=1;
delay5(5000);
p02=0;
p03=1;
delay5(5000);
p04=0;
p05=1;
delay5(5000);
p06=0;
p07=1;
delay5(5000);
p07=0;
p06=1;
delay5(5000);
p05=0;
p04=1;
delay5(5000);
p03=0;
p02=1;
delay5(5000);
p01=0;
p00=1;
delay5(5000);}
void deng3() //流水灯
{p00=0;
p01=0;
delay5(5000);
p02=0;
p03=0;
delay5(5000);
p04=0;
p05=0;
delay5(5000);
p06=0;
p07=0;
delay5(5000);
p07=1;
p06=1;
delay5(5000);
p05=1;
p04=1;
delay5(5000);
p03=1;
p02=1;
delay5(5000);
p01=1;
p00=1;
delay5(5000);}
void deng4() //流水灯
{p00=1;
p01=1;
p02=1;
p03=1;
p04=1;
p05=1;
p06=1;
p07=1;
}
void Robot_Avoidance() //机器人避障子程序
{
if(LeftIR==1&&RightIR ==1) //LeftIRBZ RightIRBZ
{
deng1();
qianjin();
delay_nms (10);
// SB1=1;
}
else
{
if(LeftIR==1&&RightIR ==0) //右边检测到红外信号
{
deng4();
youzhuan(); //右转
delay_nms (300); //停止300MS 防止电机反相电压冲击 导致系统复位
deng1();
}
if(RightIR ==1&&LeftIR==0) //左边检测到红外信号
{
deng4();
zuozhuan(); //左转
delay_nms (300); //停止300MS 防止电机反相电压冲击 导致系统复位
deng1();
}
if(RightIR==0&&LeftIR==0) //两边传感器同时检测到红外
{
// SB1=0;
deng4();
tingzhi(); //停止
delay_nms (300); //停止300MS 防止电机反相电压冲击 导致系统复位
houtui(); //调用电机后退函数
delay_nms (300); //后退50毫秒
youzhuan(); //调用电机右转函数
delay_nms (400);
deng1();
}
}
qianjin();
}
void ControlCar_yaokong(unsigned char ConType) //定义电机控制子程序 (红外遥控单独设置一个 switch case 语句 )
{
tingzhi();
switch(ConType) //判断用户设定电机形式
{
case 1: //前进 //判断用户是否选择形式1
{
tingzhi(); //进入前进之前 先停止一段时间 防止电机反向电压冲击主板 导致系统复位
Delay1ms(150);
// LeftLed = 0 ;
qianjin();
break;
}
case 2: //后退 //判断用户是否选择形式2
{
tingzhi(); //进入后退之前 先停止一段时间 防止电机反向电压冲击主板 导致系统复位
Delay1ms(150);
// LeftLed = 1 ;
houtui(); //M2电机反转
break;
}
case 3: //右转 //判断用户是否选择形式3
{
tingzhi(); //进入左转之前 先停止一段时间 防止电机反向电压冲击主板 导致系统复位
Delay1ms(150);
youzhuan();
//M2电机正转
break;
}
case 4: //左转 //判断用户是否选择形式4
{
tingzhi(); //进入右转之前 先停止一段时间 防止电机反向电压冲击主板 导致系统复位
Delay1ms(150);
zuozhuan(); //M1电机正转 //M2电机反转
break;
}
case 5: //停止 //判断用户是否选择形式8
{
tingzhi();
break; //退出当前选择
}
case 6: //左转 //判断用户是否选择形式4
{
//进入右转之前 先停止一段时间 防止电机反向电压冲击主板 导致系统复位
Robot_Avoidance();
break;
}
case 7: //停止 //判断用户是否选择形式8
{
deng2();
break; //退出当前选择
}
case 8: //停止 //判断用户是否选择形式8
{
deng4();
break; //退出当前选择
}
}
}
//----------红外遥控-------------------------------------------------------------
void IR_IN() interrupt 2 using 0 //定义INT2外部中断函数
{
unsigned char j,k,N=0; //定义临时接收变量
EX1 = 0; //关闭外部中断,防止再有信号到达
delayms(15); //延时时间,进行红外消抖
if (IRIN==1) //判断红外信号是否消失
{
EX1 =1; //外部中断开
return; //返回
}
while (!IRIN) //等IR变为高电平,跳过9ms的前导低电平信号。
{
delayms(1); //延时等待
}
for (j=0;j<4;j++) //采集红外遥控器数据
{
for (k=0;k<8;k++) //分次采集8位数据
{
while (IRIN) //等 IR 变为低电平,跳过4.5ms的前导高电平信号。
{
delayms(1); //延时等待
}
while (!IRIN) //等 IR 变为高电平
{
delayms(1); //延时等待
}
while (IRIN) //计算IR高电平时长
{
delayms(1); //延时等待
N++; //计数器加加
if (N>=30) //判断计数器累加值
{
EX1=1; //打开外部中断功能
return; //返回
}
}
IRCOM[j]=IRCOM[j] >> 1; //进行数据位移操作并自动补零
if (N>=8) //判断数据长度
{
IRCOM[j] = IRCOM[j] | 0x80; //数据最高位补1
}
N=0; //清零位数计录器
}
}
if (IRCOM[2]!=~IRCOM[3]) //判断地址码是否相同
{
EX1=1; //打开外部中断
return; //返回
}
for(j=0;j<10;j++) //循环进行键码解析
{
if(IRCOM[2]==RecvData[j]) //进行键位对应
{
// ControlCar(j);
ControlCar_yaokong(j); //数码管显示相应数码
}
}
EX1 = 1; //外部中断开
}
void SendData ( unsigned char addr )
{
unsigned char i;
// EA = 0;/*发送时关掉中断,防止中断影响时序 */
sda = 1;/*开始拉搞 */
Delay1us ( 1000 );
sda = 0;/*开始引导码*/
Delay1us ( 3000 );/*此处延时最少要大于2ms,此参数延时为310ms */
for ( i = 0; i < 8; i++ ) /*总共8位数据 */
{
sda = 1;
if ( addr & 0x01 ) /*3:1表示数据位1,每个位用两个脉冲表示 */
{
Delay1us ( 500 );
sda = 0;
Delay1us ( 210 );
}
else /*1:3表示数据位0 ,每个位用两个脉冲表示 */
{
Delay1us ( 210 );
sda = 0;
Delay1us ( 500 );
}
addr >>= 1;
}
sda = 1;
// EA = 1;
}
void Stop_Music()
{
SendData(0x0a);
SendData(0x13);
}
void Star_Music()
{
SendData(0x0a);
SendData(0x03);
SendData(0x0b);
wudao();
}
//-------------------------------------------------------------------------------------------------------
void main() //主程序入口
{
// bit RunFlag=0; //定义小车运行标志位
// LedFlash=3000; //对闪灯数据进行初始化
EX1=1; //同意开启外部中断1
IT1=1; //设定外部中断1为低边缘触发类型
EA=1; //总中断开启
// ET1=1;
tingzhi();
//初始化小车运行状态
while(1) //程序主循环
{
if(key == 0)
{
delay_nms(10);
if(key == 0)
{
temp++;
while(!key);
}
}
if(temp > 4)
{
temp = 1;
}
switch(temp)
{
case 1:tingzhi();
//forward();
Stop_Music();
break;
case 2:
Robot_Avoidance();EX1 = 0;break;
case 3:
EX1 = 1;break;
case 4:
Star_Music();
break;
}
}
}
|