蓝桥杯真题——自动售水机
Posted ArtoriaLili
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝桥杯真题——自动售水机相关的知识,希望对你有一定的参考价值。
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();
以上是关于蓝桥杯真题——自动售水机的主要内容,如果未能解决你的问题,请参考以下文章
《蓝桥杯真题》:2017年单片机省赛(内附两种代码实现风格)
《蓝桥杯真题》:2017年单片机省赛(第八届)(内附两种代码实现风格)
《蓝桥杯真题》:2020年单片机省赛(第十一 / 11届第一场)