基于51单片机的超声波测距程序(含12864液晶显示)

2020-02-04 09:08发布

#include   <AT89X51.H>
#include   <intrins.h>       
//引脚定义
    sbit     RX    =  P1 ^ 1;        //超声波的TRIG
    sbit     TX    =  P1 ^ 2;        //c超声波的ECHO
    sbit     SID   =  P2^1;        //数据        12864的R/W(SID)
    sbit     SCLK  =  P2^2;        //时钟         12864的E(SLCK)

//Function Definition 函数声明
//12864
void Write_char(bit start, unsigned char ddata);
void Send_byte(unsigned char bbyte);
void Delaynms(unsigned int di);
void Lcd_init(void);
void Disp_img(unsigned char *img);
void LCD_Write_string(unsigned char X,unsigned char Y,unsigned char *s);
void LCD_set_xy( unsigned char x, unsigned char y );
void LCD_w_word(unsigned char *str);
unsigned char code num[]={"0123456789 :.-"};
unsigned char code CM[] =  {"CM"};
unsigned int  time=0;
         long S=0;
         bit  flag =0;
unsigned char disbuff[4]           ={ 0,0,0,0};

/******************************************************************************/
void Lcd_init(void)        //初始化LCD
{
        Delaynms(10); //启动等待,等LCM讲入工作状态
          Write_char(0,0x30);  //8 位介面,基本指令集
          Write_char(0,0x0c);  //显示打开,光标关,反白关
          Write_char(0,0x01);  //清屏,将DDRAM的地址计数器归零  
}

/******************************************************************************/
void Write_char(bit start, unsigned char ddata) //写指令或数据
{
        unsigned char start_data,Hdata,Ldata;
          if(start==0)
                start_data=0xf8;         //写指令
    else   
            start_data=0xfa;  //写数据
  
          Hdata=ddata&0xf0;                  //取高四位
          Ldata=(ddata<<4)&0xf0;  //取低四位
          Send_byte(start_data);          //发送起始信号
          Delaynms(5); //延时是必须的
          Send_byte(Hdata);              //发送高四位
          Delaynms(1);  //延时是必须的
          Send_byte(Ldata);                  //发送低四位
          Delaynms(1);  //延时是必须的
}

/******************************************************************************/
void Send_byte(unsigned char bbyte) //发送一个字节
{
        unsigned char i;
        for(i=0;i<8;i++)
           {
                   SID=bbyte&0x80; //取出最高位
                SCLK=1;
                   SCLK=0;
                   bbyte<<=1; //左移
           }  
}

/******************************************************************************/
void Delaynms(unsigned int di) //延时
{
        unsigned int da,db;
        for(da=0;da<di;da++)
                   for(db=0;db<10;db++);
}

/******************************************************************************/
       
/******************************************************************************/
void Clr_Scr(void)//清屏函数
{
        Write_char(0,0x01);
}

/******************************************************************************/
//设置LCD显示的起始位置,X为行,Y为列
void LCD_set_xy( unsigned char x, unsigned char y )
{       
    unsigned char 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(unsigned char X,unsigned char Y,unsigned char *s)       
{
        LCD_set_xy( X, Y );
   
    while (*s)
    {
                Write_char( 1, *s );
            s ++;
                Delaynms(1);
        }
}

/******************************************************************************/
//        数字显示函数
void LCD_Write_number(unsigned char s)
{       
        Write_char(1,num);
        Delaynms(1);
}
/******************************************************************************/
void Lcd_Mark2(void)                //单位为CM
{
        Clr_Scr();//清屏       
        LCD_Write_string(3,6,CM);//       
}

//向LCM发送一个字符串,长度64字符之内。
//应用:lcm_w_word("您好!");
void LCD_w_word(unsigned char *str)
{
                while(*str != '')
                {
                        Write_char(1,*str++);
        }
                *str = 0;
}



/********************************************************/
void Conut(void)
{
        time=TH0*256+TL0;
        TH0=0;
        TL0=0;
        S=(time)/52;       //算出来是CM          12M晶振
        if(flag==1)                      //超出测量
        {         
                 flag=0;
                   LCD_set_xy( 3, 4 );
                   LCD_Write_number(13);
                   LCD_Write_number(12);
                   LCD_set_xy( 3, 5 );
                   LCD_Write_number(13);
                   LCD_Write_number(13);          
         }
         else
         {
//                   disbuff[1]=time/10000;
//                   disbuff[2]=time%10000/1000;
//                   disbuff[3]=time%1000/100;
//                disbuff[4]=time%100/10 ;
//                disbuff[5]=time%10;
//                   LCD_set_xy( 3, 1 );
//                   LCD_Write_number(disbuff[1]);
//                   LCD_Write_number(disbuff[2]);
//                   LCD_Write_number(disbuff[3]);
//                LCD_Write_number(disbuff[4]);
//                LCD_Write_number(disbuff[5]);
                   disbuff[1]=S%10000/1000;
                   disbuff[2]=S%1000/100;
                disbuff[3]=S%100/10 ;
                disbuff[4]=S%10;
                   LCD_set_xy( 3, 4 );
                   LCD_Write_number(disbuff[1]);
                   LCD_Write_number(disbuff[2]);
                   LCD_Write_number(disbuff[3]);
                LCD_Write_number(disbuff[4]);
         }
}
/********************************************************/
void delayms(unsigned int ms)
{
        unsigned char i=100,j;
        for(;ms;ms--)
        {
                while(--i)
                {
                        j=10;
                        while(--j);
                }
        }
}
/********************************************************/
void zd0() interrupt 1                  //T0中断用来计数器溢出,超过测距范围
{
        flag=1;                                                         //中断溢出标志
}
/********************************************************/
void  StartModule()                          //T1中断用来扫描数码管和计800MS启动模块
{
          TX=1;                                         //800MS  启动一次模块
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          TX=0;
          }
/********************************************************/
void main(void)
{  
    TMOD=0x01;                   //设T0为方式1,GATE=1
        TH0=0;
        TL0=0;
        TR0=1;
        Lcd_init();       //设置液晶显示器
        Clr_Scr();        //清屏       
        Delaynms(1000);
        Lcd_init();       //从图形显示状态下返回
    Lcd_Mark2();
        LCD_set_xy( 3, 0 );
        LCD_w_word("距离为:");

        while(1)
        {
                 StartModule();                                                
                 while(!RX);                //当RX为零时等待
                 {}
                 TR0=1;                            //开启计数
                 while(RX);                        //当RX为1计数并等待
                 {
                         TR0=0;                                //关闭计数
                         Conut();
                         delayms(100);                   //80MS
                 }       
        }

}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。