电风扇定时时间60分钟觉得短了些,如果一直开的话,吹到天亮人也难受,能定时个三四小时比较合适,手头上有若干闲置了十余年的STC89C51RC,所以就用它来制作个长定时器,使用EC11带开关旋转编码器调时间,很便宜,一块多钱一只还包邮,也可以用按键代替编码器,只是调时间的时候不如编码器那么方便快捷,显示用TM1637四位数码管显示模块,3块钱包邮,便宜又好用,它能显示到99小时,所以最长定时可达99小时59分59秒,虽然实际使用不需要那么长的定时。制作好后不对电风扇作任何改动,只是把双向可控硅的T1、T2分别与原定时器那两根线接好就可以了,也就是与原定时器并联,把原定时器调到OFF位置。单片机改用其他型号的话,需要改动一些地方,如EEPROM操作、扇区地址、数量、特殊功能寄存器地址、看门狗预分频数等等.
电路原理图如下:
单片机源程序如下:
- ;===================================================================================
- ;TM1637显示模块,EC11编码器,电风扇长定时+自然风汇编程序
- ;杨小强,2020年6月
- ;单片机:STC89C51RC,晶振:11.0592MHz
- ;显示:(TM1637)4位数码管显示模块
- ;调整、设置:EC11带开关5脚旋转编码器,也可以用按键代替
- ;电源:闲置5V手机充电器
- ;
- ;最长定时99小时59分59秒,简单的采用间歇通/断电方式模拟自然风,周期可调,用可控硅控制通断。
- ;
- ;按编码器开关1次:正常/自然风切换,自然风状态时LED指示灯亮,可控硅间歇通断电
- ;按编码器开关2次:定时时间清零,风扇电机断电,两次按键动作之间不大于0.6秒
- ;
- ;长按编码器开关5秒以上15秒以内,松开按键后进入设置状态,退出设置状态:设置完第五项后按编码器开关、或任意一
- ;项中停15秒无任何操作,就自动保存并退出。根据数码管左边显示的数字进行以下各项设置,通过旋转编码器加或减,
- ;按编码器开关进入下一项设置:
- ;一、显示1——设置自然风状态时,通断电周期时长,5~30秒,默认为10秒
- ;二、显示2——设置自然风时电机通电时长,最短为2秒;最长为上一项所设的周期减3秒,比如上一项设置的周期为10秒,
- ; 则本项最多可以设置到7秒;
- ;三、显示3——设置3小时以下定时调整时,编码器每转动一格的增(减)值:5、10、15、20、25、30分钟,默认10分钟,
- ; 3小时以上增(减)值30分钟;10小时以上增(减)值1个小时;20小时以上增(减)值2个小时
- ;四、显示4——设置电风扇插电就自动填入的定时时间,0~30小时,默认8小时
- ;五、显示5——设置数码管亮度,1~8级,默认为3级
- ;
- ;长按编码器开关15秒:恢复各项默认设置,数码管显示88:88
- ;
- ;设置保存失败显示5秒E1
- ;
- ;--------------------------- 端口定义 ---------------------------
- CLK EQU P1.5 ;接显示模块TM1637的CLK
- DIO EQU P1.6 ;接显示模块TM1637的DIO
- EC11A EQU P3.2 ;接编码器的A引脚,外部中断INT0,也可以接一个按键代替
- EC11B EQU P3.3 ;接编码器的B引脚,外部中断INT1,也可以接一个按键代替
- EC11K EQU P3.4 ;接编码器的按键开关引脚
- 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;0=正常
- ;(20H)第7位:1=显示5秒E1;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 ;数码管亮度
- DSSJS EQU 029H ;定时时间,时
- DSSJF EQU 02AH ;定时时间,分
- DSSJM EQU 02BH ;定时时间,秒
- ZQ EQU 02CH ;T0中断使用,自然风通断电周期时长
- SJ EQU 02DH ;T0中断使用,自然风时电机通电时长
- SJJS EQU 02EH ;时间计数,每10毫秒减1,为0后定时时间减1秒,重新把HMJS处定义的计数值放入这里
- MJS EQU 02FH ;按键处理时用,秒计数,每秒减1,直到为0
- SSSC EQU 030H ;闪烁时长,每秒减1,直到为0
- XSHC1 EQU 031H ;上次显示的内容,与当前不同就立即显示,相同就每0.5秒显示一次
- XSHC2 EQU 032H ;上次显示的内容,与当前不同就立即显示,相同就每0.5秒显示一次
- XXSZ EQU 033H ;下限数值,进行各项设置时用
- SXSZ EQU 034H ;上限数值,进行各项设置时用
- ZXM1 EQU 035H ;显示用,待发送到TM1637的字形码1
- ZXM2 EQU 036H ;显示用,待发送到TM1637的字形码2
- ZXM3 EQU 037H ;显示用,待发送到TM1637的字形码3
- ZXM4 EQU 038H ;显示用,待发送到TM1637的字形码4
- DSZJ EQU 039H ;加减定时时间使用
- DISPL EQU 03AH ;设置要显示的目标:
- ;0=显示定时时间
- ;1=显示1——设置自然风状态时的通断电周期时长
- ;2=显示2——设置自然风时电机通电时长
- ;3=显示3——设置3小时以下定时调整时,编码器每转动一小格的增(减)值
- ;4=显示4——设置上电自动填入的定时时间
- ;5=显示5——设置数码管亮度
- ;--------------- 看门狗、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 Control ;根据条件控制自然风LED指示灯和可控硅(或继电器)
- LCALL DISPLAY ;显示
- POP PSW
- POP ACC
- RETI
- ;--------------- 外部中断INT0,P3.2接编码器A引脚 ---------------
- INT_0: PUSH PSW
- JB 00H,INT0_1 ;如果位地址0H为1就退出中断处理程序,等待主程序处理
- SETB 00H ;把位地址00H置为1,表示编码器已转动,等待主程序处理
- SETB 01H ;是顺时针正转,把位地址01H置为1
- INT0_1: POP PSW
- RETI
- ;--------------- 外部中断INT1,P3.3接编码器B引脚 ---------------
- INT_1: PUSH PSW
- JB 00H,INT1_1 ;如果位地址0H为1就退出中断处理程序,等待主程序处理
- SETB 00H ;把位地址00H置为1,表示编码器已转动,等待主程序处理
- CLR 01H ;是逆时针反转,把位地址01H置为0
- INT1_1: POP PSW
- RETI
- ;--------------- 设置各项默认值 ----------------
- SZMRZ: MOV ZRFZQ,#10 ;自然风状态时,通断电周期时长(秒)
- MOV ZRFSJ,#5 ;自然风时电机通电时长(秒)
- MOV BMQZJ,#10 ;编码器每转动一小格的+、-值(分钟))
- MOV SDDS,#8 ;上电就自动设定的定时时间(小时)
- MOV SMGLD,#3 ;数码管亮度,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 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,#5,SAT1 ;不管是什么原因复位,只要RAM不被改变就跳过初始化,继续运行
- 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,显示定时时间
- CLR 07H ;位地址07H置为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次(正常/自然风切换)就转移
- CPL 02H ;是按1次,位地址第02位取反,自然风/正常状态切换
- LJMP START2
- START4: CJNE A,#2,START5 ;如果不是2(定时时间置为零)就转移
- LCALL DSSJQL ;是按2次,定时时间清零
- LJMP START2
- START5: CJNE A,#3,START7 ;如果不是3(恢复默认设置)就转移
- 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 ;是15秒无操作自动保存返回,设置结束
- START9: MOV DISPL,#3 ;3=显示“3——设置2小时以下定时调整时,编码器每转动一格的增(减)值”
- LCALL BMQZJZ ;编码器增减值设置
- JNZ STARTA ;如果是按下编码器按键开关返回,就转移,进行下一项设置
- LJMP START2 ;是15秒无操作自动保存返回,设置结束
- STARTA: MOV DISPL,#4 ;4=显示“4——设置插电自动填入的定时时间”
- LCALL SDDSSJ ;上电定时时间设置(小时)
- JNZ STARTB ;如果是按下编码器按键开关返回,就转移,进行下一项设置
- LJMP START2 ;是15秒无操作自动保存返回,设置结束
- STARTB: MOV DISPL,#5 ;5=显示“5——设置数码管亮度”
- LCALL LDSZ ;亮度设置
- LJMP START2
- ;--------------------------------------------------------------------------------------------------------
- ;子程序:根据编码器旋转方向加减定时时间。
- ;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
- ;----------------------------------------------------------------------------------------
- ;设置自然风通断电周期时长,5~30秒
- ;----------------------------------------------------------------------------------------
- ZQSZ: MOV XXSZ,#5 ;下限为5秒
- MOV SXSZ,#30 ;上限为30秒
- LJMP LDSZ1
- ;----------------------------------------------------------------------------------------
- ;设置自然风时电机通电时长,最短为2秒;最长为上一项(自然风通断电周期)所设的周期减3秒
- ;----------------------------------------------------------------------------------------
- TDSC: MOV A,ZRFZQ ;装入“自然风通断电周期”
- SUBB A,#3 ;减3秒
- MOV SXSZ,A ;放入上限值
- MOV XXSZ,#2 ;下限为2秒
- LJMP LDSZ1
- ;----------------------------------------------------------------------------------------
- ;设置2小时以下定时调整时,编码器每转动一小格的增(减)值,5、10、15、20、25、30分钟
- ;----------------------------------------------------------------------------------------
- BMQZJZ: MOV XXSZ,#5 ;下限为5
- MOV SXSZ,#30 ;上限为30
- MOV R4,#5 ;调整时的加减步长值
- LJMP SZTZ
- ;----------------------------------------------------------------------------------------
- ;设置插电就自动填入的定时时间,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 ;调整时的加减步长值
- LJMP SZTZ
- ;----------------------------------------------------------------------------------------
- ;子程序:根据XXSZ、SXSZ设定的上下限范围、编码器旋转方向,调整DISPL指向的对象。
- ;无操作10秒后开始闪烁显示,15秒自动保存并退出;有按键动作就保存并退出
- ;入口参数:下限值放入XXSZ;上限值放入SXSZ;R4=加、减步长值
- ;出口参数:15秒无操作自动保存退出A=0;按编码器按键开关保存退出A=1
- ;----------------------------------------------------------------------------------------
- SZTZ: MOV MJS,#15 ;放入15秒
- CLR 03H ;位地址03H置为0,允许检查剩余时间
- SZTZ1: LCALL SKEY ;扫描编码器按键开关
- JNC SZTZ2 ;没有按键动作(C=0)就转移
- CLR 04H ;有按键动作,把位地址04H置为0,不闪烁显示
- LCALL WSET ;保存设置
- LCALL KEYEX ;等待按键松开
- LCALL SKEY1 ;延时10毫秒
- LCALL SKEY1 ;
- LCALL SKEY1 ;共延时30毫秒
- MOV A,#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长按达到了15秒;A=4长按达到了5秒
- ;----------------------------------------------------------------------------------------
- KEY: MOV MJS,#15 ;放入等待时间,15秒
- KEY1: MOV A,MJS ;装入等待时间
- JNZ KEY2 ;如果不为0就转移,时间未到
- MOV A,#3 ;为0,时间到了,放入3到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 ;等待第二次按键松开
- MOV A,#2 ;按键松开了,A=2(按了2次)
- 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,#5 ;总共5个字节
- 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,#7 ;共7个字节
- 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 07H ;已经试完8个扇区,都失败了,位地址07H置为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 07H ;显示结束,位地址07H置为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操作子程序 ********************************************
- ;------------------------------------------------------------------------------------------
- ;子程序:T0中断调用,时间计数及倒计时处理
- ;------------------------------------------------------------------------------------------
- TIME: 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 TIME20 ;如果是0就转移
- DEC MJS ;不是0,减1秒
- TIME20: MOV A,SSSC ;装入闪烁时长秒计数
- JZ TIME3 ;如果是0就转移
- DEC SSSC ;不是0,减1秒
- TIME3: MOV A,SJ ;装入自然风时电机通电时长到寄存器A
- JZ TIME4 ;如果是0就转移
- DEC SJ ;不是0,减1秒
- TIME4: MOV A,ZQ ;装入自然风变化周期时长到寄存器A
- DEC ZQ ;先减1
- JNZ TIME5 ;如果不是0就转移
- MOV ZQ,ZRFZQ ;是0,重新装入设置值
- MOV SJ,ZRFSJ ;是0,重新装入设置值
- TIME5: MOV A,DSSJM ;装入定时时间(秒)到寄存器A
- JZ TIME7 ;如果是0就转移
- CJNE A,#59,TIME6 ;如果不是59秒就转移
- MOV A,DSSJF ;是59秒,检查“时”
- JNZ TIME6 ;不是0就转移
- MOV A,DSSJS ;检查“分”
- JNZ TIME6 ;不是0就转移
- MOV DSSJM,A ;“时、分”都是0,把“秒”也清零
- RET
- TIME6: DEC DSSJM ;不是0,减1秒
- RET
- TIME7: MOV A,DSSJF ;装入定时时间(分)到寄存器A
- JZ TIME8 ;如果是0就转移
- DEC DSSJF ;不是0,减1分
- MOV DSSJM,#59 ;把59放入定时时间(秒)
- RET
- TIME8: MOV A,DSSJS ;装入定时时间(时)到寄存器A
- JZ TIME9 ;如果是0就转移,退出
- DEC DSSJS ;不是0,小时减1
- MOV DSSJM,#59 ;把59放入定时时间(秒)
- MOV DSSJF,#59 ;把59放入定时时间(分)
- TIME9: RET
- ;---------------------------------------------------------------------------------------------
- ;子程序:T0中断调用,根据条件控制自然风状态LED指示灯和可控硅
- ;---------------------------------------------------------------------------------------------
- Control:SETB LED ;先熄灭自然风LED指示灯
- JNB 02H,CTL00 ;如果位地址02H(正常/自然风切换)为0(正常)就转移,保持熄灭状态
- CLR LED ;为1,自然风状态,点亮LED指示灯
- CTL00: MOV A,DSSJM ;装入定时时间(秒)到寄存器A
- JNZ CTL02 ;如果不是0就转移
- MOV A,DSSJF ;装入定时时间(分)到寄存器A
- JNZ CTL02 ;如果不是0就转移
- MOV A,DSSJS ;装入定时时间(时)到寄存器A
- JNZ CTL02 ;如果不是0就转移
- CTL01: SETB MOC ;置MOC为高电平,断电
- RET
- CTL02: JNB 02H,CTL03 ;如果位地址02H(正常/自然风切换)为0(正常)就转移,通电
- MOV A,SJ ;是自然风状态,装入自然风时电机通电时长到寄存器A
- JZ CTL01 ;如果为0(通电倒计时结束)就转移,断电
- CTL03: CLR MOC ;置MOC为低电平,通电
- RET
- ;------------------------------------------------------------------------------------------
- ;子程序:T0中断调用,显示定时时间及各项设置的内容
- ;------------------------------------------------------------------------------------------
- DISPLAY:JB 06H,DPYSZ1 ;如果位地址06H为1就转移退出,主程序显示88:88
- JB 07H,DPYSZ1 ;如果位地址07H为1就转移退出,主程序显示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
-
复制代码
以上资料51hei下载地址:
电风扇长定时器.rar
(95.52 KB, 下载次数: 98)
|