⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spdi2c.asm

📁 X86 GX1 BOOTLOAD代码 ,支持WINCE操作系统!
💻 ASM
📖 第 1 页 / 共 2 页
字号:
	mov	bh, cl
	mov	cx, 00101h		; CH=send offset and CL=write 1 byte
	jmp	csI2C_Write
csWriteINDEXEDbyte ENDP

;**************************************************************************
;*
;*	csWriteINDEXEDbyteStack
;*
;*	This routine calls csWriteINDEXEDbyte (above) and saves/restores
;*	registers.  See above for details.
;*
;*	Entry:
;*	  BL = chip address
;*	  CL = register address
;*	  AL = byte to write
;*
;*	Exit:
;*		CF=0 success BH = 0
;*		CF=1 failure BH = ERROR
;*			BH = 01h	Invalid size ( CL = 0 )
;*			BH = 02h	I2C Comm Error
;*			BH = 03h	Buffer address wrap 
;*
;*	Destroys:
;*	  BH
;*
;**************************************************************************
csWriteINDEXEDbyteStack PROC NEAR PUBLIC
	pushad

	NOSTACK	dx, csWriteINDEXEDbyte

	; restore all while preserving BH
	mov	eax, DWORD PTR ss:[esp+16]
	mov	ah, bh
	mov	DWORD PTR ss:[esp+16], eax
	popad

	ret
csWriteINDEXEDbyteStack ENDP

;**************************************************************************
;*
;*	csWriteI2CBlockStack 
;*
;*	See above csI2C_Write for details
;*
;*	Entry:  
;*		CH = chip address
;*		CL = register
;*		DL = number of bytes to transfer
;*		DS:SI = pointer to data to write to device 
;*
;*	Exit:
;*		CF=0 success
;*		CF=1 failure
;*
;*	Destroys:
;*	  nothing only flags changed
;*
;**************************************************************************
csWriteI2CBlockStack PROC NEAR PUBLIC
	pushad			; save all registers
	push es

	mov	bh, cl		; Offset
	mov bl, ch		; Address
	mov	ch, 001h	; Use offset flag
	mov	cl, dl		; # of bytes
	mov di, si		; Buffer address
	push ds
	pop	es

	cmp	dl, 4
	ja	csWIBS_Go

	; 4 or less bytes, move data to EAX
	mov eax, DWORD PTR es:[DI]

csWIBS_Go:

	NOSTACK	dx, csI2C_Write

	; Restore Registers
	; Update BH on the stack before restoring other registers
	;mov	eax, DWORD PTR ss:[esp+16]
	;mov	ah, bh
	;mov	DWORD PTR ss:[esp+16], eax
	pop es
	popad
	ret
csWriteI2CBlockStack ENDP


;**************************************************************************
;*
;*	csInitI2C
;*
;*	(STACKLESS)
;*
;*	1) Call the Hook Procedure that sets up GPIO
;*	2) Initialize the I2C interface
;*	  a) SCL Out
;*	  b) SDA Out
;*	  c) SCL Low
;*	  d) SDA High
;*	  e) SCL High
;*
;*	Entry:
;*	  SI = Return address
;*
;*	Exit:
;*	Destroys:
;*		EAX, DX
;*
;**************************************************************************
csInitI2C PROC NEAR PUBLIC

	; Set PCI Address register to point to 55x0 GPIO direction register
	; and set DX to point to the PCI data register (CFCh)

	;cli	; some platforms have problems with noise on interupt lines at power-on. 
	;Since this happens before an interupt code is initiazed this can cause teh system to crash.
	mov	dx,  0CF8h		; Point to PCI address register
	mov	eax, CX55x0_ID+090h	; 55XX GPIO direction register
	out	dx,  eax
	mov	dl,  0FCh		; Point to PCI data register (CFCh)
	;sti

	; Initialize the I2C Interface
	in	ax, dx			; Drive SDA High
	or	ah, SDA
	out	dx, ax

	in	ax, dx			; Drive SCL High
	or	ah, SCL
	out	dx, ax

	in	al, dx			; Make SCL GPIO an output
	or	al, SCL
	out	dx, al

	in	al, dx			; Make SDA GPIO an output
	or	al, SDA
	out	dx, al

	jmp	si			; Return to calling address

csInitI2C ENDP

;**************************************************************************
;*
;*	csInitI2CStack
;*
;*	Initialize the I2C interface (calls stackless version)
;*
;*	Entry:
;*	Exit:
;*	Destroys:
;*		Nothing
;*
;**************************************************************************
csInitI2CStack PROC NEAR PUBLIC
	push	esi
	push	eax
	push	edx
	NOSTACK	si, csInitI2C		; Call stackless version
	pop	edx
	pop	eax
	pop	esi
	ret
csInitI2CStack ENDP


;**************************************************************************
;*
;*	csStartCondition
;*
;*	(STACKLESS)
;*
;*	This routine triggers the start condition on the I2C bus.
;*
;*	Entry:
;*	  SI = Return Address
;*
;*	Exit:
;*
;*	Destroys:
;*	  AX, DX
;*
;**************************************************************************
csStartCondition PROC NEAR

	in	ax, dx			; Drive SDA and SCL High
	or	ah, SDA
	or	ah, SCL
	out	dx, ax

	IOPAUSE
	IOPAUSE
	IOPAUSE

	in	al, dx			; Make SDA an output
	or	al, SDA
	out	dx, al

	IOPAUSE
	IOPAUSE
	IOPAUSE

	in	ax, dx			; Drive SDA Low
	and	ah, NOT SDA
	out	dx, ax

	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE

	in	ax, dx			; Drive SCL Low
	and	ah, NOT SCL
	out	dx, ax

	clc
	jmp	si
csStartCondition ENDP

;**************************************************************************
;*
;*	csStopCondition
;*
;*	(STACKLESS)
;*
;*	This routine triggers the stop condition on the I2C bus.
;*
;*	Entry:
;*	  SI = Return Address
;*
;*	Exit:
;*
;*	Destroys
;*	  AX, DX
;*
;**************************************************************************
csStopCondition PROC NEAR
	in	al, dx			; Make SDA an output
	or	al, SDA
	out	dx, al

	in	ax, dx			; Drive SCL Low
	and	ah, NOT SCL
	out	dx, ax

	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE

	in	ax, dx			; Drive SDA Low
	and	ah, NOT SDA
	out	dx, ax

	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE

	in	ax, dx			; Drive SCL High
	or	ah, SCL
	out	dx, ax

	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE

	in	ax, dx			; Drive SDA High
	or	ah, SDA			
	out	dx, ax

	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE

	clc
	jmp	si
csStopCondition ENDP

;**************************************************************************
;*
;*	csWriteI2CData
;*
;*	(STACKLESS)
;*
;*	This routine writes the 8-bit value in BL to the I2C bus.
;*
;*	Entry:
;*	  BL = data value
;*	  SI = return address
;*
;*	Exit:
;*	  Carry flag set as follows
;*	    Set = acknowledge bit = 1
;*	    Clr = acknowledge bit = 0
;*
;*	Destroys
;*	  AX, BL, CX, DX
;*
;**************************************************************************
csWriteI2CData PROC NEAR
	in	ax, dx			; Drive SCL Low
	and	ah, NOT SCL
	out	dx, ax

	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE

	in	al, dx			; Make SDA an output
	or	al, SDA
	out	dx, al

	IOPAUSE
	IOPAUSE
	IOPAUSE

	mov	cx, 8			; 8 bits to send

SetI2CDataBitLoop:
	test	bl, 80h			; Check data bit
	jz	SetI2CDataBitLow	; Branch if low

	in	ax, dx			; Drive SDA High
	or	ah, SDA
	out	dx, ax

	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE 

	jmp	SetI2CDataBitClock

SetI2CDataBitLow:
	in	ax, dx			; Drive SDA Low
	and	ah, NOT SDA
	out	dx, ax

	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE 

SetI2CDataBitClock:
	in	ax, dx			; Drive SCL High
	or	ah, SCL
	out	dx, ax

	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE

	in	ax, dx			; Drive SCL Low
	and	ah, NOT SCL
	out	dx, ax

	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE 

	shl	bl, 1			; Justify next bit
	loop SetI2CDataBitLoop		; Next bit

	in	ax, dx			; Drive SDA High when done
	or	ah, SDA
	out	dx, ax

	in	al, dx			; Set SDA as input to check ACK
	and	al, NOT SDA
	out	dx, al

	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE

	in	ax, dx			; Clock in ACK
	or	ah, SCL			; Drive SCK high
	out	dx, ax

	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE 

	in	ax, dx			; Read SDA (ACK)
	shr	ax, 8

	mov	cl, al			; Save the reading of ACK bit

	in	ax, dx			; Drive SCK Low
	and	ah, NOT SCL
	out	dx, ax

	IOPAUSE
	IOPAUSE 
	IOPAUSE
	IOPAUSE
	IOPAUSE 

	mov	al, cl			; Retrieve save ACK value
	test	al, NOACK		; Make sure ACK was driven low
	stc
	jnz	NoAckRcvd
	clc

NoAckRcvd:
	jmp	si
csWriteI2CData ENDP

;**************************************************************************
;*
;*	csReadI2CData
;*
;*	(STACKLESS)
;*
;*	This routine reads an 8-bit value from the I2C bus
;*  This is a wrapper for the generic read
;*
;*	Entry:
;*		SI = return address
;*
;*	Exit:
;*		BL = data value
;*		DI = 0  (ACK_FLAG clear)
;*
;*	Destroys:
;*	  AX, BX, CX, DX, DI
;*
;**************************************************************************
csReadI2CData PROC NEAR

	mov	di, 0000h	; Say we don't want an acknowledge
	jmp	csRealReadI2CData

csReadI2CData ENDP

;**************************************************************************
;*
;*	csReadAckI2CData
;*
;*	(STACKLESS)
;*
;*	This routine reads an 8-bit value from the I2C bus with acknowledge
;*  This is a wrapper for the generic read
;*
;*	Entry:
;*		SI = return address
;*
;*	Exit:
;*		BL = data value
;*		DI = ACK_FLAG
;*
;*	Destroys:
;*	  AX, BX, CX, DX, DI
;*
;**************************************************************************
csReadAckI2CData PROC NEAR

	mov	di, ACK_FLAG	; Say we want an acknowledge
	jmp	csRealReadI2CData

csReadAckI2CData ENDP

;**************************************************************************
;*
;*	csRealReadI2CData
;*
;*	(STACKLESS)
;*
;*	This routine reads an 8-bit value from the I2C bus
;*
;*	Entry:
;*	  SI = return address
;*	  DI = acknowledge flag 
;*		0000 = No acknowledge
;*		ACK_FLAG = Acknowledge
;*
;*	Exit:
;*	  BL = data value
;*
;*	Destroys:
;*	  AX, BX, CX, DX
;*
;**************************************************************************
csRealReadI2CData PROC NEAR
	in	ax, dx				; Drive SCL Low
	and	ah, NOT SCL
	out	dx, ax

	in	al, dx				; Make SDA an input
	and	al, NOT SDA
	out	dx, al

	mov	cx, 8				; 8 bits to read
	mov	bl, 0				; Clear out BL

csGetI2CDataBitLoop:
	shl	bl, 1				; Align Next Bit

	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE

	in	ax, dx				; Drive SCL High
	or	ah, SCL
	out	dx, ax

	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE

	in	ax, dx
	shr	ax, 8				; Use AH

	test	al, SDA				; Data Low?
	jz	csGetI2CDataBitLow		; Yes, leave bit (0)
	or	bx, 01h				; No, OR in bit (1)

csGetI2CDataBitLow:
	in	ax, dx				; Drive SCL Low
	and	ah, NOT SCL
	out	dx, ax

	loop csGetI2CDataBitLoop		; Next bit

	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE 

	test di, ACK_FLAG	; Do we need to ACK?
	jz	@f				; No, skip it

	; Start ACK cycle
	in	al, dx			; Make SDA an output
	or	al, SDA
	out	dx, al

	in	ax, dx			; Drive SDA Low to start ACK
	and	ah, NOT SDA
	out	dx, ax

	; Go ahead and toggle the clock
@@:
	in	ax, dx				; Drive SCL High
	or	ah, SCL
	out	dx, ax

	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE

	in	ax, dx				; Drive SCL Low
	and	ah, NOT SCL
	out	dx, ax

	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE

	test di, ACK_FLAG	; Do we need to ACK?
	jz	@f				; No, skip it

	; End ACK cycle
	in	ax, dx			; Drive SDA High to end ACK
	or	ah, SDA			
	out	dx, ax

	IOPAUSE
	IOPAUSE
	IOPAUSE
	IOPAUSE

@@:
	clc					; Clear Carry Flag
	jmp	si				; Return to calling address
csRealReadI2CData ENDP


_TEXT ENDS

	END

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -