文档库 最新最全的文档下载
当前位置:文档库 › 基于51单片机红外小车控制C程序

基于51单片机红外小车控制C程序

/**********************************************************
平台 :AT89C52单片机,L293D电机驱动模块,8位数码管,
红外遥控及红外接收头

实验目的:通过红外控制实现小车前进,后退,左转,右转,停止,加速,减速。
同时数码管显示相应键值

编程组成:红外接收发射,电机处理,数码管显示

编写 :坑口yano
日期 :2014.9.17
***********************************************************/
#include

#define uchar unsigned char
#define uint unsigned int

//电机控制位定义,基于L293D电机控制芯片
sbit EN_A=P1^0;//电机A使能
sbit EN_B=P1^1;//电机B使能
sbit IN_A1=P1^2;//电机A方向控制位1
sbit IN_A2=P1^3;//电机A方向控制位2
sbit IN_B1=P1^4;//电机B方向控制位1
sbit IN_B2=P1^5;//电机B方向控制位2

//PWM加减速指示LED位定义
sbit led1=P1^6;
sbit led2=P1^7;

//数码管位定义
sbit dula=P2^6;
sbit wela=P2^7;

//数码管段选数组
uchar code smg_du[]={
0x3f,//0
0x06,//1
0x5b,//2
0x4f,//3
0x66,//4
0x6d,//5
0x7d,//6
0x07,//7
0x7f,//8
0x6f,//9
0x77,//A
0x7c,//B
0x39,//C
0x5e,//D
0x79,//E
0x71 //F
};

//数码管位选数组
uchar code smg_we[]={
0xfe,
0xfd,
0xfb,
0xf7,
0xef,
0xdf,
0xbf,
0x7f
};

//定义红外全局变量
uchar irtime;
uchar startflag;
uchar bitnum;
uchar irdata[33];
uchar irreceok;
uchar ircode[4];
uchar irprosok;
uchar dis[8];

//定义PWM全局变量
uchar e1;
uchar e2;
uchar pwm;
uchar pwm_num;
uchar add_flag;
uchar dec_flag;

//函数声明
void delay_ms(ms);
void time0_init(void);
void int0_init(void);
void irpros(void);
void irwork(void);
void display(void);

void time1_init(void);
void add_work(void);
void dec_work(void);

void forward(void);
void back(void);
void left(void);
void right(void);
void stop(void);
void adding(void);
void decreasing(void);
void motor(void);

//延时函数,延时1ms(晶振为11.0592MHz时得0.96831272ms,约为1ms)
void delay_ms(ms)
{
uchar i,j;
for(i=ms;i>0;i--)
for(j=110;j>0;j--);
}

/************************************************
红外遥控
************************************************/
//定时器T0初始化,完成红外计时
void time0_init(void)
{
TMOD=0X12;//方式2,自动重装初值

的8位定时器
TH0=0X00;
TL0=0X00;
EA=1;
ET0=1;
TR0=1;
}

//外部中断INT0初始化
void int0_init(void)
{
IT0=1;
EX0=1;
EA=1;
}

//定时器T0中断服务函数
void time0(void)interrupt 1
{
irtime++;//256//每加1计数256次
}

//外部中断INT0中断服务函数
void int0(void)interrupt 0
{
if(startflag)
{
if(irtime>=33&&irtime<64)//引导码时间13.5ms,13.5/0.256约等于52.7
{
bitnum=0;
}
irdata[bitnum]=irtime; //把irtime的值赋给数组irdata[bitnum]循环32次
irtime=0;
bitnum++;
if(bitnum==33)
{
bitnum=0;
irreceok=1; //irtime读完标志位
}
}
else
{
irtime=0;
startflag=1;
}
}

//取码
void irpros(void)
{
uchar i,j,k;
uchar value;
k=1;//跳过引导码
for(j=0;j<4;j++)
{
for(i=0;i<8;i++)
{
value=value>>1;//左移7次判断8次
if(irdata[k]>6)
{
value=value | 0x80;
}
k++;
}
ircode[j]=value;
value=0;
}
irprosok=1;
}


/**********************************************
数码管显示
***********************************************/
//转码,把接收到的4位红外码转成8位数码管显示
void irwork(void)
{
dis[0]=ircode[0]/16;
dis[1]=ircode[0]%16;
dis[2]=ircode[1]/16;
dis[3]=ircode[1]%16;
dis[4]=ircode[2]/16;
dis[5]=ircode[2]%16;
dis[6]=ircode[3]/16;
dis[7]=ircode[3]%16;
}

//数码管显示
void display(void)
{
uchar i;
for(i=0;i<8;i++)
{
dula=1;
P0=smg_du[dis[i]];
dula=0;
P0=0xff;

wela=1;
P0=smg_we[i];
wela=0;
delay_ms(1);
P0=0xff;
delay_ms(1);
}
}

/**********************************************
PWM
1.拟产生一个100hz的PWM,故周期为10ms
2.设定一个周期由100次中断产生,故中断一次为100us
***********************************************/
//定时器T1初始化,用于产生PWM周期计时。
void time1_init(void)
{
TMOD=0X12;//方式1
TH1=(65536-100)/256;
TL1=(65536-100)%256;
EA=1;
ET1=1;
TR1=1;
//PT1=1;//设定PWM中断为最高优先级
}

//pwm加速工作
void add_work(void)
{
add_flag=1;

if(add_flag==1)
{
delay_ms(50); //延时消抖
if(add_flag==1)
{
if(pwm<100)
{
pwm++;
}
else
{
led1=1;
led2=1;
}
}
}
}

//pwm减速工作
void dec_work(void)
{
dec_flag=1;

if(dec_flag==1)
{
delay_ms(50); //延时消抖
if(dec_flag==1)
{
if(pwm>1)
{
pwm--;
}
else
{
led1=0;
led2=0;
}
}

}
}

//定时器T1中断服务函数
void time1(void)interrupt 3
{
TR1=0;//进入中断暂停定时器T1工作,并重新赋初值
TH1=(65536-100)/256;
TL1=(65536-100)%256;

pwm_num++;//中断递增计数
if(pwm_num>100)
{
pwm_num=0;
}

if(pwm_num<=pwm)
{
e1=1;
e2=1;
led1=0;//随着PWM增大LED越来越亮
led2=0;
}
else
{
e1=0;
e2=0;
led1=1;//随着PWM减少LED越来越暗
led2=1;
}
TR1=1;
}

/**********************************************
电机控制
**********************************************/

//前进
void forward(void)
{
EN_A=1;//开两个电机使能
EN_B=1;
IN_A1=1;//电机A正转
IN_A2=0;
IN_B1=1;//电机B正转
IN_B2=0;
}

//后退
void back(void)
{
EN_A=1;//开两个电机使能
EN_B=1;
IN_A1=0;//电机A反转
IN_A2=1;
IN_B1=0;//电机B反转
IN_B2=1;
}

//左转
void left(void)
{
EN_A=1;//开两个电机使能
EN_B=1;
IN_A1=0;//电机A不转
IN_A2=0;
IN_B1=1;//电机B正转
IN_B2=0;
}

//右转
void right(void)
{
EN_A=1;//开两个电机使能
EN_B=1;
IN_A1=1;//电机A正转
IN_A2=0;
IN_B1=0;//电机B不转
IN_B2=0;
}

//停止
void stop(void)
{
EN_A=0;//两个电机关使能
EN_B=0;
}

//加速
void adding(void)
{
add_work();

EN_A=e1;//开两个电机使能
EN_B=e2;
IN_A1=1;//电机A正转
IN_A2=0;
IN_B1=1;//电机B正转
IN_B2=0;
}

//减速
void decreasing(void)
{
dec_work();

EN_A=e1;//开两个电机使能
EN_B=e2;
IN_A1=1;//电机A正转
IN_A2=0;
IN_B1=1;//电机B正转
IN_B2=0;
}

//电机控制
void motor(void)
{
switch(ircode[2])
{
case 0x18:forward();break;// 2 前进
case 0x1c:back();break; // 5 后退
case 0x0c:left();break; // 1 左转
case 0x5e:right();break; // 3 右转
case 0x16:stop();break; // 0 停止
case 0x15:adding();break; // + 加速
case 0x07:decreasing();break; // - 减速
default:break;
}
}


//主函数
void main(void)
{
time0_init();//初始化定时器和外部中断
int0_init();
time1_init();

while(1)
{
if(irreceok)//如果红外接收完毕就取码
{
irpros();
irreceok=0;
}
if(irprosok)//如果取码完毕就转化成数码管8位显示
{
irwork();
irprosok=0;
}
display();//数码管显示
delay_ms(1);
motor();//电机工作
}
}


相关文档
相关文档 最新文档