【藍橋杯單片機組第十一屆模擬題】— 智能門鎖

1、題目

(1)硬件框圖

(2) 功能描述

   1、基本功能

   通過單片機控制外圍器件完成智能門鎖的設計。其中,繼電器顯示門狀態,LED指示門開啓的狀態和按鍵輸入模式,數碼管顯示基本信息,E2PROM可以對設置的新密碼進行保存。

   2、初始化狀態說明

  • 指示燈全部熄滅
  • 數碼管全部熄滅
  • 繼電器關閉

   3、按鍵功能

  • 按S16鍵進入密碼輸入模式,密碼輸入時,每按一個鍵,對應的數字在數碼管的最右位,同時原來顯示的數字向左移動一位。

  • 密碼輸入正確,繼電器打開,數碼管最左側顯示O,最右側四位顯示open,其餘位關閉。門開啓5秒後,無按鍵操作,進入關門狀態,繼電器、數碼管和LED全部關閉。

  • 密碼輸入錯誤,L1指示燈點亮5秒,5秒後,指示燈L1熄滅,設備進入初始狀態,等待新的密碼輸入操作。
  • 密碼輸入正確後,在門開啓的狀態下,按S12按鍵可以修改密碼,修改時數碼管最左邊一位顯示C,輸入6位新密碼後再按S12按鍵,密碼修改完成。退出密碼修改界面,門開啓5s之內沒有按鍵操作,門、LED和數碼管全部關閉,進入初始狀態。
  • 密碼輸入未完成且輸入錯誤時,可以使用清除按鍵,清除已經輸入的密碼。
  • 鍵盤功能定義
     

   4、存儲功能

  • 密碼存儲在EEPROM存儲器中,修改後自動保存。

   5、 LED指示功能

  • 指示燈L1: 密碼輸入錯誤時,L1點亮,5秒後熄滅。
  • 指示燈L7: 密碼輸入狀態下亮,其他狀態熄滅。
  • 指示燈L8: 密碼修改狀態下亮,其他狀態熄滅。

(3)設計說明

  • 關閉蜂鳴器等與本試題程序設計無關的外設資源;
  • 設備首次上電時,初始密碼默認未6個8。

2、試題分析

 在這裏先分析一下這個題目:

矩陣按鍵:

//定義r爲行,c爲列,如果r1=0,c1=0,按鍵則爲第一行第一列,其餘同理;
sbit r1=P3^0;
sbit r2=P3^1;
sbit r3=P3^2;
sbit r4=P3^3;
sbit c1=P4^4;
sbit c2=P4^2;
sbit c3=P3^5;
sbit c4=P3^4;

注意按鍵端口表示方法,可參考:

https://blog.csdn.net/fanjufei123456/article/details/104263738

按鍵函數定義(flag和flag1分別爲輸入、修改模式下的標誌位):

void keyscan(){
r1=0;r2=1;r3=1;r4=1;
c1=1;c2=1;c3=1;c4=1;
if(!c1)
{
  delayms(5);
  {
    num=0;
	flag=1;
	flag1=1;
  }
while(!c1);
}

else if(!c2)
{
  delayms(5);
  {
    num=1;
	flag=1;
	flag1=1;
  }
while(!c2);
}

else if(!c3)
{
  delayms(5);
  {
    num=2;
	flag=1;
	flag1=1;
  }
while(!c3);
}

else if(!c4)
{
  delayms(5);
  {
    num=3;
	flag=1;
	flag1=1;
  }
while(!c4);
}

r1=1;r2=0;r3=1;r4=1;
c1=1;c2=1;c3=1;c4=1;
if(!c1)
{
  delayms(5);
  {
    num=4;
	flag=1;
	flag1=1;
  }
while(!c1);
}

else if(!c2)
{
  delayms(5);
  {
    num=5;
	flag=1;
	flag1=1;
  }
while(!c2);
}

else if(!c3)
{
  delayms(5);
  {
    num=6;
	flag=1;
	flag1=1;
  }
while(!c3);
}

else if(!c4)
{
  delayms(5);
  {
    num=7;
	flag=1;
	flag1=1;
  }
while(!c4);
}

r1=1;r2=1;r3=0;r4=1;
c1=1;c2=1;c3=1;c4=1;
if(!c1)
{
  delayms(5);
  {
    num=8;
	flag=1;
	flag1=1;
  }
while(!c1);
}

else if(!c2)
{
  delayms(5);
  {
    num=9;
	flag=1;
	flag1=1;
  }
while(!c2);
}

r1=1;r2=1;r3=1;r4=0;
c1=1;c2=1;c3=1;c4=1;
if(!c2)
{
  delayms(5);
  {
    clean=1;
  }
while(!c2);
}

else if(!c3)
{
  delayms(5);
  {
    if(xiugai==0)
	{
       xiugai=1;
	}
	else if(xiugai==1)
	{
	   xiugai=0;
	}
  }
while(!c3);
}

else if(!c4)
{
  delayms(5);
  {
    moshi=1;
  }
while(!c4);
}

}
if(moshi==1)
  {	
 
    if(clean==1)
	{
	  clean=0;
	  f1=10;f2=11;f3=11;f4=11;f5=11;f6=11;f7=11;f8=11;
	}
	f1=10;
	if((f8==11)&&(flag==1))
	{
	   flag=0;
	   f8=num;
	}
	else if((f7==11)&&(flag==1))
	{
	   flag=0;
	   f7=num;
	}
	else if((f6==11)&&(flag==1))
	{
	   flag=0;
	   f6=num;
	}
	else if((f5==11)&&(flag==1))
	{
	   flag=0;
	   f5=num;
	}
	else if((f4==11)&&(flag==1))
	{
	   flag=0;
	   f4=num;
	}
	else if((f3==11)&&(flag==1))
	{
	   flag=0;
	   f3=num;  
	}
  }
  

 

 if((xiugai==1)&&(flag2==1))
	 {
	   if(xiugai_show==0)
	   {
	   xiugai_show=1;
	   EA=0;ET0=0;
	   f1=12;f2=11;f3=11;f4=11;f5=11;f6=11;f7=11;f8=11;
	   }
	   P2=0X80;P0=0X7F;
	   
	   if((f8==11)&&(flag1==1))
       {  
	      flag1=0;
	      f8=num;
	      m8=num;
	      EEPROM_Write(m8,0x00);
   	   }
	   else if((f7==11)&&(flag1==1))
	   {
		  flag1=0;
	      f7=num;
	      m7=num;
	      EEPROM_Write(m7,0x01);
   	   }
	   else if((f6==11)&&(flag1==1))
	   {  
	      flag1=0;
	      f6=num;
	      m6=num;
	      EEPROM_Write(m6,0x02);
	   }
       else if((f5==11)&&(flag1==1))
	   {
	      count2=0;
	      flag1=0;
	      f5=num;
	      m5=num;
	      EEPROM_Write(m5,0x03);
	   }
       else if((f4==11)&&(flag1==1))
	   {
	      flag1=0;
	      f4=num;
	      m4=num;
	      EEPROM_Write(m4,0x04);
	   }
   	   else if((f3==11)&&(flag1==1))
	   {
	      flag1=0;
	      f3=num; 
	      m3=num;
	      EEPROM_Write(m3,0x05);
	   }
	 }
     

初始化繼電器蜂鳴器:

void init_buzzer_relay(){
P2=0XA0; //P27=1,P26=0,P25=1,其餘爲0,此時38譯碼器中的Y5=0,進而的得到Y5C=1
P0=0X00; //P06=0關閉蜂鳴器,P04=0關閉集電器
}

3、驅動代碼

iic.c

/*
  程序說明: IIC總線驅動程序
  軟件環境: Keil uVision 4.10 
  硬件環境: CT107單片機綜合實訓平臺(12MHz)
  日    期: 2011-8-9
*/

#include "iic.h"

//總線啓動條件
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;
	}
}

//通過I2C總線發送數據
void IIC_SendByte(unsigned char byt)
{
	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;
	}
}

//從I2C總線上接收數據
unsigned char IIC_RecByte(void)
{
	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;
}

//EEPROM讀
unsigned char EEPROM_Read(unsigned char add)
{
		unsigned char temp;
		IIC_Start(); 
		IIC_SendByte(0xa0);
		IIC_WaitAck();
		IIC_SendByte(add);
		IIC_WaitAck();
		IIC_Stop();

		IIC_Start(); 
		IIC_SendByte(0xa1);
		IIC_WaitAck();
		temp=IIC_RecByte(); 
		IIC_Stop();
	 
		return temp;
}


//EEPROM寫
void EEPROM_Write(unsigned char dat,unsigned char add)
{
		IIC_Start();
		IIC_SendByte(0xa0);
		IIC_WaitAck();
		IIC_SendByte(add);
		IIC_WaitAck();
	
		IIC_SendByte(dat);
		IIC_WaitAck();
	
		IIC_Stop();
	 
}

iic.h

#ifndef _IIC_H
#define _IIC_H

#include "stc15f2k60s2.h"
#include "intrins.h"

#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();}
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1

//總線引腳定義
sbit SDA = P2^1;  /* 數據線 */
sbit SCL = P2^0;  /* 時鐘線 */

//函數聲明
void IIC_Start(void); 
void IIC_Stop(void); 
void IIC_Ack(unsigned char ackbit); 
void IIC_SendByte(unsigned char byt); 
bit IIC_WaitAck(void);  
unsigned char IIC_RecByte(void);

unsigned char EEPROM_Read(unsigned char add);
void EEPROM_Write(unsigned char dat,unsigned char add);
#endif

 

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