上次制作的STC89C51RC單片機電風扇長定時+自然風,一直覺得不自然,現在升級加了個“漸慢——漸快”變化方式和慢速檔(按編碼器開關3次快速進入轉速調整),用起來不那么生硬,仍然保留間歇通/斷電方式。升級版需增加一個過零檢測電路接到外部中斷INT0,編碼器的A、B、K改接P3.3(INT1)、P3.4、P3.5,不能用按鍵代替編碼器了,轉速調整共設20級,再往上調變化不明顯,意義不大。改變可控硅導通角的調速方式電機會產生嗡嗡響的噪音,所以采用每間隔1~20個過零檢測信號脈沖,截止一個正半周一個負半周的調速方式,但也有缺點,低速時電機會有抖動現象,只要速度不調得太低,影響不大。本人只知道一點點匯編語言,別的語言也不懂,從自學編程到現在,算起來平均一年編程不到一次,并不熟練,應該會有很多不規范和羅嗦的地方
電路原理圖:
電路原理圖.JPG (143.19 KB, 下載次數: 81)
下載附件
2020-7-18 08:06 上傳
單片機匯編語言源代碼:
;STC89C51RC+TM1637顯示模塊+EC11編碼器,電風扇長定時+自然風匯編程序
;楊小強,2020年7月
;晶振:11.0592MHz
;顯示:(TM1637)4位數碼管顯示模塊
;調整、設置:EC11帶開關5腳旋轉編碼器
;電源:閑置5V手機充電器
;
;最長定時99小時59分59秒;自然風周期可調,有漸慢——漸快、間歇通/斷電兩種方式可選擇
;如果過零檢測不接或者有故障將沒有慢速功能,自然風自動改為間歇通/斷電方式
;
;按編碼器開關1次:常速/自然風切換
;按編碼器開關2次:常速/慢速切換。兩次按鍵動作之間不大于0.6秒
;按編碼器開關3次:快速進入慢速時的轉速調整,1~20級;自然風狀態漸慢時降到這里設置的轉速。
; 12級以上時轉速調整變化不明顯,自然風狀態將沒有漸慢——漸快循環。
; 60秒無任何操作或按編碼器開關自動保存并退出。
;
;長按編碼器開關5秒以上15秒以內,松開按鍵后進入設置狀態,設置完第7項按編碼器開關1次后又跳轉到第一項
;退出設置狀態:15秒無任何操作或按編碼器開關2次自動保存并退出。
;根據數碼管左邊顯示的數字進行以下各項設置,通過旋轉編碼器加或減,按編碼器開關1次進入下一項設置:
;一、顯示1——設置自然風狀態時,常速——慢速周期時長,10~60秒,默認20秒
;二、顯示2——設置自然風間歇通/斷電方式時常速通電時長,最短為1秒;最長為上一項所設的周期減3秒
;三、顯示3——設置3小時以下定時調整時,編碼器每轉動一格的增(減)值:5、10、15、20、25、30分鐘,默
; 認10分鐘,3小時以上增(減)值30分鐘;10小時以上增(減)值1個小時;20小時以上增(減)值2個小時
;四、顯示4——設置電風扇插電就自動填入的定時時間,0~30小時,默認8小時
;五、顯示5——設置數碼管亮度,1~8級,默認為3級
;六、顯示6——設置自然風方式,0=漸慢——漸快變化方式,1=間歇通/斷電方式
;七、顯示7——設置慢速狀態時的轉速,1~20級,本項60秒無任何操作自動保存并退出。
;
;長按編碼器開關15秒:恢復各項默認設置,數碼管顯示88:88
;設置保存失敗顯示5秒E1
;
;--------------------------- 端口定義 ---------------------------
CLK EQU P1.5 ;接顯示模塊TM1637的CLK
DIO EQU P1.6 ;接顯示模塊TM1637的DIO
GLJC EQU P3.2 ;過零檢測,外部中斷INT0
EC11A EQU P3.3 ;接編碼器的A引腳,外部中斷INT1
EC11B EQU P3.4 ;接編碼器的B引腳
EC11K EQU P3.5 ;接編碼器的按鍵開關引腳
RLED EQU P0.4 ;慢速狀態LED指示燈,低電平亮;單片機發生復位時也亮
LED EQU P0.5 ;自然風狀態LED指示燈,低電平亮
MOC EQU P0.7 ;接MOC3022光控可控硅,低電平時風扇電機通電
;--------------------------- 位地址及RAM的使用 ---------------------------
;(20H)第0位:1=編碼器已經轉動,等待主程序處理,0=沒有轉動或主程序已處理
;(20H)第1位:1=編碼器順時針正轉;0=編碼器逆時針反轉
;(20H)第2位:1=自然風狀態;0=正常狀態
;(20H)第3位:1=禁止;0=允許。進行各項設置時使用,允許/禁止檢查剩余時間
;(20H)第4位:1=閃爍顯示;0=不閃爍。進行各項設置時用
;(20H)第5位:1=不顯示,0=顯示,數字及冒號閃爍時用,由T0中斷每0.5秒取反一次
;(20H)第6位:1=主程序顯示3秒88:88或5秒E1;0=正常
;(20H)第7位:1=慢速狀態;0=常速。“常速/慢速”切換
;(21H)第8位:1=允許;0=禁止。漸變控制標志
;(21H)第9位:1=漸快;0=漸慢。漸變控制時的調速方向
FWBZ1 EQU 022H ;復位判斷標志1,也作EEPROM數據判斷標志
FWBZ2 EQU 023H ;復位判斷標志2,也作EEPROM數據判斷標志
ZRFZQ EQU 024H ;自然風時狀態常速——慢速變化周期時長
ZRFSJ EQU 025H ;自然風時電機常速通電時長
BMQZJ EQU 026H ;編碼器每轉動一小格的增(減)值
SDDS EQU 027H ;上電就自動設定的定時時間(小時)
SMGLD EQU 028H ;數碼管亮度
ZRFFS EQU 029H ;自然風方式
MSZTZS EQU 02AH ;慢速狀態轉速
DSSJS EQU 02BH ;定時時間,時
DSSJF EQU 02CH ;定時時間,分
DSSJM EQU 02DH ;定時時間,秒
ZQ EQU 02EH ;T0、INT0中斷使用,自然風常速——慢速周期時長
SJ EQU 02FH ;T0、INT0中斷使用,自然風時電機常速通電時長
SJJS EQU 030H ;時間計數,每10毫秒減1,為0后定時時間減1秒,重新放入定義的計數值
MJS EQU 031H ;按鍵處理時用,秒計數,每秒減1,直到為0
SSSC EQU 032H ;閃爍時長,每秒減1,直到為0
XSHC1 EQU 033H ;上次顯示的內容,與當前不同就立即顯示,相同就每0.5秒顯示一次
XSHC2 EQU 034H ;上次顯示的內容,與當前不同就立即顯示,相同就每0.5秒顯示一次
XXSZ EQU 035H ;下限數值,進行各項設置時用
SXSZ EQU 036H ;上限數值,進行各項設置時用
WCZSJ EQU 037H ;無操作時間,進行各項設置時用
ZXM1 EQU 038H ;顯示用,待發送到TM1637的字形碼1
ZXM2 EQU 039H ;顯示用,待發送到TM1637的字形碼2
ZXM3 EQU 03AH ;顯示用,待發送到TM1637的字形碼3
ZXM4 EQU 03BH ;顯示用,待發送到TM1637的字形碼4
DSZJ EQU 03CH ;加減定時時間使用
JCGLMC1 EQU 03DH ;檢查過零脈沖用
JCGLMC2 EQU 03EH ;檢查過零脈沖用
GLMC EQU 03FH ;過零脈沖計數
DDMC EQU 040H ;斷電脈沖計數
MSZS EQU 041H ;T0、INT0中斷使用,設置的轉速級數
JBJS1 EQU 042H ;T0、INT0中斷使用,漸變計數
JBJS2 EQU 043H ;T0、INT0中斷使用,漸變計數
JKTZSJ EQU 044H ;漸快——漸慢變化調整時用
DISPL EQU 045H ;設置要顯示的目標:
;0=顯示定時時間
;1=顯示1——設置自然風狀態時的常速——慢速周期時長
;2=顯示2——設置自然風時電機常速通電時長
;3=顯示3——設置3小時以下定時調整時,編碼器每轉動一小格的增(減)值
;4=顯示4——設置上電自動填入的定時時間
;5=顯示5——設置數碼管亮度
;6=顯示6——設置自然風方式
;7=顯示7——設置慢速時的轉速
;--------------- 看門狗、EEPROM特殊功能寄存器地址 ---------------
AUXR EQU 08EH ;輔助寄存器
WDT_CONTR EQU 0E1H ;看門狗地址
IAP_DATA EQU 0E2H ;數據寄存器,讀出、寫入的數據放在此處
IAP_ADDRH EQU 0E3H ;地址寄存器高八位
IAP_ADDRL EQU 0E4H ;地址寄存器低八位
IAP_CMD EQU 0E5H ;命令寄存器,0=關閉,1=讀,2=寫,3=擦除
IAP_TRIG EQU 0E6H ;命令觸發寄存器,每次操作先放入46H再放入B9,命令立即被觸發起動
IAP_CONTR EQU 0E7H ;控制寄存器,Flash操作允許/禁止及等待時間
ENABLE_IAP EQU 083H ;定義Flash操作等待時間及允許IAP/ISP/EEPROM操作的常數,時鐘<12MHz時為83H
;=====================================================================================
ORG 0000H
LJMP START
ORG 0003H ;外部中斷INT0入口
LJMP INT_0 ;外部中斷INT0入口
ORG 000BH ;T0中斷入口
LJMP T0INT ;T0中斷入口
ORG 0013H ;外部中斷INT1入口
LJMP INT_1 ;外部中斷INT1入口
ORG 0030H ;程序代碼始址安排在30H
;----------------------------------------------------------------------------------------
;定義時間計數值,當定時時間實際走時誤差較大時,可調整此數值使誤差減小
;例如每分鐘快7秒,就把此數值改為112D(7秒÷60秒×100≈12,12+100=112);每分鐘慢6秒,就
;把此數值改為90D(6秒÷60秒×100=10,100-10=90)
;----------------------------------------------------------------------------------------
HMJS: DB 100D ;定義時間計數值,100表示100×10毫秒=1秒,后面的D表示是十進制數
;--------------- 定時器0中斷(10毫秒產生一次中斷) ---------------
T0INT: PUSH ACC
PUSH PSW
LCALL TIME ;處理各項時間
LCALL DISPLAY ;顯示
LCALL JCGLMC ;檢查過零檢測脈沖,如果有故障就由本中斷控制可控硅、LED指示燈
POP PSW
POP ACC
RETI
;--------------- 外部中斷INT0,接過零檢測電路,控制轉速、狀態LED指示燈 ---------------
INT_0: PUSH ACC
PUSH PSW
LCALL Control ;根據條件控制可控硅、狀態LED指示燈
POP PSW
POP ACC
RETI
;------ 外部中斷INT1,P3.3接編碼器A引腳 ------
INT_1: SETB EC11B ;拉高編碼器B引腳電平
PUSH PSW
JB 00H,INT1_2 ;如果位地址0H為1就退出中斷處理程序,等待主程序處理
SETB 00H ;把位地址00H置為1,表示編碼器已轉動,等待主程序處理
JB EC11B,INT1_1 ;如果編碼器B引腳為1(高電平)就轉移,說明是順時針正轉
CLR 01H ;是0(低電平),逆時針反轉,把位地址01H置為0
LJMP INT1_2
INT1_1: SETB 01H ;是順時針正轉,把位地址01H置為1
INT1_2: POP PSW
RETI
;--------------- 設置各項默認值 ----------------
SZMRZ: MOV ZRFZQ,#20 ;自然風狀周期時長(秒)
MOV ZRFSJ,#5 ;自然風間歇通/斷電方式時的電機通電時長(秒)
MOV BMQZJ,#10 ;編碼器每轉動一小格的+、-值(分鐘))
MOV SDDS,#8 ;上電就自動設定的定時時間(小時)
MOV SMGLD,#3 ;數碼管亮度,8級亮度最高
MOV ZRFFS,#0 ;自然風方式,0=漸慢——漸快循環方式
MOV MSZTZS,#8 ;慢速狀態轉速
RET
;--------------- T0、INT0、INT1中斷設置 ----------------
SETINT: ANL AUXR,#7FH ;定時器時鐘12T模式
ANL TMOD,#0F0H ;設置定時器模式
MOV TL0,#000H ;設置定時初值,10毫秒產生一次中斷(晶振:11.0592MHz)
MOV TH0,#0DCH ;設置定時初值,10毫秒產生一次中斷(晶振:11.0592MHz)
CLR TF0 ;清除TF0標志
SETB ET0 ;允許定時器0中斷
SETB TR0 ;定時器0開始計時
SETB IT0 ;設外部中斷INT0為下降沿觸發
SETB EX0 ;允許外部中斷INT0
SETB PX0 ;設外部中斷INT0為高優先級
SETB IT1 ;設外部中斷INT1為下降沿觸發
SETB EX1 ;允許外部中斷INT1
SETB EA ;允許全局中斷
RET
;---- 啟動看門狗及喂狗,11.0592MHz預分頻數=4(142.2毫秒),00111001B(39H) ----
WG: MOV WDT_CONTR,#00111001B
RET
;********************************* 主程序開始 ********************************
START: MOV SP,#050H ;設置堆棧指針
MOV A,FWBZ1 ;
CJNE A,#0C8H,START0 ;
MOV A,FWBZ2 ;檢查復位判斷標志,不相同說明是初次上電,從初始化開始運行
CJNE A,#0D9H,START0 ;
LCALL SETINT ;中斷設置
CLR RLED ;RAM內容沒變,說明是被干擾等原因復位,不是初次上電,點亮復位LED指示燈
MOV A,DISPL ;
CJNE A,#7,SAT ;不管是什么原因復位,只要RAM不被改變就跳過初始化,繼續運行
LJMP STARTD ;
SAT: CJNE A,#6,SAT0 ;
LJMP STARTC
SAT0: CJNE A,#5,SAT1 ;
LJMP STARTB ;
SAT1: CJNE A,#4,SAT2 ;
LJMP STARTA ;
SAT2: CJNE A,#3,SAT3 ;根據DISPL的內容跳轉到復位前的位置
LJMP START9 ;
SAT3: CJNE A,#2,SAT4 ;
LJMP START8 ;
SAT4: CJNE A,#1,START2 ;
LJMP START7 ;
START0: CLR A
MOV R0,#30H ;
MOV R1,#20H ;
START1: MOV @R1,A ;初始化,從RAM地址20H開始清零30H個字節
INC R1 ;
DJNZ R0,START1 ;
LCALL SETINT ;初始化,中斷設置
MOV FWBZ1,#0C8H ;初始化,放入復位判斷標志1到RAM
MOV FWBZ2,#0D9H ;初始化,放入復位判斷標志2到RAM
LCALL REEP ;初始化,讀EEPROM保存的各項設置,如果沒有就設為默認值并保存
SETB RLED ;初始化,設RLED為高電平,復位LED指示燈不亮
;
START2: LCALL WG ;喂狗
MOV DISPL,#0 ;設置要顯示的目標,0=顯示定時時間
CLR 06H ;位地址06H置為0,顯示定時時間
JNB 00H,START3 ;如果位地址00H為0(編碼器沒有轉動)就轉移
SETB EC11A ;拉高編碼器A引腳電平
SETB EC11B ;拉高編碼器B引腳電平
JNB EC11A,START3 ;如果仍為0(低電平)就轉移,說明還沒有旋轉到卡點位置
JNB EC11B,START3 ;如果仍為0(低電平)就轉移,說明還沒有旋轉到卡點位置
LCALL DSSJZJ ;AB引腳都為高電平了,已經旋轉到卡點位置,根據方向增減定時時間
CLR 00H ;把位地址00H置為0,表示已經響應并處理編碼器旋轉動作
START3: LCALL SKEY ;掃描編碼器按鍵開關
JNC START2 ;沒有按鍵動作(C=0)就轉移
LCALL KEY ;有按鍵動作,調用編碼器按鍵開關處理子程序
CJNE A,#1,START4 ;如果不是按下1次(正常/自然風切換)就轉移
JNB 07H,STAT2 ;如果當前不是慢速狀態就轉移
CLR 07H ;是慢速狀態,位地址第07位置為0,先退出慢速狀態
STAT1: SETB RLED ;關LED2
LJMP START2
STAT2: CPL 02H ;位地址第02位取反,自然風/正常狀態切換
MOV MSZS,MSZTZS ;把設置的慢速狀態轉速放入MSZS
MOV ZQ,#0
MOV SJ,#0
LJMP START2
START4: CJNE A,#2,STAT3 ;如果不是2(正常/慢速之間切換)就轉移
CPL 07H ;是按2次,位地址第07位取反,“正常/慢速”狀態切換
JNB 07H,STAT1 ;如果取反后不是慢速狀態就轉移,關LED2
CLR RLED ;是慢速狀態,點亮LED2
LJMP START2
STAT3: CJNE A,#3,START5 ;如果不是3(設置慢速狀態時的轉速)就轉移
LCALL MSSZ ;設置慢速狀態時的轉速
LJMP START2
START5: CJNE A,#5,START7 ;如果不是5(恢復默認設置)就轉移
LCALL SZMRZ ;恢復各項默認設置
SETB 06H ;把位地址06H設置為1,數碼管顯示3秒88:88
MOV SSSC,#3 ;3秒
MOV ZXM1,#0FFH ;8
MOV ZXM2,#0FFH ;8
MOV ZXM3,#0FFH ;8
MOV ZXM4,#0FFH ;8
LCALL DISP ;顯示
START6: MOV A,SSSC
LCALL WG ;喂狗
JNZ START6 ;等待SSSC為0秒
LCALL WSET ;保存設置
LCALL KEYEX ;等待按鍵松開
LJMP START2
START7: MOV DISPL,#1 ;是4,進入各項設置,1=顯示“1——設置自然風狀態時通斷電周期時長”
LCALL ZQSZ ;周期時長設置
JNZ START8 ;如果是按下編碼器按鍵開關返回,就轉移,進行下一項設置
LJMP START2 ;是15秒無操作自動保存返回,設置結束
START8: MOV DISPL,#2 ;2=顯示“2——設置自然風時電機通電時長”
LCALL TDSC ;通電時長設置
JNZ START9 ;如果是按下編碼器按鍵開關返回,就轉移,進行下一項設置
LJMP START2
START9: MOV DISPL,#3 ;3=顯示“3——設置2小時以下定時調整時,編碼器每轉動一格的增(減)值”
LCALL BMQZJZ ;編碼器增減值設置
JNZ STARTA ;如果是按下編碼器按鍵開關返回,就轉移,進行下一項設置
LJMP START2
STARTA: MOV DISPL,#4 ;4=顯示“4——設置插電自動填入的定時時間”
LCALL SDDSSJ ;上電定時時間設置(小時)
JNZ STARTB ;如果是按下編碼器按鍵開關返回,就轉移,進行下一項設置
LJMP START2
STARTB: MOV DISPL,#5 ;5=顯示“5——設置數碼管亮度”
LCALL LDSZ ;亮度設置
JNZ STARTC ;如果是按下編碼器按鍵開關返回,就轉移,進行下一項設置
LJMP START2
STARTC: MOV DISPL,#6 ;6=顯示“6——設置自然風方式”
LCALL FSSZ ;自然風方式設置
JNZ STARTD ;如果是按下編碼器按鍵開關返回,就轉移,進行下一項設置
LJMP START2
STARTD: MOV DISPL,#7 ;7=顯示“7——設置慢速時的轉速”
LCALL MSSZ ;慢速轉速設置
JNZ START7 ;如果是按下編碼器按鍵開關返回,就轉移到第一項設置
LJMP START2 ;是15秒無操作自動保存返回,設置結束
;-------------------------------------------------------------------------------------
;子程序:根據編碼器旋轉方向加減定時時間。
;3小時及以下,按設置的值加減:5、10、15、20、25、30分鐘
;3小時以上每次增(減)30分鐘;10小時以上每次增(減)1個小時;20小時以上每次增(減)2個小時
;-------------------------------------------------------------------------------------
DSSJZJ: MOV DSSJM,#59 ;先放入59到定時時間(秒)
MOV A,DSSJS ;裝入定時時間(時)
CJNE A,#20,DSZJ1 ;當前“時”是否等于或大于20
DSZJ1: JC DSZJ2 ;小于就轉移
MOV DSZJ,#2 ;等于或大于20,加減2個小時
LJMP DSZJ4
DSZJ2: CJNE A,#10,DSZJ3 ;當前“時”是否等于或大于10
DSZJ3: JC DSZJ8 ;小于就轉移
MOV DSZJ,#1 ;等于或大于10,加減1個小時
DSZJ4: JNB 01H,DSZJ6 ;如果位地址01H為0(逆時針反轉)就轉移
ADD A,DSZJ ;是正轉,加
CJNE A,#100,DSZJ5 ;加完后是否等于或大于100
DSZJ5: JC DSZJ7 ;如果小于就轉移,把A放回到DSSJS
MOV DSSJS,#99 ;已經大于99了,直接設置為99:59:59
MOV DSSJF,#59 ;已經大于99了,直接設置為99:59:59
RET
DSZJ6: SUBB A,DSZJ ;是反轉,減
DSZJ7: MOV DSSJS,A ;把計算結果放入DSSJS
RET
DSZJ8: MOV DSZJ,BMQZJ ;把設置的“增(減)值”放入DSZJ
CJNE A,#3,DSZJ11 ;當前“時”不是3就轉移
JB 01H,DSZJ12 ;是3,如果位地址01H為1(正轉)就轉移,把DSZJ處的“增(減)值”改為30(分鐘)
MOV A,DSSJF ;是反轉,裝入定時時間(分)
JZ DSZJ13 ;如果當前“分”為0(3:00)就轉移,按設置的增(減)值減
CJNE A,#30,DSZJ9 ;“分”不為0,是否等于或大于30
DSZJ9: JC DSZJ10 ;小于就轉移,把0放入定時時間(分),使時間變為3:00
SUBB A,#30 ;等于或大于,減30分
MOV DSSJF,A ;把計算結果放入定時時間(分)
RET
DSZJ10: MOV DSSJF,#0 ;小于30,把0放入定時時間(分),使時間變為3:00
RET
DSZJ11: JC DSZJ13 ;小于3就轉移
DSZJ12: MOV DSZJ,#30 ;大于3:00,把DSZJ處的“增(減)值”改為30(分鐘)
DSZJ13: MOV A,DSSJF ;裝入定時時間(分)
JNB 01H,DSZJ16 ;如果位地址01H為0(逆時針反轉)就轉移
ADD A,DSZJ ;是正轉,當前“分”直接加DSZJ處的“增(減)值”
CJNE A,#60,DSZJ14 ;加完后“分”是否等于或大于60
DSZJ14: JC DSZJ15 ;小于60就轉移,把A放入定時時間(分)
SUBB A,#60 ;等于或大于60,就減60,然后小時加1
MOV DSSJF,A ;把A放入定時時間(分)
MOV A,DSSJS ;裝入“時”
INC A ;小時加1
MOV DSSJS,A
CJNE A,#3,DSZJ19 ;加完后“時”不是3就轉移,退出
CLR A ;加完后大于3:00了,把0放入定時時間(分),使時間變為3:00
DSZJ15: MOV DSSJF,A
RET
DSZJ16: CJNE A,DSZJ,DSZJ17 ;是逆時針反轉,當前“分”是否等于或大于DSZJ處的“增(減)值”
DSZJ17: JC DSZJ20 ;小于就轉移
SUBB A,DSZJ ;等于或大于,定時時間(分)減“增(減)值”
MOV DSSJF,A ;把計算結果放入定時時間(分)
JZ DSZJ18 ;如果“分”為0就轉移
RET
DSZJ18: CJNE A,DSSJS,DSZJ19 ;如果“時”不為0就轉移
MOV DSSJM,A ;“時、分”都為0,“秒”也清零
DSZJ19: RET
DSZJ20: MOV A,DSZJ ;“分”小于“增(減)值”,裝入DSZJ處的“增(減)值”
CLR C ;進位標志清0
SUBB A,DSSJF ;“增(減)值”減“定時時間(分)”
MOV DSSJF,A ;減完后的結果暫時放入DSSJF
MOV A,#60
SUBB A,DSSJF ;60減上面的計算結果,得出定時時間(分),然后小時減1
MOV DSSJF,A ;得出的數放入定時時間(分)
MOV A,DSSJS ;裝入定時時間(時)
JZ DSSJQL ;如果“時”為0就轉移(不夠減了,把定時時間清零)
DEC DSSJS ;“時”不為0,減1
RET
DSSJQL: CLR A
MOV DSSJS,A ;定時時間清零
MOV DSSJF,A ;定時時間清零
MOV DSSJM,A ;定時時間清零
RET
;----------------------------------------------------------------------------------------
;設置自然風周期時長
;----------------------------------------------------------------------------------------
ZQSZ: MOV XXSZ,#10 ;下限為10秒
MOV SXSZ,#60 ;上限為60秒
LCALL LDSZ1 ;設置
PUSH ACC
MOV A,ZRFZQ ;裝入自然風周期
SUBB A,#3 ;減
CJNE A,ZRFSJ,ZQSZ1
ZQSZ1: JNC ZQSZ2 ;減完后等于或大于就轉移
MOV ZRFSJ,A ;小于,修改為減3后的數
LCALL WSET ;保存設置
ZQSZ2: POP ACC
RET
;----------------------------------------------------------------------------------------
;設置自然風時電機常速通電時長,最短為1秒;最長為上一項所設的周期減3秒
;----------------------------------------------------------------------------------------
TDSC: MOV A,ZRFZQ ;裝入“自然風周期”
SUBB A,#3 ;減
MOV SXSZ,A ;放入上限值
MOV XXSZ,#1 ;下限為1秒
LJMP LDSZ1
;----------------------------------------------------------------------------------------
;設置2小時以下定時調整時,編碼器每轉動一小格的增(減)值,5、10、15、20、25、30分鐘
;----------------------------------------------------------------------------------------
BMQZJZ: MOV XXSZ,#5 ;下限為5
MOV SXSZ,#30 ;上限為30
MOV R4,#5 ;調整時的加減步長值
LJMP LDSZ2
;----------------------------------------------------------------------------------------
;設置插電就自動填入的定時時間,0~30小時
;----------------------------------------------------------------------------------------
SDDSSJ: MOV XXSZ,#0 ;下限為0小時
MOV SXSZ,#30 ;上限為30小時
LJMP LDSZ1
;----------------------------------------------------------------------------------------
;設置數碼管亮度,1~8級,8級亮度最高
;----------------------------------------------------------------------------------------
LDSZ: MOV XXSZ,#1 ;下限為1
MOV SXSZ,#8 ;上限為8
LDSZ1: MOV R4,#1 ;調整時的加減步長值
LDSZ2: MOV WCZSJ,#15 ;無操作等待時間15秒
LJMP SZTZ
;----------------------------------------------------------------------------------------
;設置自然風方式,0=漸慢——漸快變化方式,1=間歇通/斷電方式
;----------------------------------------------------------------------------------------
FSSZ: MOV XXSZ,#0 ;下限
MOV SXSZ,#1 ;上限
LJMP LDSZ1
;----------------------------------------------------------------------------------------
;設置慢速時的轉速,1~20級,本項60秒無任何操作自動保存并退出。
;----------------------------------------------------------------------------------------
MSSZ: MOV DISPL,#7 ;7=顯示“7——慢速狀態時的轉速設置”
MOV XXSZ,#1 ;下限
MOV SXSZ,#20 ;上限
MOV R4,#1 ;調整時的加減步長值
MOV WCZSJ,#60 ;無操作等待時間60秒
LJMP SZTZ
;----------------------------------------------------------------------------------------
;子程序:根據XXSZ、SXSZ設定的上下限范圍、編碼器旋轉方向,調整DISPL指向的對象。
;無操作10秒后開始閃爍顯示,15秒自動保存并退出;有按鍵動作就保存并退出
;入口參數:下限值放入XXSZ;上限值放入SXSZ;R4=加、減步長值
;出口參數:15秒無操作或按下2次以上自動保存退出A=0;按編碼器按鍵開關1次保存退出A=1
;----------------------------------------------------------------------------------------
SZTZ: MOV MJS,WCZSJ ;裝入無操作等待時間到MJS
CLR 03H ;位地址03H置為0,允許檢查剩余時間
SZTZ1: LCALL SKEY ;掃描編碼器按鍵開關
JNC SZTZ2 ;沒有按鍵動作(C=0)就轉移
LCALL KEY ;有按鍵動作,調用編碼器按鍵開關處理子程序
CJNE A,#2,SZTZ11
SZTZ11: JNC SZTZ3 ;如果是按下2次以上就轉移
CLR 04H ;把位地址04H置為0,不閃爍顯示
LCALL WSET ;保存設置
MOV A,#1 ;按編碼器按鍵開關1次保存退出A=1
RET
SZTZ2: JB 00H,SZTZ4 ;如果位地址00H為1(編碼器已經轉動)就轉移
MOV A,MJS ;沒有轉動,裝入秒計數到寄存器A
JZ SZTZ3 ;如果秒計數為0(15秒無操作)就轉移
JB 03H,SZTZ1 ;不為0,如果位地址03H為1就轉移,不檢查剩余時間
CJNE A,#5,SZTZ1 ;檢查剩余時間,如果不是5秒就轉移,繼續掃描編碼器
SETB 04H ;還剩5秒,把位地址04H置為1,設置為閃爍顯示
MOV SSSC,A ;閃爍時長5秒放入SSSC
SETB 03H ;位地址03H置為1,禁止檢查剩余時間
LJMP SZTZ1
SZTZ3: CLR 04H ;15秒時間到,把位地址04H置為0,不閃爍顯示
LCALL WSET ;保存設置
CLR A ;15秒無操作自動保存退出A=0
RET
SZTZ4: CLR 04H ;編碼器已經轉動,把位地址04H置為0,不閃爍顯示
SETB EC11A ;拉高編碼器A引腳電平
SETB EC11B ;拉高編碼器B引腳電平
JNB EC11A,SZTZ ;如果仍為0(低電平)就轉移,說明還沒有旋轉到卡點位置
JNB EC11B,SZTZ ;如果仍為0(低電平)就轉移,說明還沒有旋轉到卡點位置
MOV A,DISPL ;AB引腳都為高電平,已經旋轉到卡點位置了,裝入要設置的目標項
DEC A ;減1
ADD A,#ZRFZQ ;加上各項設置的起始地址
MOV R0,A ;把得出的具體地址放入R0
JB 01H,SZTZ7 ;如果位地址01H為1(順時針正轉)就轉移
MOV A,XXSZ ;是反轉,裝入下限數值到A寄存器
ADD A,R4 ;加步長值
MOV MJS,A ;把下限值+步長值的結果暫時放入MJS
MOV A,@R0 ;裝入R0指向的RAM地址的調整對象數值
CJNE A,MJS,SZTZ5 ;調整對象數值與“下限值+步長值”比較
SZTZ5: JC SZTZ6 ;如果調整對象數值小于“下限值+步長值”(不夠減)就轉移
SUBB A,R4 ;等于或大于,減步長值
MOV @R0,A ;把計算結果放回去
LJMP SZTZ10
SZTZ6: MOV @R0,XXSZ ;不夠減了,直接放入下限值
LJMP SZTZ10
SZTZ7: MOV A,@R0 ;是正轉,裝入R0指向的RAM地址的調整對象數值
ADD A,R4 ;加步長值
CJNE A,SXSZ,SZTZ8 ;加完后與上限數值比較
SZTZ8: JC SZTZ9 ;如果小于就轉移
MOV @R0,SXSZ ;等于或大于,直接放入上限值
LJMP SZTZ10
SZTZ9: MOV @R0,A ;小于上限數值,把計算結果放回去
SZTZ10: CLR 00H ;把位地址00H置為0,表示已經處理編碼器旋轉動作
LJMP SZTZ
;----------------------------------------------------------------------------------------
;子程序:編碼器按鍵開關處理
;出口參數:A=1(按了1次);A=2(按了2次);A=3(按了3次);A=4長按達到了5秒;A=5長按達到了15秒
;----------------------------------------------------------------------------------------
KEY: MOV MJS,#15 ;放入等待時間,15秒
KEY1: MOV A,MJS ;裝入等待時間
JNZ KEY2 ;如果不為0就轉移,時間未到
MOV A,#5 ;為0,時間到了,放入5到A寄存器,長按達到了15秒
RET
KEY2: LCALL SKEY ;掃描按鍵
JC KEY1 ;如果C=1(按鍵還沒松開),就繼續掃描
CJNE A,#10,KEY3 ;按鍵松開了,剩余時間與10比較,不等于就轉移
LJMP KEY4 ;等于10,長按時間達到了5秒(15-10=5)
KEY3: JNC KEY5 ;大于10就轉移
KEY4: MOV A,#4 ;等于或小于10,放入4到A寄存器,長按時間達到了5秒以上
RET
KEY5: LCALL KEYA ;大于10,按下的時間小于5秒,掃描按鍵600毫秒
JZ KEY6 ;如果600毫秒內有按鍵動作就轉移
RET ;600毫秒內沒有按鍵動作,這時A=1(按了1次),退出
KEY6: LCALL KEYEX ;等待第二次按鍵松開
LCALL KEYA ;按鍵松開了,掃描按鍵600毫秒
JZ KEY7 ;如果600毫秒內有按鍵動作就轉移
MOV A,#2 ;600毫秒內沒有按鍵動作,A=2(按了2次)
RET
KEY7: LCALL KEYEX ;等待第三次按鍵松開
MOV A,#3 ;第三次按鍵松開了,A=3(按了3次)
RET
;------------------ 掃描按鍵開關600毫秒,有按鍵動作A=0,無按鍵動作A=1 ------------------
KEYA: PUSH 03H
MOV 03H,#60 ;等待600毫秒,10*60=600毫秒
KEYB: MOV A,SJJS ;裝入(10)毫秒計數
KEYC: CJNE A,SJJS,KEYD ;如果不相同就轉移,說明時間已經過了10毫秒
LCALL SKEY ;掃描按鍵
JC KEYE ;如果有按鍵動作(C=1)就轉移
LJMP KEYC
KEYD: DJNZ 03H,KEYB ;03H減1,不為0就轉移,繼續掃描
POP 03H
MOV A,#1 ;600毫秒等待時間已到,A=1沒有按鍵動作
RET
KEYE: POP 03H
CLR A ;600毫秒內有按鍵動作A=0
RET
;------------------ 等待按鍵松開 ------------------
KEYEX: LCALL SKEY ;掃描按鍵
JC KEYEX ;如果C=1(按鍵還沒松開),就繼續掃描
RET
;------------------ 按鍵開關掃描,未按C=0,已按下C=1 ------------------
SKEY: SETB EC11K ;按鍵開關設為高電平
JNB EC11K,SKEY1 ;為0(低電平)就轉移,表示按鍵開關已經被按下
SKEY0: CLR C ;為1(高電平),C置為0,沒有按鍵動作
LCALL WG ;喂狗
RET
SKEY1: PUSH 00H ;按鍵已被按下,延時10毫秒
PUSH 01H ;延時10毫秒
MOV 00H,#87 ;延時10毫秒
MOV 01H,#10 ;延時10毫秒
SKEY2: DJNZ 01H,SKEY2 ;延時10毫秒
DJNZ 00H,SKEY2 ;延時10毫秒
POP 01H ;延時10毫秒
POP 00H ;延時10毫秒
SETB EC11K ;延時結束后再次把按鍵開關設為高電平
JB EC11K,SKEY0 ;為1就轉移,按鍵開關未被有效按下
SETB C ;為1,按鍵動作有效,置C為1
LCALL WG ;喂狗
RET
;*************************** 以下為EEPROM操作子程序 **********************************
;STC89C51RC有4K字節的EEPROM,由8個扇區組成,每個扇區512字節,地址2000H-2FFFH
;第1扇區:2000H~21FFH,第2扇區:2200H~23FFH……第8扇區:2E00H~2FFFH
;-------------------------------------------
;讀一字節,A=讀出的數據
Byte_Read:
MOV IAP_CONTR,#ENABLE_IAP ;打開IAP功能,設置Flash操作等待時間(83H)
MOV IAP_CMD,#01 ;設置為IAP/ISP/EEPROM字節讀模式命令(1)
MOV IAP_TRIG,#46H ;先送46H
MOV IAP_TRIG,#0B9H ;再送B9H,ISP/IAP命令立即被觸發起動
NOP
MOV A,IAP_DATA ;讀出的數據在IAP_DATA單元中,送入累加器A
RET
;-------------------------------------------
;字節編程,A=需寫入的數據
Byte_Program:
MOV IAP_CONTR,#ENABLE_IAP ;打開IAP功能,設置Flash操作等待時間(83H)
MOV IAP_CMD,#02 ;設置為IAP/ISP/EEPROM字節編程模式命令(2)
MOV IAP_DATA,A ;要編程的數據先送進IAP_DATA寄存器
MOV IAP_TRIG,#46H ;先送46H
MOV IAP_TRIG,#0B9H ;再送B9H,ISP/IAP命令立即被觸發起動
RET
;-------------------------------------------
;擦除扇區
Sector_Erase:
MOV IAP_CONTR,#ENABLE_IAP ;打開IAP功能,設置Flash操作等待時間(83H)
MOV IAP_CMD,#03 ;設置為IAP/ISP/EEPROM扇區擦除模式命令(3)
MOV IAP_TRIG,#46H ;先送46H
MOV IAP_TRIG,#0B9H ;再送B9H,ISP/IAP命令立即被觸發起動
NOP
RET
;---------- 讀EEPROM保存的各項設置,如果沒有就設置為默認值并保存 ------------
REEP: LCALL RE00 ;讀EEPROM保存的各項設置
MOV A,SDDS ;裝入“上電就自動設定的定時時間(小時)”
JZ REEP0 ;如果是0就轉移,退出
MOV DSSJS,A ;放入“定時時間(小時)”
MOV DSSJM,#59 ;放入59到“定時時間(秒)”
REEP0: RET
RE00: MOV IAP_ADDRH,#020H ;從第一個扇區開始搜索,地址的高8位
RE01: MOV IAP_ADDRL,#0 ;從第一個扇區開始搜索,地址的低8位
LCALL Byte_Read ;讀第一個字節,返回:A=讀出的數據
CJNE A,FWBZ1,RE03 ;是否保存在當前扇區,不是就轉移到RE03
INC IAP_ADDRL ;EEPROM字節地址增1
LCALL Byte_Read ;讀第二個字節
CJNE A,FWBZ2,RE03 ;第二個字節是否相符
MOV R1,#ZRFZQ ;相符,從ZRFZQ開始放置讀出的設置值
MOV R2,#7 ;總共7個字節
RE02: INC IAP_ADDRL ;EEPROM字節地址增1
LCALL Byte_Read ;讀一個字節,返回:A=讀出的數據
MOV @R1,A ;放到R1指向的RAM地址
INC R1 ;RAM地址增1
DJNZ R2,RE02 ;未讀完就繼續
RET ;讀完了,退出
RE03: MOV A,IAP_ADDRH ;裝入扇區地址的高8位
ADD A,#2 ;扇區增1
MOV IAP_ADDRH,A ;放入IAP_ADDRH
CJNE A,#30H,RE01 ;如果未搜索完最后一個扇區+2(2EH+2=30H)就轉移,繼續搜索
LCALL SZMRZ ;已經搜索全部八個扇區,未找到保存的內容,設置為默認值
MOV R0,#8 ;總扇區數量,共8個扇區
LJMP WSET3 ;跳轉到WSET3保存設置
;------------------ 保存設置,不固定保存到某個扇區,各扇區輪流使用 ------------------
WSET: MOV R0,#8 ;扇區總數量,共8個扇區
MOV IAP_ADDRH,#020H ;從第一個扇區開始搜索上次保存的設置
WSET1: MOV IAP_ADDRL,#0 ;地址低位指向第一個字節
LCALL Byte_Read ;讀第一個字節,返回:A=讀出的數據
CJNE A,FWBZ1,WSET7 ;如果與EEPROM數據判斷標志1不相同就轉移
INC IAP_ADDRL ;第一個字節相同,EEPROM字節地址增1
LCALL Byte_Read ;讀第二個字節
CJNE A,FWBZ2,WSET7 ;如果與EEPROM數據判斷標志2不相同就轉移
MOV IAP_ADDRL,#0 ;是在當前扇區,地址指向扇區第一個字節
LCALL Sector_Erase ;擦除當前扇區,另換一個扇區保存
WSET2: MOV A,IAP_ADDRH ;裝入扇區地址高位到寄存器A
CJNE A,#020H,WSET3 ;當前扇區地址高位如果不是20H(第一個扇區)就轉移
MOV IAP_ADDRH,#30H ;是20H,把IAP_ADDRH設置為最后一個扇區+2(2EH+2=30H)
WSET3: DEC IAP_ADDRH ;減1
DEC IAP_ADDRH ;再減1,指向上一個扇區首址
MOV IAP_ADDRL,#0 ;低8位指向扇區第一個字節
LCALL Sector_Erase ;擦除整個扇區
MOV R1,#FWBZ1 ;要保存的內容始址
MOV R2,#9 ;共9個字節
WSET4: MOV A,@R1 ;裝入R1指向的RAM地址的內容到A
LCALL Byte_Program ;字節編程(寫入EEPROM)
INC IAP_ADDRL ;EEPROM地址加1
INC R1 ;RAM地址增1
DJNZ R2,WSET4 ;未保存完就繼續
MOV IAP_ADDRL,#0 ;保存完了,扇區地址低位指向0(當前扇區首址)
LCALL Byte_Read ;讀出來檢查看是否寫入成功
CJNE A,FWBZ1,WSET5 ;如果與EEPROM數據判斷標志1不相同就轉移
INC IAP_ADDRL ;EEPROM地址加1
LCALL Byte_Read ;讀第二個字節
CJNE A,FWBZ2,WSET5 ;如果與EEPROM數據判斷標志2不相同就轉移
RET ;成功了,退出
WSET5: DJNZ R0,WSET2 ;如果未試完8個扇區就轉移到WSET2繼續往前一個扇區寫
SETB 06H ;已經試完8個扇區,都失敗了,位地址06H置為1
MOV SSSC,#5 ;顯示E1五秒
MOV ZXM1,#0 ;消隱碼
MOV ZXM2,#079H ;E
MOV ZXM3,#006H ;1
MOV ZXM4,#0 ;消隱碼
LCALL DISP ;顯示
WSET6: MOV A,SSSC
LCALL WG ;喂狗
JNZ WSET6 ;等待SSSC為0秒
CLR 06H ;顯示結束,位地址06H置為0
RET
WSET7: MOV A,IAP_ADDRH ;裝入扇區地址高位
ADD A,#2 ;加2,指向下一個扇區首址
MOV IAP_ADDRH,A ;放回IAP_ADDRH
CJNE A,#30H,WSET1 ;如果未到最后一個扇區地址高位+2(2EH+2=30H)就轉移到WSET1繼續搜索
LJMP WSET3 ;是30H,已經搜索完所有扇區,未找到上次保存的數據,跳轉到WSET3保存當前設置
;***************************************** 以上為EEPROM操作子程序 ********************************************
;-------------------------------------------------------------------
;子程序:外部中斷INT0調用,根據條件控制可控硅、狀態LED指示燈
;-------------------------------------------------------------------
Control:MOV A,JCGLMC1
JZ CTL01
DEC JCGLMC1 ;JCGLMC1不為0就減1
CTL01: SETB LED ;先熄滅自然風LED指示燈
JNB 07H,CTL02 ;如果位地址07H位為0(不是固定慢速狀態)就轉移
MOV MSZS,MSZTZS ;是固定慢速狀態,把設置的轉速放入到MSZS
LJMP CTL03
CTL02: JNB 02H,CTL03 ;如果位地址02H為0(常速狀態)就轉移
CLR LED ;為1,自然風狀態,點亮LED指示燈
CTL03: MOV A,DSSJM ;裝入定時時間(秒)到寄存器A
JNZ CTL05 ;不是0就轉移
MOV A,DSSJF ;裝入定時時間(分)到寄存器A
JNZ CTL05 ;不是0就轉移
MOV A,DSSJS ;裝入定時時間(時)到寄存器A
JNZ CTL05 ;不是0就轉移
CTL04: SETB MOC ;定時時間為0,置MOC為高電平,斷電
RET
CTL05: JB 07H,CTL07 ;如果位地址07H位為1(處于固定慢速狀態)就轉移
JNB 02H,CTL06 ;如果位地址02H為0(常速狀態)就轉移,通電
MOV A,ZRFFS ;裝入自然風方式
JZ CTL07 ;如果為漸慢——漸快變化方式就轉移
MOV A,SJ ;是通/斷電方式,裝入自然風時電機常速通電時長
JZ CTL04 ;如果為0就轉移,斷電
CTL06: CLR MOC ;通電
RET
CTL07: MOV A,DDMC ;裝入斷電(截止)脈沖計數
JZ CTL08 ;如果是0就轉移
SETB MOC ;可控硅斷電
DEC DDMC ;計數減1
RET
CTL08: CLR MOC ;斷電(截止)脈沖計數已經為0,可控硅通電
MOV A,GLMC ;裝入過零信號脈沖計數
JNZ CTL09 ;不是0就轉移
MOV GLMC,MSZS ;是0,重新裝入調速級數(過零信號脈沖計數)
MOV DDMC,#2 ;設置斷電(截止)脈沖計數
RET
CTL09: DEC GLMC ;過零信號脈沖計數減1
RET
;---------------------------------------------------------------------------------------------
;子程序:T0中斷調用,檢查過零檢測脈沖,如果有故障就由本子程序控制可控硅、LED指示燈
;---------------------------------------------------------------------------------------------
JCGLMC: MOV A,JCGLMC1
JNZ JCGL1 ;JCGLMC1不為0就轉移
MOV JCGLMC1,#1 ;為0,過零檢測正常,重新放入檢查計數
MOV JCGLMC2,#10 ;重新放入計數,檢查10個周期(100毫秒)
RET
JCGL1: MOV A,JCGLMC2
JZ JCGL2 ;JCGLMC2是0就轉移,說明已經檢查了10個周期(100毫秒)
DEC JCGLMC2 ;減1(10毫秒)
RET
JCGL2: MOV JCGLMC2,#10 ;為0,無過零脈沖,過零檢測有故障或不存在,重新放入檢查計數
SETB LED ;先熄滅自然風LED指示燈
JNB 02H,JCGL3 ;如果位地址02H為0(常速狀態)就轉移
JB 07H,JCGL3 ;如果位地址07H位為1(固定慢速狀態)就轉移
CLR LED ;為自然風狀態,點亮LED指示燈
JCGL3: MOV A,DSSJM ;裝入定時時間(秒)到寄存器A
JNZ JCGL5 ;不是0就轉移
MOV A,DSSJF ;裝入定時時間(分)到寄存器A
JNZ JCGL5 ;不是0就轉移
MOV A,DSSJS ;裝入定時時間(時)到寄存器A
JNZ JCGL5 ;不是0就轉移
JCGL4: SETB MOC ;是0,置MOC為高電平,斷電
RET
JCGL5: JNB 02H,JCGL6 ;如果位地址02H為0(常速狀態)就轉移,通電
JB 07H,JCGL6 ;如果位地址07H位為1(固定慢速狀態)就轉移,通電
MOV A,SJ ;裝入自然風時電機常速通電時長
JZ JCGL4 ;如果為0就轉移,斷電
JCGL6: CLR MOC ;通電
RET
;------------------------------------------------------------------------------------------
;子程序:T0中斷調用,時間計數及倒計時處理、自然風速度漸變控制
;------------------------------------------------------------------------------------------
TIME: LCALL TSD ;自然風時的漸快、漸慢變化控制
MOV A,SJJS ;裝入(10)毫秒時間計數
JZ TIME2 ;如果是0就轉移
DEC SJJS ;不是0,減1
CJNE A,#50,TIME1 ;如果不是50就轉移退出
CPL 05H ;位地址第05位取反,數字及冒號閃爍時用,每0.5秒取反一次
TIME1: RET
TIME2: CPL 05H ;是0,位地址第05位取反,數字及冒號閃爍時用,每0.5秒取反一次
MOV DPTR,#HMJS ;把定義的時間計數值地址裝入數據指針DPTR
MOVC A,@A+DPTR ;從程序存儲區裝入時間計數值到A寄存器
MOV SJJS,A ;時間計數值放入SJJS,重新計數
MOV A,MJS ;裝入秒計數
JZ TIME3 ;如果是0就轉移
DEC MJS ;不是0,減1秒
TIME3: MOV A,SSSC ;裝入閃爍時長秒計數
JZ TIME4 ;如果是0就轉移
DEC SSSC ;不是0,減1秒
TIME4: LCALL ZRFCL ;自然風時間處理
MOV A,DSSJM ;裝入定時時間(秒)到寄存器A
JZ TIME6 ;如果是0就轉移
CJNE A,#59,TIME5 ;如果不是59秒就轉移
MOV A,DSSJF ;是59秒,檢查“時”
JNZ TIME5 ;不是0就轉移
MOV A,DSSJS ;檢查“分”
JNZ TIME5 ;不是0就轉移
MOV DSSJM,A ;“時、分”都是0,把“秒”也清零
RET
TIME5: DEC DSSJM ;不是0,減1秒
RET
TIME6: MOV A,DSSJF ;裝入定時時間(分)到寄存器A
JZ TIME7 ;如果是0就轉移
DEC DSSJF ;不是0,減1分
MOV DSSJM,#59 ;把59放入定時時間(秒)
RET
TIME7: MOV A,DSSJS ;裝入定時時間(時)到寄存器A
JZ TIME8 ;如果是0就轉移,退出
DEC DSSJS ;不是0,小時減1
MOV DSSJM,#59 ;把59放入定時時間(秒)
MOV DSSJF,#59 ;把59放入定時時間(分)
TIME8: RET
;自然風時間處理
ZRFCL: MOV A,SJ ;裝入自然風時電機常速通電時間到寄存器A
JZ ZRFCL1 ;是0就轉移
DEC SJ ;減1秒
ZRFCL1: MOV A,ZQ ;裝入自然風變化周期時長
DEC ZQ ;先減1
JNZ ZRFCL3 ;如果不是0就轉移
MOV ZQ,ZRFZQ ;是0,重新裝入設置值
MOV SJ,ZRFSJ ;是0,重新裝入設置值
LCALL JBJS ;設置漸變調整的間隔計數(T0中斷次數)和允許/禁止標志
MOV MSZS,#20 ;放入最大轉速級數
CLR 09H ;位地址09H置0,漸慢調整
ZRFCL2: RET
ZRFCL3: CJNE A,JKTZSJ,ZRFCL4 ;如果“漸快調整時間”未到就轉移
LCALL JBJS ;設置漸變調整的間隔計數(T0中斷次數)和允許/禁止標志
MOV MSZS,MSZTZS ;放入設置的慢速狀態轉速
SETB 09H ;位地址09H置1,漸快調整
ZRFCL4: RET
;自然風時的漸快、漸慢變化控制
TSD: JB 08H,TSD1 ;如果位地址08H為1(允許漸變控制)就轉移
RET
TSD1: MOV A,MSZS
CJNE A,#12,TSD2
TSD2: JC TSD3 ;小于12級就轉移,按設置的間隔計數(T0中斷次數)調速
MOV A,JBJS2 ;轉速級數12以上調速時,變化不明顯,所以每120毫秒就調一次
SUBB A,JBJS1 ;設置的漸變調整間隔計數(T0中斷次數)減已過去的時間
CJNE A,#12,TSD3 ;不是12(120毫秒)就轉移,按設置的間隔計數(T0中斷次數)調速
LJMP TSD4 ;到120毫秒了,調速。
TSD3: MOV A,JBJS1 ;裝入漸變調整間隔計數(T0中斷次數)
JZ TSD4 ;如果是0(時間到)就轉移
DEC JBJS1 ;非0,時間未到,減1
RET
TSD4: MOV JBJS1,JBJS2 ;重新放入設置的漸變調整間隔計數(T0中斷次數)到JBJS1
MOV A,MSZS ;裝入轉速級數
JB 09H,TSD6 ;如果位地址09H為1(漸快)就轉移
CJNE A,MSZTZS,TSD5 ;漸慢,如果還沒減到“設置的慢速狀態轉速”就轉移
CLR 08H ;位地址08H置為0,漸變結束
RET
TSD5: DEC MSZS ;減1(漸慢)
RET
TSD6: CJNE A,#20,TSD7 ;如果還沒加到最大轉速級數20就轉移
CLR 08H ;位地址08H置為0,漸變結束
RET
TSD7: INC MSZS ;加1(漸快)
RET
;設置漸變調整的間隔計數(T0中斷次數)和標志
JBJS: JB 07H,JBJS_1 ;如果位地址07H位為1(固定慢速狀態)就轉移
JB 02H,JBJS_2 ;如果位地址02H為1(自然風狀態)就轉移
JBJS_1: CLR 08H ;是慢速狀態或常速狀態,位地址08H置為0,禁止漸變控制
RET
JBJS_2: MOV A,MSZTZS ;裝入設置的慢速狀態轉速
CJNE A,#12,JBJS_3
JBJS_3: JNC JBJS_1 ;等于或大于12就轉移,變化不明顯,無漸變控制必要
MOV A,ZRFZQ ;裝入自然風變化周期(10~60秒)
MOV B,#2
DIV AB ;除2
MOV JKTZSJ,A ;得出漸快調整的開始時間(5~30)
DEC A ;減1,12級以上另外調速(1秒內完成)
CJNE A,#26,JBJS_4 ;漸變的單個方向時間長度(4~29)是否大于26
JBJS_4: JC JBJS_5 ;小于26就轉移
MOV A,#25 ;等于或大于26,修改為25
JBJS_5: MOV B,#10
MUL AB ;乘10后結果為40~250
MOV B,A ;放入B寄存器
MOV A,#12 ;最大級數11+1(12級以上不進行漸變控制,所以最大為11)
SUBB A,MSZTZS ;減設置的慢速狀態轉速,得出要調整的級數數量(1~11)
XCH A,B ;A、B寄存器內容交換
DIV AB ;除級數數量(1~11)
CJNE A,#26,JBJS_6 ;
JBJS_6: JC JBJS_7 ;商小于26就轉移
MOV A,#25 ;商等于或大于26,修改為25
JBJS_7: XCH A,B ;A、B寄存器內容交換
JZ JBJS_9 ;如果余數為0就轉移
DEC A ;余數不為0,減1,修正誤差
CJNE A,#6,JBJS_8 ;
JBJS_8: JC JBJS_9 ;余數小于6就轉移
MOV A,#5 ;余數等于或大于6,修改為5
JBJS_9: MOV JBJS1,A ;暫時放入JBJS1
XCH A,B ;A、B寄存器內容交換
MOV B,#10
MUL AB ;商乘10
ADD A,JBJS1 ;加上余數,得出間隔計數(T0中斷次數)
MOV JBJS2,A
SETB 08H ;位地址08H置為0,允許漸變控制
RET
;------------------------------------------------------------------------------------------
;子程序:T0中斷調用,顯示定時時間及各項設置的內容
;------------------------------------------------------------------------------------------
DISPLAY:JB 06H,DPYSZ1 ;如果位地址06H為1就轉移退出,主程序顯示88:88或E1
MOV A,DISPL ;裝入要顯示的目標
JZ DISPL0 ;如果是0(顯示定時時間)就轉移
DPYSZ: PUSH ACC
MOV DPTR,#SEGTAB ;查表獲取字形碼
MOVC A,@A+DPTR ;查表獲取字形碼
MOV ZXM1,A ;項目編號字形碼放到待發送TM1637區1
MOV ZXM2,#40H ;放入“-”的字形碼到待發送TM1637區2
POP ACC
DEC A ;減1
PUSH 01H
MOV R1,#ZRFZQ ;各項設置值始址
ADD A,R1 ;加上項目號
MOV R1,A ;得出設置項目的實際地址放入R1
MOV A,@R1 ;裝入設置值
POP 01H
MOV B,A ;放入B寄存器
CJNE A,XSHC1,DPYSZ3 ;當前設置值與顯示緩存1不相同就轉移,立即顯示
MOV A,SJJS ;相同,裝入時間計數
JNZ DPYSZ2 ;不是0就轉移,每半秒(遇到50或0)顯示一次
LJMP DPYSZ3 ;是0,顯示
DPYSZ1: RET
DPYSZ2: CJNE A,#50,DPYSZ1 ;不是50就轉移退出,每半秒(遇到50或0)顯示一次
DPYSZ3: MOV XSHC1,B ;當前設置值放入顯示緩存1
JNB 04H,DPYSZ4 ;如果位地址04H為0(不閃爍)就轉移
JNB 05H,DPYSZ4 ;為1,閃爍顯示,如果位地址05H為0(顯示)就轉移
CLR A ;為1,處于閃爍顯示中的“不顯示”狀態,放入消隱碼
MOV ZXM1,A ;放入消隱碼
MOV ZXM2,A ;放入消隱碼
MOV ZXM3,A ;放入消隱碼
MOV ZXM4,A ;放入消隱碼
LJMP disp ;跳轉到disp,發送4個字節數據到TM1637顯示
DPYSZ4: MOV A,B ;當前設置值放入A寄存器
LCALL DISPL6 ;轉換并獲取字形碼放到待發送TM1637區3和4
LJMP disp ;跳轉到disp,發送4個字節數據到TM1637顯示
DISPL0: MOV A,DSSJS ;顯示定時時間,裝入定時時間(時)
CJNE A,XSHC1,DISPL3 ;定時時間(時)與顯示緩存1不相同就轉移,顯示
MOV A,DSSJF
CJNE A,XSHC2,DISPL3 ;定時時間(分)與顯示緩存2不相同就轉移,顯示
MOV A,SJJS ;時、分都相同,裝入(10)毫秒時間計數
JNZ DISPL2 ;不是0就轉移
LJMP DISPL3 ;是0,顯示,每半秒(遇到50或0)顯示一次
DISPL1: RET
DISPL2: CJNE A,#50,DISPL1 ;不是50就轉移,每半秒(遇到50或0)顯示一次
DISPL3: MOV XSHC1,DSSJS ;當前時間放入顯示緩存1
MOV XSHC2,DSSJF ;當前時間放入顯示緩存2
MOV A,DSSJM ;
JNZ DISPL4 ;檢查當前定時時間是否全部為0,不是就轉移
MOV A,DSSJF ;
JNZ DISPL4 ;檢查當前定時時間是否全部為0,不是就轉移
MOV A,DSSJS ;
JNZ DISPL4 ;檢查當前定時時間是否全部為0,不是就轉移
CLR 05H ;定時時間為0,把位地址05H置為0,冒號不閃爍顯示
DISPL4: MOV A,DSSJS ;裝入“時”
MOV B,#10 ;轉換為BCD碼
DIV AB ;轉換為BCD碼
MOV DPTR,#SEGTAB ;查表獲取字形碼
MOVC A,@A+DPTR ;查表獲取字形碼
MOV ZXM1,A ;字形碼放入待發送TM1637區1
XCH A,B ;A、B寄存器內容交換
MOVC A,@A+DPTR ;查表獲取字形碼
JB 05H,DISPL5 ;如果05H為1就轉移,不顯示冒號
ORL A,#10000000B ;為0,把最高位置為1,顯示冒號(字形碼的最高位為1就顯示冒號)
DISPL5: MOV ZXM2,A ;放入待發送TM1637區2
MOV A,DSSJF ;裝入“分”
LCALL DISPL6 ;轉換并獲取字形碼放到待發送TM1637區3和4
LJMP disp ;跳轉到disp,發送4個字節數據到TM1637顯示
DISPL6: MOV B,#10 ;轉換為BCD碼
DIV AB ;轉換為BCD碼
MOV DPTR,#SEGTAB ;查表獲取字形碼
MOVC A,@A+DPTR ;查表獲取字形碼
MOV ZXM3,A ;字形碼放入待發送TM1637區3
XCH A,B ;A、B寄存器內容交換
MOVC A,@A+DPTR ;查表獲取字形碼
MOV ZXM4,A ;字形碼放入待發送TM1637區4
RET
;------------------ 發送4個字節數據到TM1637顯示,地址自動加1 ------------------
disp: LCALL Srt
MOV A,#040H ;數據命令設置40H:地址自動加1,寫數據到顯示寄存器
LCALL Writebyte ;發送一個字節
LCALL Stop
NOP
LCALL Srt
MOV A,#0C0H ;地址命令設置C0H:初始地址為00H
LCALL Writebyte ;發送一個字節
PUSH 01H
PUSH 06H
MOV 06H,#4 ;發送4個字節數據
MOV R1,#ZXM1 ;等待發送的字形碼始址
disp1: MOV A,@R1 ;裝入要發送的字形碼
LCALL Writebyte ;發送一個字節
INC R1 ;地址加1
DJNZ 06H,disp1 ;如果還未發送完就繼續
POP 06H
POP 01H
LCALL Stop
LCALL Srt
MOV A,SMGLD ;裝入設置的數碼管亮度(1~8)
ADD A,#087H ;加上87H后即為對應的亮度控制命令88H~8FH
LCALL Writebyte ;按設置的亮度開顯示
LJMP Stop
;------------------ 發送8bit(一個字節)數據到TM1637,A=要發送的數據,從低位開始 ------------------
Writebyte:
PUSH 00H
MOV 00H,#8 ;發送8位數據
WBY1: CLR CLK ;拉低CLK
JNB ACC.0,WBY2 ;A寄存器的低位(0位)如果為0就轉移
SETB DIO ;為1,拉高DIO
SJMP WBY3
WBY2: CLR DIO ;為0,拉低DIO
WBY3: NOP
NOP
NOP
NOP
NOP
SETB CLK ;拉高CLK
CLR C ;進位標志清0
RRC A ;A寄存器內容帶進位循環右移
DJNZ 00H,WBY1 ;如果還未發送完8bit數據就繼續
WBY4: CLR CLK ;8位數據發送完了
NOP
MOV 00H,#05 ;設置等待應答信號計數值,防止萬一與TM1637通訊失敗而造成死循環
WBY5: DEC 00H ;減1,正常情況下ACK應答信號很快,第一次減1就會有應答
MOV A,00H ;裝入計數值到A
JZ WBY6 ;如果為0就轉移退出,說明與TM1637通訊失敗,或TM1637不存在
JB DIO,WBY5 ;不為0,判斷TM1637發過來的ACK應答信號,未應答(為1,高電平)就轉移
WBY6: POP 00H
NOP
NOP
NOP
SETB CLK
NOP
NOP
NOP
RET
;------------------ Start子程序 ------------------
Srt: SETB DIO ;拉高DIO
SETB CLK ;拉高CLK
NOP
NOP
NOP
NOP
NOP
SETB DIO ;拉高DIO
NOP
NOP
NOP
NOP
NOP
CLR DIO ;拉低DIO
NOP
NOP
NOP
NOP
NOP
CLR CLK ;拉低CLK
RET
;------------------ Stop子程序 ------------------
Stop: CLR CLK
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
CLR DIO
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
SETB CLK
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
SETB DIO
NOP
NOP
NOP
NOP
NOP
CLR CLK
CLR DIO
RET
;------------------ 字形表 ------------------
SEGTAB:
DB 00111111B ;0(3FH)
DB 00000110B ;1(06H)
DB 01011011B ;2(5BH)
DB 01001111B ;3(4FH)
DB 01100110B ;4(66H)
DB 01101101B ;5(6DH)
DB 01111101B ;6(7DH)
DB 00000111B ;7(07H)
DB 01111111B ;8(7FH)
DB 01101111B ;9(6FH)
DB 01110111B ;A(77H)
DB 01111100B ;B(7CH)
DB 00111001B ;C(39H)
DB 01011110B ;D(5EH)
DB 01111001B ;E(79H)
DB 01110001B ;F(71H)
DB 00000000B ;消隱碼(00)
;------------------------------------------------------------------------------------------
END
壓縮文件的內容:
壓縮文件內容.png (2.67 KB, 下載次數: 78)
下載附件
2020-7-18 08:10 上傳
電風扇長定時+自然風.rar
(149.27 KB, 下載次數: 80)
2020-7-18 08:10 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|