设计水位监控系统(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(); // 检查水位并控制红灯
}
}
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();
}
}