我是靠谱客的博主 听话香烟,最近开发中收集的这篇文章主要介绍蓝桥杯------自动售水机,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

目录

题目及其要求

考察模块

分析:

1、模块分析

2、题目要求分析

代码实现

1、主函数

2、I2C(AD)


题目及其要求

考察模块

  1. 三大金刚:LED,按键,数码管
  2. 继电器。
  3. AD。

分析:

1、模块分析

定时器的生成:使用烧录软件stc-isp来实现。

void Timer0Init(void)		//1毫秒@12.000MHz
{
	EA=1;ET0=1;            //一定!一定!一定!要开中断
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x20;		//设置定时初值
	TH0 = 0xD1;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
}

 注意:一定要开中断,要不然后面数码管和按键都会没反应。

数码管段码和位码表的生成:使用烧录软件stc-isp来实现。


/*************  本地常量声明    **************/
u8 code t_display[]={                       //标准字库
//   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
    0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black  -     H    J    K    L    N    o   P    U     t    G    Q    r   M    y
    0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
    0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46};    //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1

u8 code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};      //位码

按键

        因为只需要按键S7和S6,题目也明确要求,所以我采用独立按键的方式来实现按键S7和S6。

        注:按键消抖采用定时器来实现,使用10ms进行消抖。

//独立按键的三行代码
void ReadKey()
{
 	ReadData=P3^0xff;
	Trg= ReadData&(ReadData^Cont);
	Cont= ReadData;
}
void dsp_key()
{
	if(key_flag)
	{
		key_flag=0;
		ReadKey();
		switch(Trg)
		{
			case 0x02:			  //s6
			 ....//按键功能实现代码
			break;
			case 0x01:			  //s7
			    ....//按键功能实现代码
			break;
		}
	}

}

数码管       

        数码管的动态扫描使用定时器实现,每2ms扫描一次。

  if(++Smg_count>= 2 )					//2ms扫描刷新数码管
  {
  	Smg_count=0;
	P2=0xe0;P0=0xff;P2=0x00;				 //数码管消隐
	P2=0xc0;P0=T_COM[i];P2=0x00;    //位选
	P2=0xe0;P0=~t_display[smg_table[i]];P2=0x00;        //段选

	i++;
	if(i>=8)i=0;
  }

LED

        本次只使用L1实现亮灭,则:

L1灭: P2 = 0x80;P0 = 0xff; P2 = 0x00;
L1亮: P2 = 0x80;P0 = 0xfe; P2 = 0x00;

继电器

        继电器打开和关闭

  
sbit buzzer = P0^6;					  //蜂鸣器
sbit relay = P0^4;					  //继电器

继电器关闭:P2 = 0xa0;buzzer = 0 ;relay = 0; P2 = 0x00;
继电器打开:P2 = 0xa0;buzzer = 0 ;relay = 1; P2 = 0x00;

AD

        除了官方数据包里面给的iic代码,还需自己写的代码部分。

//写需要读取的地址
void write_adc(unsigned char add)
{
	 IIC_Start();
	 IIC_SendByte(0x90);
	 IIC_WaitAck();
	 IIC_SendByte(add);
	 IIC_WaitAck();
	 IIC_Stop();
}

//读取				
unsigned char read_adc(unsigned char add)
{
	unsigned char temp;
	 IIC_Start();
	 IIC_SendByte(0x90);
	 IIC_WaitAck();
	 IIC_SendByte(add);
	 IIC_WaitAck();
	 IIC_Start();
	 IIC_SendByte(0x91);
	 IIC_WaitAck();
	 temp=IIC_RecByte();
	 IIC_WaitAck();
	 IIC_Stop();
	 return temp;
}

2、题目要求分析

问题:
S7为出水控制按键,按下后,售水机持续出水(继电器接通,指示灯L10点亮)。
S6为停水控制按键,按下后,停止出水(继电器断开,指示灯L10熄灭)。

方法:设置一个标志mode,当mode=0为停水模式mode=1为出水模式,相应模式下继电器实现相应亮灭。

问题

假定水价为0.5 元/升,出水速度为100毫升/秒。
一次出水总量达到99.99L时,继电器自动断开,数码管显示DS2显示价格。

方法:出水速度为100毫升/秒将其转换为0.01L/100ms。

问题

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

方法:按照0~255对应0~5V,我们只需要将0~1.25V的对应值算出来,之后对读取的数据进行IF判断,就可以控制等来作显示信息了。
 

注意:这个要求得注意 

代码实现

1、主函数

#include<stc15f2k60s2.h>
#include "iic.h"
#define u8 unsigned char
#define u16 unsigned int

sbit buzzer = P0^6;					  //蜂鸣器
sbit relay = P0^4;					  //继电器


/*************  本地常量声明    **************/
u8 code t_display[]={                       //标准字库
//   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
    0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black  -     H    J    K    L    N    o   P    U     t    G    Q    r   M    y
    0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
    0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46};    //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1

u8 code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};      //位码
u8 smg_table[]={16,16,16,16,16,16,16,16};				  //black

u8 ReadData,Trg,Cont;
u16 water_number=0,water_price=0;				  //水量和水费
u16 Voltage;					   //光敏电阻电阻值
bit mode;				//mode=0为停水模式mode=1为出水模式
bit key_flag,flag;			//扫描按键标志位和出水量清除标志
void Close_Peripherals ()
{
  P2 = 0x80;P0 = 0xff; P2 = 0x00;
  P2 = 0xa0;buzzer = 0 ;relay = 0; P2 = 0x00;
}

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


void Time_0()  interrupt  1
{
  static u16 Smg_count,key_count,i,water_count;
  if(++Smg_count>= 2 )					//2ms扫描刷新数码管
  {
  	Smg_count=0;
	P2=0xe0;P0=0xff;P2=0x00;				 //数码管消隐
	P2=0xc0;P0=T_COM[i];P2=0x00;
	P2=0xe0;P0=~t_display[smg_table[i]];P2=0x00;

	i++;
	if(i>=8)i=0;
  }
  if(++key_count>=10){					//10ms扫描独立按键
  	 key_count=0;
	 key_flag=1;
  }
  if(mode)
  {
	  if(++water_count>=100)					  //  0.01L/100ms
	  {
	  	water_count=0;
		water_number++;
		if(water_number==9999)
		{
		  P2 = 0xa0;buzzer = 0 ;relay = 0; P2 = 0x00;		 //继电器断开
		  mode=0;
		}
	  }
  }
  else{
  		water_count=0;
		water_price=water_number/2;				//水费
  }
}

//独立按键的三行代码
void ReadKey()
{
 	ReadData=P3^0xff;
	Trg= ReadData&(ReadData^Cont);
	Cont= ReadData;
}
void dsp_key()
{
	if(key_flag)
	{
		key_flag=0;
		ReadKey();
		switch(Trg)
		{
			case 0x02:			  //s6
			 	P2 = 0xa0;buzzer = 0 ;relay = 0; P2 = 0x00;		 //继电器断开
			  	mode=0;
				flag=1;			//设置出水量清除标志位
			break;
			case 0x01:			  //s7
				P2 = 0xa0;buzzer = 0 ;relay = 1; P2 = 0x00;		 //继电器接通
			  	mode=1;
			break;
		}
	}

}
void main()
{
	Close_Peripherals();//关闭外设
	Timer0Init();			   //定时器初始化
	write_adc(0x01);		   
	while(1){
		EA=0;
		Voltage=read_adc(0x01);	   //读取光敏电阻的电阻值
		EA=1;
		if((Voltage*5.0/255)<1.25){        //电阻与电压之间的转换
		   	  P2=0x80;P0=0xfe;P2=0x00;			 //L1亮
		}else{
		   	  P2=0x80;P0=0xff;P2=0x00;			//L1灭
		}
		dsp_key();
		if(mode)
		{
			if(flag){
				flag=0;
				water_number=0;			//清除出水量
			}
			//费率0.50
		    smg_table[0]=16;
		    smg_table[1]=32;
		    smg_table[2]=5;
		    smg_table[3]=0;
			//出水量
			smg_table[4]=water_number/1000;
			smg_table[5]=(water_number%1000/100)+32;
			smg_table[6]=water_number%100/10;
			smg_table[7]=water_number%10;
		}else{
			//费率0.50
		    smg_table[0]=16;
		    smg_table[1]=32;
		    smg_table[2]=5;
		    smg_table[3]=0;
			//水费
			smg_table[4]=water_price/1000;
			smg_table[5]=(water_price%1000/100)+32;
			smg_table[6]=water_price%100/10;
			smg_table[7]=water_price%10;
		
		}
	}
}

2、I2C(AD)

iic.c

#include "iic.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);
}

//等待应答
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;    
}

void write_adc(unsigned char add)
{
	 IIC_Start();
	 IIC_SendByte(0x90);
	 IIC_WaitAck();
	 IIC_SendByte(add);
	 IIC_WaitAck();
	 IIC_Stop();
}
				
unsigned char read_adc(unsigned char add)
{
	unsigned char temp;
	 IIC_Start();
	 IIC_SendByte(0x90);
	 IIC_WaitAck();
	 IIC_SendByte(add);
	 IIC_WaitAck();
	 IIC_Start();
	 IIC_SendByte(0x91);
	 IIC_WaitAck();
	 temp=IIC_RecByte();
	 IIC_WaitAck();
	 IIC_Stop();
	 return temp;
}

iic.h


#include<stc15f2k60s2.h>
#include "intrins.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 write_adc(unsigned char add);
unsigned char read_adc(unsigned char add);

注:小白而已,写博客只是为了让自己对本次刷题加深印象,同时也希望能对你有一点点帮助!!!

最后

以上就是听话香烟为你收集整理的蓝桥杯------自动售水机的全部内容,希望文章能够帮你解决蓝桥杯------自动售水机所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(45)

评论列表共有 0 条评论

立即
投稿
返回
顶部