蓝桥杯第十一届省赛模拟试题--“智能门锁”

题目要求

1. 基本要求
1.1 使用国信长天单片机竞赛实训平台,完成“智能门锁”功能的程序设计与调试
1.2 设计与调试过程中,可参考组委会提供的“资源数据包”。
1.3 Keil工程文件以准考证号命名,完成设计后,提交完整、可编译的Keil工程文件到服务器。
2. 硬件框图
蓝桥杯第十一届省赛模拟试题--“智能门锁”_第1张图片
3. 功能描述
3.1 基本功能
通过单片机控制外围器件完成智能门锁的设计。其中,继电器显示门状态,LED指示门开启的状态和按键输入模式,数码管显示基本信息,E2PROM可以对设置的新密码进行保存。
3.2 初始状态说明
指示灯全部熄灭
数码管全部熄灭
继电器关闭
3.3 按键功能

  1. 按S16键进入密码输入模式,密码输入时,每按一个键,对应的数字在数码管的最右位,同时原来显示的数字向左移动一位。
    在这里插入图片描述
  2. 密码输入正确,继电器打开,数码管最左侧显示O,最右侧四位显示open,其余位关闭。门开启5秒后,无按键操作,进入关门状态,继电器、数码管和LED全部关闭。
    在这里插入图片描述
  3. 密码输入错误,L1指示灯点亮5秒,5秒后,指示灯L1熄灭,设备进入初始状态,等待新的密码输入操作。
  4. 密码输入正确后,在门开启的状态下,按S12按键可以修改密码,修改时数码管最左边一位显示C,输入6位新密码后再按S12按键,密码修改完成。退出密码修改界面,门开启5s之内没有按键操作,门、LED和数码管全部关闭,进入初始状态。
  5. 密码输入未完成且输入错误时,可以使用清除按键,清除已经输入的密码。
  6. 键盘功能定义
    蓝桥杯第十一届省赛模拟试题--“智能门锁”_第2张图片
    3.4 存储功能
    密码存储在EEPROM存储器中,修改后自动保存。
    3.5 LED指示功能
    指示灯L1: 密码输入错误时,L1点亮,5秒后熄灭。
    指示灯L7: 密码输入状态下亮,其他状态熄灭。
    指示灯L8: 密码修改状态下亮,其他状态熄灭。
    4. 设计说明
    关闭蜂鸣器等与本试题程序设计无关的外设资源;
    设备首次上电时,初始密码默认未6个8。

程序代码

主函数

#include "stc15f2k60s2.h"
#include "iic.h"
#include "key.h"
#include "led.h"

typedef unsigned char uchar;
typedef unsigned int uint;

uchar code SMG_duan[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x40,0x00,0x39};
uchar SMG_wei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};

uchar pass_word[]={0x08,0x08,0x08,0x08,0x08,0x08};	//密码
uchar tab[]={10,11,11,11,11,11,11,11};		//密码输入显示缓存区
uchar tab_xiugai[]={12,11,11,11,11,11,11,11}; // 密码修改显示缓存区
uchar open_display[8];			//门打开显示
uchar init_display[8];			//初始化显示

uchar e2_flag;
uchar open_flag;				//开门标志
uchar error_flag;				//密码错误标志
uchar led_flag;
uchar mode_display=0;			//显示模式
uchar password;				   //按键输入密码
static uchar a,b;
uchar count;			 //按下次数
uchar gai_count;		 //修改密码时,对按键计数
uchar ffff;


uchar key_init();
void Timer0Init();		//1毫秒@11.0592MHz
void password_init();

void delay_ms(unsigned int ms)
{
  unsigned int i,j;
  for(i=0;i<ms;i++)
  for(j=850;j>0;j--);
}

void main()
{
  uchar key_val;
  All_init();
  Timer0Init();
	password_init();
  while(1)
  {
	init_display[0]=0x00;    init_display[1]=0x00;
	init_display[2]=0x00;    init_display[3]=0x00;
	init_display[4]=0x00;    init_display[5]=0x00;
	init_display[6]=0x00;    init_display[7]=0x00;

	open_display[0]=0x3f;    open_display[1]=0x00;
	open_display[2]=0x00;    open_display[3]=0x00;
	open_display[4]=0x3f;    open_display[5]=0x73;
	open_display[6]=0x79;    open_display[7]=0x37;
		
  
	
	if(mode_display==1)
	{
	  if((key_val)&&(key_val!=13)&&(key_val!=17)&&(key_val!=4)&&(key_val!=8)&&(key_val!=12)&&(key_val!=16))
	  {		
		for(a=2;a<=7;a++)
		{
		  tab[a]=tab[a+1];
		}
		tab[7]=password;
		count++;		
	  ledlight(0xbf); 
	  }	  
	}  
	
		
	if(count==6)			//密码输入完成
	{
	  count=0;						/*密码正确*/
	  
	  if((tab[2]==pass_word[0])&&(tab[3]==pass_word[1])&&(tab[4]==pass_word[2])&&(tab[5]==pass_word[3])&&(tab[6]==pass_word[4])&&(tab[7]==pass_word[5]))
	  {
		  if(mode_display==1)
		  {
		   open_flag=1;
		   mode_display=2;
		  }	  
	  }
							   /*密码错误*/
	   if((tab[2]!=pass_word[0])||(tab[3]!=pass_word[1])||(tab[4]!=pass_word[2])||(tab[5]!=pass_word[3])||(tab[6]!=pass_word[4])||(tab[7]!=pass_word[5]))
	   {	  
	    error_flag=1;
		  led_flag=1;	 
	   }	
	}	   

	key_val=key_init();
	switch(key_val)
	{
		case 7:
	  password=0;
	  break;

	  case 11:
	  password=1;
	  break;

	  case 15:
	  password=2;
	  break;

	  case 19:
	  password=3;
	  break;

	  case 6:
	  password=4;
	  break;

	  case 10:
	  password=5;
	  break;

	  case 14:
	  password=6;
	  break;

	  case 18:
	  password=7;
	  break;

	  case 5:
	  password=8;
	  break;

	  case 9:
	  password=9;
	  break;

	  case 16:
	  if(mode_display==0)
	  mode_display=1;
	  tab[0]=10; tab[1]=11;
	  tab[2]=11; tab[3]=11;
	  tab[4]=11; tab[5]=11;
	  tab[6]=11; tab[7]=11;
	  count=0;
		
	  break;

	  case 8:						//清除
	  tab[0]=10; tab[1]=11;
	  tab[2]=11; tab[3]=11;
	  tab[4]=11; tab[5]=11;
	  tab[6]=11; tab[7]=11;
		
		tab_xiugai[0]=12; tab_xiugai[1]=11;
	  tab_xiugai[2]=11; tab_xiugai[3]=11;
	  tab_xiugai[4]=11; tab_xiugai[5]=11;
	  tab_xiugai[6]=11; tab_xiugai[7]=11;
	  count=0;
		gai_count=0;
	  break;

	  case 12:				   //修改
	  if(mode_display==2)
		{
	    mode_display=3;
			
		}
	  if(mode_display==3)
	  {	  
	   ffff++;
		 
	   if(ffff==2)				//回到初始状态
	   {
	     ffff=0;
		   mode_display=0;
			 
		   P2=(P2&0X1F)|0XA0;
	     P0=0X00;
	     P2=P2&0X1F;
			 
		   ledlight(0xff);
		   count=0;
			if(gai_count==6)
			{
				gai_count=0;
				pass_word[0]=tab_xiugai[2];
				pass_word[1]=tab_xiugai[3];
				pass_word[2]=tab_xiugai[4];
				pass_word[3]=tab_xiugai[5];
				pass_word[4]=tab_xiugai[6];
				pass_word[5]=tab_xiugai[7];		  		  
			}
		  write_2402(0x00,pass_word[0]);
	    delay_ms(10);					 //每次写完要延时10ms
	    write_2402(0x01,pass_word[1]);
	    delay_ms(10);
	    write_2402(0x02,pass_word[2]);
	    delay_ms(10);
	    write_2402(0x03,pass_word[3]);
	    delay_ms(10);
	    write_2402(0x04,pass_word[4]);
	    delay_ms(10);
	    write_2402(0x05,pass_word[5]);
	    delay_ms(10);
	   }
	  }
	  break;
	}
	    
   if(mode_display==3)
	 {
	  if((key_val)&&(key_val!=13)&&(key_val!=17)&&(key_val!=4)&&(key_val!=8)&&(key_val!=12)&&(key_val!=16))
	  {		
			for(b=2;b<=7;b++)
			{
				tab_xiugai[b]=tab_xiugai[b+1];
			}
			tab_xiugai[7]=password;
			gai_count++;		
	    ledlight(0x7f); 
	  }	  
	 }     	  
 }
}

void password_init()
{
	e2_flag=read_2402(0x09);
	if(e2_flag==10)					//确保第一次程序下载到板子上后,初始密码为888 888
	{  
		pass_word[0]=read_2402(0x00);
		delay_ms(10);										//防止连续读取数据时出错
		pass_word[1]=read_2402(0x01);
		delay_ms(10);
		pass_word[2]=read_2402(0x02);
		delay_ms(10);
		pass_word[3]=read_2402(0x03);
		delay_ms(10);
		pass_word[4]=read_2402(0x04);
		delay_ms(10);
		pass_word[5]=read_2402(0x05);
		delay_ms(10);
	}
	else
	{
	  pass_word[0]=8; 	pass_word[1]=8;
	  pass_word[2]=8; 	pass_word[3]=8;
	  pass_word[4]=8; 	pass_word[5]=8;
		
		write_2402(0x09,10);
	  delay_ms(5);
	}
}

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

void timer0() interrupt 1
{
   uchar i;
  static uchar SMG_count;
  static uint door_count,led_count;
  SMG_count++;
   
  if(SMG_count==3)
  {
    SMG_count=0;
	P2=0XC0; P0=0X00;
	P2=0XC0;
	P0=SMG_wei[i];

	if(mode_display==0)			  //初始化显示
	{
	 P2=0Xe0;
	 P0=~init_display[i];
	}

	if(mode_display==1)			//密码输入显示
	{
	 P2=0Xe0;
	 P0=~SMG_duan[tab[i]];
	}

	if(mode_display==2)		   //门打开显示
	{
	 P2=0Xe0;
	 P0=~open_display[i];
	}

	if(mode_display==3)		 //修改页面
	{
	 P2=0Xe0;
	 P0=~SMG_duan[tab_xiugai[i]];
	}
	
	i++;
	if(i==8)
	i=0;
  }

 if(mode_display!=3)
 {
  if(mode_display==2)
  {
   if(open_flag)				 //密码正确,门打开
	{
	  P2=(P2&0X1F)|0XA0;
	  P0=0X10;
	  P2=P2&0X1F;
	  ledlight(0xff);
	  door_count++;
	  if(door_count>5000)
	  {
	    door_count=0;
	    open_flag=0;	   
	  }
	}
    if(open_flag==0)
	{
	  P2=(P2&0X1F)|0XA0;
	  P0=0X00;
	  P2=P2&0X1F;
	  mode_display=0;
	  tab[0]=10; tab[1]=11;
	  tab[2]=11; tab[3]=11;
	  tab[4]=11; tab[5]=11;
	  tab[6]=11; tab[7]=11;
	}
  }

  if(error_flag)				 //密码错误
	{	  
	  led_count++;	  
	  if(led_flag)
	  {
	    ledlight(0xfe);		//L1点亮
	  }
	  if(led_flag==0)
	  {
	    ledlight(0xff);	   //亮5秒熄灭
		 mode_display=0;
	   tab[0]=10; tab[1]=11;
	   tab[2]=11; tab[3]=11;
	   tab[4]=11; tab[5]=11;
	   tab[6]=11; tab[7]=11;
		error_flag=0;
	  }

	  if(led_count>5000)
	  {
	    led_count=0;
		led_flag=0;	   
	  }
	}
 } 
}

按键模块

#include "key.h"

unsigned char key_init()
{
  static unsigned char key_state=0;
  unsigned char key1,key2;
  unsigned char key_value=0;
  unsigned char key_press;
  
  P30=0; P31=0; P32=0; P33=0; P34=1; P35=1; P42=1; P44=1;
  if(P34==0) key1=0xe0;
  if(P35==0) key1=0xd0;
  if(P42==0) key1=0xb0;
  if(P44==0) key1=0x70;
  if((P34==1)&&(P35==1)&&(P42==1)&&(P44==1))
  key1=0xf0;
  
  P30=1; P31=1; P32=1; P33=1; P34=0; P35=0; P42=0; P44=0;
  if(P30==0) key2=0x0e;
  if(P31==0) key2=0x0d;
  if(P32==0) key2=0x0b;
  if(P33==0) key2=0x07;
  if((P30==1)&&(P31==1)&&(P32==1)&&(P33==1))
  key2=0x0f;
  
  key_press=key1|key2;
  
  switch(key_state)
  {
    case 0:
	if(key_press!=0xff)
	key_state=1;
	break;

	case 1:
    if(key_press!=0xff)
	{
	  if(key_press==0x7e)  key_value=7;
	  if(key_press==0x7d)  key_value=6;
	  if(key_press==0x7b)  key_value=5;
	  if(key_press==0x77)  key_value=4;
	  
	  if(key_press==0xBe)  key_value=11;
	  if(key_press==0xBd)  key_value=10;
	  if(key_press==0xBb)  key_value=9;
	  if(key_press==0xB7)  key_value=8;
	  
	  if(key_press==0xDe)  key_value=15;
	  if(key_press==0xDd)  key_value=14;
	  if(key_press==0xDb)  key_value=13;
	  if(key_press==0xD7)  key_value=12;
	  
	  if(key_press==0xEe)  key_value=19;
	  if(key_press==0xEd)  key_value=18;
	  if(key_press==0xEb)  key_value=17;
	  if(key_press==0xE7)  key_value=16;
	  
	  key_state=2; 
	}
	else
	key_state=0;
	break;

	case 2:
	if(key_press==0xff)
	key_state=0;
	break;
  }  
  return key_value; 
}

LED驱动模块

#include "led.h"

void All_init()
{
	P2=(P2&0X1F)|0X80;
	P0=0XFF;
	P2=P2&0X1F;
	
	P2=(P2&0X1F)|0XA0;
	P0=0X00;
	P2=P2&0X1F;
}

void ledlight(unsigned char led)
{
	P0=0XFF;
	P2=(P2&0X1F)|0X80;
	P0=led;
	P2=P2&0X1F;
}

EEPROM模块

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

#include "iic.h"

void iic_delay(unsigned char i)
{
    do
	{
	   _nop_();
	}while(i--);
}
void IIC_Start(void)
{
	SDA = 1;
	SCL = 1;
	iic_delay(5);
	SDA = 0;
	iic_delay(5);
	SCL = 0;	
}

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

//应答位控制
void IIC_Ack(unsigned char ackbit)
{
	if(ackbit) 
	{	
		SDA = 0;
	}
	else 
	{
		SDA = 1;
	}
	iic_delay(5);
	SCL = 1;
	iic_delay(5);
	SCL = 0;
	SDA = 1; 
	iic_delay(5);
}

//等待应答
bit IIC_WaitAck(void)
{
	SDA = 1;
	iic_delay(5);
	SCL = 1;
	iic_delay(5);
	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;
		}
		iic_delay(5);
		SCL = 1;
		byt <<= 1;
		iic_delay(5);
		SCL = 0;
	}
}

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

void write_2402(unsigned char add,unsigned char dat)
{
   IIC_Start();
   IIC_SendByte(0xa0);
   IIC_WaitAck();
   IIC_SendByte(add);
   IIC_WaitAck();
   IIC_SendByte(dat);
   IIC_WaitAck();
   IIC_Stop();
}

unsigned char read_2402(unsigned char dat)
{
   unsigned char  temp;
   IIC_Start();
   IIC_SendByte(0xa0);						 //写入  为0
   IIC_WaitAck();
   IIC_SendByte(dat);
   IIC_WaitAck();

   IIC_Start();
   IIC_SendByte(0xa1);					   //读出为1
   IIC_WaitAck();
   temp=IIC_RecByte();
   IIC_Ack(0);
   IIC_Stop();

   return temp;
}

以上就是代码全部内容,手敲代码不易,留个关注和赞再走吧~

你可能感兴趣的:(蓝桥杯)