oliver1 发表于 2010-11-2 18:12:11

一个超声波测距的程序源码(和大家分享一下)

下面是一个超声波测距的程序,硬件电路由于电脑格盘已丢失,下面的代码是从样机上复制的。
硬件电路包括液晶显示、超声波的发射、超声波的接受、滤波、单片机处理。
液晶显示采用LCD1602模块,下面的代码里有液晶的驱动,可以拷贝用于它处。
超声波发射电路包括压电换能器及其支持电路,发射约44KHz的超声波。
超声波的接收电路包含一块CD40106处理芯片。
技术指标大约是测距范围在三米左右,测量精度约在厘米级别。大量用于倒车雷达的测距中。
#include<reg51.h>
#include <intrins.h>
#define Busy    0x80//用于检测LCM状态字中的Busy标识
#define LCM_DataP0
#define uchar unsigned char
#define uintunsigned int
#define ulong unsigned long


extern void cs_t(void);
extern void delay(uint);



void LCMInit(void);
void DisplayOneChar(uchar X, uchar Y, uchar DData);
void DisplayListChar(uchar X, uchar Y, uchar*DData);
void Delay5Ms(void);
void Delay100Ms(void);

void WriteDataLCM(uchar WDLCM);
void WriteCommandLCM(uchar WCLCM,BuysC);


data float distant=0.0;
uchar ReadDataLCM(void);
uchar ReadStatusLCM(void);
ucharcdle_net[] = {"--Daoche_Leida--"};
ucharemail[] = {"Juli:"};
ucharcls[]={"         "};
uchar DIS;
data ulong time;
float distant;
sbit LCM_RS=P1^1;//定义LCD引脚
sbit LCM_RW=P1^2;
sbit LCM_E=P1^3;
sbit P10=P1^0;


data uchar flag;

void zhuanhuan(float juli)
{
unsigned long juli1;
juli1=juli*100;
DIS=juli1%10+0x30;
juli1=juli1/10;
DIS=juli1%10+0x30;
juli1=juli1/10;
DIS='.';
DIS=juli1%10+0x30;
juli1=juli1/10;
DIS=juli1%10+0x30;
juli1=juli1/10;
DIS=juli1%10+0x30;
DIS=juli1/10+0x30;

}

void main(void)
{
   
    Delay100Ms(); //启动等待,等LCM讲入工作状态
    P10=1;   
    TMOD=0x01;             //计数器0工作在方式1
    TH0=0;
    TL0=0;                  //计数值初始化
    IT1=0;               //低电平触发中断
    EA=1;                //开总中断
    //IP=0x04;             //设置外部中断1为高优先级中断
    flag=0;
    LCMInit(); //LCM初始化
   
   
    while(1)
    {
   cs_t();
   Delay5Ms();      
   ET0=1;         //打开计数器0中断
   EX1=1;         //打开外部中断1
   TR0=1;
   while(!flag)
   {
      DisplayListChar(0, 0, cdle_net);
      DisplayListChar(0, 1, email);
   }
   if(flag==1)
   {
      time=TH0;
      time=(time<<8)|TL0;
      distant=time*1.72/100;
      zhuanhuan(distant);
      if(DIS=='0')      DisplayOneChar(5,1,' ');
      else   DisplayOneChar(5,1,DIS);
      if((DIS=='0')&&(DIS=='0'))      DisplayOneChar(6,1,' ');
      else   DisplayOneChar(6,1,DIS);
      if((DIS=='0')&&(DIS=='0')&&(DIS=='0'))DisplayOneChar(7,1,' ');
      else   DisplayOneChar(7,1,DIS);
      DisplayOneChar(8,1,DIS);
      DisplayOneChar(9,1,DIS);
      DisplayOneChar(10,1,DIS);
      DisplayOneChar(11,1,DIS);
      DisplayOneChar(12,1,'c');
      DisplayOneChar(13,1,'m');
      flag=0;
      }
   else
   {
      DisplayListChar(5,1,"error!      ");
      flag=0;
   }
   TH0=0;
   TL0=0;
    Delay100Ms();
    }
}



void cs_r(void) interrupt 2
{
TR0=0;
EX1=0;
ET0=0;
flag=1;
}


void overtime(void) interrupt 1
{
EX1=0;
TR0=0;
ET0=0;
flag=2;
}


//写数据
void WriteDataLCM(uchar WDLCM)
{
    ReadStatusLCM(); //检测忙
    LCM_Data=WDLCM;
    LCM_RS=1;
    LCM_RW=0;
    LCM_E=0; //若晶振速度太高可以在这后加小的延时
    LCM_E=0; //延时
    LCM_E=1;
}

//写指令
void WriteCommandLCM(uchar WCLCM,BuysC) //BuysC为0时忽略忙检测
{
    if (BuysC) ReadStatusLCM(); //根据需要检测忙
    LCM_Data = WCLCM;
    LCM_RS = 0;
    LCM_RW = 0;   
    LCM_E = 0;
    LCM_E = 0;
    LCM_E = 1;   
}

//读数据
uchar ReadDataLCM(void)
{
    LCM_RS = 1;
    LCM_RW = 1;
    LCM_E = 0;
    LCM_E = 0;
    LCM_E = 1;
    return(LCM_Data);
}

//读状态
uchar ReadStatusLCM(void)
{
    LCM_Data=0xFF;
    LCM_RS=0;
    LCM_RW=1;
    LCM_E=0;
    LCM_E=0;
    LCM_E=1;
    while(LCM_Data & Busy); //检测忙信号
    return(LCM_Data);
}

void LCMInit(void) //LCM初始化
{
    LCM_Data=0;
    WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号
    Delay5Ms();
    WriteCommandLCM(0x38,0);
    Delay5Ms();
    WriteCommandLCM(0x38,0);
    Delay5Ms();

    WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号
    WriteCommandLCM(0x08,1); //关闭显示
    WriteCommandLCM(0x01,1); //显示清屏
    WriteCommandLCM(0x06,1); // 显示光标移动设置
    WriteCommandLCM(0x0F,1); // 显示开及光标设置
}

//按指定位置显示一个字符
void DisplayOneChar(uchar X, uchar Y, uchar DData)
{
    Y &= 0x1;
    X &= 0xF; //限制X不能大于15,Y不能大于1
    if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
    X |= 0x80; //算出指令码
    WriteCommandLCM(X, 1); //发命令字
    WriteDataLCM(DData); //发数据
}

//按指定位置显示一串字符
void DisplayListChar(uchar X, uchar Y, uchar*DData)
{
    uchar ListLength;

ListLength = 0;
    Y &= 0x1;
    X &= 0xF; //限制X不能大于15,Y不能大于1
    while (DData>0x20) //若到达字串尾则退出
      {
            if (X <= 0xF) //X坐标应小于0xF
                {
                  DisplayOneChar(X, Y, DData); //显示单个字符
                  ListLength++;
                  X++;
                }
      }
}

//5ms延时
void Delay5Ms(void)
{
    uint TempCyc = 200;
    while(TempCyc--);
}

//400ms延时
void Delay100Ms(void)
{
    uchar TempCycA = 1;
    uint TempCycB;
    while(TempCycA--)
      {
            TempCycB=7269;
            while(TempCycB--);
      }
}
页: [1]
查看完整版本: 一个超声波测距的程序源码(和大家分享一下)

招聘斑竹