單片機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
;============程序結束========================================
|