找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2383|回复: 6
收起左侧

大侠们帮忙指点一下这个单片机汇编程序,几天了找不到原因

[复制链接]
ID:421538 发表于 2018-11-11 15:15 | 显示全部楼层 |阅读模式
50黑币
单片机STC15W404AS的串口中断方式接收上位机的命令(5个字节,5F 01 02 XX  FE,其中第四字节XX是变量,根据XX做相应的判断执行不同动作)
当第四字节为#11H时,串口发送递增再递减的电压值(做呼吸灯控制)现在只能执行一次,第二次就不行,死机了。如果上电后接收到命令,不是11H
都能正常工作,只要有#11H,可以执行循环,但是要是有新的命令过来,就会死机了
TmpData  EQU    01H
AUXR     EQU    08EH
P5   DATA 0C8H
P1M1 DATA 091H
P1M0 DATA 092H

T2H  DATA 0D6H
T2L  DATA 0D7H
FagHX BIT P1.0       ;呼吸模式循环标志
TmpVset EQU 17H      ;临时电压变量地址
TmpVsetL EQU 18H     ;递增初始电压值地址
TmpVsetH EQU 19H     ;递减终止电压值地址

    ORG 0000H
    LJMP MAIN                   ;上电,转向主程序
    ORG 0023H                   ;串行口的中断入口地址
    LJMP Uart1_Int_Recceive     ;转向中断服务程序
    ORG 0100H
;=======主程序开始=====================================================================
       MAIN:     LCALL Uart1_Initial     ;串口初始化
                 MOV R3,#0               ;亮度档位标识清零
       Waitdata: SETB ES                 ;允许串行口中断
                 SETB EA                 ;CPU开中断
                 MOV R0,#40H       ;存放接受的数据首地址---------------------
                 MOV R2,#0         ;存放接受的数据长度---------------------
   Save_UartData:
             LOP:MOV A,TmpData     ;等待新的数据
                 CJNE R2,#5,LOP
                 CLR FagHX         ; 呼吸循环标志:0---退出 ,1---执行
                 CLR ES            ;所有数据接收完毕,禁止串行中断
                 CLR EA
;------------------------------------------------------------------------
;======根据上位机命令(5F 01 FE 11 FE,第四字节是变量)控制对应灯具亮度(变量放在43H的地址中)
        KK:   MOV A,43H                 ;查看地址43H(接收到的5个字节数据的第四个字节内容做相应的功能判断)
              CJNE A,#11H,JJ
              SETB FagHX
              JMP HuxiMode
        JJ:   CJNE A,#12H,HH
              MOV  DPTR,#LED_AC5      ; 调光5档
              LCALL SendString        ; UART发送 A220V
              JMP Waitdata
        HH:   CJNE A,#13H,WW
              MOV  DPTR,#LED_AC1      ; 调光1档
              LCALL SendString        ; UART发送 A030V
              JMP Waitdata
        WW:   CJNE A,#14H,WW
              MOV  DPTR,#LED_AC3      ; 调光1档
              LCALL SendString        ; UART发送 A100V
              JMP Waitdata
;--------呼吸模式串口控制--------------------------------------
    HuxiMode:
             JNB FagHX,ExitHuxi   ; 呼吸循环标志:0---退出 ,1---执行
             MOV 10H,#41H  ;A
             MOV 11H,#30H  ;可控硅电压值百位  0
             MOV 12H,#30H  ;可控硅电压值十位  0
             MOV 13H,#30H  ;可控硅电压值个位  0
             MOV 14H,#56H  ;V
             MOV 15H,#0DH  ;0D
             MOV 16H,#0AH  ;0A
             MOV TmpVsetH,#0AAH    ;6EH=110V,78H=120V,82=130v 8CH=140V 96H=150V A0H=160V  AAH=170V  B4H=180V  BEH=190V  C8H=200V
             MOV TmpVsetL, #4BH    ;1EH=30v 23H=35v  28H=40v,2DH=45v 32H=50V   37H=55V 3CH=60v  41H=65v 46H=70v 4BH=75v 50H=80v
  AdjVsetUP:
             MOV A,TmpVsetL       ;起始电压递增
             MOV TmpVset,A
     VsetUP: JNB FagHX,ExitHuxi   ; 呼吸循环标志:0---退出 ,1---执行
             MOV A,TmpVset     ;起始电压递增
             ADD A,#02H        ;递增步进值
             MOV TmpVset,A     ;步进增加的值保存
             LCALL HextoASC    ;转ASCC字符
             LCALL Uart1_Send  ;发送控制值
             LCALL Dly200ms    ;延时
        
               ;  Mov  R1,#30            ; 30X10MS=300ms秒延时子程序
          ; DL44: LCall  Delay
              ;   JNB FagHX,XX  ; 呼吸循环标志:0---退出 ,1---执行
              ;   Djnz  R1,DL44
              ;  XX:
             MOV A,TmpVset
             CJNE A,TmpVsetH,UPstop  ;递增后是否超过最大值
             JMP  VsetDonw
      UPstop:JC VsetUP               ;小于最大值继续递增
    VsetDonw:
             JNB FagHX,ExitHuxi  ; 呼吸循环标志:0---退出 ,1---执行
             MOV A,TmpVset       ;起始电压递减
             SUBB A,#02H         ;递减步进值
             MOV TmpVset,A       ;步进递减的值保存
             LCALL HextoASC      ;转ASCC字符
             LCALL Uart1_Send    ;发送控制值
             LCALL Dly200ms
          ;   Mov R1,#30            ; 30X10MS=300ms秒延时子程序
     ; DL444: LCall  Delay
           ;  JNB FagHX,YY  ; 呼吸循环标志:0---退出 ,1---执行
           ;  Djnz  R1,DL444
           ;YY:  
             MOV A,TmpVset
             CJNE A,TmpVsetL,DownStop  ;递减后的值与设定的最小值比较
             JMP LOOPSTOP
    DownStop:JC  LOOPSTOP          ;大于最小值继续递减
             JMP VsetDonw
    LOOPSTOP:JMP HuxiMode          ;继续下一次继续循环
    ExitHuxi:Ljmp MAIN
;----------单字节16进制数转为3字节的ASCII码-------------------------------
   HextoASC: MOV      A,TmpVset        ;待转的16进制数
             MOV      B,#100
             DIV      AB
             ADD      A,#30H
             MOV      11H,A            ;百位数存入地址11H
             MOV      A,B
             MOV      B,#10
             DIV       AB
             ADD      A,#30H
             MOV      12H,A             ;十位数存入地址12H
             MOV      A,B
             ADD      A,#30H
             MOV     13H,A              ;个位数存入地址13H
        RET
;---------串口初始化-------------------------------------------------------        
Uart1_Initial:
       ; CLR A
       ; CLR BUSY
       ; CLR EA
        MOV SP, #3FH
        MOV SCON,#50H  ;8位数据,可变波特率
ORL AUXR,#01H  ;串口1选择定时器2为波特率发生器
ORL AUXR,#04H  ;定时器2时钟为Fosc,即1T
MOV T2L,#0E0H  ;设定定时初值
MOV T2H,#0FEH  ;设定定时初值
        ORL AUXR,#10H  ;启动定时器2
      ; SETB ES                 ;允许串行口中断
      ; SETB EA                 ;CPU开中断
       RET
;-----------串口中断接收---------------------------------------      
UART1_Int_Recceive:
                    PUSH ACC
             U1REC1:JBC RI,GetData1 ;是接收中断,清除此标志,转向GetData1接收
                    CLR TI          ;是发送中断,清除此标志,中断返回
                    SJMP U1REC1
           GetData1:MOV A,SBUF      ;接收(读入)数据
                    MOV @R0,A       ;存放数据到30H开头的RAM-----------
                    MOV TmpData,A
                    INC R0          ;修改数据区指针-------------
                    INC R2          ;是否接收到5个字节 ,数据长度为5个字节
                    CLR  FagHX      ;呼吸模式循环标志置零
                    POP ACC                  
              RETI;中断返回
;16进制发送---------------------------------------------------            
Uart1_Send:     CLR ES                     ; 禁止串行口中断
                 CLR EA                     ; 禁止CPU中断
                 CLR A
                 MOV R0,#10H  ;发送从10H地址开始中的数据
                 MOV R2,#07   ;转发的数据长度7个字节
             S1: MOV A,@R0                  ; 串口发送子程序/取码指针
                 MOV  SBUF,A                ; 载入SBUF发送
              S2:JBC  TI,S3                 ; 是否发送完?
                 SJMP S2
              S3:INC  R0                    ; 取下一个码
                 DJNZ R2,S1
                 SETB ES                    ; 允许串行口中断
                 SETB EA                    ; CPU开中断
               RET
;----串口发送字符串-------------------------------------------------
      SendString:
                 CLR ES                     ; 禁止串行口中断
                 CLR EA                     ; 禁止CPU中断
                 CLR A
                 MOVC A,@A+DPTR             ; 到TABLE取码
                 MOV  SBUF,A                ; 载入SBUF发送
          SCONQ2:JBC  TI,SCONQ3             ; 是否发送完?
                 SJMP SCONQ2
          SCONQ3:INC  DPTR                  ; 取下一个码
                 CJNE A,#0AH,SendString     ; 数据块取码未完成继续取码  发送AXXXV  如果发到字母V(ACSII码56H)则结束
                 SETB ES                    ; 允许串行口中断
                 SETB EA                    ; CPU开中断
            RET
;-----------软件延时----------------------------------------------
     Dly800ms:  Mov    R1,#80               ; 80X10MS=800ms秒延时子程序
          DL6:  Call   Delay
                Djnz   R1,DL6
               Ret
      Dly500ms:  Mov    R1,#50             ; 50X10MS=500ms秒延时子程序
           DL5:  Call   Delay
                 Djnz   R1,DL5
               Ret
     Dly300ms:  Mov    R1,#30            ; 20X10MS=200ms秒延时子程序
           DL4:  Call   Delay              
                 Djnz   R1,DL4         
               Ret
      Dly200ms:  Mov    R1,#20            ; 20X10MS=200ms秒延时子程序
           DL3:  Call   Delay
                 Djnz   R1,DL3
               Ret
      Dly100ms:  Mov    R1,#10            ; 20X10MS=200ms秒延时子程序
           DL2:  Call   Delay
                 Djnz   R1,DL2
               Ret
         Delay:MOV R7,#01H                ;误差 0.000000000000us  3.6864M 10ms
           DL1:MOV R6,#0DEH              ; 222
           DL0:MOV R5,#28H               ;40
               DJNZ R5,$           
               DJNZ R6,DL0
               DJNZ R7,DL1
            RET
;====PWM对应亮度的可控硅电压设置=============================
LED_OFF:DB 'A020V',0DH,0AH     ;关机控制命令
LED_ON:DB 'A030V',0DH,0AH      ;开机默认亮度
LED_AC1:DB 'A030V',0DH,0AH     ;第一档亮度控制
LED_AC2:DB 'A080V',0DH,0AH     ;第二档亮度控制
LED_AC3:DB 'A100V',0DH,0AH     ;第三档亮度控制
LED_AC4:DB 'A140V',0DH,0AH     ;第四档亮度控制
LED_AC5:DB 'A220V',0DH,0AH     ;第五档亮度控制
LED_Sleep:DB 'A030V',0DH,0AH   ;睡眠模式亮度控制
LED_Warm:DB 'A070V',0DH,0AH    ;温馨模式亮度控制
LED_Reading:DB 'A190V',0DH,0AH ;阅读模式亮度控制
LED_Bright:DB 'A220V',0DH,0AH  ;明亮模式亮度控制
LED_Moon:DB 'A040V',0DH,0AH    ;夜灯模式亮度控制
  END
;============程序结束========================================

回复

使用道具 举报

ID:401564 发表于 2018-11-11 20:15 | 显示全部楼层
你又来了,我告诉你吧,这在用汇编的人不多的,你的程序越大越看不明白
你还是自己找问题吧,你的程序有点乱,跳转的和主循环尽量分开,尽量短一点,尽量把一些初始化的操作放在前面,相关的操作尽量放在子程序中
我有时候一个很简单的错误也是搞上三四天也找不到问题的,汇编就是这样的了
给你参考一下我的格式,如果觉得可以,就改动一下代码的风格,如果觉得不可以,我也是照着前辈抄的..... QQ截图20181111201012.png

回复

使用道具 举报

ID:111634 发表于 2018-11-11 21:20 | 显示全部楼层
本帖最后由 zl2168 于 2018-11-12 08:28 编辑

实例77  双机串行通信方式1
串行方式1.PNG
Proteus仿真一下,确认有效。
实例77 双机通信方式1.rar (40.4 KB, 下载次数: 5)
回复

使用道具 举报

ID:111634 发表于 2018-11-11 21:22 | 显示全部楼层
实例78  双机串行通信方式2
回复

使用道具 举报

ID:111634 发表于 2018-11-11 21:22 | 显示全部楼层
本帖最后由 zl2168 于 2018-11-12 08:42 编辑

实例79  双机串行通信方式3
串行方式3.PNG
Proteus仿真一下,确认有效。
实例79 双机通信方式3.rar (45.3 KB, 下载次数: 2)
回复

使用道具 举报

ID:387733 发表于 2018-11-11 21:55 | 显示全部楼层
找问题不能光靠看程序,自己写的程序有错误,自己很难看出来的。为了纠正程序中的问题,一定要掌握DEBUG方式,根据自己的编程思路,一小段一小段的跟踪,可以设置断点,设置中间变量,跟踪运行,检查是否按照自己的思路在运行。
回复

使用道具 举报

ID:123289 发表于 2018-11-12 12:00 | 显示全部楼层
画个流程序图就明白了,做汇编的必须画流程图!
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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