久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 6863|回復: 6
打印 上一主題 下一主題
收起左側

單片機+TM1637顯示模塊+EC11編碼器,電風扇長定時+自然風升級版 源程序

  [復制鏈接]
跳轉到指定樓層
樓主
上次制作的STC89C51RC單片機電風扇長定時+自然風,一直覺得不自然,現在升級加了個“漸慢——漸快”變化方式和慢速檔(按編碼器開關3次快速進入轉速調整),用起來不那么生硬,仍然保留間歇通/斷電方式。升級版需增加一個過零檢測電路接到外部中斷INT0,編碼器的A、B、K改接P3.3(INT1)、P3.4、P3.5,不能用按鍵代替編碼器了,轉速調整共設20級,再往上調變化不明顯,意義不大。改變可控硅導通角的調速方式電機會產生嗡嗡響的噪音,所以采用每間隔1~20個過零檢測信號脈沖,截止一個正半周一個負半周的調速方式,但也有缺點,低速時電機會有抖動現象,只要速度不調得太低,影響不大。本人只知道一點點匯編語言,別的語言也不懂,從自學編程到現在,算起來平均一年編程不到一次,并不熟練,應該會有很多不規范和羅嗦的地方


電路原理圖:




單片機匯編語言源代碼:
;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

壓縮文件的內容:


電風扇長定時+自然風.rar (149.27 KB, 下載次數: 80)




評分

參與人數 1黑幣 +90 收起 理由
admin + 90 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏7 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:89286 發表于 2020-7-19 02:20 | 只看該作者
Thanks for sharing
回復

使用道具 舉報

板凳
ID:23844 發表于 2021-1-30 17:49 | 只看該作者
下載一個學習仿制玩玩,謝樓主分享
回復

使用道具 舉報

地板
ID:951974 發表于 2021-8-19 21:29 | 只看該作者
匯編,,厲害了 word鍋
回復

使用道具 舉報

5#
ID:97678 發表于 2021-8-21 10:27 | 只看該作者
我用可控硅控制和對電機調速,每次開機時,電機都是有嗡嗡的聲音。幾秒鐘后,才正常,怎么可以解決?
回復

使用道具 舉報

6#
ID:961733 發表于 2021-8-22 11:38 | 只看該作者

下載一個學習仿制玩玩,謝樓主分享
回復

使用道具 舉報

7#
ID:1111684 發表于 2024-7-30 19:30 | 只看該作者
最近才看到了樓主本貼,對以過零檢測獲得脈沖而截止電源的若干個周期的調速方式極為好奇,由于本人不懂匯編語言,無法移植到其他STC芯片,只好購買STC89C52RC芯片重構建樓主分享的裝置,由于光耦合零件尚未送達,今天將MPU,顯示屏TM1637,編碼器連接好,開始測試軟件的界面架構,目前看到,軟件的界面架構全部正常可用,體會到樓主設計如此復雜的界面架構代碼能力高超,佩服!佩服!后續光耦合零件送達后,完成這個裝置,會評測對比這種調速方式與改變可控硅導通角的調速方式的優劣差異,待續。。。。。
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 99精品免费久久久久久日本 | 99精品国自产在线 | 国产精品伦理一区二区三区 | 免费黄色的视频 | 波多野结衣先锋影音 | 欧美激情精品久久久久久免费 | 亚洲女人的天堂 | 日韩久久网 | 91观看| 国产日韩一区二区三区 | 欧美一区二区三区免费在线观看 | 久久久久网站 | 色本道 | 美女爽到呻吟久久久久 | 国产成人精品久久二区二区 | 91视频日本| 亚洲第一天堂 | 国产精品视频免费观看 | 欧美区日韩区 | 亚州av | 天天拍天天射 | 国产一卡二卡三卡 | 久久一二| 亚洲色片网站 | 在线中文字幕国产 | 亚洲黄色一级 | 中文字幕精品一区 | 国产精品美女一区二区 | 国产精品久久性 | 欧美日韩三区 | 一区二区三区国产 | 91视频播放 | 国产精品1区 | 日韩电影在线一区 | 五月天天丁香婷婷在线中 | 中文字幕精品一区 | 久久免费精品视频 | 国产精品美女一区二区 | 91视频亚洲| 午夜无码国产理论在线 | 国产在线观看一区二区 |