⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 51

📁 51单片机应用系统典型模块开发大全
💻
字号:
#include <reg51.h>
#include <absacc.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int

#define COM XBYTE [0x7fff]       //8279命令状态地址
#define DAT XBYTE [0x77fF]       //8279数据地址
uchar code table[]={
	0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,   //0,1,2,3,4,5,6,7
	0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71    //8,9,A,B,C,D,E,F     
};                              //共阳极数码管显示段码
uchar idata diss[8];            //显示用数据暂存器  8位数据
uchar idata mima[6];            //密码用数据暂存器  6位数据

sbit clflag=ACC^7;              //记录状态字 最高位
sbit SDA=P1^1;                  //24c02数据端
sbit SCL=P1^0;                  //24c02时钟端
sbit error=P1^2;                //闭锁指示端
sbit right=P1^3;                //开锁指示端 和开锁输出

uchar keyin();                   //8279读键号子程序      
uchar deky();                    //8279监测有无按键按下子程序 
void disp(uchar idata *d);       //8279显示子程序
void start_bit(void);            //2402开始位
void stop_bit(void);             //2402停止位
void mast_ack(void);             //2402主答函数
bit write_8bit(uchar ch);        //2402写一个字节(8位)数据
uchar page_wr(uint firstw_ad,uint counter,uchar *firstr_ad);
//2402页面写函数
uchar page_rd(uint firstrd_ad,uint count,uchar *firstwr_ad);
//页面读函数
void mimakey(void);             //密码锁设置密码 输入密码子程序


main()                          //主函数
{
	uchar i;
	COM=0xd1;                   //11010001  总清除命令
	do{ACC=COM;}                //读状态字 直到清除完成
	while(clflag==1);           //读状态字 最高位
	COM=0x00;                   //键盘/显示器工作方式 左端送入8×8显示双键锁定编码扫描
	COM=0x34;                   //时钟分频  20分频
	right=0;error=1;            //默认闭锁
//************以下测试用*****************//
	for(i=0;i<6;i++) {mima[i]=i+2;}  //设置初始密码为234567 测试用 
	while(page_wr(0,6,&mima[0])==0); //写入2402
//测试用 当2402存好密码后 该部分程序可以撤除	
//************以上测试用*****************//	
	while(1)
	{
		mimakey();              //密码锁 设置密码、输入密码子程序
	}		
}

void mimakey(void)              //密码锁 设置密码、输入密码子程序
{
	uchar i,key;                //i循环变量 key键号暂存器 
	bit keyok;                  //解锁标志位  
	for(i=0;i<6;i++){diss[i]=i;}//在“无输入和设置密码时”默认显示012345
	disp(diss);                 //送显示
	key=keyin();		        //等待键按下 读键号
	//*************以下为 输入密码状态*************//
	if((key==0x0b)&(keyok==0))  //在闭锁状态下,密码输入键按下时,进入输入密码状态
	{
		for(i=0;i<6;i++)        //6位密码输入
		{
				
			key=keyin();        //读一位键
			if(key==0x0d) break;//是取消键时 输入密码取消
			if(key>=0x0a) {do{key=keyin();}while(key>=0x0a);}
			                    //不是取消键且输入键号不是0~9的数字键时 等待1位数字键输入
			mima[i]=key;        //密码数字存于mima暂存器中
			diss[i]=15;         //每输入一位密码数码管显示“F”
			disp(diss);         //送显示				 
		}
		if(key!=0x0d)           //6位密码输入完成时  看是否要确认;未完成6位输入时  返回
		{
			key=keyin();        //等待按键输入
			if (key==0x0d);     //是取消键时 输入密码取消
			else                //不是取消键时 等待输入密码确认
			{                   
				if(key!=0x0c)  	while(keyin()!=0x0c);//等待确认键按下
				while(page_rd(0,6,&diss[0])==0);     //在2402中读取密码 
				keyok=1;                             //把解锁标志位设为1 解锁       
				for(i=0;i<6;i++)                     //比较6位密码
				{                                    //有1位密码不同时 密码错误 无需再比较   
					if(mima[i]!=diss[i]) {keyok=0;break;}//密码错误时 解锁状态位设为0 为闭锁状态
				}
				if(keyok==1)  {right=1;error=0;}     //当密码正确时  开锁
				else  {right=0;error=1;}             //当密码错误时  闭锁
			}  
					
		}	
			
	}
	//*************以上为 输入密码状态*************//
		
	
	//*************以下为设置密码状态*************//	
	if(keyok==1)                    //在开锁状态下 可以设置密码或关锁         
	{
		if(key==0x0d)               //开锁状态时 按下取消键时 关锁
		{
			keyok=0;right=0;error=1;//解锁状态位设为0  闭锁
		}
		if(key==0x0a)               //是设定键时 进入设置密码状态
		{
			for(i=0;i<6;i++)        //6位密码输入
			{
			key=keyin();            //读一位键
			if(key==0x0d)  break;   //是取消键时 密码设置取消
			if(key>=0x0a) {do{key=keyin();}while(key>=0x0a);}
			                        //不是取消键且输入键号不是0~9的数字键时 等待1位数字键输入
			mima[i]=key;            //密码数字存于mima暂存器中
			diss[i]=14;             //每输入一位密码数码管显示“E”
			disp(diss);             //送显示				 
			}
			if(key!=0x0d)           //6位密码输入完成时  看是否要确认;未完成6位输入时  返回
			{
				key=keyin();        //读一位键
				if (key==0x0d);		//是取消键时 设置密码取消		
				else                //不是取消键时 等待设置密码确认
				{                   
					if(key!=0x0c)  	while(keyin()!=0x0c);  //等待确认键按下
					while(page_wr(0,6,&mima[0])==0);       //密码写入24lc02		
				}
						
			}
				
		}
			
	}		
	//*************以上为设置密码状态*************//	
	
}



void disp(uchar idata *d)       //显示子程序             
{ 
	uchar j;
	COM=0x90;                   //写显示RAM 自动加1
	for(j=0;j<6;j++)            //
	{
		COM=j+0x80;             //写显示RAM 从0~6地址 此命令可省略 能自动加1
		DAT=table[*d];          //调要显示的数据
		d++;                    //指针加1
	}
}

uchar keyin(void)               //读键号
{
	uchar j;
	do
	{
	while(deky()==0);           //监测有键按下吗 无键时等待
	COM=0x40;                   //读FIFO/传感器RAM  不自动加1  地址为0
	j=DAT;                      //读数据
	j=j&0x3f;                   //读低6位  D5D4D3为键盘所在列号 D2D1D0为键盘所在行号	
	}while(j>=0x0e);	        //只读取0~9和A~D键 不读取E和F键
	return(j);                  //返回键号
}

uchar deky(void)                 //监测有无按键按下 
{
	uchar k;
	k=COM;                       //读状态
	return(k&0x03);              //只监测2行按键 有键返回1 无键返回0
}


/*-----------------------------------------------
调用方式:void start_bit(void)
函数说明:2402开始位
在时钟端SCL为高电平时,数据端SDA发生由高到低的变化,为起始条件
启动I2C总线
-----------------------------------------------*/
void start_bit(void)
{
   SCL=1;//_nop_();
   SDA=1;//_nop_();
   SDA=0;//_nop_();
   SCL=0;//_nop_();
}
/*-----------------------------------------------
调用方式:void stop_bit(void)
函数说明:2402停止位
在时钟端SCL为高电平时,数据端SDA发生由低到高的变化,为停止条件
停止I2C总线数据传输
-----------------------------------------------*/
void stop_bit(void)
{
   SDA=0;//_nop_();
   SCL=1;//_nop_();
   SDA=1;//_nop_();
}
/*-----------------------------------------------
调用方式:void mast_ack(void)
函数说明:2402主答函数
主器件在收发每一个字节后产生一个时钟应答脉冲,
在这期间,发送器必须保证SDA为高,由接收器SDA拉低,
称为应答信号(ACK)。
-----------------------------------------------*/
void mast_ack(void)
{
   SCL=0;_nop_();
   SDA=0;_nop_();
   SCL=1;_nop_();
   SCL=0;_nop_();
   SDA=1;_nop_();
}

/*-----------------------------------------------
调用方式:write_8bit(uchar ch)
函数说明:2402写一个字节(8位)数据
-----------------------------------------------*/
bit write_8bit(uchar ch)
{
   uchar i=8;
   bit fan_w;
   SCL=0;_nop_();
   while(i--)
   {
      SDA=(bit)(ch&0x80); //取字节的最高位
	  _nop_();
      ch<<=1;             //字节左移一位
      SCL=1;_nop_();      //上升沿锁存数据
      SCL=0;_nop_();
   }
   SDA=1;_nop_();
   SCL=1;_nop_();
   fan_w=SDA;             //读应答信号
   SCL=0;_nop_();
   return(fan_w);         //返回应答信号
}

/*-----------------------------------------------
调用方式:void page_wr(uint firstw_ad,uint counter,uint data *firstr_ad)
函数说明:2402页面写函数,firstw_ad为写入字节单元的首地址,
          *firstr-ad为被写入数据所在首地址指针
          counter为写入数据字节数
-----------------------------------------------*/
uchar page_wr(uint firstw_ad,uint counter,uchar *firstr_ad)
{
   uchar data *ufirstr_ad;
   ufirstr_ad=firstr_ad;
   start_bit();                                       //写开始位
   if(write_8bit(0xA0)!=0){stop_bit();return(0);}     //写命令
   if(write_8bit(firstw_ad)!=0){stop_bit();return(0);}//写首地址 
   while(counter--)                                   //写字节数减1 
   {
      if(write_8bit(*ufirstr_ad)!=0){stop_bit();return(0);}//写1字节
      ufirstr_ad++;		                             //地址加1
   }
   stop_bit();                                       //写停止位
   return(1);
}
/*-----------------------------------------------
调用方式:void page_rd(uint firstrd_ad,uint count,uint firstwr_ad)
函数说明:2402页面读函数,firstrd-ad为所读字节首地址,count为读字节数
           *ufirstwr-ad为读出数据存储首地址指针
-----------------------------------------------*/
uchar page_rd(uint firstrd_ad,uint count,uchar *firstwr_ad)
{
   uchar j=8;
   uchar data *ufirstwr_ad;
   ufirstwr_ad=firstwr_ad;
   start_bit();                                        //写开始位
   if(write_8bit(0xA0)!=0){stop_bit();return(0);}      //写命令
   if(write_8bit(firstrd_ad)!=0){stop_bit();return(0);}//写首地址
   start_bit();                                        //写开始位
   if(write_8bit(0xA1)!=0){stop_bit();return(0);}      //读命令
   while(count--)                                      //读字节数减1 
   {
      uchar i=8;
      while(i--)
      {
         (*ufirstwr_ad)<<=1;		        //读对应地址的数据左移	       					
         SCL=1;_nop_();                     //上升沿
         if(SDA) (*ufirstwr_ad)|=0x01;      //数据端为1时 存1
         SCL=0; _nop_();
      }
      ufirstwr_ad++;                        //地址加1
      mast_ack();                           //应答信号
   }
   while(j--)
   {
      (*ufirstwr_ad)<<=1;
      SCL=0;_nop_();_nop_();SCL=1;
      if(SDA) (*ufirstwr_ad)|=0x01;
   }
   stop_bit();                              //写停止位
   return(1);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -