- LCD_X EQU 23H ;LCD 地址变量(决定文字的在LCD上的显示位置)
- FSJCQ EQU 33H ;TMOD工作方式暂存寄存器
- BJZC EQU 34H ;需要比较数据暂存寄存器,用于报警显示
- BJWX EQU 35H ;超标设定值暂存寄存器
- BJJG EQU 36H ;偏高设定值暂存寄存器
- JJCQ EQU 37H ;酒精显示0%暂存寄存器
- YYBZ EQU 38H ;语音播放标志
- DJSJCQ EQU 39H ;10S倒计时寄存器
- JJCYCS EQU 3AH ;酒精检测采样次数寄存器
- SHZZ2 EQU 3BH ;数据中转寄存器
- XSYSSJ DATA 5 ;正常时显示延时时间
- YWBJCS EQU 5 ;缺油报警次数
- WXBJZ1 EQU 100 ;有害气体危险报警设定值200PPM
- ;实际设定值=200(显示设定值)/2(修正倍率)
- JGBJZ1 EQU 60 ;有害气体警告报警设定值120PPM
- ;实际设定值=120(显示设定值)/2(修正倍率)
- WXBJZ2 EQU 50 ;酒精危险报警设定值0.05% BAC
- ;实际设定值=0.05%(显示设定值)*1000(显示位修正)/1(修正倍率)
- JGBJZ2 EQU 20 ;酒精警告报警设定值0.02% BAC
- ;实际设定值=0.02%(显示设定值)*1000(显示位修正)/1(修正倍率)
- XIUZ1 EQU 10 ;有害气体浓度显示数据修正值,设置大时则显示数值小,反之显示大
- XIUZ2 EQU 34 ;酒精浓度显示数据修正值,设置大时则显示数值小,反之显示大
- ;-----------------------------------------------------------
- LCD_RS EQU P4.0 ;LCD 数据/命令选择端
- LCD_RW EQU P4.1 ;LCD 读/写选择端
- LCD_EN EQU P4.2 ;LCD 使能信号
- LCD_BG EQU P4.3 ;LCD 背光控制端
- LCD_SJ EQU P0 ;LCD 数据
- BITE EQU 9 ;串口发送9位数据
- FSSZ EQU 40H ;主机发送的数据块首址
- JSSZ EQU 50H ;主机接收的数据块首址
- YY_DAT DATA 29H ;语音段地址存放单元
- YYRST EQU P3.3 ;语音模块复位信号引脚
- BUSY EQU P1.0 ;语音忙控制端,0为正在播放1为没有播放空闲时
- YYSDA EQU P1.1 ;语音模块数据线引脚
- ;===========================================================
- ORG 0000H
- AJMP MAIN
- ORG 0100H
- ;=========================================
- ;以下为主程序
- ;=========================================
- ;以下为油位显示和报警程序
- MAIN: MOV SP,#60H
- CLR LCD_BG ;打开LCD背光
- LCALL SET_LCD ;初始化 LCD
- CLR A
- MOV R0,#20H ;将20H-7FH 单元清零
- MOV R1,#63
- CLEAR: MOV @R0,A
- INC R0
- DJNZ R1,CLEAR
- MOV A,#5
- MOV DPTR,#1000H ;查看语音报警次数
- MOVX @DPTR,A
- ;MOV 08H,#5
- YWJCCX: LCALL MENU_7 ;显示菜单1
- FFFF: LCALL YWJC ;调用油位检测程序
- LCALL DYXZ ;调用电瓶电压检测程序
- LCALL DELAY3
- LCALL DELAY3
- SJMP FFFF
- ;***************************************************
- ;以下为子程序
- ;==============================================
- ;以下为LCD显示有害气体程序
- ;72H-70H 分别存放百位、十位、个位的数据
- ;==============================================
- CONV400: MOV A,73H ;加载百位数据
- MOV LCD_X,#0 ;设置显示位置
- CJNE A,#00H,CONV410
- MOV A,#" " ;百位数等于0显示空格
- MOV B,LCD_X
- CALL LCDP2
- JMP CONV420
- CONV410: CALL SHOW_DIG2 ;显示数据
- CONV420: INC LCD_X ;调整显示地址
- MOV A,72H ;十位
- CALL SHOW_DIG2
- INC LCD_X ;调整显示地址
- MOV A,#'.'
- MOV B,LCD_X
- CALL LCDP2
- INC LCD_X ;调整显示地址
- MOV A,71H ;十位
- CALL SHOW_DIG2
- RET
- ;=========================================
- ;LCD 显示菜单1
- ;=========================================
- MENU_7: MOV DPTR,#M_OK31 ;指针指到显示信息区
- MOV A,#1 ;显示在第一行
- CALL LCD_PRINT
- MOV DPTR,#M_OK32 ;指针指到显示信息区
- MOV A,#2 ;显示在第二行
- CALL LCD_PRINT
- MOV DPTR,#M_OK33 ;指针指到显示信息区
- MOV A,#3 ;显示在第二行
- CALL LCD_PRINT
- MOV DPTR,#M_OK34 ;指针指到显示信息区
- MOV A,#4 ;显示在第二行
- CALL LCD_PRINT
- RET
- M_OK31: DB"油量: ",0
- M_OK32: DB" 升 ",0
- M_OK33: DB"电瓶电压: ",0
- M_OK34: DB" V ",0
- ;--------------------------------------------------------------------------
- ;以下为油位检测和报警显示程序
- ;--------------------------------------------------------------------------
- YWJC: MOV R2,#0AH ;与10号从机串口通信,多功能板地址为0AH
- MOV R3,#01H ;主机要求从机发送数据块
- LCALL COM ;主机与多功能检测板串口通信,要求其发送9个字节数据块
- MOV A,JSSZ+3 ;取出传感器检测到的电压读数(原始数据,16进制)
- MOV B,#2 ;显示修正倍率,原始数*倍率=LCD显示值
- LCALL HEX2BCD1 ;调用数值转换程序
- MOV YYBZ,#JSSZ+3 ;设标志
- MOV DPTR,#BJ61 ;显示油位过低
- LCALL BTT5 ;显示清屏
- LCALL CONV400 ;调用LCD显示程序
- LCALL YWBJ ;调用报警比较程序
- RET
- YWBJ: MOV A,JSSZ+3 ;取出检测到的电压读数(原始数据,16进制)
- SUBB A,#19H ;比较,查看是否是低油位
- JNC BTT6 ;油位没有过低直接返回
- MOV DPTR,#1000H ;查看语音报警次数
- MOVX A,@DPTR
- JZ YWBJ1 ;等于0FF说明首次打开此段语音
- DEC A ;没有播放完允许再播放
- MOV DPTR,#1000H ;查看语音报警次数
- MOVX @DPTR,A
- ;MOV A,08H ;查看语音报警次数
- ;JZ YWBJ1 ;等于0FF说明首次打开此段语音
- ;DEC A ;没有播放完允许再播放
- ;MOV 08H,A ;查看语音报警次数
- JNB BUSY,$ ;如果语言正在播放,则等待
- MOV YY_DAT,#38 ;报出“油位过低请加油”
- LCALL YUYIN ;开始语音播放
- YWBJ1: LCALL DELAY3 ;延时
- MOV DPTR,#BJ60 ;显示油位过低
- BTT5: MOV A,#90H ;设置 LCD 显示的地址(第四行)
- CALL WCOM ;写入指令
- BLC: CLR A ;填入字符
- MOVC A,@A+DPTR ;由信息区取出字符
- CJNE A,#0,BLD ;判断是否为结束码
- BTT6: RET
- BLD: CALL WDATA ;写入数据
- INC DPTR ;指针加1
- JMP BLC ;继续填入字符
- BJ60: DB "低油位,请加油 ",0
- BJ61: DB " 升 ",0
- ;--------------------------------------------------------------------------
- ;以下为电瓶电压检测和报警显示程序
- ;--------------------------------------------------------------------------
- DYXZ: MOV R2,#0AH ;与10号从机串口通信,多功能板地址为0AH
- MOV R3,#01H ;主机要求从机发送数据块
- LCALL COM ;主机与多功能检测板串口通信,要求其发送9个字节数据块
- ;电压比较程序
- MOV A,JSSZ+5 ;取出检测到的电压读数(原始数据,16进制)
- SUBB A,#7AH ;比较,查看电压是否高于8V
- JC BTT1 ;电压高于8V小于15.5V显示电压值,超过不显示只报警
- MOV R1,A ;送暂存器
- MOV A,JSSZ+5
- SUBB A,#0C2H ;超过15.5V报警
- JC BTT2
- ;电压过高
- JNB BUSY,$ ;如果语言正在播放,则等待
- MOV YY_DAT,#20 ;报出“电瓶电压过高,请检查”
- LCALL YUYIN ;开始语音播放
- MOV DPTR,#BJ50 ;超标显示的内容
- LCALL DYBJXS ;超过15.5V报警显示电压过高
- SJMP BTT3
- ;电压正常显示电压值
- BTT2: MOV DPTR,#BJ52 ;显示清屏
- LCALL DYBJXS
- MOV A,R1
- MOV DPTR,#DAB8 ;电压值修正(实际电压与检测到的数值成非线性)
- MOVC A,@A+DPTR
- MOV B,#100 ;把十进制数值分离出来
- DIV AB
- MOV 73H,A ;十位
- MOV A,B
- MOV B,#10
- DIV AB
- MOV 72H,A ;个位
- MOV 71H,B ;小数点后1位
- MOV YYBZ,#JSSZ+5 ;设标志
- LCALL CONV400 ;电压值显示
- SJMP BTT3 ;返回主程序
- ;电压过低
- BTT1: JNB BUSY,$ ;如果语言正在播放,则等待
- MOV YY_DAT,#19 ;报出“电瓶电压过低,请检查”
- LCALL YUYIN ;开始语音播放
- MOV DPTR,#BJ51 ;未达到8V报警电压过低
- LCALL DYBJXS ;调用报警显示程序
- BTT3: RET
- DYBJXS: MOV A,#98H ;设置 LCD 显示的地址(第四行)
- CALL WCOM ;写入指令
- BLA: CLR A ;填入字符
- MOVC A,@A+DPTR ;由信息区取出字符
- CJNE A,#0,BLB ;判断是否为结束码
- RET
- BLB: CALL WDATA ;写入数据
- INC DPTR ;指针加1
- JMP BLA ;继续填入字符
- BJ50: DB "电压过高,请检查",0
- BJ51: DB "电压过低,请检查",0
- BJ52: DB" V ",0
- DAB8: ;电压值修正
- DB 80,80,81,82,83,84,85,85,
- DB 86,87,88,89,90,90,91,91,
- DB 92,92,93,93,94,94,95,95,
- DB 96,97,98,98,99,100,100,101,
- DB 102,103,104,105,105,106,107,108,
- DB 109,110,110,111,112,113,114,115,
- DB 116,117,118,119,120,121,122,123,
- DB 124,125,126,128,130,132,134,135,
- DB 137,139,140,142,144,145,148,150,
- DB 153,155,158,160,163,165,170,173,
- DB 175,178,180,185,190,195,200,205,
- DB 0,
-
-
- ;=========================================
- ;以下为两个单字节十六进制相乘
- ;入口:A*B
- ;出口:16位低字节放A中,高字节放B中
- ;=========================================
- HEX2BCD1: MUL AB
- MOV R6,B
- MOV R7,A
- MOV JJCQ,A ;为显示0%作准备
- ;=========================================
- ;以下为双字节十六进制整数转换成双字节BCD码整数
- ;入口条件:待转换的双字节十六进制整数在R6、R7中。
- ;出口信息:转换后的三字节BCD码整数在R3、R4、R5中。
- ;影响资源:PSW、A、R2~R7,堆栈需求:2字节
- ;=========================================
- CLR A ;BCD码初始化
- MOV R3,A
- MOV R4,A
- MOV R5,A
- MOV R2,#10H ;转换双字节十六进制整数
- HB3: MOV A,R7 ;从高端移出待转换数的一位到CY中
- RLC A
- MOV R7,A
- MOV A,R6
- RLC A
- MOV R6,A
- MOV A,R5 ;BCD码带进位自身相加,相当于乘2
- ADDC A,R5
- DA A ;十进制调整
- MOV R5,A
- MOV A,R4
- ADDC A,R4
- DA A
- MOV R4,A
- MOV A,R3
- ADDC A,R3
- MOV R3,A ;双字节十六进制数的万位数不超过6,不用调整
- DJNZ R2,HB3 ;处理完16bit
- ;=========================================
- ;以下为把BCD码提取出并送显示寄存器70H~73H
- ;入口:;三字节BCD码整数在R3(高位为十万低位为万)、
- ;R4(高位为千低位为百)、R5(高位为十低位为个)中。
- ;出口:73H-70H(舍去十万、万位)
- ;=========================================
- MOV A,R4
- ANL A,#00001111B
- MOV 73H,A
- MOV A,R5
- ANL A,#11110000B
- SWAP A
- MOV 72H,A
- MOV A,R5
- ANL A,#00001111B
- MOV 71H,A
- MOV 70H,#0
- RET
- ;=========================================
- ;以下为主机串行通信程序
- ;占用资源:R0~R4,A、40H、50H
- ;=========================================
- COM: MOV A,TMOD ;设置T1工作方式为方式2、T0工作方式保持不变
- MOV FSJCQ,A
- ORL A,#00101111B
- MOV TMOD,A
- MOV TH1,#0FDH ;11.0592MHz 晶振,波特率=9600,时长0.6695
- MOV TL1,#0FDH
- MOV SCON,#0D8H ;置串行模式3,SM2=1,允许接收
- SETB TR1 ;启动T1
- LCALL COM1 ;调用一线发码子程序
- MOV TMOD,FSJCQ ;恢复T1、T0原先的工作方式
- RET
- COM1: MOV A,R2 ;发送地址帧
- MOV SBUF,A
- JNB TI,$
- CLR TI
- JNB RI,$ ;等待从机应答
- CLR RI
- MOV A,SBUF
- XRL A,R2
- JNZ MS104 ;判应答地址是否相符
- CLR TB8 ;地址符合,准备发送命令
- MOV SBUF,R3 ;发送发送或接收数据命令
- JNB TI,$
- CLR TI
- JNB RI,$ ;等待从机应答
- CLR RI
- MOV A,SBUF ;取应答信息
- JNB ACC.7,MS102 ;判断是否出错
- MS101: SETB TB8
- MOV SBUF,#0FFH ;不相符重新联络
- JNB TI,$
- CLR TI
- SJMP COM1 ;转重发地址
- MS102: CJNE R3,#00H,MS103 ;判是否要求从机接收数据
- JNB ACC.0,MS101 ;从机接收数据准备就绪否?
- MOV R0,#FSSZ ;主机发送的数据块首址
- MOV R4,#BITE ;设数据块长度(9字节)
- LPTX: MOV SBUF,@R0 ;主机发送数据块
- JNB TI,$ ;等待发送完1帧
- CLR TI
- INC R0 ;修改地址指针
- DJNZ R4,LPTX ;判数据块是否传完
- SJMP MS104 ;返回主程序
- MS103: JNB ACC.1,MS101 ;从机发送数据准备就绪否?
- MOV R1,#JSSZ ;主机接收的数据块首址
- MOV R4,#BITE ;设数据块长度(9字节)
- LPRX: JNB RI,LPRX ;等待接收完1帧
- CLR RI
- MOV A,SBUF ;取出接收到的字符
- MOV @R1,A
- INC R1
- DJNZ R4,LPRX ;未接收完则继续
- MS104: CLR TR1 ;关闭T1
- RET
- ;=============================================
- ;在LCD的第二行显示数据字符
- ;A=ASCII 数据, B=位置变量
- ;==============================================
- LCDP2: PUSH ACC ;在LCD的第二行显示字符
- MOV A,B ;设置显示地址
- MOV R0,YYBZ
- CJNE R0,#JSSZ+3,LCDP3
- ADD A,#90H ;设置LCD的第二行地址90
- SJMP LCDP4
- LCDP3: CJNE R0,#JSSZ+5,LCDP5
- ADD A,#98H ;设置LCD的第四行地址98
- LCDP4: CALL WCOM ;写入命令
- LCDP5: POP ACC ;由堆栈取出A
- CALL WDATA ;写入数据
- RET
- ;-------------------------------------------------------
- SHOW_DIG2: ;在 LCD 的第二行显示数字
- ADD A,#30H ;加30H,转换为ASCII码
- MOV B,LCD_X ;确定显示位置
- CALL LCDP2 ;送显示
- RET
- ;=================================================
- ;对 LCD 做初始化设置
- ;=================================================
- SET_LCD: MOV A,#34H ;34H--扩充指令操作
- CALL WCOM ;写入命令
- MOV A,#30H ;30H--基本指令操作
- CALL WCOM ;写入命令
- MOV A,#01H ;清除显示
- CALL WCOM ;写入命令
- MOV A,#06H ;指定在资料写入或读取时,光标的移动方向
- CALL WCOM ;DDRAM 的地址计数器(AC)加1
- MOV A,#0CH ;开显示,关光标,不闪烁
- CALL WCOM ;写入命令
- RET
- ;===============================================
- ;命令写入子程序
- ;RS=L,RW=L,D0-D7=指令码,E=高脉冲
- ;以8位控制方式将命令写至LCD
- ;===============================================
- WCOM: LCALL CHK_BUSY ;写入指令
- CLR LCD_RS
- CLR LCD_RW
- MOV LCD_SJ,A
- SETB LCD_EN
- NOP
- NOP
- CLR LCD_EN
- RET
- ;===============================================
- ;数据写入子程序
- ;RS=H,RW=L,D0-D7=指令码,E=高脉冲
- ;以8位控制方式将数据写至LCD
- ;===============================================
- WDATA: MOV LCD_SJ,A ;写入数据
- SETB LCD_RS
- CLR LCD_RW
- SETB LCD_EN
- CALL DE
- CLR LCD_EN
- CALL DE
- RET
- ;===============================================
- ;测LCD忙碌子程序
- ;RS=0,RW=1,E=H,D0-D7=状态字
- ;===============================================
- CHK_BUSY: MOV LCD_SJ,#0FFH ;测忙碌子程序
- CLR LCD_RS
- SETB LCD_RW
- SETB LCD_EN
- JB LCD_SJ.7,$
- CLR LCD_EN
- RET
- ;==================================================
- ;在LCD的显示字符串
- ;DPTR = 放字符串的地址
- ;==================================================
- LCD_PRINT:CJNE A,#1,LINE2 ;判断是否为第一行
- LINE1: MOV A,#80H ;设置 LCD 的第一行地址
- CALL WCOM ;写入命令
- CALL CLR_LINE ;清除该行字符数据
- MOV A,#80H ;设置 LCD 的第一行地址
- CALL WCOM ;写入命令
- JMP FILL
- LINE2: CJNE A,#2,LINE3 ;判断是否为第二行
- MOV A,#90H ;设置 LCD 的第二行地址
- CALL WCOM ;写入命令
- CALL CLR_LINE ;清除该行字符数据
- MOV A,#90H ;设置 LCD 的第二行地址
- CALL WCOM
- JMP FILL
- LINE3: CJNE A,#3,LINE4 ;判断是否为第三行
- MOV A,#88H ;设置 LCD 的第三行地址
- CALL WCOM ;写入命令
- CALL CLR_LINE ;清除该行字符数据
- MOV A,#88H ;设置 LCD 的第三行地址
- CALL WCOM
- JMP FILL
- LINE4: MOV A,#98H ;设置 LCD 的第四行地址
- CALL WCOM ;写入命令
- CALL CLR_LINE ;清除该行字符数据
- MOV A,#98H ;设置 LCD 的第四行地址
- CALL WCOM
- FILL: CLR A ;填入字符
- MOVC A,@A+DPTR ;由信息区取出字符
- CJNE A,#0,LC1 ;判断是否为结束码
- RET
- LC1: CALL WDATA ;写入数据
- INC DPTR ;指针加1
- JMP FILL ;继续填入字符
- ;===============================================
- ;清除一行 LCD 的字符
- ;输入一行空格,来替代原显示字符
- ;===============================================
- CLR_LINE: MOV R0,#16 ;清除该行 LCD 的字符
- CL1: MOV A,#' '
- CALL WDATA
- DJNZ R0,CL1
- RET
- ;**********************************************************
- ;延时子程序
- ;**********************************************************
- DE: MOV R7,#229 ;延时 500 微秒,此条2个机器周期
- DJNZ R7,$
- RET ;此条2个机器周期,总延时(229*2+2+2)*(12/11.0592)≈500uS
- DELAY: MOV R5,#20 ;延时200MS
- DELAY1: MOV R6,#96 ;100
- DL1: MOV R7,#96 ;100
- DJNZ R7,$
- DJNZ R6,DL1
- DJNZ R5,DELAY1 ;96*2*48*(12/11.0592)+2*(12/11.0592)≈10000uS=10mS
- RET
- DELAY2: MOV R6,#10 ;延时5MS
- DL2: MOV R7,#229 ;100微秒
- DJNZ R7,$
- DJNZ R6,DL2
- DJNZ R5,DELAY2
- RET
- DELAY3: MOV R5,#10 ;延时200MS
- DELA: MOV R6,#255
- DL3: MOV R7,#255
- DJNZ R7,$
- DJNZ R6,DL3
- DJNZ R5,DELA
- RET
- ;**********************************************************
- ;语音驱动和播放程序
- ;**********************************************************
- ;50H为语音段地址暂存器,1到210段,实际用到40
- ;50H为E0H~E7H时分别代表自低往高的8级音量
- ;在语音播放过程中发送F2H至50H可循环播放当前地址语音
- ;发送FEH至50H停止播放语音
- ;****************************************************
- YUYIN: MOV A,TMOD ;设置T1工作方式为方式1、T0工作方式保持不变
- MOV FSJCQ,A
- ORL A,#00011111B
- MOV TMOD,A
- MOV R6,#08H ;发码8位循环数据
- LCALL ONE_LINE ;调用一线发码子程序
- MOV TMOD,FSJCQ ;恢复T1、T0原先的工作方式
- RET
- ONE_LINE: ;////一线发码子程序
- SETB YYRST ;复位
- MOV R7,#2 ;延时2MS
- LCALL DELAY1MS
- CLR YYRST ;延时使系统稳定
- MOV R7,#6 ;延时6MS
- LCALL DELAY1MS
- CLR YYSDA ;唤醒语音芯片
- MOV R7,#17 ;延时17MS
- LCALL DELAY1MS
- MOV A,YY_DAT
- LP1: SETB YYSDA
- RRC A ;分辨50H内的数据各位是高电平还是低电平
- JNC DIDIANPIN ;高电平用高:低=2:1的脉宽表示
- LCALL DELAY200US
- LCALL DELAY200US
- LCALL DELAY200US
- CLR YYSDA
- LCALL DELAY200US
- LP2: DJNZ R6,LP1 ;查看数据是否发完,未发完继续发
- MOV R6,#08H
- SETB YYSDA
- RET
- DIDIANPIN: ;低电平用高:低=1:2的脉宽表示
- LCALL DELAY200US
- CLR YYSDA
- LCALL DELAY200US
- LCALL DELAY200US
- LCALL DELAY200US
- SJMP LP2
- ;以下为延时子程序
- DELAY200US: ;延时200US子程序,晶振11.0592MHz,方式1
- MOV TH1,#0FFH
- MOV TL1,#47H
- SETB TR1
- LOP1: JBC TF1,NEXT1
- SJMP LOP1
- NEXT1: CLR TR1
- RET
- DELAY1MS:MOV TH1,#0FCH ;延时1ms子程序
- MOV TL1,#66H
- SETB TR1
- LOP2: JBC TF1,NEXT2
- SJMP LOP2
- NEXT2: DJNZ R7,DELAY1MS
- CLR TR1
- RET
- END
复制代码
|