/****************************************************************************** **
*红外遥控小车程序*
* *
******************************************************************************* */
#include
#include
#define uchar unsigned char
#define uint unsigned int
uchar LCD_ID_1[16] = {"Red Control"};
uchar LCD_ID_2[16] = {"IR CODE:--H"};
void delay(uchar x); //x*0.14MS
void delay1(int ms);
void beep();
unsigned char pwm_val_left =0;//变量定义
unsigned char push_val_left =0;// 左电机占空比N/10
unsigned char pwm_val_right =0;
unsigned char push_val_right=0;// 右电机占空比N/10
bit Right_moto_stop=1;
bit Left_moto_stop =1;
unsigned int time=0;
sbit IN1=P1^0;
sbit IN2=P1^1;
sbit IN3=P1^2;
sbit IN4=P1^3;
sbit Left_moto_pwm=P1^6; //接驱动模块ENA 使能端,输入PWM信号调节速度sbit Right_moto_pwm=P1^7;
sbit zuo=P2^0;
sbit you=P2^1;
sbit IRIN = P3^3; //红外接收器数据线
sbit BEEP = P1^5; //蜂鸣器驱动线
uchar IRCOM[7];
sbit E=P2^7; //1602使能引脚
sbit RW=P2^6; //1602读写引脚
sbit RS=P2^5; //1602数据/命令选择引脚
void run()
{ push_val_left =3; //PWM 调节参数1-10 1为最慢,10是最快改这个值可以改变其速度
push_val_right =3; //PWM 调节参数1-10 1为最慢,10是最快改这个值可以改变其速度
IN1=1;
IN2=0;
IN3=1;
IN4=0;
beep();
}
//左转
void rightrun()
{
push_val_left =2; //PWM 调节参数1-10 1为最慢,10是最快改这个值可以改变其速度
push_val_right =2; //PWM 调节参数1-10 1为最慢,10是最快改这个值可以改变其速度
IN1=1;
IN2=0;
IN3=0;
IN4=1;//右轮倒转
}
//右转
void leftrun()
{
push_val_left =2 ; //PWM 调节参数1-10 1为最慢,10是最快改这个值可以改变其速度
push_val_right =2; //PWM 调节参数1-10 1为最慢,10是最快改这个值可以改变其速度
IN1=0;//左轮倒转
IN2=1;
IN3=1;//右轮正传
IN4=0;
}
//STOP
void hou()
{
push_val_left =3 ; //PWM 调节参数1-10 1为最慢,10是最快改这个值可以改变其速度
push_val_right =3; //PWM 调节参数1-10 1为最慢,10是最快改这个值可以改变其速度
IN1=0;
IN2=1;
IN3=0;
IN4=1;
}
void stop()
{
IN1=0;
IN2=0;
IN3=0;
IN4=0;
}
/************************************************************************/
/* 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>=10)
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>=10)
pwm_val_right=0;
}
else Right_moto_pwm=0;
}
/***************************************************/
///*TIMER0中断服务子函数产生PWM信号*/
void timer0()interrupt 1 using 2
{
TH0=0XF8; //1Ms定时
TL0=0X30;
time++;
pwm_val_left++;
pwm_val_right++;
pwm_out_left_moto();
pwm_out_right_moto();
}
/********************************************************************
* 名称: delay()
* 功能: 延时,延时时间大概为140US。
* 输入: 无
* 输出: 无
***********************************************************************/
void Delay2()
{
int i,j;
for(i=0; i<=10; i++)
for(j=0; j<=2; j++)
;
}
/********************************************************************
* 名称: enable(uchar del)
* 功能: 1602命令函数
* 输入: 输入的命令值
* 输出: 无
***********************************************************************/
void enable(uchar del)
{
P0 = del;
RS = 0;
RW = 0;
E = 0;
Delay2();
E = 1;
Delay2();
}
/********************************************************************
* 名称: write(uchar del)
* 功能: 1602写数据函数
* 输入: 需要写入1602的数据
* 输出: 无
***********************************************************************/
void write(uchar del)
{
P0 = del;
RS = 1;
RW = 0;
E = 0;
Delay2();
E = 1;
Delay2();
}
/********************************************************************
* 名称: L1602_init()
* 功能: 1602初始化,请参考1602的资料
* 输入: 无
* 输出: 无
***********************************************************************/ void L1602_init(void)
{
enable(0x01);
enable(0x38);
enable(0x0c);
enable(0x06);
enable(0xd0);
}
/********************************************************************
* 名称: L1602_char(uchar hang,uchar lie,char sign)
* 功能: 改变液晶中某位的值,如果要让第一行,第五个字符显示"b" ,调用该函数如下L1602_char(1,5,'b')
* 输入: 行,列,需要输入1602的数据
* 输出: 无
***********************************************************************/
void L1602_char(uchar hang,uchar lie,char sign)
{
uchar a;
if(hang == 1) a = 0x80;
if(hang == 2) a = 0xc0;
a = a + lie - 1;
enable(a);
write(sign);
}
/********************************************************************
* 名称: L1602_string(uchar hang,uchar lie,uchar *p)
* 功能: 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下
L1602_string(1,5,"ab cd ef;")
* 输入: 行,列,需要输入1602的数据
* 输出: 无
***********************************************************************/
void L1602_string(uchar hang,uchar lie,uchar *p)
{
uchar a;
if(hang == 1) a = 0x80;
if(hang == 2) a = 0xc0;
a = a + lie - 1;
enable(a);
while(1)
{
if(*p == '\0') break;
write(*p);
p++;
}
}
/*******************************************************************/ void main()
{
TMOD=0X01;
IE = 0x84; //允许总中断中断,使能INT1 外部中断
TCON = 0x10; //触发方式为脉冲负边沿触发
TH0= 0XF8; //1ms定时
TL0= 0X30;
TR0= 1;
ET0= 1;
EA = 1;
IRIN=1; //I/O口初始化
BEEP=1;
delay1(10); //延时
L1602_init(); //初始化LCD
L1602_string(1, 1, LCD_ID_1);
L1602_string(2, 1, LCD_ID_2);
while(1) ;
} //end main
/**********************************************************/
void IR_IN() interrupt 2 using 0
{
unsigned char j,k,N=0;
EX1 = 0;
delay(15);
if (IRIN==1)
{ EX1 =1;
return;
}
//确认IR信号出现
while (!IRIN) //等IR变为高电平,跳过9ms的前导低电平信号。
{delay(1);}
for (j=0;j<4;j++) //收集四组数据
{
for (k=0;k<8;k++) //每组数据有8位
{
while (IRIN) //等IR 变为低电平,跳过4.5ms的前导高电平信号。
{delay(1);}
while (!IRIN) //等IR 变为高电平
{delay(1);}
while (IRIN) //计算IR高电平时长
{
delay(1);
N++;
if (N>=30)
{ EX1=1;
return;} //0.14ms计数过长自动离开。
} //高电平计数完毕
IRCOM[j]=IRCOM[j] >> 1; //数据最高位补“0”
if (N>=8) {IRCOM[j] = IRCOM[j] | 0x80;} //数据最高位补“1”
N=0;
}//end for k
}//end for j
if (IRCOM[2]!=~IRCOM[3])
{ EX1=1;
return; }
IRCOM[5]=IRCOM[2] & 0x10F; //取键码的低四位
IRCOM[6]=IRCOM[2] >> 4; //右移4次,高四位变为低四位
if(IRCOM[5]>9)
{ IRCOM[5]=IRCOM[5]+0x37;}
else
IRCOM[5]=IRCOM[5]+0x30;
if(IRCOM[6]>9)
{ IRCOM[6]=IRCOM[6]+0x37;}
else
IRCOM[6]=IRCOM[6]+0x30;
//////////////////////////
L1602_char(2,10,IRCOM[5]);
L1602_char(2,9,IRCOM[6]);
if(IRCOM[2]==0x43)
{
rightrun();
}
if(IRCOM[2]==0x44)
{
leftrun();
}
if(IRCOM[2]==0x46)
{
run();
}
if(IRCOM[2]==0x40)
{stop();
}
EX1 = 1;
if(IRCOM[2]==0x15)
{hou();
}
}
/**********************************************************/ void beep()
{
unsigned char i;
for (i=0;i<100;i++)
{
delay(4);
BEEP=!BEEP; //BEEP取反
}
BEEP=1; //关闭蜂鸣器
}
/**********************************************************/ void delay(unsigned char x) //x*0.14MS
{
unsigned char i;
while(x--)
{
for (i = 0; i<13; i++) {}
}
}
/**********************************************************/ void delay1(int ms)
{
unsigned char y;
while(ms--)
{
for(y = 0; y<250; y++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}