单片机超声波实时测量

设计水位监控系统(AT89C51)
1)实现超声波实时测量并显示水位的功能;
2)精度达到±1cm,测量范围2cm-30cm。
3)当水位低于下限值时,红灯亮表示抽水,高于上限值红灯灭表示停止抽水,上下限值可以通过按键进行设置。


#include <reg51.h>

#define TRIG_PIN P1        // 超声波传感器Trig引脚连接到P1口
#define ECHO_PIN P2        // 超声波传感器Echo引脚连接到P2口
#define DISPLAY_PORT P3    // 数码管显示模块连接到P3口
#define LED_PIN P0        // 红色LED灯连接到P0口
#define UP_LIMIT_PIN P2    // 上限设置按键连接到P2口的一个引脚
#define DOWN_LIMIT_PIN P2    // 下限设置按键连接到P2口的另一个引脚

unsigned int distance = 0;    // 存储测量得到的距离
unsigned int upLimit = 0;    // 上限值
unsigned int downLimit = 0;    // 下限值

// 延时函数
void delay(unsigned int milliseconds) {
    unsigned int i, j;
    for (i = 0; i < milliseconds; i++)
        for (j = 0; j < 120; j++);
}

// 发送一个脉冲到超声波传感器,触发测量
void triggerSensor() {
    TRIG_PIN = 1;    // 发送高电平脉冲
    delay(10);        // 持续一段时间
    TRIG_PIN = 0;    // 恢复低电平
}

// 测量脉冲宽度并计算距离
void measureDistance() interrupt 2 {
    unsigned int pulseWidth = 0;
    while (ECHO_PIN) {
        delay(1);
        pulseWidth++;
    }
    distance = pulseWidth / 58;    // 转换为距离(单位:厘米)
}

// 初始化系统
void init() {
    TMOD = 0x20;        // 使用定时器1的工作模式2
    TH1 = 0xFD;        // 设置计时器初值
    IE = 0x88;        // 开启计时器1中断
    TR1 = 1;        // 启动计时器1
}

// 数码管显示距离值
void displayDistance(unsigned int value) {
    unsigned int thousands, hundreds, tens, units;
    thousands = value / 1000;
    hundreds = (value % 1000) / 100;
    tens = (value % 100) / 10;
    units = value % 10;
    DISPLAY_PORT = (0x01 << 4) | thousands;    // 数码管第一位显示千位
    delay(5);
    DISPLAY_PORT = (0x01 << 3) | hundreds;    // 数码管第二位显示百位
    delay(5);
    DISPLAY_PORT = (0x01 << 2) | tens;        // 数码管第三位显示十位
    delay(5);
    DISPLAY_PORT = (0x01 << 1) | units;        // 数码管第四位显示个位
    delay(5);
}

// 检查水位并控制红灯状态
void checkWaterLevel() {
    if (distance < downLimit) {
        LED_PIN = 1;    // 红灯亮表示抽水
    } else if (distance > upLimit) {
        LED_PIN = 0;    // 红灯灭表示停止抽水
    }
}

// 主函数
void main() {
    init();
    while (1) {
        triggerSensor();            // 触发测量
        displayDistance(distance);    // 显示距离值
        checkWaterLevel();            // 检查水位并控制红灯
    }
}

  • 你可以参考下这个问题的回答, 看看是否对你有帮助, 链接: https://ask.csdn.net/questions/7610485
  • 这篇博客你也可以参考下:单片机 流水灯
  • 除此之外, 这篇博客: 单片机(AT89C51)的仿真实验——流水灯和逐一闪烁灯(输入与输出)中的 流水灯的实现(正向的流水灯): 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • P1初始值是:1111 1111和temp(0000 0001)异或等于以后  P1=1111 1110使得第一个灯亮着,

    进入循环0000 0001左移一位得到0000 0010,然后再和P1(1111 1110)异或等于以后  P1=1111 1100使得第一个灯和第二个灯都亮着,下面也是如此往复的循环,一盏一盏的连着点亮就实现了流水灯,然后一盏接着一盏的灭掉。

    #include<reg51.h>
    void delay02s(void)                    //延时函数的定义申明
    {
    unsigned char i,j,k;
     for(i=20;i>0;i--)
      for(j=20;j>0;j--)
        for(k=248;k>0;k--);
    }
    void main(void)
    {
        char temp;
    	char i;
       while(1)
       {
    
    	   	temp=0x01;
    		for(i=0;i<8;i++)        
    		{
    		P1^=temp;              //异或等于的运算使得可以保留前一次的结果
    		delay02s();            //延时函数
    		temp=temp<<1;          //左移实现
    		} 
    			
       }
    }
    #include<reg51.h>
    unsigned char code Tab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
    unsigned char i;
    void delay02s(void)
    {
    unsigned char i,j,k;
     for(i=20;i>0;i--)
      for(j=20;j>0;j--)
        for(k=248;k>0;k--);
    }
    void main(void)
    {
      while(1)
      {
       if(i<8)
       {
       P1=Tab[i];
       delay02s();
       i++;
       }
       else
       i=0;
      }
    }

    原理和正向的流水灯雷同。

    #include<reg51.h>
    void delay02s(void)                 //延时函数的定义申明
    {
    unsigned char i,j,k;
     for(i=20;i>0;i--)
      for(j=20;j>0;j--)
        for(k=248;k>0;k--);
    }
    void main(void)
    {
        char temp;
    	char i;
       while(1)
       {
    	
    		temp=0x80;
    		for(i=0;i<8;i++)
    		{
    		P1^=temp;              //异或等于的运算使得可以保留前一次的结果
    		delay02s();            //延时函数
    		temp=temp>>1;          //右移实现
    		} 
       }
    }

    直接把八个灯的接口全部定义一遍,然后在循环中写入各个接口的关闭和打开的代码,再在中间加入延时函数。比较的暴力,容易理解,容量大。

    #include<reg51.h>
    sbit  P1_0=P1^0;
    sbit  P1_1=P1^1;
    sbit  P1_2=P1^2;
    sbit  P1_3=P1^3;
    sbit  P1_4=P1^4;
    sbit  P1_5=P1^5;
    sbit  P1_6=P1^6;
    sbit  P1_7=P1^7;
    
    void delay02s(void)             //延时函数的定义申明
    {
        unsigned char i,j,k;
        for(i=20;i>0;i--)
         for(j=20;j>0;j--)
           for(k=248;k>0;k--);
    }
    void main(void)
    {
       int i=0;
       while(1)
       {
           P1_0=0;                 //第一盏灯的开启
           delay02s();             //延时函数   
           P1_0=1;                 //第一盏灯的关闭
           delay02s();
    
    	   P1_1=0;
           delay02s();
           P1_1=1;
           delay02s();
    
    	   P1_2=0;
           delay02s();
           P1_2=1;
           delay02s();
    
    	   P1_3=0;
           delay02s();
           P1_3=1;
           delay02s();
    
    	   P1_4=0;
           delay02s();
           P1_4=1;
           delay02s();
    
    	   P1_5=0;
           delay02s();
           P1_5=1;
           delay02s();
    
    	   P1_6=0;
           delay02s();
           P1_6=1;
           delay02s();
    
    	   P1_7=0;
           delay02s();
           P1_7=1;
           delay02s();
       }
    }
    
    
    

     

  • 您还可以看一下 洪青霞老师的Unity益智游戏之快乐玻璃杯课程中的 水龙头出水小节, 巩固相关知识点