8月的夏天还太热了,想DIY一个电风扇
初步我觉得电风扇定时时间60分钟觉得短了些,如果一直开的话,吹到天亮人也难受,能定时个三四小时比较合适,手头上有若干闲置了十余年的STC89C51RC,所以就用它来制作个长定时器,使用EC11带开关旋转编码器调时间,很便宜,一块多钱一只还包邮,也可以用按键代替编码器,只是调时间的时候不如编码器那么方便快捷,显示用TM1637四位数码管显示模块,3块钱包邮,便宜又好用,它能显示到99小时,所以最长定时可达99小时59分59秒,虽然实际使用不需要那么长的定时。制作好后不对电风扇作任何改动,只是把双向可控硅的T1、T2分别与原定时器那两根线接好就可以了,也就是与原定时器并联,把原定时器调到OFF位置。单片机改用其他型号的话,需要改动一些地方,如EEPROM操作、扇区地址、数量、特殊功能寄存器地址、看门狗预分频数等等.
电路原理图如下:
MCU源码(仅供参考):
;===================================================================================
;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