[藍橋杯開源項目與實踐] 第三屆(自動售水機)


這是我自己在學習藍橋杯過程中總結的一些知識,希望對今後的學習和備戰藍橋的同學能夠提供一些幫助吧,一起加油哦,預祝各位在比賽中取得優異成績。

藍橋杯-第三屆(自動售水機)

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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章