[蓝桥杯开源项目与实践] 第三届(自动售水机)


这是我自己在学习蓝桥杯过程中总结的一些知识,希望对今后的学习和备战蓝桥的同学能够提供一些帮助吧,一起加油哦,预祝各位在比赛中取得优异成绩。

蓝桥杯-第三届(自动售水机)

1.

试题要求如下

2.题目要点分析

1) 上电后各部分要初始化(关闭蜂咛器、数码管、led灯、继电器),并且数码管要显示题目要求初始的数(含格式)

2)按下 S7 清屏开始计数(计数器中断)流水显示,S6停止流水计数并且计算显示出流水价格

3) 通过光敏电阻读取环境的亮度,当其发生改变时,做出不同的响应

4)掌握IIC

3.注意事项

1)数码管小数的显示,需要重新计算数码管段选数组 tab_spot[] ,都加上h,使其显示出小数点

2)S7按键不会改变流水的状态,唯有S6可以改变, S7作用只有一个,就是清屏开始流水计数

3)通过流水量计算出价格这方法要注意

4)光敏电阻读取数据与显示的转换要注意( IIC 写0x90, 读0x91)

5) 引用头文件并且定义无符号类型

#include "STC15f2k60S2.h"
#include "intrins.h"   // 引用头文件  调用iic里面的延时函数 _nop_()

#define uchar unsigned char
#define uint unsigned int

4.代码实现

首先是进行初始化
void allinit()  // 初始化
{
	P2=0XA0;
	P0=0X00;
	
	P2=0X80;
	P0=0XFF;

	P2=0XC0;
	P0=0XFF;
	
	P2=0XFF;
	P0=0XFF;
}
延时函数
void delayms(uchar a)
{
	uint b;
	for(;a>0;a--)
	{
	for(b=845;b>0;b--)
		{
		}
	}
}
数码管显示(双重----正常不加小数点和加小数点)
uchar tab[]={0xc0,
0xf9,0xa4,0xB0,0x99,0x92,0x82,0xf8,0x80,0x90,
0xff};  // 不加小数点

uchar tab_spot[]={0x40,
0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,
0xff};  // 加上小数点的


void display(uchar channel,uchar num)  // 不加小数点段选的数码管显示
{
	P2=0XC0;
	P0=0X01<<channel;

	P2=0XE0;
	P0=tab[num];
	delayms(2);
}

void display_spot(uchar channel,uchar num)   // 加小数点段选的数码管显示
{
	P2=0XC0;
	P0=0X01<<channel;

	P2=0XE0;
	P0=tab_spot[num];
	delayms(2);
}
题目要求的数码管显示格式
uchar yi,er,san,si,wu,liu,qi,ba;  // 全局变量

void display_SMG()
{
    display(0,yi);
	display_spot(1,er);
	display(2,san);
	display(3,si);
	
	display(4,wu);
	display_spot(5,liu);
	display(6,qi);
	display(7,ba);
}
中断
void Timer0Init(void)	// 5毫秒 来源stc定时器计算器 波特率11.0592 定时器0 16位自动重载
{
	AUXR |= 0x80;		
	TMOD &= 0xF0;	
	TL0 = 0x00;		
	TH0 = 0x28;		
	TF0 = 0;		
	TR0 = 1;		
}

uint aa=0;             // 三个全局变量  进行时间、金钱计算
uint bb=0;
uint money=0;

void time0 () interrupt 1  // 定时器中断服务函数 1
{
		aa++;             
		if(aa==20)        // 100毫秒
		{
		bb++;             // 100毫秒=10毫升 (相当于数码管最后一位)
		aa=0;
		 
		ba=bb%10;
		qi=bb%100/10;
		liu=bb%1000/100;
		wu=bb/1000;	
		}
		
	if(bb==9999)
		{
		bb=0;            
		money=bb*0.5;     // 进行金钱转化
		ba=money%10;
		qi=money%100/10;
		liu=money%1000/100;
		wu=money/1000;	
		}	
}
按键操作
void start()              // S7按下 开启
{
  wu=liu=qi=ba=0;         // 使得开始按按键时 数码管后四位清零
 
	P2=0XA0;              // 开启继电器
	P0=0X10;
	
	ET0=1;                // 开启定时器
	EA=1;

}

void off()                // S6按下 关闭
{

	P2=0XA0;              // 关闭继电器
	P0=0X00;

	EA=0;                 // 关闭定时器
	ET0=0;
	       
	money=bb*0.5;         // 关闭时自动显示价钱
	ba=money%10;
	qi=money%100/10;
	liu=money%1000/100;
	wu=money/1000;	
	
	bb=0;                 // 确保下次开始计数时 从0开始
}

void keyscan()
{
if(P30==0)
 {
 delayms(2);
	 if(P30==0)
	 {
	  start();
	 }
	 while(!P30);
 }
 
 if(P31==0)
 {
 delayms(2);
	 if(P31==0)
	 {
	  off();
	 }
	  while(!P31);
 }

}
实现光敏电阻的各项功能 (要利用给的IIC文件夹,稍加修改即可)
/*********************************************/  // 以下函数在官方数据手册提供
/*********************************************/  // _nop_() 需要引入头文件 "intrins.h"
#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();}    // 这为官方给的51
#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_(); // 15的延时大概为51的8倍
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_(); }
                                 
#define SlaveAddrW 0xA0   // 写
#define SlaveAddrR 0xA1   // 读

sbit SDA = P2^1;  /* 数据线 */
sbit SCL = P2^0;  /* 时钟线 */

void IIC_Start(void)  // 启动条件
{
	SDA = 1;
	SCL = 1;
	somenop;
	SDA = 0;
	somenop;
	SCL = 0;	
}

void IIC_Stop(void)   // 停止条件
{
	SDA = 0;
	SCL = 1;
	somenop;
	SDA = 1;
}

bit IIC_WaitAck(void)  // 等待应答
{
	SDA = 1;
	somenop;
	SCL = 1;
	somenop;
	if(SDA)    
	{   
		SCL = 0;
		IIC_Stop();
		return 0;
	}
	else  
	{ 
		SCL = 0;
		return 1;
	}
}

void IIC_SendByte(unsigned char byt) // 通过iic发送数据
{
	unsigned char i;
	for(i=0;i<8;i++)
	{   
		if(byt&0x80) 
		{	
			SDA = 1;
		}
		else 
		{
			SDA = 0;
		}
		somenop;
		SCL = 1;
		byt <<= 1;
		somenop;
		SCL = 0;
	}
}

unsigned char IIC_RecByte(void)  // 接收iic数据
{
	unsigned char da;
	unsigned char i;
	
	for(i=0;i<8;i++)
	{   
		SCL = 1;
		somenop;
		da <<= 1;
		if(SDA) 
		da |= 0x01;
		SCL = 0;
		somenop;
	}
	return da;
}

/***********************************/   //以下的函数需要自己根据官方提供的函数来编写
uchar iic_read(uchar add)
{
    uchar temp;
    
    /******************/
    IIC_Start();
    
    IIC_SendByte(0x90);
    IIC_WaitAck();
    
    IIC_SendByte(add);
    IIC_WaitAck();
    
    IIC_Stop();
    
    /*****************/
    IIC_Start(0x91);
    
    IIC_SendByte(0x91);
    IIC_WaitAck();
    
    temp=IIC_RecByte();
    IIC_WaitAck();
    
    IIC_Stop();
    
    /****************/
    return temp;
}
主函数
void main()
{
	uchar guangmin;   // 记录数码管的值
	all_init();       // 初始化,关闭蜂咛器,继电器之类
	Timer0Init();     // 中断初始化

	yi=10,er=0,san=5,si=0,wu=0,liu=1,qi=0,ba=0;  // 开始数码管的显示
	while(1)
	{
		display_SMG();   // 初始化数码管
		keyscan();       // 读取按键反馈回来的全局变量 yi ~ ba 的值,并且控制其他模块
			
		guangmin=iic_read(0x01); //  !!!  iic读取光敏电阻的值并进行转换
	   if(guangmin<64) // !!!
	  {
		P0=0XFF;      // 避免其小灯的干扰
		P2=0X80;
		P00=0;        // 点亮
	  }
	  else
	  {
		P2=0X80;
		P0=0XFF;
	  }					
   }
}

注: 本文为原创,未经允许,禁止转载!
有什么问题欢迎给我留言哦
hexo博客:https:www.ho-brother.ltd
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章