基于单片机的小区自动售水机系统 (包含C语言代码+PCB板设计+Proteus仿真+演示视频)


在这里插入图片描述 在这里插入图片描述

1. 背景与意义

  随着我国的快速发展,人民生活质量日益提高,对于健康的追求也日益加剧,因此对于优质的水源产生了巨大的需求,这就导致了自动售水机的诞生,并且其可以放置在小区内,可以实现不出小区就能喝到优质的水,其次其价格便宜也促进了自动售水机的快速普及。但目前市场上的自动售水机的价格昂贵,急需一种可以节约成本的电路设计。

2. 系统功能

  本系统设计是基于ATMEL公司的AT89C51单片机开发平台实现一种智能化的小区自动售水机系统。AT89C51 是一种带 4K 字节闪存可编程可擦除只读存储器(FPEROM—Flash Programmable and Erasable Read Only Memory) 的低电压、高性能 CMOS 8 位微处理器,采用 AT89C51 单片机为控制核心,在相应的软件控制下可以完成要求的功能,主要实现功能包括按键控制售水机水流出和停止,通过数码管显示单价、出水量及总费用通过光敏电阻检测环境亮度,当出水量达到预设限制会启动蜂鸣器报警,停止放水,在亮度过低的情况下,自动开灯,以及保存当前设置的水费单价。Proteus仿真图如下:

在这里插入图片描述

3. 元件清单

 1) AT89C51
 2) Lcd1602液晶显示屏
 3) LDR1 (光敏电阻)
 4) 有源蜂鸣器
 5) 电容 *2(20pf)
 6) CRYSTAL (12MHz)
 7) 电阻 *7(4k)
 8) AT24C02
 9) PCF8591
 10) 独立按键 *5

4. 系统设计

 4.1 系统执行流程图

  如下图为本设计的软件设计构图,它主要由主程序和光敏电阻模块、按键控制模块、LCD显示模块、定时器中断模块等子程序组成,其中主程序的功能是要先初始化系统的工作参数,通过主程序循环调用各个功能模块子程序,对相关事件的处理是依靠标志位和判断标志位来实现。

在这里插入图片描述)

 4.2 功能设计

  4.2.1 计费功能

  如下图为单价和水费显示流程图,在本设计中,当标志位为0时,LCD显示单价和水量,初始状态单价为0.5,水费为0。当标志位为1时,判断按键k2是否按下,按下按键k2,则LCD显示单价和水费,实现结账功能,下图为单价和水量显示界面,当k2被按下,界面会跳转到计费界面,如下图。

  4.2.2 水量预警

  如下图为水量检测流程图,按键k1按下,设备启动,计数器开始计数,中断返回,判断水量是否达到峰值,未达到则继续计数,达到峰值则蜂鸣器启动,设备停止工作,跳到计费界面。
在这里插入图片描述)

  4.2.3 环境亮暗检测及单价存储

  如下图所示,为了模拟当周围环境变暗的情况,我们设计了一个光敏电阻来实时检测环境亮度,当周围环境变暗时,光敏电阻检测到之后,返回电压值到主芯片,通过判断电压值小于某个值后,开启led灯。

  为了商家可以随时更改水的单价,当按下按键k3,单价每次增加0.5,当按下按键k4按键每次减少0.5。我们通过按键k5可以保存当前设置的单价,通过AT24C02芯片存储当前单价。当系统断电之后,也能保证下次能读取到上次保存的单价,下图为存储芯片工作时。

5. C语言主程序、仿真电路、PCB版设计和演示视频自取

  a. 主代码如下:

#include<reg51.h>
#include "lcd.h"
#include "iic.h"
#define uchar unsigned char
#define uint unsigned int
#define  GPIO_KEY P1  //独立键盘用P1口
sbit buzzer=P2^4;//蜂鸣器
sbit led=P2^2;//LED
uchar PuZh[] ="danjia:";
uchar CnCh[] = "suiliang:";
uchar z_money[]="feiyong:";
uchar pat[]={0};//显示单价
uchar kat[]={0};//显示水量
uchar lat[]={0};//总价钱
uchar water=0;
uchar money=0;
uint flag=0;
uint i=0;   //必须定义在这
uint MenNum=0;
uchar Num;
uint change=1;//切换菜单
uint danjia=5;
uchar keyNum=0;
uint adcValue=0;//读取电压
uchar Key_Scan(void);
uchar keyscan(void);
void key(void);
void Delay10ms(unsigned int c)   //误差 0us
{
    unsigned char a, b;
//--c已经在传递过来的时候已经赋值了,所以在for语句第一句就不用赋值了--//
    for (;c>0;c--)
{
for (b=38;b>0;b--)
{
for (a=130;a>0;a--);
}     
}       
}
/*****界面一*******/
void display_first()
{ uint i=0,j=0;
uchar k=0,t=0;
/*****显示单价********/
buzzer=1;
LcdWriteCom(0x80);
for(i=0; i<7; i++)
{
LcdWriteData(PuZh[i]); 
}
    LcdWriteCom(0x80+0x07);
  pat[0]=danjia/10+0x30;
  pat[1]=&apos;.&apos;;
  pat[2]=danjia%10+0x30;
   for(;k<3;k++)
  LcdWriteData(pat[k]);
/*****显示出水量********/
LcdWriteCom(0xC0);
for(j=0; j<9; j++)
{
LcdWriteData(CnCh[j]); 
}
kat[0]=water/100+0x30;
kat[1]=water%100/10+0x30; 
kat[2]=water%10+0x30;
for(;t<3;t++)
{
  LcdWriteData(kat[t])
}
}
/*****界面二*******/
void display_secend()
{ uint p=0,q=0;
uint u=0,h=0;
/*****显示单价********/
LcdWriteCom(0x80);
for(p=0; p<7; p++)
{
LcdWriteData(PuZh[p]); 
} 
    LcdWriteCom(0x80+0x07);
  pat[0]=danjia/10+0x30;
  pat[1]=&apos;.&apos;;
  pat[2]=danjia%10+0x30;
   for(;q<3;q++)
  LcdWriteData(pat[q]);

/******显示总费用******/
LcdWriteCom(0xC0);
for(u=0; u<8; u++)
{
LcdWriteData(z_money[u]); 
}
TR1=0;//关闭水量
money=water*danjia;
lat[0]=money/100+0x30;
lat[1]=money%100/10+0x30;
lat[2]=&apos;.&apos;;
lat[3]=money%10+0x30;
for(;h<4;h++)
{
 LcdWriteData(lat[h]);
}
}
void menu(uchar change)
{
 switch(change)
 {
  case 1: display_first();break;
  case 2: display_secend();break;
  }
}
void Timer0(void) 
{
 TMOD |= 0x11;   //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响      
 TH1=(65536-10000)/256;      
 TL1=(65536-10000)%256;
 EA=1;            //总中断打开
 ET1=1;           //定时器中断打开
 TR1=0;           
}
uchar keyscan()
{
  uchar keyvalue;
  keyNum=Key_Scan();   
  switch(keyNum)
  {
    case 0xfe: keyvalue = 1;break;//开启
    case 0xfd: keyvalue = 2;break;//关闭
case 0xfb: keyvalue = 3;break;//加
case 0xf7: keyvalue = 4;break;//减
case 0xef: keyvalue = 5;break;//保存
    default: break;   
} 
  return keyvalue;
}
uchar Key_Scan()
{
uchar keyValue = 0 , i; //保存键值
  GPIO_KEY=0xff;
//--检测按键1--//
if (GPIO_KEY != 0xFF) //检测按键K1是否按下
{
Delay10ms(1); //消除抖动
if (GPIO_KEY != 0xFF) //再次检测按键是否按下
{
keyValue = GPIO_KEY;
i = 0;
while ((i<50) && (GPIO_KEY != 0xFF))  //检测按键是否松开
{
Delay10ms(1);
i++;
}
}
}
return keyValue;   //将读取到键值的值返回
}
void main()
{
  LcdInit();
// danjia=epprom_read(0);
//  Delay10ms(1); 
//  adcValue=PCF85091_read(1); 
init_pcf8591(1);
Timer0();
while(1)
{ 
 Num=keyscan();   
switch(Num)
    {
case 1:    //开水键  
TR1=1;
water=0;
        change=1;
break;
case 2: //停水键    
TR1=0;
  change=2; 
money=water*danjia; 
break; 
case 3:
   danjia+=5;   
  break;
case 4:
    danjia-=5;
    if(danjia<=0)danjia=0; 
  break; 
      case 5:
  buzzer=1;//蜂鸣器关
//    epprom_write(0,danjia);
//         Delay10ms(1); 
  break; 
default:
  break;  

 }
  adcValue = adc_pcf8591();//读取光敏电阻的电压值
adcValue=adcValue*5/255.0*100+0.5;
  if(adcValue>340)
led=1;
else
led=0;
menu(change); 
}
}
void time_0() interrupt 3
{ 
static uchar i=0;
 TH1=(65536-20000)/256;      
 TL1=(65536-20000)%256; 
  if(++i == 30)
  { i=0;
water+=1;
  }
if(water == 30)
 { change=2;
     buzzer=0;//蜂鸣器响
 }  
}

  b. 完整C语言代码文件:C语言代码
  c. Proteus仿真仿真文件
  d. PCB板设计:PCB文件
  e. 演示视频:

用洞洞板连线拼接的视频演示

6. 相关作品

  请关注专栏:毕业设计作品

🤞🤞🤞

创作不易,请伸出您发财的小手,打赏下博主,非常感谢。

🤞🤞🤞

  • 58
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

时空旅行者 陈俊松

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值