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

📄 ykmd.asm

📁 采用AT89C51单片机进行编写
💻 ASM
字号:

;********************************************************************************
;*  步进电机端口:P1.0,P1.1,P1.2,P1.3,遥控器接口p3.2喇叭p3.7     		*
;*  硬件:此程序在本公司xlisp系列单片机实验仪运行通过   			*
; 按遥控器6号 键按下,步进电机正转,LCD1602  显示 >>>> 。			*
;14号键按下步进电机反转,显示 <<<< 。                                      	*
;1号键按下步进电机停止转动,显示 STOP 。                                	*
;步进电机转动时必须先按1停止后,才能切换转动方向             			*                   
;********************************************************************************
;* 【版权】 Copyright(C)深圳学林电子有限公司 www.51c51.com  All Rights Reserved *
;* 【声明】 此程序仅用于学习与参考,引用请注明版权和作者信息!                  *
;********************************************************************************
        IRCOM   EQU  30H       ;30H-33H IR使用
        LCD_X   EQU  36H       ;LCD 地址变量
        IRIN    EQU  P3.2
        BEEP    EQU  P3.7
        RELAY   EQU  P1.3
        LCD_RS  EQU  P2.0
        LCD_RW  EQU  P2.1
        LCD_EN  EQU  P2.2
        STOP_BJ BIT  20H.0   ;停止标记位
;---------------------------------------------------------
         ORG  0000H
         JMP  MAIN
         ORG  0003H         ;外部中断INT0入口地址
         JMP  IR_IN
         ORG  0030H
;---------------------------------------------------------
MAIN:
          MOV  SP,#60H
          MOV  P1,#0F0H      ;关闭步进电机
          MOV  A,#00H
          MOV  R0,#30H
LOOP0:
          MOV  @R0,A          ;30H-36H清零
          INC  R0
          CJNE R0,#37H,LOOP0
          CLR  STOP_BJ

          MOV  IE,#81H       ;允许总中断中断,使能INT0外部中断
          MOV  TCON,#01H     ;触发方式为脉冲负边沿触发

          SETB  IRIN
          CALL  SET_LCD
          MOV  DPTR,#BJ1        ;显示停止标记
          CALL  RUN_BJ
LOOP1:
          MOV  A,IRCOM+2
          CJNE  A,#1DH,LOOP2    ;UP键按下
          MOV  DPTR,#BJ2
          CALL  RUN_BJ          ;显示正转标记
          CALL  FFW
          MOV  DPTR,#BJ1        ;显示停止标记
          CALL  RUN_BJ
LOOP2:
          CJNE  A,#12H,LOOP3    ;DOWN键按下
          MOV  DPTR,#BJ3
          CALL  RUN_BJ          ;显示反转标记
          CALL  REV
          MOV  DPTR,#BJ1        ;显示停止标记
          CALL  RUN_BJ
LOOP3:
          JMP   LOOP1
;---------------------------------------------------------
;  LCD 初始化设置
;---------------------------------------------------------
SET_LCD:
          CLR  LCD_EN
          CALL  INIT_LCD     ;初始化 LCD
          CALL  DELAY1
          MOV  DPTR,#INFO1   ;指针指到显示信息1
          MOV  A,#1          ;显示在第一行
          CALL  LCD_SHOW
          MOV  DPTR,#INFO2   ;指针指到显示信息2
          MOV  A,#2          ;显示在第二行
          CALL  LCD_SHOW
          RET
INFO1:  DB  " REMOTE CONTROL ",0  ;LCD 第一行显示信息
INFO2:  DB  " IR: --H        ",0  ;LCD 第二行显示信息
;---------------------------------------------------------
;LCD 初始化
;---------------------------------------------------------
INIT_LCD:
          MOV  A,#38H     ;双列显示,字形5*7点阵
          CALL  WCOM
          CALL  DELAY1
          MOV  A,#38H     ;双列显示,字形5*7点阵
          CALL  WCOM
          CALL  DELAY1
          MOV  A,#38H     ;双列显示,字形5*7点阵
          CALL  WCOM
          CALL  DELAY1
          MOV  A,#0CH     ;开显示,关光标,
          CALL  WCOM
          CALL  DELAY1
          MOV  A,#01H     ;清除 LCD 显示屏
          CALL  WCOM
          CALL  DELAY1
          RET
;---------------------------------------------------------
;LCD显示信息字符
;---------------------------------------------------------
LCD_SHOW:

          CJNE  A,#1,LINE2  ;判断是否为第一行
  LINE1:
          MOV  A,#80H       ;设置 LCD 的第一行地址
          CALL  WCOM        ;写入命令
          CALL  CLR_LINE    ;清除该行字符数据
          MOV  A,#80H       ;设置 LCD 的第一行地址
          CALL  WCOM        ;写入命令
          JMP  FILL

  LINE2:
          MOV  A,#0C0H      ;设置 LCD 的第二行地址
          CALL  WCOM        ;写入命令
          CALL  CLR_LINE    ;清除该行字符数据
          MOV  A,#0C0H      ;设置 LCD 的第二行地址
          CALL  WCOM
  FILL:
          CLR  A            ;填入字符
          MOVC  A,@A+DPTR   ;由消息区取出字符
          CJNE  A,#0,LC1    ;判断是否为结束码
          RET
  LC1:
          CALL  WDATA       ;写入数据
          INC  DPTR         ;指针加1
          JMP  FILL         ;继续填入字符
          RET
;---------------------------------------------------------
;清除一行 LCD 的字符
;---------------------------------------------------------
CLR_LINE:
          MOV  R0,#24
   CL1:
          MOV  A,#' '
          CALL  WDATA
          DJNZ  R0,CL1
          RET
;---------------------------------------------------------
;标记字符写入子程序
;---------------------------------------------------------
RUN_BJ:
          MOV  A,#0CAH        ;指定写入地址
          CALL WCOM
          MOV  R1,#0
          MOV  R0,#4          ;写4个标记字符
RUN_BJ1:
          MOV  A,R1
          MOVC A,@A+DPTR      ;读出要写的标记字符
          CALL  WDATA         ;写入标记字符
          INC R1
          DJNZ  R0,RUN_BJ1    ;没有写完,继续
          RET
BJ1:
      DB  "STOP"              ;停止标记
BJ2:
      DB  ">>>>"              ;正转标记
BJ3:
      DB  "<<<<"              ;反转标记
;-----------------------------------------------------
; 写指令子程序
;RS=L,RW=L,D0-D7=指令码,E=高脉冲
;-----------------------------------------------------
WCOM:
          MOV  P0,A
          CLR LCD_RS
          CLR LCD_RW
          SETB LCD_EN
          CALL  DELAY0
          CLR LCD_EN
          RET
;---------------------------------------------------------
;写数据子程序
;RS=H,RW=L,D0-D7=数据,E=高脉冲
;---------------------------------------------------------
WDATA:
          MOV   P0,A
          SETB  LCD_RS
          CLR   LCD_RW
          SETB  LCD_EN
          CALL  DELAY0
          CLR   LCD_EN
          RET

DELAY0:   MOV  R7,#250      ;延时500微秒
          DJNZ  R7,$
          RET
;---------------------------------------------------------
;在 LCD 第二行显示字符
;A=ASC DATA, B=LINE X POS
;---------------------------------------------------------
LCDP2:                    ;在LCD的第二行显示字符
         PUSH  ACC        ;
         MOV  A,B         ;设置显示地址
         ADD  A,#0C0H     ;设置LCD的第二行地址
         CALL  WCOM       ;写入命令
         POP  ACC         ;由堆栈取出A
         CALL  WDATA      ;写入数据
         RET
;---------------------------------------------------------
; IR 译码子程序
; R0---存放IR数据
; R2---高电平宽度的计数值
; R3--- 一字节需接收8位计数
;---------------------------------------------------------
IR_IN:
          CLR EA         ;暂时关闭CPU的所有中断请求
          PUSH  ACC
          PUSH  PSW
          SETB  PSW.3     ;选择工作寄存器组1
          CLR   PSW.4
          MOV   R0,#IRCOM
          MOV  R4,#30
IR_IN1:
          CALL  DEL            ;延时4ms,去干扰再确认IR信号是否出现
          DJNZ  R4,IR_IN1
          JB  IRIN,IR_END      ;如果IRIN=1没有IR信号出现,则退出
WAIT_H:
          JB  IRIN,WAIT_H1     ;等IR变为高电平避开9ms低电平引导脉冲
          CALL  DEL
          JMP   WAIT_H
WAIT_H1:
          MOV  R3,#0            ;8位数清为0
WAIT_L:
          JNB  IRIN,WAIT_H2     ;等 IR 变为低电平
          CALL  DEL
          JMP  WAIT_L
WAIT_H2:
          JB  IRIN,IR_COUN    ;等 IR 变为高电平
          CALL  DEL
          JMP  WAIT_H2
IR_COUN:
          MOV  R2,#0         ;对高电平进行0.14ms计数
IR_COUN1:
          CALL  DEL
          JB  IRIN, IR_COUN2  ;等 IR 变为高电平
                             ;IR=0,检查R2中的计数值
          MOV  A,#8
          CLR  C             ;清借位标志
          SUBB  A,R2         ;判断高低位
                             ;若C=0,则解码为“0"
                             ;若C=1,则解码为“1"
          MOV  A,@R0         ;取出原先的数据
          RRC  A             ;将借位标志C移入A
          MOV  @R0,A         ;处理完一位,将数据写入
          INC  R3            ;接收字节计数加1
          CJNE  R3,#8,WAIT_L ;需处理完8位
          MOV  R3,#0
          INC  R0              ;存放IR数据值加1
          CJNE  R0,#IRCOM+4,WAIT_L   ;收集到4字节了
          JMP   IR_SHOW
IR_COUN2:
          INC  R2
          CJNE  R2,#20,IR_COUN1    ;0.14ms计数过长,则自动离开
IR_END:
          POP  PSW
          POP  ACC
          SETB  EA
          RETI
;---------------------------------------------------------
IR_SHOW:
          MOV A,IRCOM+2
          CJNE  A,#10H,IR_SHOW1      ;是否为遥控的K1键
          SETB STOP_BJ
IR_SHOW1:
          CPL A                     ;将22H取反后和23H比较
          CJNE A,IRCOM+3,IR_SHOW2   ;如果不等表示接收数据发生错误,放弃。
          CALL   CONV
          CALL  BEEP_BL             ;蜂鸣器鸣响表示解码成功
IR_SHOW2:
          JMP IR_END
;---------------------------------------------------------
;转换为 ASCII 码并显示
;---------------------------------------------------------
CONV:
          MOV   LCD_X,#5        ;设置显示起始位置
          MOV   A,IRCOM+2
          ANL   A,#0F0H      ;取出高四位二进制数
          SWAP  A            ;高四位与低四位互换
          PUSH  ACC          ;压入堆栈
          CLR   C            ;C=0
          SUBB  A,#0AH       ;减10
          POP   ACC          ;弹出堆栈
          JC    ASCII0       ;该数小于10,转ASCII0
          ADD   A,#07H       ;大于10的数加上37H
ASCII0:   ADD   A,#30H       ;小于10的数加上30H
          MOV   B,LCD_X
          CALL  LCDP2
          MOV   A,IRCOM+2
          ANL   A,#0FH        ;取出低四位二进制数
          PUSH  ACC
          CLR   C
          SUBB  A,#0AH        ;减10
          POP   ACC
          JC    ASCII1        ;该数小于10,转ASCII0
          ADD   A,#07H        ;大于10的数加上37H
ASCII1:   ADD   A,#30H        ;小于10的数加上30H
          INC   LCD_X
          MOV   B,LCD_X
          CALL  LCDP2
          RET
;---------------------------------------------------------
;蜂鸣器响一声子程序
;---------------------------------------------------------
BEEP_BL:
         MOV  R6,#100
  BL1:   CALL  DEX1
         CPL  BEEP
         DJNZ  R6,BL1
        ; MOV  R5,#25
        ; CALL  DELAY
         RET
 DEX1:   MOV  R7,#180
 DEX2:   NOP
         DJNZ  R7,DEX2
         RET
 DELAY:                    ;延时R5×10MS
         MOV  R6,#50
  D1:    MOV  R7,#100
         DJNZ  R7,$
         DJNZ  R6,D1
         DJNZ  R5,DELAY
         RET
;---------------------------------------------------------
; 延时0.14ms
; IR解码使用
;11.0592MHz,1.085us×(64×2)+2=140us
;---------------------------------------------------------
DEL:
         MOV  R7,#64
         DJNZ  R7,$
         RET
;---------------------------------------------------------
;延时5MS
;LCD1602延时使用
;---------------------------------------------------------
DELAY1:
         MOV  R6,#25
  DL2:
         MOV  R7,#100
         DJNZ  R7,$
         DJNZ  R6,DL2
         RET
;---------------------------------------------------------
; 步进电机正转子程序
;---------------------------------------------------------
FFW:
           MOV R0,#00H
FFW1:
           JB  STOP_BJ,FFW2   ;STOP_BJ=1,步进电机停止
           MOV P1,#0F0H
           MOV A,R0
           MOV DPTR,#TABLE_F  ;选择工作方式   
           MOVC A,@A+DPTR
           MOV P1,A
           LCALL DELAY2
           INC R0
           CJNE  A,#0FFH,FFW1
           JMP  FFW
FFW2:
           CLR  STOP_BJ
           MOV P1,#0F0H
           RET
;---------------------------------------------------------
; 步进电机反转子程序
;---------------------------------------------------------
REV:
           MOV R0,#00H
REV1:
           JB  STOP_BJ,REV2    ;STOP_BJ=1,步进电机停止
           MOV P1,#0F0H
           MOV A,R0
           MOV DPTR,#TABLE_R    ;选择工作方式  
           MOVC A,@A+DPTR
           MOV P1,A
           CALL DELAY2
           INC R0
           CJNE  A,#0FFH,REV1
           JMP  REV
REV2:
           CLR  STOP_BJ
           MOV P1,#0F0H
           RET
;---------------------------------------------------------
;延时子程序
;可调整步进电机的转速
;---------------------------------------------------------
DELAY2:
           MOV R7,#40
DEL1:      MOV R6,#248
           DJNZ R6,$
           DJNZ R7,DEL1
           RET
;---------------------------------------------------------
; 单双八拍工作方式
;---------------------------------------------------------
TABLE_F:  ;正转表
          DB  0F1H,0F3H,0F2H,0F6H,0F4H,0FCH,0F8H,0F9H
          DB  0FFH
TABLE_R:  ;反转表
          DB  0F9H,0F8H,0FCH,0F4H,0F6H,0F2H,0F3H,0F1H
          DB  0FFH
;---------------------------------------------------------
; 双四拍工作方式
;---------------------------------------------------------
TABLE1:
        DB   0F3H,0F6H,0FcH,0F9H  ;正转表
        DB   0FFH  ;正转结束
TABLE2:
        DB   0F9H,0FCH,0F6H,0F3H  ;反转表
        DB   0FFH  ;反转结束
;-------------------------------------------------------
        END

⌨️ 快捷键说明

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