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

交通灯汇编代码:

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

猜你喜欢

转载自www.cnblogs.com/guguobao/p/9901142.html