超声波传感器与PIC18F4520控制器接口

时间:2018-12-20 11:42:13

标签: c

我正在尝试在LCD上显示距离,但是它在其上显示垃圾数据

编程步骤

PIC18F4520微控制器需要向HC-SR04触发引脚发送至少10 us触发脉冲。 收到触发脉冲后,HC-SR04自动发送八个40 kHz声波并等待上升沿 在回波引脚输出。 当在连接到PIC18F4520的输入的Echo引脚上发生上升沿捕获时,启动PIC18F4520的定时器并再次等待Echo引脚上的下降沿。 在Echo引脚上捕获到下降沿后,微控制器立即读取定时器的计数。该时间计数用于计算到物体的距离。 计算(距离,以厘米为单位)

声速= 343 m / s = 34300 cm / s = 34.3cm / msec = 0.0343cm / usec

距离=速度*时间

=(34300 *计时器)/ 2 = 17150 *(计时器)= 17150xT(秒)= 0.01715xT(usec)= 17.15 xT(毫秒)

我尝试了不同的方式,但是无法显示正确的距离,这是我的代码

#include<p18f4520.h>                
#include<string.h>                   

void delay_ms(int ms);
void delay_us(int us);
void Data(char Value);             
void Cmd(char Value);                
void Send2Lcd(const char Adr,rom const char *Lcd);

void main()                            
{
    char Dist_Array1[5];
    int Time=0,j=0;
    int Distance;   
    TRISB=0XFF;
    TRISC=0X00;        /*  (RC1,RC0 - >O/P Setting by Zero)      */
    TRISD=0X00;        /*  PORTD (0 - 7)pins Config as Output    */
    delay_ms(15);                      /*  Minimum 
                Delay To Power On LCD Module To Recieve Mode*/
    Cmd(0X30);  delay_ms(5);          /*  LCD                      Specification Commands                          */
    Cmd(0X30);  delay_ms(1);          /*  LCD                         Specification Commands                          */
    Cmd(0X30);  delay_ms(2);          /*  LCD                       Specification Commands                          */
    Cmd(0X38);                         /*  LCD Double                       Line Display Command                     */
    Cmd(0X06);                         /*  LCD Auto                    Increment Location Address Command         */
    Cmd(0X01);                         /*  LCD Display                        Clear Command                           */
    Cmd(0X0C);                         /*  LCD Display                     ON Command                              */
    Send2Lcd(0x80,"  Distance");
    Send2Lcd(0xc0,"Measurement");
    delay_ms(3);
    delay_ms(1000);

    TMR1H=0; TMR1L=0;       /* Load Timer1 with 0*/
    OSCCON=0x72;        /* Use internal                    oscillator frequency */

    while(1)
    {  
        Cmd(0x01);
        PORTCbits.RC3=0;    // trigger OFF
        delay_us(2);
        PORTCbits.RC3=1; // trigger ON
        delay_us(10);       
        PORTBbits.RB1=0; // trigger OFF

        while(PORTBbits.RB0==0 );       // RB0 is             connected to Echo pin
        T1CONbits.TMR1ON=1;         
        TMR1H=0; 
        TMR1L=0;        /* Load Timer1 with 0*/

        while(PORTBbits.RB0==1  );          
        T1CONbits.TMR1ON=0;

        Time = (TMR1L | (TMR1H<<8)); 
        Distance = (int)(Time/58.2);
        Cmd(0x01); 
        for(j=0;j<=2;j++)
        {
            Dist_Array1[j]=Distance%10+'0';  
            Distance=Distance/10;
        }
        Cmd(0x80);
        for(j=2;j>=0;j--)
        {
            Data(Dist_Array1[j]);
            delay_ms(100);           
        }
    }
    Cmd(0x01); 
}   

void Cmd(char Value){
     PORTD=Value;
     PORTCbits.RC1=0;    /*  RC1=0(RS=0)                        [Command Registr Selection])    */
     PORTCbits.RC0=0;   /*  RC0=0(R/W=0)    [Write                  Process])                */
    PORTCbits.RC2=1;                /*     RC2=1(Enable=1)  [Enable Line ON]                */
    delay_ms(4);                    /*  Minimun Delay                For Hold On Data                      */
    PORTCbits.RC2=0;                /*  
    RC2=0(Enable=0) [Enable Line OFF]               */
}   

void Data(char Value){
    PORTD=Value;
    PORTCbits.RC1=1;               /*  RC1=1(RS=1)                                [Data Registr Selection])       */
    PORTCbits.RC0=0;                /*  RC0=0(R/W=0)                      [Write Process])                */
    PORTCbits.RC2=1;               /*  RC2=1(Enable=1)                       [Enable Line ON]                */
    delay_ms(4);                   /*  Minimun Delay                    For Hold On Data                      */
    PORTCbits.RC2=0;               /*  RC2=0(Enable=0)                      [Enable Line OFF]               */
}

void Send2Lcd(const char Adr,rom const char *Lcd)
{
     Cmd(Adr);
     while(*Lcd!='\0')  
     {
        Data(*Lcd); 
        Lcd++;  
      }
}

void delay_ms(int ms)
{
    int i,count;
    for(i=1;i<=ms;i++)
    {
        count=498;
        while(count!=1)
        {
            count--;
        }
    }
}

void delay_us(int us)
{
    us=us>>1;
    while(us!=1)
        us--;
}

2 个答案:

答案 0 :(得分:2)

  

当在与PIC18F4520的输入相连的Echo引脚上发生上升沿捕获时,启动PIC18F4520的定时器,并再次等待Echo引脚上的下降沿。在Echo引脚上捕获到下降沿后,微控制器立即读取定时器的计数。

这不测量回声延迟。它测量回声 duration ,它与距离无关。您应该在信号产生后立即启动计时器,并在捕获到上升沿后立即阅读计时器。

还有更多工作可以排除噪声,消除任何回声,消除抖动等。

答案 1 :(得分:0)

我很确定在启动计时器后清除计时器是一个坏主意:

while(PORTBbits.RB0==0 );       // RB0 is             connected to Echo pin
T1CONbits.TMR1ON=1;         
TMR1H=0; 
TMR1L=0;        /* Load Timer1 with 0*/ 

至少,您的最终时间将短于两条指令的执行时间。在最坏的情况下,整个读取可能是垃圾。