//超声波模块显示程序
#include <reg52.h> //包括一个52标准内核的头文件
#include<intrins.h> //包含_nop_()函数定义的头文件
#define uchar unsigned char //定义一下方便使用
#define uint unsigned int
#define ulong unsigned long
#define DataPort P2
sbit Tx = P3^4; //产生脉冲引脚
sbit Rx = P3^2; //回波引脚
sbit left1=P0^0;
sbit left2=P0^1;
sbit right1=P0^2;
sbit right2=P0^3;
sbit E=P3^5;
sbit RS=P3^7;
sbit RW=P3^6;
sbit RST=P3^0;
sbit PSB=P3^1;
unsigned char code string[ ]= {"右电机转速"};
unsigned char code unit[]={"CM/S"};
unsigned char code digit[ ]={"0123456789."}; //定义字符数组显示数字
uint distance[4],speed_dat[4]; //测距接收缓冲区
uchar ge,shi,bai,temp,outcomeH,flag,outcomeL,i,COUT_2,COUT_3;
//自定义寄存器
bit succeed_flag; //测量成功标志
//********函数声明
void conversion(uint temp_data);
void delay_20us();
void pai_xu();
void LMotRun(uchar speed1, uchar speed2);
void LMotBack(uchar speed1, uchar speed2);
void RMotRun(uchar speed1,uchar speed2);
void RMotBack(uchar speed1, uchar speed2);
void LMotStop();
void RMotStop();
void AMotRun(uchar speed1, uchar speed2);
void Tracking();
void conversion_1(uint temp_data);
void LCD_Init(void);
void Check_Busy();
void Write_char(bit start, uchar temp_data);
void Clr_Scr(void);
void LCD_set_xy( uchar x, uchar y );
void LCD_Write_string(uchar X,uchar Y,uchar *s);
void LCD_Write_number(uchar s);
void Lcd_Mark2(void);
void Conut(void);
void delay_1(uint i)
{
int j;
for(;i>0;i--)
{
for(j=120;j>0;j--);
}
}
/*****************************************************
函数功能:延时1ms
(3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒
***************************************************/
void delay1ms()
{
unsigned char i,j;
for(i=0;i<10;i++)
for(j=0;j<33;j++)
;
}
/*****************************************************
函数功能:延时若干毫秒
入口参数:n
***************************************************/
void delay(unsigned char n)
{
unsigned char i;
for(i=0;i<n;i++)
delay1ms();
}
void main(void) // 主程序
{ uint distance_data,a,b;
uint total;
uchar CONT_1;
P0=0x7a; //定义变量i指向字符串数组元素
i=0;
flag=0;
EA=1;
Tx=0; //首先拉低脉冲输入引脚
TMOD=0x11; //定时器0,定时器1,16位工作方式
IT0=0;
IT1=1;
EX1=1; //由高电平变低电平,触发外部中断
ET1=1;
TR1=1;
TH1=0;
TL1=0; //打开定时器0中断
EX0=0; //关闭外部中断
Tracking();
LCD_Init(); //设置液晶显示器
Clr_Scr(); //清屏
//从图形显示状态下返回
Lcd_Mark2();
while(1) //程序循环
{
Conut();
EX0=0;
TR0=0;
Tx=1;
delay_20us();
Tx=0; //产生一个20us的脉冲,在Tx引脚
while(Rx==0); //等待Rx回波引脚变高电平
succeed_flag=0; //清测量成功标志
EX0=1; //打开外部中断
TH0=0; //定时器0清零
TL0=0; //定时器0清零
TF0=0; //
TR0=1; //启动定时器0
while(TH0 < 30);//等待测量的结果,周期65.535毫秒(可用中断实现)
TR0=0; //关闭定时器0
EX0=0; //关闭外部中断
if(succeed_flag==1)
{
distance_data=outcomeH; //测量结果的高8位
distance_data<<=8; //放入16位的高8位
distance_data=distance_data|outcomeL;//与低8位合并成为16位结果数据
distance_data*=12; //因为定时器默认为12分频
distance_data/=58; //微秒的单位除以58等于厘米
} //为什么除以58等于厘米, Y米=(X秒*344)/2
// X秒=( 2*Y米)/344 ==》X秒=0.0058*Y米 ==》厘米=微秒/58
if(succeed_flag==0)
{
distance_data=0; //没有回波则清零
}
distance[i]=distance_data; //将测量结果的数据放入缓冲区
i++;
if(i==3)
{
distance_data=(distance[0]+distance[1]+distance[2]+distance[3])/4;
pai_xu();
distance_data=distance[1];
a=distance_data;
if(b==a) CONT_1=0;
if(b!=a) CONT_1++;
if(CONT_1>=3)
{ CONT_1=0;
b=a;
conversion(b);
}
i=0;
}
total = bai*100+shi*10+ge;
if(total<200&&total>0)
{
LMotStop();RMotStop();
}
else
{
Tracking();
}
}
}
//***************************************************************
//外部中断0,用做判断回波电平
INTO_() interrupt 0 // 外部中断是0号
{
outcomeH =TH0; //取出定时器的值
outcomeL =TL0; //取出定时器的值
succeed_flag=1; //至成功测量的标志
EX0=0; //关闭外部中断
}
INT1_() interrupt 2
{
uint speed_data;
COUT_2++;
if(COUT_2==1)
{
COUT_2=0;
conversion_1(speed_data);
TR1=0;
TH1=60;
TL1=176;
COUT_3=0;
TR1=1;
}
}
//****************************************************************
//定时器0中断,用做显示
timer1() interrupt 3
{
TH1=0;
TL1=0;
COUT_3++;
}
void conversion_1(uint temp_data)
{
temp_data=TH1*256/10000;
temp_data=temp_data+6*COUT_3;
temp_data=880/temp_data;
speed_dat[0]=temp_data/100;
speed_dat[1]=temp_data%100/10;
speed_dat[2]=temp_data%10;
temp_data=8800/temp_data%10;
speed_dat[3]=temp_data;
}
void Lcd_init(void) //初始化LCD
{
delay_1(100); //大于40MS的延时程序
PSB=1; //设置为8BIT并口工作模式
delay_1(1); //延时
RST=0; //复位
delay_1(1); //延时
RST=1; //复位置高
delay_1(1);
Write_char(0,0x30); //选择基本指令集
delay_1(1); //延时大于100us
Write_char(0,0x30); //选择8bit数据流
delay_1(1); //延时大于37us
Write_char(0,0x0c); //开显示(无游标、不反白)
delay_1(1); //延时大于100us
Write_char(0,0x01); //清除显示,并且设定地址指针为00H
delay_1(30); //延时大于10ms
Write_char(0,0x06); //指定在资料的读取及写入时,设定游标的移动方向及指定显示的移位,光标从右向左加1位移动
delay_1(1); //延时大于100us
}
void Check_Busy()
{
RS=0;
RW=1;
E=1;
DataPort=0xff;
while((DataPort&0x80)==0x80);
E=0;
}
void Write_char(bit start, uchar temp_data) //写指令或数据
{
if(start==0)
{ Check_Busy();
RS=0;
RW=0;
E=1;
DataPort=temp_data;
E=0;
}
else
{ Check_Busy();
RS=1;
RW=0;
E=1;
DataPort=temp_data;
E=0;
}
}
void Clr_Scr(void)//清屏函数
{
Write_char(0,0x01);
}
/******************************************************************************/
void LCD_set_xy( uchar x, uchar y )
{ //设置LCD显示的起始位置,X为行,Y为列
uchar address;
switch(x)
{
case 0: address = 0x80 + y; break;
case 1: address = 0x80 + y; break;
case 2: address = 0x90 + y; break;
case 3: address = 0x88 + y; break;
case 4: address = 0x98 + y; break;
default:address = 0x80 + y; break;
}
Write_char(0, address);
}
void LCD_Write_string(uchar X,uchar Y,uchar *s)
{
LCD_set_xy( X, Y );
while (*s)
{
Write_char( 1, *s);
s++;
delay_1(5);
}
}
/******************************************************************************/
void LCD_Write_number(uchar s)// 数字显示函数
{
Write_char(1,digit[s]);
delay_1(5);
}
/******************************************************************************/
void Lcd_Mark2(void)
{
Clr_Scr();//清屏
LCD_Write_string(1,0,string);
LCD_Write_string(2,3,unit);
}
/********************************************************/
void Conut(void)
{
LCD_set_xy( 2, 0 );
LCD_Write_number(speed_dat[0]);
LCD_Write_number(speed_dat[1]);
LCD_Write_number(speed_dat[2]);
LCD_Write_number(10);
LCD_W