• 单片机期末实训---- 密码锁和交通灯


    交通灯汇编代码:

    ORG 0000H
    LJMP MAIN
    A_BIT EQU 20H
    B_BIT EQU 21H
    C_BIT EQU 22H
    D_BIT EQU 23H
    TEMP1  EQU 24H
    TEMP2  EQU 25H
    TEMP3  EQU 26H
    TEMP4  EQU 27H
    
    ORG 0003H
    LJMP INTER0
    
    ORG 0013H
    LJMP INTER1
    
    
    ORG 0050H 
    MAIN:  
          ;定义中断
          MOV SP,#60H
          SETB IT0 ;边沿触发
          SETB EX0;允许外部中断0
          SETB EX1;允许外部中断1
          SETB EA;允许总中断
         
    START:  
          MOV R4,#00;初始自由模式还是控制模式
          MOV P1,#0FFH
          MOV P2,#0FFH
          MOV TEMP1,#10
          MOV TEMP2,#15
          MOV TEMP3,#15;南北显示
          MOV TEMP4,#10;东西显示
          MOV R3,#20;定时50ms循环次数
          MOV TMOD,#01H;定时器0方式一
          MOV TH0,#3CH
          MOV TL0,#0B0H
          SETB TR0;启动T1
          
          ;南北通行20s
          SETB P1.5
          CLR  P1.4
          CLR  P1.3
          SETB P1.0
          CLR  P1.1
          CLR  P1.2
    
          SETB P1.7;控制蜂鸣器
          ;显示时间
    STL0P0:
          ;软件查询中断
          ACALL TEST
          
          ACALL DISPLAY      ;调用显示
          DEC TEMP1
          DEC TEMP2
          MOV A,TEMP1
         
                    
          CJNE A,#0,STL0P0
          
          ;南北黄灯通行5s
          CLR P1.5
          SETB  P1.4
          CLR  P1.3
          SETB P1.0
          CLR  P1.1
          CLR  P1.2
          CLR P1.7;控制蜂鸣器
          
          MOV TEMP1,#05
          MOV TEMP2,#05
          ;显示时间
    STL0P1:
     ;软件查询中断
          ACALL TEST
          
          ACALL DISPLAY      ;调用显示
          DEC TEMP1
          DEC TEMP2
          MOV A,TEMP1
          
         
          CJNE A,#0,STL0P1
          
          ;东西向通行5s
          CLR P1.5
          CLR  P1.4
          SETB  P1.3
          CLR P1.0
          CLR  P1.1
          SETB  P1.2
          
          SETB P1.7
          ;显示时间
    STL0P2:
     ;软件查询中断
          ACALL TEST
          
          ACALL DISPLAY1      ;调用显示
          DEC TEMP3
          DEC TEMP4
          MOV A,TEMP4
    
          CJNE A,#0,STL0P2
          
          ;东西向黄灯
          CLR P1.5
          CLR  P1.4
          SETB  P1.3
          CLR P1.0
          SETB  P1.1
          CLR  P1.2
          
          CLR P1.7;控制蜂鸣器
          MOV TEMP3,#05
          MOV TEMP4,#05
          
          ;显示时间
    STL0P3:
           ;软件查询中断
          ACALL TEST
          ACALL DISPLAY1      ;调用显示
          DEC TEMP3
          DEC TEMP4
          MOV A,TEMP4 
          CJNE A,#0,STL0P3
          LJMP MAIN
          
    DISPLAY: 
          MOV A,TEMP1; TEMP1,#20H
          MOV B,#10
          DIV AB
          MOV A_BIT,B
          MOV B_BIT,A      ;B_BIT是十位
          MOV A,TEMP2       ; TEMP2,#20H
          MOV B,#10
          DIV AB
          MOV C_BIT,A 
          MOV D_BIT,B
          MOV DPTR,#NUMT
    LP1:  ;显示南北个十位
          MOV A,A_BIT
          MOVC A,@A+DPTR
          MOV P0,A
          SETB P2.4
          ACALL D1MS
          CLR P2.4
          MOV A,B_BIT
          MOVC A,@A+DPTR
          MOV P0,A
          SETB P2.5
          ACALL D1MS
          CLR P2.5
          ;显示东西个十位
          MOV A,D_BIT
          MOVC A,@A+DPTR
          MOV P0,A
          SETB P2.6
          ACALL D1MS
          CLR P2.6
          MOV A,C_BIT
          MOVC A,@A+DPTR
          MOV P0,A
          SETB P2.7
          ACALL D1MS
          CLR P2.7
          ;查询计数溢出
          JBC TF0,LP2
          SJMP LP1
          
    LP2: MOV TH0,#03CH
         MOV TL0,#0B0H  
         ;软件查询中断
         ACALL TEST 
         DJNZ R3,LP1 ;未到1S,继续循环,20*50MS=1000MS=1S
         MOV R3,#20
         RET
         
         
    DISPLAY1:
          MOV A,TEMP3
          MOV B,#10
          DIV AB
          MOV A_BIT,B
          MOV B_BIT,A
          MOV A,TEMP4
          MOV B,#10
          DIV AB
          MOV C_BIT,A 
          MOV D_BIT,B
          MOV DPTR,#NUMT
    LP3:  ;显示南北个十位
          MOV A,A_BIT
          MOVC A,@A+DPTR
          MOV P0,A
          SETB P2.4
          ACALL D1MS
          CLR P2.4
          MOV A,B_BIT
          MOVC A,@A+DPTR
          MOV P0,A
          SETB P2.5
          ACALL D1MS
          CLR P2.5
          ;显示东西个十位
          MOV A,D_BIT
          MOVC A,@A+DPTR
          MOV P0,A
          SETB P2.6
          ACALL D1MS
          CLR P2.6
          MOV A,C_BIT
          MOVC A,@A+DPTR
          MOV P0,A
          SETB P2.7
          ACALL D1MS
          CLR P2.7
          ;查询计数溢出
          JBC TF0,LP4
          SJMP LP3
          
    LP4: MOV TH0,#03CH
         MOV TL0,#0B0H
        ;软件查询中断
          ACALL TEST
         DJNZ R3,LP3 ;未到1S,继续循环,20*50MS=1000MS=1S
         MOV R3,#20
         RET
          
    INTER0:
          MOV R4,#01
           RETI ;中断返回  
    INTER1:
          MOV R4,#00
           RETI
    
    START1: 
            ;南北通行
          SETB P1.5
          CLR  P1.4
          CLR  P1.3
          SETB P1.0
          CLR  P1.1
          CLR  P1.2
          RET
    
    START2:
           ;东北通行
          CLR P1.5
          CLR  P1.4
          SETB  P1.3
          CLR P1.0
          CLR  P1.1
          SETB  P1.2
          RET
          
    K1K:  ACALL START2
          SJMP KEY1
          ;选择模式
    KEY0:
          
          CJNE R4,#01,K1K;当R4=00或02是东西通行
          ACALL START1;当01是南北通行
          
    KEY1: ACALL DELAY1
    
          ;软件查询中断
          MOV P3,#0FFH
          MOV A,P3
          CJNE A,#0FFH,PL1
          SJMP KEY0
    PL1:   ACALL DELAY1
           MOV P3,#0FFH
           MOV  A,P3
           CJNE A,#0FFH,PL2
           SJMP KEY0  
    PL2:  JNB ACC.4,K8K;定义多一个k8k,目的要远距离地址调用,如果直接跳到START,会出现address 
    
    out range
          SJMP KEY0
    
    K8K: LJMP START
          ;K0软件查询
    TEST:
          MOV P3,#0FFH
          MOV A,P3
          CJNE A,#0FFH,L2P1
          RET   
    L2P1: ACALL DELAY1
          MOV P3,#0FFH
          MOV A,P3
          CJNE A,#0FFH,L2P2
          RET    
    L2P2: JNB ACC.4,KEY0
          RET
          
        
    D1MS: MOV R7,#250
          DJNZ R7,$
          RET
          
    DELAY1:
       MOV R5,#255
    D1: MOV R6,#255
        DJNZ R6,$
        DJNZ R5,D1
        RET
        
         
    NUMT: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH
    
    NUMT1:  DB 0C0H,0f9H,0a4H,0b0H,99H,92H,82H,0f8H,80H,90H
    
    END
    
    
    

    C语言版:

    /**************************************************************************************
    *		              交通灯实验												  *
    实现现象:下载程序后,按照视频操作正确接线,呈现交通灯现象
    注意事项:																				  
    ***************************************************************************************/
    
    #include "reg52.h"			 //此文件中定义了单片机的一些特殊功能寄存器
    
    typedef unsigned int u16;	  //对数据类型进行声明定义
    typedef unsigned char u8;
    
    static u16 R4=0;  //
    static u16 flag=0; //模式切换标志位
    
    //--定义使用的IO口--//
    #define GPIO_DIG   P0
    #define GPIO_TRAFFIC P1
    
       
    sbit P25   = P2^5;   
    sbit P24   = P2^4;  
    sbit P10   = P1^0;
    sbit P11   = P1^1;
    sbit P12   = P1^2;
    sbit P13   = P1^3;
    sbit P14   = P1^4;
    sbit P15   = P1^5;
    sbit P17   = P1^7;
    //中断
    sbit P32   = P3^2;
    sbit P33   = P3^3;
    sbit P34   = P3^4;
    
    u8 code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
    					0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示0~F的值
    
    u8 DisplayData[8];
    u8 Second;
    
    int interr_P33();
    void _mode();
    void west_east();
    void north_th();
    
    /*******************************************************************************
    * 函 数 名         : delay
    * 函数功能		   : 延时函数,i=1时,大约延时10us
    *******************************************************************************/
    void delay(u16 i)
    {
    	while(i--);	
    }
    
    /*******************************************************************************
    * 函 数 名         : DigDisplay
    * 函数功能		   : 数码管动态扫描函数,循环扫描8个数码管显示
    *******************************************************************************/
    void DigDisplay()
    {
    	u8 i;
    	for(i=0;i<2;i++)
    	{
    		switch(i)	 //位选,选择点亮的数码管,
    		{
    			case(0):
    				P25=1; P24=0 ; break;//显示第0位
    			case(1):
    				P24=1; P25=0; break;//显示第1位
    		
    		}
    		GPIO_DIG=DisplayData[i];//发送段码
    		delay(100); //间隔一段时间扫描	
    		GPIO_DIG=0x00;//消隐
    	}
    }
    
    
    /*******************************************************************************
    * 函 数 名         : Timer0Init
    * 函数功能		   : 定时器0初始化
    * 输    入         : 无
    * 输    出         : 无
    *******************************************************************************/
    void Timer0Init()
    {
    	TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。
    
    	TH0=0X3C;	//给定时器赋初值,定时1ms
    	TL0=0X0B0;	
    	ET0=1;//打开定时器0中断允许
    	IT0=1;//边沿触发
    	EX0=1;//允许外部中断0
    	EX1=1;//允许外部中断1
    	EA=1;//打开总中断
    	TR0=1;//打开定时器			
    }
    
    /*******************************************************************************
    * 函 数 名       : main
    * 函数功能		 : 主函数
    * 输    入       : 无
    * 输    出    	 : 无
    *******************************************************************************/
    void main()
    {	
    	Second = 1;
    
    	Timer0Init();
    
    	while(1)
    	{
    		
    		if(Second == 78)
    		{
    			Second = 1;
    		}
    
    		//--东西通行,10秒--//
    		if(flag==0)
    		{
    			if(Second < 35)
    			{
    				DisplayData[1] = smgduan[( 34- Second) % 100 / 10];
    				DisplayData[0] = smgduan[(34 - Second) %10];
    		
    				DigDisplay();
    	
    				//--东西通行--//
    	
    				GPIO_TRAFFIC = 0x00;  //将所有的灯熄灭
    				P12 = 1;
    				P11 = 0;
    			    P10 = 0;
    				 //南北红灯
    	
    			    P13= 1;    //			
    				P14= 0;    //
    				P15 = 0;   //
    				P17 = 1;//蜂鸣器关闭
    			}
    	
    			//--黄灯等待切换状态,5秒--//
    			else if(  Second < 40) 
    			{
    				DisplayData[1] = smgduan[( 39- Second) % 100 / 10];
    				DisplayData[0] = smgduan[(39 - Second) %10];
    		
    				DigDisplay();
    	
    				//--黄灯阶段--//
    	
    				GPIO_TRAFFIC = 0x00;  //将所有的灯熄灭
    				P12 = 0;
    				P11 = 1;
    			    P10 = 0;
    				 //南北红灯
    	
    			    P13= 1;    //			
    				P14= 0;    //
    				P15 = 0;   //
    					P17 = 0;//蜂鸣器打开
    			
    			}
    	
    			//--南北通行--//
    			else if( Second < 74) 
    			{
    				DisplayData[1] = smgduan[( 73- Second) % 100 / 10];
    				DisplayData[0] = smgduan[( 73 - Second) %10];
    		
    				DigDisplay();
    	
    				//--东西红灯阶段--//
    				GPIO_TRAFFIC = 0x00;  //将所有的灯熄灭
    				P12 = 0;
    				P11 = 0;
    			    P10 = 1;
    				 //南北绿灯
    	
    			    P13= 0;    //			
    				P14= 0;    //
    				P15= 1;   //
    				P17 = 1;//蜂鸣器关闭
    			
    			}
    	
    			//--黄灯等待切换状态,5秒--//
    			else if(  Second < 79) 
    			{
    				DisplayData[1] = smgduan[( 78- Second) % 100 / 10];
    				DisplayData[0] = smgduan[(78 - Second) %10];
    		
    				DigDisplay();
    	
    				//--东西红灯--//
    	
    				GPIO_TRAFFIC = 0x00;  //将所有的灯熄灭
    				P12 = 0;
    				P11 = 0;
    			    P10 = 1;
    				 //南北黄灯
    	
    			    P13= 0;    //			
    				P14= 1;    //
    				P15= 0;   //
    				P17 = 0;//蜂鸣器打开
    			
    			}
    		}
    		else if(flag==1)
    		{
    		   _mode();
    		   	P17 = 1;//蜂鸣器关闭
    		}
    			interr_P33(); //每50ms扫描P3^4
    	}
    						
    }
    
    
    
    /*******************************************************************************
    * 函 数 名         : Int0()	interrupt 0
    * 函数功能		   : 外部中断0的中断函数
    * 输    入         : 无
    * 输    出         : 无
    *******************************************************************************/
    void Int0() interrupt 0
    {
    	delay(1000);
    	if(P32==0)
    	{
    	     R4=1;//东西通行
    	}
    
    }
    
     /*******************************************************************************
    * 函 数 名         : Int1()	interrupt 0
    * 函数功能		   : 外部中断1的中断函数
    * 输    入         : 无
    * 输    出         : 无
    *******************************************************************************/
    void Int2() interrupt 2
    {
    	delay(1000);
    	if(P33==0)
    	{
    	     R4=0;//南北通行
    	}
    
    }
    
    //程序扫描端口中断
    int	interr_P33()
    {
    	   
    	  if(P34==0)
    	  {
    		delay(1000);
    		if(P34==1)
    		 {   return 0;  }
    		else
    		  {	 
    		    TR0 = !TR0;
    		 	flag=!flag;
    			while(P34==0)
    			;
    		     return 0 ;
    		  }
    	  }
    		  return 0 ;
    }
    //自由模式
    void _mode()
    {
       
    		if(R4==0)
    		 west_east();
    		else if(R4==1) 
    		 north_th();
    	
    }
    
    
    
    /*******************************************************************************
    * 函 数 名         : void Timer0() interrupt 1
    * 函数功能		   : 定时器0中断函数
    * 输    入         : 无
    * 输    出         : 无
    *******************************************************************************/
    void Timer0() interrupt 1
    {
    	static u16 i;
    	TH0=0X3C;	//给定时器赋初值,定时50ms
    	TL0=0X0B0;
    	i++;
    	if(i==20)
    	{
    		i=0;
    		Second ++;	
    	}	
    }
    
    
    //东西通行
    void  west_east()
    {
    	   	//--东西通行--//
    
    			P12 = 1;
    			P11 = 0;
    		    P10 = 0;
    			 //南北红灯
    
    		    P13= 1;    //			
    			P14= 0;    //
    			P15 = 0;   //
    }
    
    //南北通行
    void north_th()
    {
    	   	//--东西红灯阶段--//
    		
    			P12 = 0;
    			P11 = 0;
    		    P10 = 1;
    			 //南北绿灯
    
    		    P13= 0;    //			
    			P14= 0;    //
    			P15= 1;   //
    
    }
    				  
    
    

    密码锁汇编代码:

    ORG  0000H
    LJMP MAIN
    ;定义EEPROM特殊功能寄存器
    ISP_DATA DATA 0E2H
    ISP_ADDRH DATA 0E3H
    ISP_ADDRL DATA 0E4H
    ISP_CMD DATA 0E5H
    ISP_TRIG DATA 0E6H
    ISP_CONTR DATA 0E7H
    
    ;定义ISP/IAP命令及等待时间
    ISP_IAP_BYTE_READ EQU 1
    ISP_IAP_BYTE_PROGRAM EQU 2
    ISP_IAP_SECTOR_ERASE EQU 3
    WAIT_TIME EQU 0
    
    ;----89c51引脚定义-----
    TEMP EQU 20H
    RS EQU P3.7
    RW EQU P3.6
    E EQU P3.5
    TIME EQU 23H
    PASSWORD EQU 2000H;EEROM起始地址
    ORG 0070H
    
    MAIN: 
        ACALL LCD
        MOV TEMP,#0AH
        MOV R4,#0;初始8位密码输入
        MOV P2,#00H
        SETB P2.2
        MOV 25H,#50H;初始保存密码起始地址
        MOV 26H,#0
        MOV R6,#0;修改密码标志位
        ;时钟定时初始
        MOV TMOD,#01H
        MOV TH0,#3CH
        MOV TL0,#0B0H
        ACALL DISPLAYINPUT
        MOV 40H,#0
    KEYSCAN:
       
       MOV P1,#0FFH
       MOV P1,#0F0H;设定高位为行线,低位为列线
       MOV A,P1
       CJNE A,#0F0H,M;判断是否有键按下,有延时去抖动  
       SJMP KEYSCAN
        
    M:  ;去抖动
       ACALL DELAY
       MOV P1,#0F0H
       MOV A,P1
       CJNE A,#0F0H,MM;判断是否有键还在按下,
       SJMP KEYSCAN
    
    MM:
       MOV 21H,A;行为输入,并记录
       MOV P1,#0FH;设置列线为输入
       MOV 31H,P1
      ;等按键松开
    MMM:
       MOV P1,#0F0H
       MOV A,P1
       CJNE A,#0F0H,MMM
    ;查询行号
       MOV A,21H
       JNB ACC.4,E1
       JNB ACC.5,E2
       JNB ACC.6,E3
       JNB ACC.7,E4
    ;设置行号初值
    E1:
       MOV 22H,#0
       LJMP KEYH
    E2:
       MOV 22H,#4
       LJMP KEYH
    E3:
       MOV 22H,#8
       LJMP KEYH
    E4:
       MOV 22H,#0CH
       LJMP KEYRESET
    ;查询列好
    KEYH:
       MOV A,31H
       JNB ACC.0,D0
       JNB ACC.1,D1
       JNB ACC.2,D2
       JNB ACC.3,D3
    ;计算键值
    D0:
       CJNE R4,#8,CONTINUE;不等继续输,每输入一位,减一
       LJMP PASS
    CONTINUE:
       MOV A,25H
       ADD A,R4 ;R2保存密码的地址
       MOV R0,A
       MOV A,#0
       ADD A,22H
       MOV @R0,A ;保存当前输入值
       MOV TEMP,A
       ACALL DISPLAYNUM;显示当前输入值
       INC R4
       CJNE R4,#8,RETURN
       LJMP PASS
        
    D1:
       CJNE R4,#8,CONTINUE1;不等继续输,每输入一位,减一
       LJMP PASS
    CONTINUE1:
       MOV A,25H
       ADD A,R4 ;R2保存密码的地址
       MOV R0,A
       MOV A,#1
       ADD A,22H
       MOV @R0,A ;保存当前输入值
       MOV TEMP,A
       ACALL DISPLAYNUM;显示当前输入值
       INC R4
       CJNE R4,#8,RETURN
       LJMP PASS
       
    D2:
       MOV A,#2
       ADD A,22H
       CJNE A,#0AH,DD2;符合第三行
       SJMP DELETE
    DD2:
       CJNE R4,#8,CONTINUE2;不等继续输,每输入一位,减一
       LJMP PASS
    CONTINUE2:
       MOV A,25H
       ADD A,R4 ;R2保存密码的地址
       MOV R0,A
       MOV A,#2 
       ADD A,22H
       MOV @R0,A ;保存当前输入值
       MOV TEMP,A
       ACALL DISPLAYNUM;显示当前输入值
       INC R4
       CJNE R4,#8,RETURN
       LJMP PASS
       
    D3:
       MOV A,#3
       ADD A,22H
       CJNE A,#0BH,DD3;符合第三行
       LJMP ENTER
    DD3:
       CJNE R4,#8,CONTINUE3;不等继续输,每输入一位,减一
       LJMP PASS
    CONTINUE3:
       MOV A,25H
       ADD A,R4 ;R2保存密码的地址
       MOV R0,A
       MOV A,#3
       ADD A,22H
       MOV @R0,A ;保存当前输入值
       MOV TEMP,A
       ACALL DISPLAYNUM;显示当前输入值
       INC R4
       CJNE R4,#8,RETURN
       LJMP PASS
       
    RETURN:
       ACALL DISPLAYINPUT
       LJMP KEYSCAN
       
    KEYRESET:
       MOV A,31H
       JNB ACC.0,SET0
       JNB ACC.1,NOSET
    SET0:;修改密码
       MOV A,26H
       JNZ SET2;判断是否进入密码确定状态
       LJMP KEYSCAN
    SET2: 
       ACALL DISPASSWORDRESET
       ACALL DELAYTIME
       MOV R4,#0;使能键盘能正常输入
       MOV 25H,#60H;
       MOV R6,#1;进入密码修改状态
       ACALL DISPLAYCLL
       LJMP KEYSCAN
    
    NOSET:
       MOV A,40H
       CJNE A,#1,NOSET2
       MOV A,26H
       JNZ NOSET1;判断是否进入密码确定状态
    NOSET2:
       LJMP KEYSCAN
    NOSET1:
       LJMP MAIN
       
    ;按了delete  
    DELETE:
       CJNE R4,#0,DELETE2
       LJMP KEYSCAN
    DELETE2:
       CJNE R4,#8,DELETE3
       LJMP KEYSCAN;如果等于8,就是没有输入任何密码来
    DELETE3:
       MOV TEMP,#0AH
       ACALL DISPLAYNUM
       DEC R4 
       MOV R0,25H
       MOV A,R4
       ADD A,R0 ;R2保存密码的地址
       MOV R0,A
       MOV @R0,#0
       ;删了密码,需要显示器重新显示
       ACALL DISPLAYNUM
       ACALL BUSY
       MOV A,#83H
       ADD A,R4
       MOV P0,A;第一韩第三个位置
       ACALL ENABLE
       LJMP KEYSCAN
    ;密码修改
    PASSRESETOK:
       ACALL DISPLAYRESETOK
       MOV 25H,#50H;恢复保存地址
       MOV R6,#0;退出密码修改状态
       ACALL PASSSAVE
       ACALL DELAYTIME;延时3s
       MOV 26H,#0;退出密码修改状态
       LJMP MAIN
    ;用户按了enter
    ENTER:
       CJNE R4,#8,RETURN;不等于8,跳转
       CJNE R6,#0,PASSRESETOK
       ;按了确认键就会跳转到这里
    PASSMATCH:
       MOV R3,#0
       ACALL ISP_READ
       MOV R0,#50H
       MOV R1,#60H
    MATCH:
       MOV A,@R0
       MOV B,@R1
       CLR C
       SUBB A,B
       JNZ MATCHNO
       INC R0
       INC R1
       CJNE R0,#59H,MATCH
       SJMP MATCHYES
      
    
    PASSSAVE:
       ACALL ISP_ERASE
       ACALL ISP_WRITE
       RET
       
    MATCHYES:
       ACALL DISPLAYTRUE
       MOV TIME,#0
       SETB P2.0
       CLR P2.1
       MOV 26H,#1;密码输入正确状态
       ACALL DELAYTIME
       ACALL DOYOUSET
       MOV 40H,#1
       ACALL YESORNO
       LJMP KEYSCAN
       
    MATCHNO:
       ACALL DISPLAYFALSE
       SETB P2.1
       CLR P2.0
       CLR P2.2
       ACALL DELAYTIME
       CLR TR0
       SETB P2.2
       LJMP MAIN
       
    ;用户输入了8个密码,继续按其他数字按键无效  
    PASS:
       MOV A,26H
       JNZ LPL
       ACALL  DISPLAYENTER
       LJMP KEYSCAN 
    LPL:
       CJNE R6,#1,LPL2
       ACALL DISPLAYENTER
       LJMP KEYSCAN
    LPL2:
       ACALL DISPLAYTRUE
       LJMP KEYSCAN 
       
    DELAYTIME:
       ;显示3s,开定时中断
       MOV R5,#60
       SETB TR0
       MOV TH0,#03CH
       MOV TL0,#0B0H
    SECOND:
       JBC TF0,SECOND1
       SJMP SECOND
    SECOND1:
       MOV TH0,#03CH
       MOV TL0,#0B0H
       DJNZ R5,SECOND
       RET
       
    DISPLAYENTER:;显示please enter
       MOV R7,#10H
       MOV DPTR,#PLEASEENTER
       ACALL BUSY
       MOV A,#0C0H
       MOV P0,A;第一韩第三个位置
       ACALL ENABLE
     
    LOOP4:
       MOV A,#00H
       MOVC A,@A+DPTR
       ACALL BUSY
       MOV P0,A
       ACALL DATAS;显示数据
       INC DPTR
       DJNZ R7,LOOP4;显示完之后就跳转
       RET
    
         
    DISPLAYNUM:;显示数字的
       ACALL BUSY
       MOV A,#84H
       ADD A,R4
       MOV P0,A;第一韩第三个位置
       ACALL ENABLE
       MOV DPTR,#NUMBER
       ACALL BUSY
       MOV A,TEMP
       MOVC A,@A+DPTR
       MOV P0,A
       ACALL DATAS;显示数据
       RET
       
       
    DISPLAYCLL:
       ACALL BUSY
       MOV A,#80H
    CLL:
       INC A
       MOV P0,A;第一韩第三个位置
       ACALL ENABLE
       ACALL BUSY
       MOV P0,#20H
       ACALL DATAS;显示数据
       CJNE A,#90H,CLL
       ACALL BUSY
       MOV A,#84H
       ADD A,R4
       MOV P0,A;第一韩第三个位置
       ACALL ENABLE
       RET
       
    DISPLAYINPUT:;显示input password
       MOV R7,#10H
       MOV DPTR,#INPUTPASSWORD
       ACALL BUSY
       MOV A,#0C0H
       MOV P0,A;第一韩第三个位置
       ACALL ENABLE
     
    LOOP1:
       MOV A,#00H
       MOVC A,@A+DPTR
       ACALL BUSY
       MOV P0,A
       ACALL DATAS;显示数据
       INC DPTR
       DJNZ R7,LOOP1;显示完之后就跳转
       RET
    
    DISPLAYTRUE:;password TRUE
       MOV R7,#10H
       MOV DPTR,#PASSWORDTRUE
       ACALL BUSY
       MOV A,#0C0H
       MOV P0,A;第一韩第三个位置
       ACALL ENABLE
     
    LOOP2:
       MOV A,#00H
       MOVC A,@A+DPTR
       ACALL BUSY
       MOV P0,A
       ACALL DATAS;显示数据
       INC DPTR
       DJNZ R7,LOOP2;显示完之后就跳转
       RET
    
    
       
    DISPLAYFALSE:;password FALSE
       MOV R7,#10H
       MOV DPTR,#PASSWORDFALSE
       ACALL BUSY
       MOV A,#0C0H
       MOV P0,A;第一韩第三个位置
       ACALL ENABLE
    LOOP3:
       MOV A,#00H
       MOVC A,@A+DPTR
       ACALL BUSY
       MOV P0,A
       ACALL DATAS;显示数据
       INC DPTR
       CJNE R7,#01H,RELOOP3
       SJMP DISFALSETIME
    RELOOP3:
       DJNZ R7,LOOP3;显示完之后就跳转
       RET
    
    DISFALSETIME:
       ACALL BUSY
       MOV A,#0CFH
       MOV P0,A;第一韩第三个位置
       ACALL ENABLE
       INC TIME;输入错误一次,加一
       MOV DPTR,#NUMBER
       MOV A,TIME
       MOVC A,@A+DPTR
       ACALL BUSY
       MOV P0,A
       ACALL DATAS;显示数据
       SJMP RELOOP3
       
    
    DISPASSWORDRESET:;显示修改密码
       MOV R7,#10H
       MOV DPTR,#PASSWORDRESET
       ACALL BUSY
       MOV A,#0C0H
       MOV P0,A;第一韩第三个位置
       ACALL ENABLE
     
    LOOP6:
       MOV A,#00H
       MOVC A,@A+DPTR
       ACALL BUSY
       MOV P0,A
       ACALL DATAS;显示数据
       INC DPTR
       DJNZ R7,LOOP6;显示完之后就跳转
       RET
    
    DISPLAYRESETOK:
       MOV R7,#10H
       MOV DPTR,#PLAYRESETOK
       ACALL BUSY
       MOV A,#0C0H
       MOV P0,A;第一韩第三个位置
       ACALL ENABLE
     
    LOOP9:
       MOV A,#00H
       MOVC A,@A+DPTR
       ACALL BUSY
       MOV P0,A
       ACALL DATAS;显示数据
       INC DPTR
       DJNZ R7,LOOP9;显示完之后就跳转
       RET
       
       
    LCD:
         MOV R0,#8
         ACALL BUSY
         MOV P0,#00000001B
         ACALL ENABLE
         ACALL BUSY
         MOV P0,#00111100B
         ACALL ENABLE
         ACALL BUSY
         MOV P0,#00001111B
         ACALL ENABLE
         ACALL BUSY
         MOV P0,#00000110B
         ACALL ENABLE
         RET
    
    DOYOUSET:
       MOV R7,#10H
       MOV DPTR,#DOYOUSETTAB
       ACALL BUSY
       MOV A,#080H
       MOV P0,A;第一韩第三个位置
       ACALL ENABLE
     
    LOOP22:
       MOV A,#00H
       MOVC A,@A+DPTR
       ACALL BUSY
       MOV P0,A
       ACALL DATAS;显示数据
       INC DPTR
       DJNZ R7,LOOP22;显示完之后就跳转
       RET    
          
    YESORNO:
       MOV R7,#10H
       MOV DPTR,#YESORNOTAB
       ACALL BUSY
       MOV A,#0C0H
       MOV P0,A;第一韩第三个位置
       ACALL ENABLE
     
    LOOP11:
       MOV A,#00H
       MOVC A,@A+DPTR
       ACALL BUSY
       MOV P0,A
       ACALL DATAS;显示数据
       INC DPTR
       DJNZ R7,LOOP11;显示完之后就跳转
       RET  
       
    ENABLE:
       SETB E;E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。
       CLR RS;RS和RW都为0,就是对应那些指令执行
       CLR RW;RW为1就是读,为0就是写
       CLR E
       RET
       
       
    BUSY:
       CLR E
       MOV P0,#0FFH;
       CLR RS;RS为0和RW为1,就是读取忙标志AC地址内容的指令执行,RW为1就是读,为0就是写
       SETB RW
       SETB E;E从0到1变化,看时序图就能明白
       JB P0.7,BUSY;如果p1.7为高电平表示忙绿就循环等待,忙标志位,高电平表示忙,此时模块不能接收命令或数据,如果为低电平表示不忙。
       RET  
       
    DATAS:
       SETB E
       SETB RS
       CLR RW
       CLR E
       RET
       
    DELAY:
       MOV R2,#3
    DE:
       MOV R3,#255
       DJNZ R3,$
       DJNZ R2,DE
       RET
       
    ;字节读
    ISP_READ:
       MOV 29H,#9
       MOV 27H,#60H
       MOV 28h,#00H
    READLP:
       MOV ISP_ADDRH,#20h   ;地址高字节
       MOV ISP_ADDRL,28H   ;地址低字节
       CLR EA
       MOV ISP_CONTR,#WAIT_TIME
       MOV ISP_CONTR,#10000000B
       MOV ISP_CMD,#ISP_IAP_BYTE_READ
       MOV ISP_TRIG,#46H
       MOV ISP_TRIG,#0B9H
       NOP
       MOV A,ISP_DATA
       SUBB A,#10
       JC READLP2
       MOV A,#00
       MOV ISP_DATA,A
    READLP2:
       MOV R0,27H
       MOV @R0,ISP_DATA
       INC 27H
       INC 28h
       ;以下语句可不用,只是出于安全考虑而已
       SETB EA
       DJNZ 29H,READLP
       RET
    
    ;字节编程
    ISP_WRITE:
       MOV 29H,#9
       MOV 27H,#60H
       MOV 28H,#00H
    WRITELP:
       MOV R0,27H
       MOV A,@R0
       MOV ISP_DATA,A
       MOV ISP_ADDRH,#20h      ;地址高字节   
       MOV ISP_ADDRL,28H      ;地址低字节
       CLR EA
       MOV ISP_CONTR,#WAIT_TIME
       MOV ISP_CONTR,#10000000B
       MOV ISP_CMD,#ISP_IAP_BYTE_PROGRAM
       MOV ISP_TRIG,#46H
       MOV ISP_TRIG,#0B9H
       NOP
       INC 27H
       INC 28H
       ;以下语句可不用,只是出于安全考虑而已
       SETB EA
       DJNZ 29H,WRITELP
       RET
       
    ;扇区擦除
    ISP_ERASE:
       MOV ISP_ADDRH,#20h   ;扇区起始地址高字节
       MOV ISP_ADDRL,#00h   ;扇区起始地址低字节
       ;第1扇区:2000h-21ffh   第2扇区:2200h-23ffh
       ;第3扇区:2400h-25ffh   第4扇区:2600h-27ffh
       ;第5扇区:2800h-29ffh   第6扇区:2a00h-2bffh
       ;第7扇区:2c00h-2dffh   第8扇区:2e00h-2fffh
       CLR EA
       MOV ISP_CONTR,#WAIT_TIME
       MOV ISP_CONTR,#10000000B
       MOV ISP_CMD,#ISP_IAP_SECTOR_ERASE
       MOV ISP_TRIG,#46H
       MOV ISP_TRIG,#0B9H
       NOP
       ;以下语句可不用,只是出于安全考虑而已
    
       SETB EA
       RET
    
    KEYIN:
       DB 01H,02H,03H,04H,05H,06H,07H,08H
    NUMBER:
       DB 030H,31H,32H,33H,34H,35H,36H,37H,38H,39H,20H
    PASSWORDTRUE:
       DB 20H,50H,61H,73H,73H,77H,6FH,72H,64H,20H,74H,72H,75H,65H,20H,20H
    PASSWORDFALSE:
       DB 50H,61H,73H,73H,77H,6FH,72H,64H,20H,66H,61H,6CH,73H,65H,30H
    INPUTPASSWORD:
       DB 20H,67H,75H,67H,75H,6FH,62H,61H,6FH,20H,49H,6EH,0F0H,75H,74H,20H
    PLEASEENTER:
       DB 20H,20H,50H,6CH,65H,61H,73H,65H,20H,45H,6EH,74H,65H,72H,20H,20H
    PASSWORDRESET:
       DB 20H,50H,61H,73H,73H,77H,6FH,72H,64H,20H,72H,65H,73H,65H,74H,20H
    PLAYRESETOK:
       DB 20H,72H,65H,73H,65H,74H,20H,20H,73H,75H,63H,63H,65H,73H,73H,20H
    DOYOUSETTAB:
       DB 20H,20H,44H,6FH,20H,79H,6FH,75H,20H,72H,65H,73H,65H,74H,20H,20H
    YESORNOTAB:
       DB 20H,20H,20H,59H,65H,73H,20H,20H,20H,20H,20H,4EH,6FH,20H,20H,20H
       END
    
    

    单片机EEROM断电保存密码:

    EEROM在写数据到EEROM时(我使用的是STC-AT89C52RC),需要进行擦写,起始擦写就是往扇区写入1,必须擦写后才能写入数据,其实内部就是与门结构。写入的数据有0,就与,为1就不变。

    ;跳线设置:默认
    ;晶振11.0592
    ;STC89C52单片机内部EEPROM测试
    ;按一下51hei学习板上的S4键,LED灯D1点亮,再按一下熄灭,关机撤掉电源后下次开机可状态保存.
    ;注意本程序只保存D1灯的状态,其他的几个灯初始为何值就是何值.
    
    ;定义EEPROM特殊功能寄存器
    ISP_DATA DATA 0E2H
    ISP_ADDRH DATA 0E3H
    ISP_ADDRL DATA 0E4H
    ISP_CMD DATA 0E5H
    ISP_TRIG DATA 0E6H
    ISP_CONTR DATA 0E7H
    
    ;定义ISP/IAP命令及等待时间
    ISP_IAP_BYTE_READ EQU 1
    ISP_IAP_BYTE_PROGRAM EQU 2
    ISP_IAP_SECTOR_ERASE EQU 3
    WAIT_TIME EQU 0
    K1 BIT P3.6
    LED BIT P0.7
    
    ORG 0000H
    AJMP MAIN
    ORG 0030H
    
    MAIN:
       clr P1.4  
       ACALL ISP_READ
       MOV P0,A
    LOOP:
    
    A1:
       ACALL DELAY
       JNB K1,A1
       CPL LED
       MOV A,P0
       ACALL ISP_ERASE
       ACALL ISP_WRITE
    NEXT:
       AJMP LOOP
    
    ;字节读
    ISP_READ:
    MOV ISP_ADDRH,#20h   ;地址高字节
    MOV ISP_ADDRL,#00h   ;地址低字节
    CLR EA
    MOV ISP_CONTR,#WAIT_TIME
    MOV ISP_CONTR,#10000000B
    MOV ISP_CMD,#ISP_IAP_BYTE_READ
    MOV ISP_TRIG,#46H
    MOV ISP_TRIG,#0B9H
    NOP
    MOV A,ISP_DATA
    ;以下语句可不用,只是出于安全考虑而已
    MOV ISP_CONTR,#00000000B
    MOV ISP_CMD,#00000000B
    MOV ISP_TRIG,#00000000B
    MOV ISP_ADDRH,#0
    MOV ISP_ADDRL,#0
    SETB EA
    RET
    
    ;字节编程
    ISP_WRITE:
    MOV ISP_DATA,A
    MOV ISP_ADDRH,#20h      ;地址高字节   
    MOV ISP_ADDRL,#00h      ;地址低字节
    CLR EA
    MOV ISP_CONTR,#WAIT_TIME
    MOV ISP_CONTR,#10000000B
    MOV ISP_CMD,#ISP_IAP_BYTE_PROGRAM
    MOV ISP_TRIG,#46H
    MOV ISP_TRIG,#0B9H
    NOP
    ;以下语句可不用,只是出于安全考虑而已
    MOV ISP_CONTR,#00000000B
    MOV ISP_CMD,#00000000B
    MOV ISP_TRIG,#00000000B
    MOV ISP_ADDRH,#0
    MOV ISP_ADDRL,#0
    SETB EA
    RET
    
    ;扇区擦除
    ISP_ERASE:
    MOV ISP_ADDRH,#20h   ;扇区起始地址高字节
    MOV ISP_ADDRL,#00h   ;扇区起始地址低字节
    ;第1扇区:2000h-21ffh   第2扇区:2200h-23ffh
    ;第3扇区:2400h-25ffh   第4扇区:2600h-27ffh
    ;第5扇区:2800h-29ffh   第6扇区:2a00h-2bffh
    ;第7扇区:2c00h-2dffh   第8扇区:2e00h-2fffh
    CLR EA
    MOV ISP_CONTR,#WAIT_TIME
    MOV ISP_CONTR,#10000000B
    MOV ISP_CMD,#ISP_IAP_SECTOR_ERASE
    MOV ISP_TRIG,#46H
    MOV ISP_TRIG,#0B9H
    NOP
    ;以下语句可不用,只是出于安全考虑而已
    MOV ISP_CONTR,#00000000B
    MOV ISP_CMD,#00000000B
    MOV ISP_TRIG,#00000000B
    MOV ISP_ADDRH,#0
    MOV ISP_ADDRL,#0
    SETB EA
    RET
    
    DELAY:
    MOV R6,#14H
    DL1:MOV R7,#19H
    DJNZ R7,$
    DJNZ R6,DL1
    RET
    
    END
    
    
    
  • 相关阅读:
    js的同步和异步
    事件三
    事件2
    JS作用域题
    游戏之乐
    NSTimer(2)
    NSTimer
    理解 Objective-C Runtime
    iOS系统安全机制概览
    Which is the best of GCD, NSThread or NSOperationQueue?
  • 原文地址:https://www.cnblogs.com/guguobao/p/9901142.html
Copyright © 2020-2023  润新知