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 #include #include #include #include #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,1unsigned 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 && Water_value= 100 && 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 && Water_money= 100 && 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;elseucLed[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();}}