;**************************************************************************
;程序名:  LLY-01.ASM (P114.ASM)(SOURCE)
;功  能:  从2543A/D转换器中的任意一通道采集模拟电压,经过转化得12位数字信号,进
;         行编码后,在用LCD液晶显示出来.
;电压规格:工作电压+5V.采集电压0至+5V.
;最大误差:±0.002V.
;完成日期:12/16/98

;*******************************引脚描述***********************************
;$NOMOD51
;$INCLUDE(MOD8751)       
	VOLTHIGH  EQU 30H
	VOLTLOW   EQU 31H
	COUNT     EQU 34H        ;定义定时器0中断溢出控制值,存到34H
	COUNTER   EQU 39H        ;定义外部中断0的次数,乘2为2404的地址
	EOC       EQU P2.7
	CL        EQU P2.6
	DIN       EQU P2.5
	DOUT      EQU P2.4
	CS        EQU P2.3
	SCL       EQU P3.6
	SDA       EQU P3.7

		  ORG 0000H
 		  AJMP START
		  ORG 0003H
		  AJMP INTT0      ;外部中断0从0003H向位开始执行                                
		  ORG 000BH
		  AJMP T0INT      ;T0中断从000BH向位开始执行

;*****************************初始化部分************************************
		  ORG 100H 
START:    MOV TMOD,#01H     ;设置时钟0工作模式
		  MOV TH0,#0EH      ;计数初值
		  MOV TL0,#0EH
		  MOV COUNT,#1
		  MOV IE,#83H       ;允许T0和INT0中断
		  MOV IP,#02H       ;设置T0中断优先
		  MOV COUNTER,#0H   ;外部中断0的次数的计数初值
		  SETB TR0          ;置1,计时器开始计数
;*****************************主程序开始************************************
		  MOV R0,#10        ;设置显示0-9(10次)
		  MOV R1,#0         ;显示从0开始
	LLL:  SETB P3.4         ;清除以前结果
		  CLR P3.4
		  SETB P2.2         ;进入计时模式
		  NOP
		  CLR P2.0
		  LCALL DELAY
		  LCALL DELAY
		  MOV R2,#10H       ;LCD16位模式
 LLLLL:   MOV A,R1
		  LCALL DISP
		  DJNZ R2,LLLLL
		  LCALL DELAY
		  ACALL DELAY
		  LCALL DELAY
		  LCALL DELAY
		  LCALL DELAY
		  LCALL DELAY
		  ACALL DELAY
		  LCALL DELAY
		  LCALL DELAY
		  LCALL DELAY
		  INC R1
		  DJNZ R0,LLL
	
MAIN:     MOV IE,#83H       ;允许时钟0中断 
		  MOV R5,#00H
		  MOV R6,#0BH
		  MOV R3,#00H
		  SETB CS    
		  SETB EOC
		  CLR CS
INITIA:   CLR C
		  MOV A,R5      ;选择通道号采集电压
		  MOV R2,#0CH   ;选用12位长度转换模式
		  SWAP A          
		  ACALL ADDRESS ;传输12位值到2543转换器
		  CLR DIN
CONVERT:  JNB EOC,CONVERT ;等待2543转换完成信号
		  CLR A

;***************************接收12位转换结果********************************
						   
READDATA: MOV R4,#04
		  CLR C
		  LCALL READ
		  MOV VOLTHIGH,A        ;前四位存放于volthhigh单元
		  CLR C
		  MOV R4,#08           
		  CLR A
		  ACALL READ
		  MOV VOLTLOW,A         ;后八位存放于voltlow单元

;************将2543A/D转换的结果从HEX码转化为BCD码**************************
;********此程序段采用按位相加的方法得取最后的BCD码转换值********************

restart:  MOV A,VOLTHIGH      ;取前4四位BCD码值
		  RL A        ;HEX码存放两个字节 (A*2)
		  MOV DPTR,#TAB1 ;16位常数送DPTR
		  MOVC A,@A+DPTR ;由A+DPTR寻址的程序字节送A
		  MOV R0,A       ;HEX码高位字节前4位转成的BCD码放在R0
		  MOV A,VOLTHIGH
		  RL A
		  INC A          ;到下一个字节(A*2+1)
		  MOVC A,@A+DPTR ;由A+DPTR寻址的程序字节送A
		  MOV R1,A       ;HEX码高位字节后4位转成的BCD码放在R1
		  MOV A,VOLTLOW       ;取中间4四位BCD码值
		  SWAP A
		  ANL A,#0FH
		  RL A
		  INC A
		  MOV DPTR,#TAB2
		  MOVC A,@A+DPTR
		  ADD A,R1       
		  DA A
		  MOV R1,A
		  MOV A,VOLTLOW       
		  SWAP A
		  ANL A,#0FH
		  RL A
		  MOVC A,@A+DPTR
		  ADDC A,R0      ;进位相加
		  DA A
		  MOV R0,A
		  MOV A,VOLTLOW       ;取后4四位BCD码值
		  ANL A,#0FH
		  MOV DPTR,#TAB3
		  MOVC A,@A+DPTR
		  ADD A,R1
		  DA A
		  MOV 33H,A           ;后八位BCD码值存放于33H单元
		  MOV A,R0
		  ADDC A,#0
		  DA A                
		  MOV 32H,A           ;前四位BCD码值存放于32H单元

;********************写24C04*************************************************  
	I2C:
		  SETB SDA          ; Set I2C lines as inputs
		  SETB SCL
	WriteByte:
		  ACALL Star
		  JC ExitWrite      ; exit if bus is busy
		  MOV A,#0A0H       ;送24C04从地址
		  ACALL Transmit    ; send the node number
		  JC StopWrite      ; exit if we do not get acknowledged
		  MOV A,R3          ;送24C04的起始地址
		  INC R3
		  INC R3
		  ACALL Transmit
		  JC Stopwrite
		  mov a,32H         ;送前4位BCD码值到24C04
		  acall transmit
		  jc stopwrite
		  mov a,33H         ;送后8位BCD码值到24C04
		  acall transmit
		  jc stopwrite
		  CLR C             ; success so reset carry
	StopWrite:
		  ACALL Stop
	ExitWrite:
		  NOP
;******************LCD显示程序***********************************************        

BEGIN:    SETB P3.4           ;清除以前结果
		  CLR P3.4
		  SETB P2.2           ;进入计时模式
		  NOP
		  CLR P2.0
		  LCALL DELAY
		  LCALL DELAY
LCD:      MOV A,#0CH
		  LCALL DISP
		  MOV A,#0DH
		  LCALL DISP
		  MOV A,#0AH
		  LCALL DISP
		  MOV A,#0BH
		  LCALL DISP
		  MOV A,#0BH
		  LCALL DISP
		  MOV A,#0BH
		  LCALL DISP
		  MOV A,R5
		  ADD A,#0
		  DA A          ;十进制调整
		  MOV R5,A
		  SWAP A
		  ANL A,#0FH
		  LCALL DISP
		  MOV A,R5
		  ANL A,#0FH
		  LCALL DISP
		  MOV A,#0BH
		  LCALL DISP
		  MOV A,#0BH
		  LCALL DISP
		  MOV A,#0BH
		  LCALL DISP
		  MOV A,32H           ;取第一位BCD码
		  SWAP A
		  ANL A,#0FH
		  LCALL DISP          ;显示此BCD码
		  MOV A,#0FH
		  LCALL DISP
		  MOV A,32H
		  ANL A,#0FH          ;取第二位BCD码
		  LCALL DISP          ;显示此BCD码
		  mov a,33H       ;取第三位BCD码
		  SWAP A
		  ANL A,#0FH
		  lcall disp          ;显示此BCD码
		  MOV A,33H
		  ANL A,#0FH
		  LCALL DISP 
		  LCALL DELAY
		  LCALL DELAY
		  INC R5          ;通道号加1
		  DJNZ R6,LL
		  LJMP MAIN
LL:       LJMP INITIA
		  RET
	
;*****************读24C04记忆体值(INT0)****************************************************
		  
INTT0:    MOV IE,#82H
		  PUSH ACC
		  PUSH B
		  PUSH PSW
ReadByte: ACALL Star
		  JC ExitRead       ; exit if bus is busy
		  MOV A,#0A0H       ; 送24C04从地址
		  ACALL Transmit    ; send the node number
		  JC StopRead       ; exit if we do not get acknowledged
		  MOV A,COUNTER     ; low byte of address to read from(外部中断0的次数)
		  RL A              ; 24C04的地址
		  ACALL Transmit    ; send low byte of address              
		  JC StopRead       ; exit if we do not get acknowledged
		  ACALL ReadCurrent ; ACALL Current Address Read function. 
		  LCALL ACK
		  MOV 37H,A
		  ACALL ReadCurrent
		  LCALL NAK
		  MOV 38H,A
		  LCALL RELCD
		  MOV 40H,#3        
TENSECON: LCALL DELAY
		  DJNZ 40H,TENSECON
		  SJMP ExitRead     ; we are done so exit
		  LCALL STOP
	ExitRead:
		  MOV A,COUNTER
		  CJNE A,#0BH,AA
		  MOV COUNTER,#0H
AA:       POP PSW
		  POP B
		  POP ACC 
		  MOV IE,#83H
		  RETI 

;***************************************************************************

ReadCurrent:
	       ACALL Star
	       JC ExitReadCurrent; exit if bus is busy
	       MOV A,#0A1H
	       ACALL Transmit    ; send the node number
	       JC StopRead       ; exit if we do not get acknowledged
	       ACALL Receive     ; receive the data byte
	       CLR C             ; success so reset carry
	StopReadCurrent:
	       ACALL Stop
	ExitReadCurrent:
	       RET
;****************************************************************************                      
	StopRead:
		  ACALL Stop

;**************从2543A/D转换器读取转换值程序********************************

READ:     MOV C,DOUT
		  RLC A
		  SETB CL
		  CLR CL
		  DJNZ R4,READ
		  RET

;**************中断子程序,以P0口灯闪烁证明程序正在执行中********************
	
T0INT:    MOV IE,#82H
		  PUSH ACC      
		  MOV TH0,#01H
		  MOV TL0,#01H
		  DJNZ COUNT,T0END
		  MOV A,P0
		  CPL A 
		  MOV P0,A
		  MOV COUNT,#05
T0END:    POP ACC
		  MOV IE,#83H
		  RETI

;**********************传输数据到2543A/D转换器******************************

ADDRESS:  RLC A
		  MOV DIN,C
		  SETB CL
		  CLR CL
		  DJNZ R2,ADDRESS
		  RET

TAB0:     DB 50H,08H,10H,18H,20H,28H,30H,38H
	  	  DB 40H,48H,80H,78H,90H,0B0H,0A0H,00H
tab1:     dw 0000h,0313h,0625h,0938h,1250h,1562h,1875h,2188h
	  	  dw 2500h,2813h,3125h,3438h,3750h,4063h,4375h,4688h
tab2:     dw 0000h,0020h,0039h,0059h,0078h,0098h,0117h,0136H
	 	  DW 0156h,0176h,0196h,0215h,0234h,0254h,0273H,0293H
tab3:     db 00h,01h,02h,04h,05h,06h,07H,09h,10h,11h,12h,13H
	 	  db 15H,16h,17h,18h
		 
;***********************延时子程序******************************************
			     
	DELAY:    MOV 35H,#255
	DEL:      MOV 36H,#255
	LOOP:     DJNZ 36H,LOOP
		  DJNZ 35H,DEL
		  RET


DISP:     CLR C
		  MOV R7,#5
		  MOV DPTR,#TAB0
		  MOVC A,@A+DPTR
DISP1:    RLC A
		  MOV P2.1,C
		  SETB P2.2
		  CLR P2.2
		  DJNZ R7,DISP1
		  RET
;*****************传送子程序*************************************************
Transmit:
	       PUSH B
	       MOV B,#8          ; loop counter
XmitLoop:                      
	       RLC A
	       MOV SDA,C
	       NOP
	       SETB SCL
	       NOP
	       NOP
	       NOP
	       CLR SCL
	       DJNZ B,XmitLoop
	       SETB SDA
	       NOP
	       NOP
	       SETB SCL
	       NOP
	       NOP
	       NOP
	       NOP
	       MOV C,SDA
	       CLR SCL
	       POP B
	       RET
	Receive:
		SETB SDA                 ; SDA is an input
		PUSH B
		MOV B,#8                 ; loop counter
	RcvLoop:
		NOP
		NOP
		NOP
		SETB SCL
		NOP
		NOP
		MOV C,SDA
		RLC A
		CLR SCL
		DJNZ B,RcvLoop
		POP B
		RET             
	Nak:
		SETB SDA                 ; negative acknowledgement      
		NOP                      ; small delay for data setup
		NOP
		NOP
		SETB SCL                 ; clock high
		NOP                      ; small delay for clock setup
		NOP                     
		NOP
		NOP                     
		CLR SCL                  ; clock low
		RET
	Ack:
		CLR SDA                  ; acknowledgement       
		NOP                      ; small delay for data setup
		NOP
		NOP
		SETB SCL                 ; clock high
		NOP                      ; small delay for clock setup
		NOP                     
		NOP
		NOP                     
		CLR SCL                  ; clock low
		RET
	Star:
		SETB SDA
		SETB SCL                  ; Verify bus available.
		JNB SDA, StartFail
		JNB SCL, StartFail
		NOP
		CLR SDA
		NOP
		NOP
		NOP
		NOP
		NOP
		CLR SCL                   ; SCL置高过程中SDA有个下降沿
		CLR C                    ; success
		SJMP StartExit
	StartFail:
		SETB C                   ; error flag
	StartExit:
		RET
	Stop:
		CLR SDA                  ; SCL置高过程中SDA有个上升沿
		NOP
		NOP
		SETB SCL
		NOP
		NOP
		NOP
		NOP
		NOP
		SETB SDA
		RET
	 
;*************************************************************************

	RELCD:    
		  SETB P3.4           ;清除以前结果
		  CLR P3.4
		  SETB P2.2           ;进入计时模式
		  NOP
		  CLR P2.0
		  LCALL DELAY
		  LCALL DELAY
		  LCALL DELAY
		  MOV A,#0CH
		  LCALL DISP
		  MOV A,#0DH
		  LCALL DISP
		  MOV A,#0AH
		  LCALL DISP
		  MOV A,#0BH
		  LCALL DISP
		  MOV A,#0BH
		  LCALL DISP
		  MOV A,#0BH
		  LCALL DISP
		  MOV 41H,COUNTER
		  MOV A,COUNTER
		  ADD A,#0H
		  DA A
		  MOV COUNTER,A
		  SWAP A
		  ANL A,#0FH
		  LCALL DISP
		  MOV A,COUNTER
		  ANL A,#0FH
		  LCALL DISP
		  MOV A,#0BH
		  LCALL DISP
		  MOV A,#0BH
		  LCALL DISP
		  MOV A,#0BH
		  LCALL DISP
		  MOV A,37H           ;取第一位BCD码
		  SWAP A
		  ANL A,#0FH
		  LCALL DISP          ;显示此BCD码
		  MOV A,#0FH
		  LCALL DISP
		  MOV A,37H
		  ANL A,#0FH          ;取第二位BCD码
		  LCALL DISP          ;显示此BCD码
		  mov a,38H           ;取第三位BCD码
		  SWAP A
		  ANL A,#0FH
		  lcall disp          ;显示此BCD码
		  MOV A,38H
		  ANL A,#0FH
		  LCALL DISP 
		  ACALL DELAY
		  ACALL DELAY
		  ACALL DELAY
		  ACALL DELAY
		  MOV COUNTER,41H
		  INC COUNTER
		  
		  RET
		  END
;************************************************************************