1. 程式人生 > >單片機期末實訓---- 密碼鎖和交通燈

單片機期末實訓---- 密碼鎖和交通燈

dff 1.3 all traffic 一次 let rom 從0到1 掃描端口

交通燈匯編代碼:

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

單片機期末實訓---- 密碼鎖和交通燈