找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1021|回复: 1
收起左侧

单片机汇编代码有什么问题?按键没法用,电机类型调节也不太对

[复制链接]
ID:1085671 发表于 2023-6-24 22:06 | 显示全部楼层 |阅读模式
;================定义字符===============================
          RS BIT P2.6                               ;RS=P2.6
          RW BIT P2.5                               ;RW=P2.5
          E BIT P2.7                                ;E=P2.7
                  DATALINE EQU P3.7                         ;定义引脚
          FLAG1 EQU 20H.0                           ;20H单元可位寻址区
          KEY1 BIT P3.0
                  KEY2 BIT P3.1
                  KEY3 BIT P3.2
                  KEY4 BIT P3.3
          Y EQU 60H                                 ;定义运行与否Y存储单元
          M EQU 61H                                 ;定义模式M存储单元
          S EQU 62H                                 ;定义风速S存储单元
          L EQU 63H                                 ;定义类型L存储单元
          DDJ BIT P1.0                              ;DDJ=P1.0
;====================主程序========================
              ORG 0000H
          AJMP MAIN
          ORG 000BH     ;T0中断入口
          LJMP TIME0
                  ORG 001BH
                  LJMP TIME1    ;T1中断入口
                  ORG 0030H
MAIN:     CLR A
          MOV B,#00H
                  MOV 25H,#00H
                  MOV 26H,#00H
                  MOV 27H,#00H
                  MOV 28H,#00H
                  MOV 29H,#00H
          MOV Y,#0                           ;Y=0,不运行
          MOV M,#1                           ;模式为1,手动
          MOV S,#1                           ;风速为0
          MOV L,#1                           ;类型为1,正常
          CLR DDJ                            ;将DDJ置0,风扇不转动
          LCALL LCDRESET                     ;液晶显示器初始化
          LCALL B20_INIT                     ;DS18B20初始化
                  LCALL FBLCHANGE                    ;改变温度分辨率为9位
                  LCALL TMAIN                        ;读取温度并显示
          LCALL KEYA
                  JMP $
                          
;======================扫描按键程序=================================                          
KEYA:   MOV A,M
                CJNE A,#2,KEYB
                LCALL TMAIN
                LCALL WENKONG
KEYB:   MOV A,#0FFH                 ;扫描按键并处理
        MOV P3,A                    ;P3口置1,使其为输入模式
        JNB KEY1,D1                 ;KEY1=0,说明K1键按下,转到D1
        JNB KEY2,D2                 ;KEY2=0,说明K1键按下,转到D2
        JNB KEY3,D3                 ;KEY4=0,说明K1键按下,转到D4
                LJMP KEYA                   ;KEY3=0,说明K1键按下,转到D3
        JNB KEY4,D4      
D1:     LCALL DELAY12ms             ;延时12ms,消抖
        JNB KEY1,K1                 ;再次判断按键状态,若仍为0,转到K1
                LJMP KEYA                    ;若不为0,返回继续查询
D2:     LCALL DELAY12ms             ;延时12ms,消抖
        JNB KEY2,K2                 ;再次判断按键状态,若仍为0,转到K2
                LJMP KEYA                    ;若不为0,返回继续查询
D3:     LCALL DELAY12ms             ;延时12ms,消抖
        JNB KEY3,K3                 ;再次判断按键状态,若仍为0,转到K3
                LJMP KEYA                    ;若不为0,返回继续查询
D4:     LCALL DELAY12ms             ;延时12ms,消抖
        JNB KEY4,K4                 ;再次判断按键状态,若仍为0,转到K4
                LJMP KEYA                    ;若不为0,返回继续查询
K1:     LCALL EK1                   ;调按键K1处理子程序EK1
        LJMP KEYA
K2:     LCALL EK2                   ;调按键K2处理子程序EK2
        LJMP KEYA
K3:     LCALL EK3                   ;调按键K3处理子程序EK3
        LJMP KEYA
K4:     LCALL EK4                   ;调按键K4处理子程序EK4
        LJMP KEYA
;===================== K1处理子程序EK1======================
EK1:    JNB KEY1,EK1                ;再次判断KEY1状态,KEY1=0,按键K1未释放,等待
;之后判断风扇工作状态,如果是运行状态,则按下K1后停止转动;若是停止状态,则按下K2后开始转动。

        MOV A,Y                     ;P3.1=1,按键K1已释放,则执行按键K1功能
        CJNE A,#0,STOP              ;Y不为0,说明风扇在转动,转到STOP,使其停止转动
        MOV Y,#01H              ;Y=0,说明风扇不转动,之后判断风扇停止前的状态,逐一恢复
        MOV A,Y
        MOV P0,#82H
        LCALL LOAD
        ORL A,#30H
        LCALL SENDDATA              ;改变显示器上的Y=1
        MOV A,M
        CJNE A,#1,EK11              ;判断M的状态,M不为1,则为温控模式,转到EK11
        MOV A,S                     ;M=1,则为手动模式,继续执行,判断S、L的状态
        CJNE A,#1,EK12
        LCALL DANG1
        LJMP EK14
   EK12:CJNE A,#2,EK13
        LCALL DANG2
        LJMP EK14
   EK13:LCALL DANG3                   ;判断了S的状态并恢复
   EK14:MOV A,L
        CJNE A,#1,EK15
        LCALL ZHENGCHANG
        LJMP EK17
   EK15:CJNE A,#2,EK16
        LCALL ZIRAN
        LJMP EK17
   EK16:LCALL SHUIMIAN
        LJMP EK17                   ;判断了L的状态并恢复
   EK11:LCALL WENKONG                  ;温控模式        
        LJMP EK17
   STOP:MOV Y,#0                    ;停止运行程序
       MOV A,Y
       MOV P0,#82H
        LCALL LOAD
        ADD A,#'0'
        LCALL SENDDATA              ;改变显示器上的Y=0
        CLR DDJ                    ;风扇停止转动
   EK17:RET

;=============================K2处理子程序EK2===========================
EK2:    JNB KEY2,EK2                ;再次判断KEY2状态,KEY2=0,按键K2未释放,等待
;判断风扇模式,若自动,则转为手动;若手动,则转为自动
        MOV A,Y                   ;P3.0=1,按键K2已释放,则执行按键K2功能
        CJNE A,#1,EK21           ;判断风扇运行情况,若风扇不运行,此键无效,跳转到EK21     
        MOV A,M                  ;Y=1,风扇运行,判断M的状态
        CJNE A,#1,EK22           ;M=2,风扇为自动模式,则转到EK22,变为手动
        MOV M,#2                 ;M=1,风扇为手动模式,改为自动温控
        MOV A,M
        MOV P0,#86H
        LCALL LOAD
        ADD A,#'0'
        LCALL SENDDATA           ;改变显示器上M=2
        LCALL WENKONG
        LJMP EK21
EK22: MOV M,#1                 
        MOV A,M
        MOV P0,#86H
        LCALL LOAD
        ADD A,#'0'
        LCALL SENDDATA            ;改变显示器上M=1
        MOV A,S                   ;之后判断S、L的状态并恢复
        CJNE A,#1,EK23
        LCALL DANG1
        LJMP EK25
   EK23:CJNE A,#2,EK24
        LCALL DANG2
        LJMP EK25
   EK24:LJMP DANG3                   ;判断了S的状态并恢复
   EK25:MOV A,L
        CJNE A,#1,EK26
        LCALL ZHENGCHANG
        LJMP EK21
   EK26:CJNE A,#2,EK27
        LCALL ZIRAN
        LJMP EK21
   EK27:LCALL SHUIMIAN              ;判断了L的状态并恢复


   EK21: RET
;========================= K3处理子程序EK3=====================
EK3:    JNB KEY3,EK3                ;再次判断KEY3状态,KEY3=0,按键K3未释放,等待
;判断风扇是否运行,不允许此键无效。判断风扇模式,手动模式下风扇变速,自动模式下此键无效。判断当前风速,弱→中、中→强、强→弱
        MOV A,Y                     ;P3.2=1,按键K3已释放,则执行按键K3功能
        CJNE A,#1,EK31              ;Y=0,风扇不运行,此键无效跳转到EK31
        MOV A,M
        CJNE A,#1,EK31              ;M=2,自动模式,此键无效,跳转到EK31
        MOV A,S
        CJNE A,#1,EK32              ;S不为1,跳转到EK32
        MOV S,#2                    ;S=1,风速为1档,改为2档
        MOV A,S
        MOV P0,#8AH
        LCALL LOAD
        ADD A,#'0'
        LCALL SENDDATA              ;改变显示器S=2
        LCALL DANG2                 ;调风速
        LJMP EK31
  EK32: CJNE A,#2,EK33               ;S不为2,跳转到EK33
        MOV S,#3                     ;S=2,风速为2档,调为3档
        MOV A,S
        MOV P0,#8AH
        LCALL LOAD
        ADD A,#'0'
        LCALL SENDDATA               ;改变显示器上S=3
        LCALL DANG3
        LJMP EK31
EK33: MOV S,#1                     ;S=3,风速为3档,调到1档
        MOV A,S
        MOV P0,#8AH
        LCALL LOAD
        ADD A,#'0'
        LCALL SENDDATA               ;改变显示器上S=1
        LCALL DANG1
EK31: RET
;============================== K4处理子程序EK4=============================
EK4:    JNB KEY4,EK4                ;再次判断KEY4状态,KEY4=0,按键K4未释放,等待
;判断风扇模式,手动模式下风扇变类型, 判断当前模式,正常→睡眠、睡眠→自然、自然→正常
        MOV A,Y                     ;P3.3=1,按键K4已释放,则执行按键K4功能
        CJNE A,#1,EK41              ;Y=0,风扇不运行,此键无效跳转到EK41
        MOV A,M
        CJNE A,#1,EK41              ;M=2,自动模式,此键无效,跳转到EK41
        MOV A,L
        CJNE A,#1,EK42
        MOV L,#2
        MOV A,L
        MOV P0,#8EH
        LCALL LOAD
        ADD A,#'0'
        LCALL SENDDATA
        LCALL SHUIMIAN
        LJMP EK41
  EK42: CJNE A,#2,EK43
        MOV L,#3
        MOV A,L
        MOV P0,#8EH
        LCALL LOAD
        ADD A,#'0'
        LCALL SENDDATA
        LCALL ZIRAN
        LJMP EK41
EK43: MOV L,#1
        MOV A,L
        MOV P0,#8EH
        LCALL LOAD
        ADD A,#'0'
        LCALL SENDDATA
        LCALL ZHENGCHANG
EK41:   RET
;==================== 12ms延时子程序====================
DELAY12ms:  MOV R7,#26                    ;12ms延时子程序
DEL3:   MOV R6,#200
DJNZ    R6,$
DJNZ    R7,DEL3
RET
;=====================温度控制子程序====================
WENKONG:MOV A,29H
        SUBB A,#20
                JNC WEN1
                MOV S,#1
                MOV A,S
                MOV P0,#8AH
                LCALL LOAD
                ADD A,#'0'
                LCALL SENDDATA
                LCALL DANG1
                LJMP WEN2
   WEN1:MOV A,29H
                SUBB A,#20
                JNC WEN3
                MOV S,#2
                MOV A,S
                MOV P0,#8AH
                LCALL LOAD
                ADD A,#'0'
                LCALL SENDDATA
                LCALL DANG2
                LJMP WEN2
   WEN3:MOV S,#3
                MOV A,S
                MOV P0,#8AH
                LCALL LOAD
                ADD A,#'0'
                LCALL SENDDATA
                LCALL DANG3
   WEN2:RET
;===================调速程序DANG1、DANG2、DANG3=========
DANG1:MOV SP,#70H
      SETB DDJ
      MOV TMOD,#11H
      MOV TH0,#0D8H
      MOV TL0,#0F0H
      SETB ET0
      SETB EA
      SETB TR0
      RET
DANG2:MOV SP,#70H
      SETB DDJ
      MOV TMOD,#11H
      MOV TH0,#0B1H
      MOV TL0,#0E0H
      SETB ET0
      SETB EA
      SETB TR0
      RET
DANG3:SETB DDJ
      CLR TR0
      RET

;===================T0中断服务子程序===================
TIME0:CLR EA
      PUSH PSW
      PUSH Acc
      SETB EA
          MOV A,S
      CJNE A,#1,TIME01
      JB DDJ,TIME02
      CPL DDJ
      MOV TH0,#0D8H
      MOV TL0,#0F0H
      LJMP TIME03
TIME02:CPL DDJ
MOV TH0,#0B1H
MOV TL0,#0E0H
LJMP TIME03
TIME01:JB DDJ,TIME04
      CPL DDJ
      MOV TH0,#0B1H
      MOV TL0,#0E0H
      LJMP TIME03
TIME04: CPL DDJ
      MOV TH0,#0D8H
      MOV TL0,#0F0H
TIME03:CLR EA
      POP Acc
      POP PSW
      SETB EA
      RETI
;=======================模式改变程序 正常、睡眠、自然================
ZHENGCHANG:CLR TR1
           CLR ET1
                   RET
SHUIMIAN:  MOV TMOD,#11H
           MOV TH1,#3CH
                   MOV TL1,#0B0H
                   MOV R7,#80
                   SETB EA
                   SETB TR1
                   SETB ET1
                   SETB PT1
                   RET
   ZIRAN:  MOV TMOD,#11H
           MOV TH1,#3CH                                                                    
                   MOV TL1,#0B0H
                   MOV R7,#160
                   SETB EA
                   SETB TR1
                   SETB ET1
                   SETB PT1
                   RET
;=======================T1中断服务子程序=====================
TIME1:     CLR EA
           PUSH PSW
           PUSH Acc
           SETB EA
           MOV TH1,#3CH
                   MOV TL1,#0B0H
                   DJNZ R7,TIME11
                   MOV A,L
                   CJNE A,#2,TIME14
                   MOV R7,#80
                   LJMP TIME15
   TIME14: MOV R7,#160
   TIME15: MOV A,S
                   CJNE A,#3,TIME12
                   CPL DDJ
           LJMP TIME11
   TIME12: JB TR0,TIME13
                   SETB TR0
                   LJMP TIME11
   TIME13: CLR TR0
                   CLR DDJ
   TIME11: CLR EA
           POP Acc
           POP PSW
           SETB EA
           RETI
;=========================改变温度分辨率=====================
FBLCHANGE:
          LCALL B20_INIT                     ;复位
                  MOV A,#0CCH                        ;跳过ROM
                  LCALL WRITE
                  MOV A,#1FH                         ;改变分辨率为9
                  LCALL WRITE
                  RET
;========================= 液晶显示器初始化==================
LCDRESET:                                    
          MOV P0,#01H                               ;清屏(命令1)
          LCALL LOAD                                ;向LCD1602 写入命令字 01H
          MOV P0,#38H                               ;显示设定,显示两行(命令 6)
          LCALL LOAD                                ;向LCD1602写入命令字38H
          MOV P0,#0FH                             ;打开显示和光标,光标闪烁(命令4)
          LCALL LOAD                                ;向 LCD1602 写入命令字 0FH
          MOV P0,#14H                               ;光标右移(命令5)
          LCALL LOAD                                ;向LCD1602写人命令字 14H
          MOV P0,#80H                              ;光标回到第1行00H位置(命令8)
          LCALL LOAD                            ;向LCD1602写人命令字80H(80H+00H)
          MOV DPTR,#TABLE1                          ;DPTR指向TABLE1的表
          LCALL DISPLAY                             ;调用液晶屏显示字程序
          MOV P0,#0C0H                             ;光标回到第2行40H位置(命令8)
          LCALL LOAD                                ;向LCD1602写入命令字COH(80H+40H)
          MOV DPTR,#TABLE2                          ;DPTR指向 TABLE 2 的表
          CALL DISPLAY                              ;调用液晶屏显示字程序
          RET                                       ;返回主程序
;======================命令装载子程序,对液晶屏下命令LOAD=========================
LOAD:                                            
          CLR RS                                    ;RS=0,D0~D7 上的信号作为命令使用
          CLR RW                                    ;RW=0,写数据
          CLR E                                     ;E=0,E引脚电平由1变0,数据被读入
          LCALL DELAY                               ;延时
          SETB E                                    ;E=1,屏蔽DO~D7的数据
          RET                                       ;返回
;============================初始化显示子程序=============================
DISPLAY:                                       
          MOV R0,#00H                               ;取数据表时,用RO为指针
REFETCH:
          MOV A,R0
          MOVC A,@A+DPTR                            ;ACC装载数据表中的数据
          LCALL SENDDATA                           ;调用显示数据发送子程序
          INC R0                                    ;R0 增加 1
          CJNE R0,#10H,REFETCH                   ;如R0=10H,取表结束,否则跳回REFETCH
          RET                                       ;返回
;============================显示数据发送子程序===========================
SENDDATA:                                      
          MOV P0,A                                  ;显示数据从 P1口送出
          SETB RS                                   ;RS=1,D0~D7 上的信号作为显示数据使用
          CLR RW                                    ;RW=0,写数据
          CLR E                                     ;E=0,引脚电平由1变0,D0~D7数据被读入
          LCALL DELAY                               ;延时
          SETB E                                    ;E=1,屏蔽 D0~D7 的数据
          RET                                       ;返回
;=========================延时子程序=================================
DELAY:                                          
          MOV R5,#100
DEL1:     MOV R6,#20
DEL2:     DJNZ R6,DEL2
DJNZ R5,DEL1
RET
TABLE1:                                        ;数据表,第1行字符 .
DB'Y:0 M:1 S:1 L:1 '
TABLE2:                                        ;数据表,第2行字符
DB'    T:  . '
DB 0DFH
DB'C    '
;=====================温度读取+显示程序======================
TMAIN:     MOV SP,#30H
LCALL B20_INIT                  ;复位与检测DS18B20

SETB DATALINE
LCALL B20_INIT
JB FLAG1,START
RET
START:
MOV A,#0CCH                          ;跳过ROM 匹配
LCALL WRITE
MOV A,#44H                           ;发出温度转换命令
LCALL WRITE
;LCALL DISPLAYT
LCALL B20_INIT
MOV A,#0CCH                          ;跳过ROM 匹配
LCALL WRITE
MOV A,#0BEH                         ;发出读温度命令
LCALL WRITE
LCALL READ                          ;读温度数据
LCALL CTEMP                         ;计算温度值
LCALL DISPLAYT                         ;显示
RET


;=========================DS18B20初始化子程序======================
;DS18B20 复位与检测子程序
;FLAG1-1OKFLAG1=0ERROR
B20_INIT:
SETB DATALINE
NOP
ClR DATALINE
MOV R0,#0FBH                          ;主机发出延时600us 的复位低脉冲

B20_INIT1:
DJNZ R0,B20_INIT1

SETB DATALINE           ;拉高数据线

MOV R0,#25H
B20_INIT2:
JNB DATALINE,B20_INIT3 ;等待DS18B20 回应
DJNZ R0,B20_INIT2
           ;延时
B20_INIT3:
SETB FLAG1
MOV R0,#06BH              ;置标志位,表示DS18B20 存在

B20_INIT4:DJNZ R0,B20_INIT4              ;清标志位,表示DS18B20 不存在
          SETB DATALINE

RET
;====================读字节子程序READ============================
READ: MOV R4,#2                    ;  读取两个八位数据,外层循环次数
      MOV R1,#29H                  ;  立即数寻址给定存储位置
REE0: MOV R2,#8                    ;  给定数据位数,是内层循环次数
REE1: CLR C                        ;  进位标志位初始置零
      SETB C
      NOP
      NOP
      CLR DATALINE
      NOP
      NOP
      NOP
      SETB DATALINE                 ;  输入脉冲并持续2-3个机器周期
      MOV R3,#7                    
      DJNZ R3,$                     ;  延时,等待传感器响应
      MOV C,DATALINE                ;  按位读出
      MOV R3,#23
      DJNZ R3,$                     ;  延时
      RRC A                         ;  把C存入A内
      DJNZ R2,REE1                  ;  循环8次
      MOV @R1,A                     ;  在29H存储A,数据的低八位
      DEC R1                        ;  更换地址为28H,存储数据高八位
      DJNZ R4,REE0                  ;  循环2次
RET
;===================写字节子程序WRITE==========================
WRITE:
MOV R2,#8                    ;  写入八位二进制码,即循环次数
      CLR C                        ;  进位标志位初始置零
WR1:  CLR DATALINE                       ;  拉低总线为写入做准备
      MOV R3,#6
      DJNZ R3,$                    ;  延时
      RRC A                        ;  A的最低为给CY,使A从低到高写入从机
      MOV DATALINE,C              ;  将A又循环写入C,写入总线以输入到传感器
      MOV R3,#23
      DJNZ R3,$                    ;  延时
      SETB DATALINE                  ;  释放,表示此位写入完毕
      NOP
      DJNZ R2,WR1              ;  循环八次,一次写入八位
      SETB DATALINE                  ;  释放总线
RET
;=========================计算温度值CTEMP========================
CTEMP:
  MOV A,29H
  MOV 26H,29H
  MOV 25H,28H
  MOV 24H,28H                                       ;  在24H存储原始数据防止丢失
  MOV C,25H.7                                         ;  存储符号位进C
  JNC SN1                                 ;  判断温度的正负,正数则跳过转补码程序
  MOV A,25H
  CPL A                           ;  取补码,由于无效位置1,25H不必担心数据溢出
  MOV 25H,A
  MOV A,26H
  CPL A
  INC A                                                 ;  由于是末位,需要加一
  MOV 26H,A
  MOV 29H,26H
  MOV 28H,25H                            ;  在26H,25H中操作后放回29H,28H
SN1:
  MOV C,28H.0                         ;  正负温度到此均得到整数部分绝对值
  RRC A
  MOV C,28H.1
  RRC A
  MOV C,28H.2
  RRC A
  MOV C,28H.3                         ;  分别循环,存入A内,连续4次滤掉小数部分
  RRC A                               ;  可分析A内八位恰为整数部分(最高位为0)
  JC SL0
  MOV 27H,#00H
  AJMP SL5
SL0:
  MOV 27H,#05H                           ;为小数部分显示0和5做准备
SL5:
  MOV 29H,A                             ;29H内存放的是温度的整数部分
  LCALL DISPLAYT                                      ;27H内存放的是温度的小数部分
RET
;=====================温度显示DISPLAYT=========================
DISPLAYT:
MOV P0,#0C9H
LCALL LOAD
MOV R1,#27H
CJNE @R1,#0,AAA
MOV A,#'0'
AJMP BBB
AAA:MOV A,#'5'
BBB:LCALL SENDDATA             ;显示小数部分
MOV A,29H
MOV B,#10
DIV AB
MOV P0,#0C6H
LCALL LOAD
ADD A,#'0'
LCALL SENDDATA                    ;显示十位数
MOV P0,#0C7H
LCALL LOAD
MOV A,B
ADD A,#'0'
LCALL SENDDATA                    ;显示个位数
MOV P0,#0CH
LCALL LOAD                        ;关掉光标
RET


      END


回复

使用道具 举报

ID:123289 发表于 2023-6-25 08:30 | 显示全部楼层
1、写程序之前,一定会构思一下达成方案的方案的,这一点相信你已做了。
2、将构思写成逻辑框图,审视流程的逻辑是否能达成目的,流得通。
3、按照流程图写程序。
补一下第2、吧,试试中不中。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表