#include
#include
//#include uint unsigned int
//#include uchar unsigned char
#define Stop 0 //停止
#define Left 1 //左转
#define Right 2 //右转
***it L1=P2^0; //左电机反转
***it L2=P2^1; //左电机正转
***it R3=P2^2; //右电机正转
***it R4=P2^3; //右电机反转
***it ControlPort = P1^5; //舵机信号端
//***it KeyLeft = P1^0; //左转按键端口
//***it KeyRight = P1^1; //右转按键端口
//***it KeyStop = P1^2; //归为按键端口
***it rs=P2^6; //1602的数据/指令选择控制线
***it rw=P2^5; //1602的读写控制线
***it en=P2^7; //1602的使能控制线
***it trig=P2^4; //超声波测距模块Trig
***it echo=P3^2; //超声波测距模块Echo
bit flag1; //触发信号标志位//
unsigned char count; //中断累加变量
long int distance; //测量所得距离
unsigned char timeOutCounter =0,LeftOrRight=0; //TimeOutCiunter:定时器溢出计数
//LeftOrRight :舵机左右旋转标志
unsigned char code table[]={"0123456789"}; //定义字符数组显示数字
void delay(unsigned int n) //延时函数
{
unsigned int x,y;
for(x=n;x>0;x--)
for(y=110;y>0;y--);
}
void delayt(unsigned int x) //延时函数
{
unsigned char j;
while(x-- > 0)
{
for(j = 0;j < 125;j++)
{
;
}
}
}
void Init()
{
TMOD =0x11; //定时/计数器1为工作方式1,定时/计数器0为工作方式1
TL0=0X66; //1ms
TH0=0xfc;
TH1=0xff; //赋初始值0.1ms
TH1=0xa4;
EA=1; //打开总中断
ET0=1; //打开定时器0中断
ET1=1; //打开定时器1中断
TR1=1; //启动定时器0
}
/*------------------------------------------------
1602写命令函数
------------------------------------------------*/
void lcd_wcom(unsigned char com)
{
rs=0; //选择指令寄存器
rw=0; //选择写
P0=com; //把命令字送入P0
delay(5); //延时一小会儿,让1602准备接收数据
en=1; //使能线电平变化,命令送入1602的8位数据口,这点非常重要
en=0;
}
/*------------------------------------------------
1602写数据函数
------------------------------------------------*/
void lcd_wdat(unsigned char dat)
{
rs=1; //选择数据寄存器
rw=0; //选择写
P0=dat; //把要显示的数据送入P0
delay(5); //延时一小会儿,让1602准备接收数据,也就是检测忙信号,这点非常重要。
en=1; //使能线电平变化,数据送入1602的8位数据口
en=0;
}
/*------------------------------------------------
1602初始化函数
------------------------------------------------*/
void lcd_init()
{
lcd_wcom(0x38); //8位数据,双列,5*7字形 ,用到功能设定指令
lcd_wcom(0x0c); //开启显示屏,关光标,光标不闪烁,用到显示开关控制指令
lcd_wcom(0x06); //显示地址递增,即写一个数据后,显示位置右移一位,用到了写入模式设置指令
lcd_wcom(0x01); //清屏,用到了清屏指令
}
/*------------------------------------------------
1602显示固定字符函数
------------------------------------------------*/
void lcd_xianshi()
{
lcd_wcom(0x80+0x40);
lcd_wdat('D');
lcd_wdat('i');
lcd_wdat('s');
lcd_wdat('t');
lcd_wdat('a');
lcd_wdat('n');
lcd_wdat('c');
lcd_wdat('e');
lcd_wdat(':');
lcd_wcom(0x80+0x4c);
lcd_wdat('.');
lcd_wcom(0x80+0x4e);//单位是厘米//
lcd_wdat('c');
lcd_wdat('m');
}
/*------------------------------------------------
超声波模块触发信号
------------------------------------------------*/
void trigger()
{
trig=0;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
trig=1;
}
/*------------------------------------------------
超声波模块相应端口初始化函数
------------------------------------------------*/
void init_measuring()
{
trig=1;
echo=1;
count=0;
}
/*------------------------------------------------
超声波模块距离测试函数
------------------------------------------------*/
void measuring()
{
unsigned char l;
unsigned int h,y;
TR0 = 1;
while(echo==1)
{
;
}
TR0 = 0;
l = TL0;
h = TH0;
y = (h << 8) + l;
y = y - 0xfc66;//us部分
distance = y + 1000 * count;//计算总时间,单位是微秒
TL0 = 0x66;
TH0 = 0xfc;
delayt(30);
distance = 3453* distance / 20000;//原始为:(0.34毫米/us)*时间/2//
}
/*------------------------------------------------
超声波模块测量结果显示函数
------------------------------------------------*/
void display(unsigned int x)
{
unsigned char qian,bai,shi,ge;
qian=x/1000;
bai=(x/100)%10;
shi=(x/10)%10;
ge=x%10;
lcd_wcom(0x80+0x49);//单位是厘米//
lcd_wdat(table[qian]);
lcd_wdat(table[bai]);
lcd_wdat(table[shi]);
lcd_wcom(0x80+0x4d);
lcd_wdat(table[ge]);
}
void qianxing() //前行
{
L1 =0; //前行
R4 =0;
L2 =1;
R3 =1;
}
//void houtui() //后退
//{
// L2 =0; //后退
// R3 =0;
// L1 =1;
// R4 =1;
//}
void main(void)
{
Init(); //定时器初始化
lcd_init(); //液晶初始化
init_measuring(); //超声波相应端口初始化
while(1)
{
qianxing();
lcd_xianshi(); //液晶显示特定字符
trigger(); //触发超声波启动
while(echo==0) //等待回声
{
;
}
measuring(); //进行距离测量
display(distance); //对测量结果进行显示
if(distance<30)
LeftOrRight=Left;
else
LeftOrRight=Stop;
init_measuring(); //超声波相应端口初始化
delayt(600); //每次测量间隔60ms
}
}
void Time_1(void) interrupt 3 //定时器中断函数
{
TR1 = 0;
TH1=0xff;//赋初值 0.1ms
TL1=0xa4;
switch(LeftOrRight)
{
case 0: //为0时舵机归位,脉宽1.5ms
{
if(TimeOutCounter <=9)
{
ControlPort =1;
}
else
{
ControlPort =0;
}
break;
}
case 1: //为1时,舵机左转,脉宽1ms(理论值)
{
if(TimeOutCounter <=8)
{
ControlPort =1;
}
else
{
ControlPort =0;
}
break;
}
case 2: //为1时,舵机右转,脉宽2ms(理论值)
{
if(TimeOutCounter <=11 )
{
ControlPort =1;
}
else
{
ControlPort =0;
}
break;
}
default:break;
}
TimeOutCounter++;
if(TimeOutCounter==200) //周期20ms(理论值),比较可靠
{
TimeOutCounter =0;
}
TR1=1;
}
voidT_0()interrupt 1
{
TF0 = 0;
TL0 = 0x66;
TH0 = 0xfc;
count++;
if(count==18)
{
TR0 =0;
TL0 = 0x66;
TH0 = 0xfc;
count = 0;
}
}