蓝桥杯第三届初赛“自动售水机”设计任务书

蓝桥杯第三届初赛“自动售水机”设计任务书

Author:Luis
Time:2022-04-06
Version:v1.0

说明

​ 蓝桥杯系列的代码都是本人亲手写和调试,可能有时会有点错误,请见谅。此外,代码仅供大家学习,祝福各位在蓝桥杯比赛中能获得比较满意的成绩。

功能简述

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

具体代码

iic.c

/*
  程序说明: IIC总线驱动程序
  软件环境: Keil uVision 4.10
  硬件环境: CT107单片机综合实训平台 8051,12MHz
  日    期: 2011-8-9
*/

#include "reg52.h"
#include "intrins.h"

#define DELAY_TIME 5

#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1

//总线引脚定义
sbit SDA = P2 ^ 1; /* 数据线 */
sbit SCL = P2 ^ 0; /* 时钟线 */

void IIC_Delay(unsigned char i)
{
    do
    {
        _nop_();
    } while (i--);
}
//总线启动条件
void IIC_Start(void)
{
    SDA = 1;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 0;
    IIC_Delay(DELAY_TIME);
    SCL = 0;
}

//总线停止条件
void IIC_Stop(void)
{
    SDA = 0;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

//发送应答
void IIC_SendAck(bit ackbit)
{
    SCL = 0;
    SDA = ackbit; // 0:应答,1:非应答
    IIC_Delay(DELAY_TIME);
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SCL = 0;
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

//等待应答
bit IIC_WaitAck(void)
{
    bit ackbit;

    SCL = 1;
    IIC_Delay(DELAY_TIME);
    ackbit = SDA;
    SCL = 0;
    IIC_Delay(DELAY_TIME);
    return ackbit;
}

//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
    unsigned char i;

    for (i = 0; i < 8; i++)
    {
        SCL = 0;
        IIC_Delay(DELAY_TIME);
        if (byt & 0x80)
            SDA = 1;
        else
            SDA = 0;
        IIC_Delay(DELAY_TIME);
        SCL = 1;
        byt <<= 1;
        IIC_Delay(DELAY_TIME);
    }
    SCL = 0;
}

//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
    unsigned char i, da;
    for (i = 0; i < 8; i++)
    {
        SCL = 1;
        IIC_Delay(DELAY_TIME);
        da <<= 1;
        if (SDA)
            da |= 1;
        SCL = 0;
        IIC_Delay(DELAY_TIME);
    }
    return da;
}

// addd
// PCF8591
void init_pcf8591()
{
    IIC_Start();
    IIC_SendByte(0x90);
    IIC_WaitAck();

    IIC_SendByte(0X01); // 第一通道
    IIC_WaitAck();
    IIC_Stop();
}

// 通过I2C总线读取ADC结果
unsigned char adc_pcf8591()
{
    unsigned char da;

    IIC_Start();
    IIC_SendByte(0x91);
    IIC_WaitAck();

    da = IIC_RecByte();
    IIC_SendAck(1);

    IIC_Stop();
    return da;
}

iic.h

#ifndef __IIC_H
#define __IIC_H

void IIC_Start(void);
void IIC_Stop(void);
bit IIC_WaitAck(void);
void IIC_SendAck(bit ackbit);
void IIC_SendByte(unsigned char byt);
unsigned char IIC_RecByte(void);

void init_pcf8591();         // 初始化pcf8591
unsigned char adc_pcf8591(); // 通过I2C总线读取ADC结果

#endif

main.c

// 注意:J3跳线配置为IO方式,J5配置为BTN、J2配置为1-3和2-4
#include <STC15F2K60S2.h>
#include "intrins.h"
#include "iic.h"

// 小数点是第8位为0  原本数字-0x80
unsigned char data_pros[] = {
    0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0xff, 0xbf};
unsigned char dspbuf[8] = {10, 10, 10, 10, 10, 10, 10, 10}; //显示缓冲区
unsigned char key_flag = 0;

unsigned char water_flag = 0; // 是否开始计数
int water = 0;                // 水量
int water_value = 0;          // 水价

unsigned int adc_dat = 0;
unsigned char adc_flag = 0; // 200ms一次
// 初始化值
void close_init()
{
    P2 = 0xA0;
    P0 = 0x00;
    P2 = 0x80;
    P0 = 0xff;
    P2 = 0x00;
}

void Delay5ms() //@11.0592MHz
{
    unsigned char i, j;

    i = 54;
    j = 199;
    do
    {
        while (--j)
            ;
    } while (--i);
}

// 读取独立键值 J5为BTN模式
unsigned char read_key()
{
    unsigned char key_temp;
    static unsigned char key_press = 0; // 按下次数
    static unsigned char key_right = 0; //  是否按下
    static unsigned char key_value = 0; // 按下值
    key_temp = (P3 & 0x0f);

    if (key_temp != 0x0f)
        key_press++;
    else
        key_press = 0;

    if (key_press == 5) // 按下五次算按下
    {
        key_press = 0;
        key_right = 1;
        switch (key_temp) // 检验值
        {
        case 0x0e:
            key_value = 1; // S7
            break;
        case 0x0d:
            key_value = 2; // S6
            break;
        }
    }

    if ((key_right == 1) && (key_temp == 0x0f)) // 松开手
    {
        key_right = 0;
        return key_value;
    }
    return 0xff;
}

void Timer0Init(void) // 1毫秒@11.0592MHz
{
    AUXR |= 0x80; //定时器时钟1T模式
    TMOD &= 0xF0; //设置定时器模式
    TL0 = 0xCD;   //设置定时初值
    TH0 = 0xD4;   //设置定时初值
    TF0 = 0;      //清除TF0标志
    TR0 = 1;      //定时器0开始计时
    // add
    ET0 = 1;
    EA = 1;
}

// 显示函数 dspbuf为数码管的缓冲区
void display()
{
    static unsigned char dspnum = 0; // 数码管的位置
    P2 = 0xE0;
    P2 = 0xff; // 消影

    P2 = 0xc0;
    P0 = (1 << dspnum);

    P2 = 0xe0;
    if (dspnum == 1 || dspnum == 5)
        P0 = data_pros[dspbuf[dspnum]] - 0x80;
    else
        P0 = data_pros[dspbuf[dspnum]];

    P2 = 0x00;
    if (++dspnum == 8)
        dspnum = 0;
}

void main()
{
    unsigned char key_value = 0;
    unsigned char i = 0;

    close_init();
    Timer0Init();
    init_pcf8591();
    Delay5ms();

    dspbuf[1] = 0; // 初始化值
    dspbuf[2] = 5;
    for (i = 3; i < 8; i++)
        dspbuf[i] = 0;

    while (1)
    {
        if (key_flag)
        {
            key_flag = 0;
            key_value = read_key();
            if (key_value != 0xff)
            {
                switch (key_value)
                {
                case 1:
                {
                    P2 = 0xA0;
                    P0 = 0x10;
                    P2 = 0x00;
                    water_flag = 1;
                }
                break;
                case 2:
                    P2 = 0xA0;
                    P0 = 0x00;
                    P2 = 0x00;
                    water_flag = 2;
                }
            }
        }
        if (water_flag == 1) // 1 是出水
        {
            dspbuf[4] = water / 1000;
            dspbuf[5] = water / 100 % 10;
            dspbuf[6] = water / 10 % 10;
            dspbuf[7] = water % 10;
        }
        if (water == 9999)
            water_flag = 2;  // 强制转化
        if (water_flag == 2) // 2 是总价格
        {
            water_value = water * 0.5;
            dspbuf[4] = water_value / 1000;
            dspbuf[5] = water_value / 100 % 10;
            dspbuf[6] = water_value / 10 % 10;
            dspbuf[7] = water_value % 10;
            water = 0;      // 清0
            water_flag = 0; // 状态改变
        }
        // 光敏电阻--->电压
        if (adc_flag == 1)
        {
            adc_flag = 0;
            adc_dat = adc_pcf8591();
            // 8位 255;1.25/5v=1/4  255*1/4=64;
            if (adc_dat < 64)
            {
                P2 = 0x80;
                P0 = 0xfe;
                P2 = 0x00;
            }
            else
            {
                P2 = 0x80;
                P0 = 0xff;
                P2 = 0x00;
            }
        }
    }
}

void isr_time_0() interrupt 1
{
    static unsigned char key_time = 0; // 键盘刷新次数
    static unsigned char water_time = 0;
    static unsigned char adc_time = 0;
    if (++key_time == 10)
    {
        key_flag = 1;
        key_time = 0;
    }
    display();

    if (water_flag == 1) // 1 是出水
    {
        // 100ml/s 100ms 数字加1
        if (++water_time == 100)
        {
            water_time = 0;
            water++;
        }
    }

    if (++adc_time == 200) // 200ms测一次
    {
        adc_time = 0;
        adc_flag = 1;
    }
}  
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值