蓝桥杯真题——自动售水机

时间:2022-10-16 01:08:37
                                     2012 年第四届全国电子专业人才设计与技能大赛
                                                       “自动售水机”设计任务书
1. 系统框图
蓝桥杯真题——自动售水机

竞赛要求:

通过竞赛硬件平台模拟小区自动售水机的工作流程:通过 按键控制 售水机水流出和停止;
通过 数码管显示费率、出水量及总费用 ;通过 光敏电阻检测环境亮度(AD) ,在亮度过低的情况下, 自动开灯 。系统硬件电路主要由单片机控制电路、数码管显示电路、A/D 转换电路及功能按 键组成。

1. 数码管显示单元
任务:
通过 4 位数码管 DS1 显示费率 (固定为0.5) ,单位为元 / 升,保留 2 位有效数字;
通过 4 位数码管 DS2 显示当前出水总量 (出水时,单位为升)和总价(停止时,单
位为元):按下出水按键 S7 后,清除数码管 DS2 显示数据,数码管 DS2 实时显示出水
( 保留两位有效数字 ) ,在出水状态下,再次按下 S7 ,不会影响出水状态,直到按下停
止按键 S6 为止;按下停止出水按键 S6 后,数码管 DS2 显示总价(保留两位有效数字)。

当按下S7时:

蓝桥杯真题——自动售水机

对上面的内容我们需要一点一点来,先不处理按键部分

1.在初始状态下,DS1肯定是不变的,问题在于DS2,在初始状态下 DS2也是为00.00的

(有一个想法,也就是其实可以把他视为控制部分,也就是一个显示,一个控制)

2. 当按键按下,才开始显示,所以我们设置一个值来代表出水量 Water_vaule,我们知道:出水速度为 100 ml/s,我们知道的是定时器是1ms,显示为 1L = 1000ml 1000ms =1s 所以换算我们就知道,当有10ml的时候就会显示在最后一位上,而1ms = 0.1ml,所以当计数 = 100时,就可以进行显示,也就是基础是从百位开始的。 

3. 所以这个时候我们就可以开始配合按键开始写了,首先,我们按下按键7的时候,应该进行计数重置(我在思考,这个能不能用延时来代替,目前先使用定时器) 但是要注意

按下出水按键 S7 后,清除数码管 DS2 显示数据,数码管 DS2 实时显示出水
( 保留两位有效数字 ) ,在出水状态下,再次按下 S7 ,不会影响出水状态
所以这边应该是有一个限制条件的(注意 按键时BJT(独立按键)还是 KBD 矩阵按键 )
(已完成—— 我们把重置放在按键里面就可以,加上条件,这样的话就是在按下之后就会重置一次,这下就满足了题目条件)
4. 接下来进行按键S6的操作

当按下S6时:

蓝桥杯真题——自动售水机

系统说明:

. 一次出水总量达到 99.99L 时,继电器自动断开,数码管显示 DS2 显示价格。

AD部分:

通过 光敏电阻 RD1 (读取AD 通道3)和 AD 转换芯片 PCF8591 组成的亮度检测电路(亮度值转换为 PCF8591 光敏电阻通道的电压)检测环境亮度;
PCF8591 光敏电阻通道输入电压小 1.25 V 时, L1 点亮,大于 1.25V 时, L1 熄灭

我们需要注意的是:

      光敏传感器接到AIN1,通道1;控制寄存器应写入:0x01
      电位器Rb2接到AIN3,通道3;控制寄存器应写入:0x03。 

同时也要注意,按键按下的时候需要打开继电器,所以我们就可以得到完整的代码了

(根据我们的模板写出的代码,纤细的各模块内容我就不放了,大家可以看看)


#include <STC15F2K60S2.H>
#include <Init.h>
#include <Led.h>
#include <Key.h>
#include <Seg.h>
#include "ds1302.h" 
#include "onewire.h" 
#include "iic.h"


unsigned char Key_Val,Key_Down,Key_Old,Key_Up; //按键控制专用
unsigned char Key_Slow_Down;

unsigned char Seg_Buf[8] = {10,10,10,10,10,10,10,10}; //数码管显示数组——写入数据
unsigned char Seg_Point[8] = {0,0,0,0,0,0,0,0}; //小数点,使能
unsigned char Seg_Pos; //数码管位显示,定时器使用,不需要管
unsigned int Seg_Slow_Down;

unsigned char ucLed[8] = {0,0,0,0,0,0,0,0}; //按键显示存放 0,1


unsigned char ucRtc[3] = {0x23,0x59,0x55}; //时钟初始时间
unsigned char ucRtc_Set[3];
unsigned char ucRtc_Set_Index;

unsigned int Water_value = 0; //计算出水量
unsigned int Water_count = 0; //计数
unsigned int Water_value_show = 0; //暂时没用
unsigned int Water_money; //显示钱

float dat = 0; //读取ad值

unsigned char Seg_Mode = 0; //设置模式




void Key_Proc()
{
	
	if(Key_Slow_Down) return;
	Key_Slow_Down = 1;

	Key_Val = Key_Read();
	Key_Down = Key_Val & (Key_Old ^ Key_Val);
	Key_Up = ~Key_Val & (Key_Old ^ Key_Val);
	Key_Old = Key_Val;

  
	
	switch(Key_Down)
	{
		case 7:  // 初始化显示界面切换为水量   
		
		if(Seg_Mode == 0)
		{
			Water_value = 0;
  		Water_count = 0;
		//	Water_money=(Water_value/2);
			Seg_Mode = 1;
			Relay(1);		
		}
		break;
    
		case 6: //切换为总价
		if(Seg_Mode == 1)
		{
			Water_money=(Water_value/2);
			Seg_Mode = 2;		
      Relay(0);	
		}
		break;
			
	}

}


void Seg_Proc()
{
	
	if(Seg_Slow_Down) return; 
	Seg_Slow_Down = 1;
	
	/* Êý¾Ý¶ÁÈ¡ÇøÓò */
	dat = Ad_Read(0x43) / 51.0; 

  /* Êý¾ÝÏÔʾÇøÓò */
	switch(Seg_Mode)
	{
		case 0:
		/* DS1 */
		Seg_Buf[1] = 0;
		Seg_Buf[2] = 5;
		Seg_Buf[3] = 0;
		Seg_Point[1] = 1; //ÏÔʾСÊý
		/* DS2³õʼ²¿·Ö */
		Seg_Buf[4] = 0;
		Seg_Buf[5] = 0;
		Seg_Point[5] = 1;
		Seg_Buf[6] = 0;
		Seg_Buf[7] = 0;
		break;
	
    case 1:
		//Water_money=(Water_value/2);
		if(Water_value < 10 )
		{
		Seg_Buf[4] = 0;
		Seg_Buf[5] = 0;
		Seg_Point[5] = 1;
		Seg_Buf[6] = 0;
		Seg_Buf[7] = Water_value;
		}
		else if(Water_value >= 10 && Water_value<100)
		{
			// 23
		Seg_Buf[4] = 0;
		Seg_Buf[5] = 0;
		Seg_Point[5] = 1;
		Seg_Buf[6] = Water_value / 10;
		Seg_Buf[7] = Water_value % 10;
		}
		else if(Water_value >= 100 && Water_value<1000)
		{
			// 234 
		Seg_Buf[4] = 0;
		Seg_Buf[5] = Water_value / 100 ;
		Seg_Point[5] = 1;
		Seg_Buf[6] = Water_value / 10 %10;
		Seg_Buf[7] = Water_value % 10;
		}
		else if(Water_value >= 1000 && Water_value<9999)
		{
			// 1234 
		Seg_Buf[4] = Water_value / 1000;
		Seg_Buf[5] = Water_value / 100 % 10;
		Seg_Point[5] = 1;
		Seg_Buf[6] = Water_value / 10 % 10;
		Seg_Buf[7] = Water_value % 10;
		}
		break;
		/* °´Ï°´¼ü6 */
		
		case 2:
		if(Water_money < 10 )
		{
		Seg_Buf[4] = 0;
		Seg_Buf[5] = 0;
		Seg_Point[5] = 1;
		Seg_Buf[6] = 0;
		Seg_Buf[7] = Water_money;
		}
		else if(Water_money >= 10 && Water_money<100)
		{
			// 23
		Seg_Buf[4] = 0;
		Seg_Buf[5] = 0;
		Seg_Point[5] = 1;
		Seg_Buf[6] = Water_money/ 10;
		Seg_Buf[7] = Water_money % 10;
		}
		else if(Water_money >= 100 && Water_money<1000)
		{
			// 234 
		Seg_Buf[4] = 0;
		Seg_Buf[5] = Water_money / 100 ;
		Seg_Point[5] = 1;
		Seg_Buf[6] = Water_money/ 10 %10;
		Seg_Buf[7] = Water_money % 10;
		}
		else if(Water_money >= 1000 && Water_money<9999)
		{
			// 1234 
		Seg_Buf[4] = Water_money / 1000;
		Seg_Buf[5] = Water_money / 100 % 10;
		Seg_Point[5] = 1;
		Seg_Buf[6] = Water_money / 10 % 10;
		Seg_Buf[7] = Water_money % 10;
		}			
		break;
	
			
	}
}
	


	




void Led_Proc()
{
	if(dat < 1.25)
		ucLed[0] = 1;
	else
		ucLed[0] = 0;
}

void Timer0Init(void)		//@12.000MHz
{
	AUXR &= 0x7F;		
	TMOD &= 0xF0;		
	TL0 = 0x18;		
	TH0 = 0xFC;		
	TF0 = 0;		
	TR0 = 1;		
	ET0 = 1;    
	EA = 1;     
}


void Timer0Server() interrupt 1
{  
	TL0 = 0x18;		
	TH0 = 0xFC;		
	if(++Key_Slow_Down == 10) Key_Slow_Down = 0;
	if(++Seg_Slow_Down == 500) Seg_Slow_Down = 0;
	if(++Seg_Pos == 8) Seg_Pos = 0;
	Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos],Seg_Point[Seg_Pos]);
	Led_Disp(Seg_Pos,ucLed[Seg_Pos]);
	
	/* ¼ÆËã³öË®Á¿ */
	Water_count++;
	if(Water_count == 100)
	{Water_value++;Water_count=0;}
}

/* Main */
void main()
{
	Set_Rtc(ucRtc);
	System_Init();
	Timer0Init();
	while (1)
	{
		Key_Proc();
		Seg_Proc();
		Led_Proc();
	}
}