单片机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
;============程序结束========================================
|