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

📄 师姐全部程序wsy.c

📁 cgnal c8051f020 4*6键盘 4*8 液晶显示 大容量存储
💻 C
📖 第 1 页 / 共 5 页
字号:
/*0x0020-0x36af 存储2000张卡号(5B卡号+1B权限+1B门号)   14000B
 0x36b0-0x3727 存储60个节假日   120B
 0x3730-0x386f 存储时间段       320B  
 0x3870-0xffff 存储门禁事件纪录*/


#include<c8051f020.h>                    // SFR declarations
#include<intrins.h>
#include<absacc.h>

#define   SYSCLK  22118400                   //系统时钟频率(Hz)
#define BAUDRATE     9600              //波特率
#define   uchar   unsigned char    //typedef  unsigned char uchar;
#define   uint    unsigned int
#define   nop()   _nop_()
#define cs_fm		P4&=0xF8		 // FM20l08片选允许
#define ncs_fm		P4|=~0xF8		 // 不选中任何芯片
#define BANK1		P4|=0x08	 	 // 选择BANK1:64-128K
#define BANK0		P4&=0xF7		 // 选择BANK0:0-64K
#define cs_12887    P4=P4&0xF8|0x02  // 选中DS12887
#define cs_74377    P4=P4&0xF8|0x03  // 选中74377
#define cs_74244    P4=P4&0xF8|0x04  // 选中74244
#define cs_74245    P4=P4&0xF8|0x05  // 选中74245
#define YEAR XBYTE[0x09]     //年
#define MON  XBYTE[0x08]     //月
#define DAY  XBYTE[0x07]     //日
#define WEEK XBYTE[0x06]     //星期
#define HOU  XBYTE[0x04]     //时
#define MIN  XBYTE[0x02]     //分
#define SEC  XBYTE[0x00]     //秒
#define A_12887 XBYTE[0x0a]  //12887寄存器A
#define B_12887 XBYTE[0x0b]  //12887寄存器B
#define C_12887 XBYTE[0x0c]  //12887寄存器C
#define D_12887 XBYTE[0x0d]  //12887寄存器D
#define LCD1    XBYTE[0x00]

sbit BG_IO      = P1^2;   //液晶背光
sbit rs         = P1^3;   //液晶数据指令  H=data; L=command;
sbit rw         = P1^4;   //液晶读写  H=read; L=write;
sbit RD0_IO     = P3^0;  //串口0发送控制。0为发送,1为接收
sbit RD1_IO     = P3^1;  //串口1发送控制。0为发送,1为接收
sbit BELL_IO    = P3^2;  //蜂鸣器
sbit LED_IO     = P3^3;  
sbit FQK_IO     = P3^4;  //防撬开关
sbit i_txct     = P3^6;  //读卡
sbit i_scio     = P3^5;		
sbit lvl        = P1^5;    //铁电低电压检测

bit keyon_flag=0 ;      //有键按下
bit keyon_flag1=0 ;     //最终确认键按下
bit clrlcd_flag=0 ;     //编程状态下,输入错误时,删除先前输入的数字
bit delcard_flag=0;     //编程状态下删除卡号
bit chaxun_flag=0 ;      //查询事件记录标志
bit open_flag=0 ;     //开锁标志
bit enter_flag=0 ;     //确认
bit timechange_flag=0 ; //更改时间标志
bit esc_flag=0 ;        //取消标志
bit program_flag=0;     //编程标志位
bit second_flag=0 ;     //1秒定时标志
bit readcad_flag=0;
bit keywrcard_flag=0;   //刷卡写卡号或写节假日
bit quanxian_flag=0;
bit shiqu_flag=0;       //写时区权限和门号
bit qxtime_flag=0;       //写时段 
bit delqxtime_flag=0;
bit delshijian_flag=0;
bit next_flag=0;
bit last_flag=0;
bit chacard_flag=0;
bit chashiduan_flag=0;
bit chaholiday_flag=0;
bit one_flag=0;
bit chashijian_flag=0;

uchar  count_time3=5; //定时器3定时初值10ms,而键盘扫描是50ms扫描一次,故循环值为5
uint  count_time1=1000;
uint   count_time2;
uchar  JDQ_TIME;
uchar  keytimes1=0;     //按键次数
uchar  recode ;       //列扫描码
uchar  sccode ;       //行扫描码
uchar idata keynumber ;    //键值
uchar idata pp=0xff ;      //P0口的初始化,在程序中会变化
uchar idata scantime ;      //键盘扫描程序中扫描次数
uchar idata gc_cad[8];       //存储读到的卡号
uchar idata gc_crc8=0;       
uchar idata keycodebuf[5];   
uchar idata key_card[5];    //存储键盘输入的卡号 
uchar idata key_time[7];   //键盘输入的要修改的时间
uchar idata read_time[7];   //从ds12887读到的时间
uchar idata key_holiday[2];
uchar idata key_shiqu[2];
uchar idata qx_time[10];    //键盘输入的权限时间段
uchar idata shiqu_num=0;
uchar idata door_num=0;
uchar idata shu=0;
uchar idata hang,lie;
uchar xdata *point1;
uchar idata b[10];
uchar idata quanxian_num;
uchar idata sv0count;
uchar idata kflag=0;
uint  idata check_crc=0;
uchar idata addr;
uchar idata cmdbuf[15]=0;
uchar idata sendkeycode[8];
uchar idata shiduan[8];
uchar idata holiday[2];
uchar  up_flag=0;
//sendyd();

unsigned char code crc8[256]={	0x00, 0x5e, 0xbc, 0xe2, 0x61, 0x3f, 0xdd, 0x83,
								0xc2, 0x9c, 0x7e, 0x20, 0xa3, 0xfd, 0x1f, 0x41,
								0x9d, 0xc3, 0x21, 0x7f, 0xfc, 0xa2, 0x40, 0x1e,
								0x5f, 0x01, 0xe3, 0xbd, 0x3e, 0x60, 0x82, 0xdc,
								0x23, 0x7d, 0x9f, 0xc1, 0x42, 0x1c, 0xfe, 0xa0,
								0xe1, 0xbf, 0x5d, 0x03, 0x80, 0xde, 0x3c, 0x62,
								0xbe, 0xe0, 0x02, 0x5c, 0xdf, 0x81, 0x63, 0x3d,
								0x7c, 0x22, 0xc0, 0x9e, 0x1d, 0x43, 0xa1, 0xff,
								0x46, 0x18, 0xfa, 0xa4, 0x27, 0x79, 0x9b, 0xc5,
								0x84, 0xda, 0x38, 0x66, 0xe5, 0xbb, 0x59, 0x07,
								0xdb, 0x85, 0x67, 0x39, 0xba, 0xe4, 0x06, 0x58,
								0x19, 0x47, 0xa5, 0xfb, 0x78, 0x26, 0xc4, 0x9a,
								0x65, 0x3b, 0xd9, 0x87, 0x04, 0x5a, 0xb8, 0xe6,
								0xa7, 0xf9, 0x1b, 0x45, 0xc6, 0x98, 0x7a, 0x24,
								0xf8, 0xa6, 0x44, 0x1a, 0x99, 0xc7, 0x25, 0x7b,
								0x3a, 0x64, 0x86, 0xd8, 0x5b, 0x05, 0xe7, 0xb9,
								0x8c, 0xd2, 0x30, 0x6e, 0xed, 0xb3, 0x51, 0x0f,
								0x4e, 0x10, 0xf2, 0xac, 0x2f, 0x71, 0x93, 0xcd,
								0x11, 0x4f, 0xad, 0xf3, 0x70, 0x2e, 0xcc, 0x92,
								0xd3, 0x8d, 0x6f, 0x31, 0xb2, 0xec, 0x0e, 0x50,
								0xaf, 0xf1, 0x13, 0x4d, 0xce, 0x90, 0x72, 0x2c,
								0x6d, 0x33, 0xd1, 0x8f, 0x0c, 0x52, 0xb0, 0xee,
								0x32, 0x6c, 0x8e, 0xd0, 0x53, 0x0d, 0xef, 0xb1,
								0xf0, 0xae, 0x4c, 0x12, 0x91, 0xcf, 0x2d, 0x73,
								0xca, 0x94, 0x76, 0x28, 0xab, 0xf5, 0x17, 0x49,
								0x08, 0x56, 0xb4, 0xea, 0x69, 0x37, 0xd5, 0x8b,
								0x57, 0x09, 0xeb, 0xb5, 0x36, 0x68, 0x8a, 0xd4,
								0x95, 0xcb, 0x29, 0x77, 0xf4, 0xaa, 0x48, 0x16,
								0xe9, 0xb7, 0x55, 0x0b, 0x88, 0xd6, 0x34, 0x6a,
								0x2b, 0x75, 0x97, 0xc9, 0x4a, 0x14, 0xf6, 0xa8,
								0x74, 0x2a, 0xc8, 0x96, 0x15, 0x4b, 0xa9, 0xf7,
								0xb6, 0xe8, 0x0a, 0x54, 0xd7, 0x89, 0x6b, 0x35
							};

uchar code AC_TABLE[]={
                       0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,      //第一行汉字位置
                       0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,      //第二行汉字位置
                       0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,      //第三行汉字位置
                       0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,      //第四行汉字位置
                     };

///定时器0延时1us///
void Timer0_us(uchar us)
{
 uchar i;
 TCON&=~0x30;
 TMOD&=~0x0f;
 TMOD|=0x01;
 CKCON|=0x08;
 for(i=0;i<us;i++)
 {
  TR0=0;
  TH0=(-SYSCLK/1000000)>>8;
  TL0=-SYSCLK/1000000;
  TR0=1;
  while(TF0==0);
  TF0=0;
 }
}
///定时器0延时1ms///
void Timer0_ms(uint ms)
{
 uint i;
 TCON&=~0x30;              //停止定时器0并清除溢出标志
 TMOD&=~0x0f;    
 TMOD|=0x01;               //配置定时器0为16位方式
 CKCON|=0x08;              //定时器0对SYSCLK计数,即T0M=1,定时器0使用系统时钟 
 for(i=0;i<ms;i++)
 {
  //计数毫秒
  TR0=0;                   //停止定时器T0
  TH0=(-SYSCLK/1000)>>8;   //设置定时溢出周期为1ms或TH0=(65536-SYSCLK/1000)>>8;
  TL0=(-SYSCLK/1000);      //TL0=(65536-SYSCLK/1000)&0X00ff; 
  TR0=1;                   //启动定时器0
  while(TF0==0)
  {};                      //等待溢出
  TF0=0;                   //清除溢出标志
 }
}


/////用定时器3中断扫描键盘///////////////
void time3() interrupt 14 using 1
{
 TMR3CN&=0x7F;         //清除溢出标志
 TMR3RLH =0xb8;
 TMR3RLL =0x00;       //初始化重装载值,定时10ms初值
 if(count_time3--==0)
 {
  count_time3=5;
  cs_74377;   ///////使377有效
  nop();
  P7=0x0f ;///键盘驱动信号设为低,送全0扫描码
  P4&=0x7f;   //P4.7=0 即/wr=0
  nop();
  nop();
  P4|=0x80;  ///P4.7=1,即Wr=1,产生上升沿
  nop();
  nop();
  cs_74244;    ///P4.7=1,使244有效
  //有键按下
  if((P7&0x7f)!=0x7f)   ///此时244有效,P7.7用于用于连接语音芯片的RAC管脚
    {
        Timer0_ms(20);
		//Timer0_ms(20);    ///延时20ms

        if((P7&0x7f)!=0x7f)
        {
            sccode=0xef ;              //逐行扫描初值
            while(sccode!=0xff)
            {               
                cs_74377 ;            //377有效
                nop();
                P7=pp&sccode ;        //输出行扫描码
				P4&=0x7f ;            //wr=0
                nop();
                nop();
				P4|=0x80;            //wr=1            
                nop();
                cs_74244 ;             //244有效
                nop();
                nop();
                if((P7&0x7f)!=0x7f)
                {
                    recode=(P7|0x80);    
                    keyon_flag=1 ;       //键按下标志位置1
                    BELL_IO=0;
					Timer0_ms(150);     //Timer0_ms(200);
					BELL_IO=1;
					sccode=0xff ;        
                }
         
                else
                {
                    sccode=(sccode<<1)|0x01 ;   //行扫描码左移1位
                    scantime++;
                }
            }
         
            switch(scantime)
            {
                case 0x00 :         //第一行有键按下                
                switch(recode)
                {
				    case 0xfe :
                    keynumber=0x0B ; ///B键
                    break ;
                    case 0xfd :
					if(chaxun_flag)
					 {
					  chashijian_flag=1;
					  one_flag=1;
					 }
					else
                       keynumber=0x0D ;   //D键
                    break ;
                    case 0xfb :
					if(quanxian_flag==1)
				    	{delqxtime_flag=1;}
					  else if(chaxun_flag)
					    delshijian_flag=1;
                       else
                         keynumber=0x0F ;   //F键
                    break ;
                    case 0xf7 :
                     if(quanxian_flag==1)
				    	{qxtime_flag=1;}
                     else if(chaxun_flag)
					     {chashiduan_flag=1;
						  one_flag=1;}
                      else
                       keynumber=0x0E ;    //E键
                    break ;
                    case 0xef :
					if(chaxun_flag)
					{
					 chacard_flag=1;
					 one_flag=1;
					}
					else
                     keynumber=0x0C ;   //C键
                    break ;
                    case 0xdf :
                    keynumber=0x0A;   //A键
                    break ;
                    default :
                    break ;
                   
                }
                break ;

                 case 0x01 :            //第二行有键按下               
                switch(recode)
                { 
                    case 0xfe :
					if((program_flag==1)||(quanxian_flag==1))
					delcard_flag=1;///  只有在编程状态下,按下此键才可以删除卡号
                    else
					 chaxun_flag=1 ; //查询门禁事件记录;编程状态下删除卡号
					break ;
                    case 0xfd :  //编程键或查询时下翻键
					if(chaxun_flag==1)
					    next_flag=1; 
                    else
					    program_flag=1;      
                    break ;
                    case 0xfb : //退出键                    
                    if((timechange_flag==1)||(program_flag==1)||(chaxun_flag==1)||(quanxian_flag==1)||(chaxun_flag==1))    //只有在按了"设置时间"按键或按了编程键之后,"退出"键才有效
                               esc_flag=1 ;
                              else
                               keyon_flag=0;  
                    break ;
                    case 0xf7 ://修改权限
					quanxian_flag=1;

                    break ;
                    case 0xef :
					if(quanxian_flag)
					  {shiqu_flag=1;}   //修改权限时写时区权限
                    else if(chaxun_flag)
					  last_flag=1;
                    else
                      timechange_flag=1 ;//修改时间或门禁事件查询时上翻键
                    break ;
                    case 0xdf :  // 远程开锁
					if((program_flag==1)||(quanxian_flag==1))
					 keywrcard_flag=1;
					  else if(chaxun_flag)
					     {chaholiday_flag=1;
						  one_flag=1;}
                        else
					      open_flag=1 ;
                    break ;
                    default :
                    break ;
                }
                    
                break ;
                case 0x02 :
                //第三行有键按下
                switch(recode)
                {   
				    case 0xfe :
                    keynumber=0x01 ;
                    break ;
                    case 0xfd :
                    keynumber=0x02 ;
                    break ;
                    case 0xfb :
                    keynumber=0x03 ;
                    break ;
                    case 0xf7 :
                    keynumber=0x04 ;
                    break ;
                    case 0xef :
                    keynumber=0x05 ;
                    break ;
                    case 0xdf :
                    keynumber=0x06 ;
                    break ;
                    default :
                    break ;  
                    
                   

                }
                break ;
                case 0x03 :          //第四行有键按下
                switch(recode)
                {   
				    case 0xfe :
                    keynumber=0x07 ;
                    break ;
                    case 0xfd :
                    keynumber=0x08 ;
                    break ;
                    case 0xfb :
                    keynumber=0x09 ;
                    break ;
                    case 0xf7 :
                    //keynumber='删除';
                    clrlcd_flag=1 ;
                    break ;
                    case 0xef :
                    keynumber=0x00 ;
                    break ;
                    case 0xdf :
                    //keynumber='确认';
                    if(((timechange_flag==1)&&(keytimes1>=15))||((program_flag==1)&&(keytimes1>=11))||
					    ((quanxian_flag==1)&&(keytimes1>=5))||((quanxian_flag==1)&&(keytimes1>=21))) //只有将年月日小时分钟都设置完后,
					                          //或在编程状态下,输入卡号之后,按"确认"键方可有效。
                                 enter_flag=1 ;
                               else
                                 keyon_flag=0;
                    break ;
                    default :
                    break ;
                }
                    
                break ;
                default :
                break ;
            }
            //end switch
        }
        //end 去抖if
    }
    //end
   
    if(keyon_flag)
    {
        if(P0!=0x7f)
        keyon_flag1=1 ;
    }
    scantime=0 ;
    P0=pp ;
    P4|= 0x07;
  }
}


void wr_lcd (uchar dat_comm,uchar content)
{
  //chk_busy ();
  Timer0_us(1);
  //delay (12);
  if(dat_comm)
   {
    rs=1;   //data
    rw=0;   //write
   }
  else 
   {
    rs=0;   //command
    rw=0;   //write
   }
  P7=content;   //output data or comm
  cs_74245;
 Timer0_us(1);//加延时
 //delay (24);
  P4|=0x07;
}


//------------------初始化-----------------//
void init_lcd (void)
{
  wr_lcd (0,0x30);  //30---基本指令动作  
  wr_lcd (0,0x01);  //清屏,地址指针指向00H
  wr_lcd (0,0x06);  //光标的移动方向
  wr_lcd (0,0x0c);  //开显示,关游标
}

void display(uchar *ptr,uchar ddram)
{
 uchar i;
 wr_lcd (0,0x30);
 if(ddram<0x88)
 {hang=0;}//定位行地址:第一行
  else if(ddram<0x90)
   {hang=2;}//定位行地址:第三行
    else if(ddram<0x98)
     {hang=1;}//定位行地址:第二行
     else
       {hang=3;}//定位行地址:第四行
  switch(hang)
  {
   case 0:wr_lcd(0,0x80);
       break;
   case 1:wr_lcd(0,0x90);
       break;
   case 2:wr_lcd(0,0x88);
       break;
   case 3:wr_lcd(0,0x98);
  }
  for(i=0;i<16;i++)
 {wr_lcd(1,ptr[i]);//输出单个字符
 }///end of  for(i1=0;i1<16;i1++)
}

///显示单个汉字///////
void chn_disp1 (uchar *chn,uchar addr)
{
  uchar i;
  wr_lcd (0,0x30);
  wr_lcd (0,addr);
  for(i=0;i<2;i++)
  {
   wr_lcd(1,chn[i]);
  }
}

/*void chn_disp8 (uchar *chn,uchar addr)
{
  uchar i;
  wr_lcd (0,0x30);
  wr_lcd (0,addr);
  for(i=0;i<16;i++)
  {
   wr_lcd(1,chn[i]);
  }
}*/
////在指定单元显示单个字符////
void num_disp1 (uchar *num,uchar addr)
{
  wr_lcd (0,0x30);
  wr_lcd (0,addr);
  wr_lcd(1,num[0]);

}

////在指定单元显示单个字符////
void num_disp2 (uchar *num)
{
  wr_lcd (0,0x30);
  wr_lcd(1,num[0]);

}

////在指定的单元显示一个数字////////////
void num_disp(uchar t,uchar addr)
{
 wr_lcd (0,0x30);
 switch(t)
 {
  case 0:
        wr_lcd (0,addr);
        wr_lcd (1,0x30);
		break;
  case 1:
        wr_lcd (0,addr);
        wr_lcd(1,0x31);
		break;
  case 2:
        wr_lcd (0,addr);
		wr_lcd(1,0x32);
		break;
  case 3:

⌨️ 快捷键说明

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