|
I2C_示例程序
;---------------------------------------------------------- ; File Name: I2C.ASM ; Author: Andy Yu ; Date: July 22, 1998 ;---------------------------------------------------------- #define I2C_ASM include i2c.inc public InitI2CBusMaster public _i2c_block_write public _i2c_block_read public SendData public TxmtStartBit public Txmt_Slave_Addr public IsSlaveActive public _Bus_Busy public _Txmt_Progress public _Rcv_Progress public _Txmt_Success public _Rcv_Success public _Ack_Error public _10BitAddr public _Slave_RW public _SlaveActive public DataByte public SlaveAddr public tempCount public TempStore ;------------------- ; General Equate ;------------------- TRUE EQU 1 FALSE EQU 0 LSB EQU 0 MSB EQU 7 Carry EQU [0ah].0 ;------------------- ; Port Assignment ;------------------- PortCtrlAddr EQU (PortAddr+1) I2CPORT EQU [PortAddr] SCL EQU [PortAddr+1].SCL_Bit ;PBC SDA EQU [PortAddr+1].SDA_Bit ;PBC PSCL EQU [PortAddr].SCL_Bit ;PB PSDA EQU [PortAddr].SDA_Bit ;PB ;----------------------------------------------- ; Data Section ;----------------------------------------------- I2CData .section 'data' I2CStatus label byte _Bus_Busy dbit _Abort dbit _Txmt_Progress dbit _Rcv_Progress dbit _Txmt_Success dbit _Rcv_Success dbit _Fatal_Error dbit _Ack_Error dbit I2CCtrl label byte _10BitAddr dbit _Slave_RW dbit _Last_Byte_Rcv dbit _reserve3 dbit _reserve4 dbit _reserve5 dbit _SlaveActive dbit _Time_Out dbit DataByte db ? DataByteCopy db ? BitCount db ? SlaveAddr db ? ; reserve 2 bytes to support 10 bit addr tempCount db ? TempStore db ? DelayCount db ? ;----------------------------------------------- ; Code Section ;----------------------------------------------- I2CCode .section 'code' ;------------------- ; IsSlaveAcitve ;------- IsSlaveActive proc clr _Slave_RW call TxmtStartBit call Txmt_Slave_Addr clr _SlaveActive snz _Ack_Error set _SlaveActive call TxmtStopBit ret IsSlaveActive endp ;------------------- ; _i2c_block_write ;------- _i2c_block_write proc call TxmtStartBit ; start clr _Slave_RW ; slave address call Txmt_Slave_Addr snz _Txmt_Success jmp ending MOV A,TempStore ; subaddress MOV DataByte,A call SendData _block_wr1_loop: snz _Txmt_Success jmp ending MOV A,_IAR MOV DataByte,A inc _MP call SendData sdz tempCount jmp _block_wr1_loop ending: call TxmtStopBit ; stop ret _i2c_block_write endp ;------------------- ; _i2c_block_read ;------- _i2c_block_read proc call TxmtStartBit set _Slave_RW clr _Last_Byte_Rcv call Txmt_Slave_Addr sz _Txmt_Success jmp _block_rd1_loop call TxmtStopBit ret A,FALSE _block_rd1_loop: call GetData MOV A,DataByte MOV _IAR,A inc _MP sdz tempCount jmp _block_rd1_loop ; set _Last_Byte_Rcv call GetData MOV A,DataByte MOV _IAR,A call TxmtStopBit ret A,TRUE _i2c_block_read endp ;------------------- ; InitI2CBusMaster ;------- InitI2CBusMaster proc MOV A,I2CPORT ; clear latches and A,NOT I2CPORTMASK MOV I2CPORT,A RELEASE_BUS clr I2CStatus clr I2CCtrl ret InitI2CBusMaster endp ;------------------- ; TxmtStartBit ;------- TxmtStartBit proc set SDA set SCL DELAY_tSETUP_START clr SDA DELAY_tHOLD_START set _Bus_Busy ret TxmtStartBit endp ;------------------- ; TxmtStopBit ;------- TxmtStopBit proc clr SCL clr SDA set SCL DELAY_tSETUP_STOP set SDA DELAY_tBUS_FREE clr _Bus_Busy ret TxmtStopBit endp ;------------------- ; SendData ;------- SendData proc TxmtByte: MOV A,DataByte MOV DataByteCopy,A set _Txmt_Progress clr _Txmt_Success MOV A,08h ; for BitCount=8 downto 1 MOV BitCount,A TxmtNextBit: clr SCL rlc DataByteCopy clr SDA sz Carry set SDA DELAY_tLOW set SCL DELAY_tHIGH sdz BitCount jmp TxmtNextBit ; end for ;--- check ACK clr SCL set SDA DELAY_tLOW set SCL DELAY_tHIGH sz PSDA jmp TxmtErrorAck clr SCL clr _Txmt_Progress set _Txmt_Success clr _Ack_Error ret TxmtErrorAck: RELEASE_BUS set SDA set SCL clr _Bus_Busy clr _Txmt_Progress clr _Txmt_Success set _Ack_Error ret SendData endp ;------------------- ; GetData ;------- GetData proc RcvByte: set _Rcv_Progress clr _Rcv_Success MOV A,08h MOV BitCount,A RcvNextBit: clr SCL set SDA DELAY_tLOW set SCL DELAY_tHIGH clr Carry sz PSDA set Carry rlc DataByte sdz BitCount jmp RcvNextBit ; generate ACK clr SCL clr SDA sz _Last_Byte_Rcv set SDA DELAY_tLOW set SCL DELAY_tHIGH RcvEnd: clr SCL clr _Rcv_Progress set _Rcv_Success clr _Ack_Error ret GetData endp ;------------------- ; Txmt_Slave_Addr ;------- Txmt_Slave_Addr proc clr _Ack_Error snz _10BitAddr jmp SevenBitAddr snz _Slave_RW jmp TenBitAddrWR TenBitAddrRd: clr _Slave_RW call TenBitAddrWR snz _Txmt_Success ret A,FALSE call TxmtStartBit set _Slave_RW MOV A,SlaveAddr[1] MOV DataByte,A set DataByte.LSB call SendData jmp _AddrSendTest ; snz _Txmt_Success jmp _AddrSendFail TenBitAddrWR: MOV A,SlaveAddr[1] MOV DataByte,A clr DataByte.LSB call SendData snz _Txmt_Success jmp _AddrSendFail MOV A,SlaveAddr MOV DataByte,A jmp EndTxmtAddr SevenBitAddr: MOV A,SlaveAddr MOV DataByte,A clr DataByte.LSB sz _Slave_RW set DataByte.LSB EndTxmtAddr: call SendData _AddrSendTest: snz _Txmt_Success jmp _AddrSendFail ret A,TRUE _AddrSendFail: snz _Ack_Error ret A,FALSE call TxmtStopBit ret A,FALSE Txmt_Slave_Addr endp ;********************************************************* ;---------------------------------------------------------- ; File Name: I2C.INC ; Author: Andy Yu ; Date: July 22, 1998 ;---------------------------------------------------------- ; ; modify these equates to suit your application ; PortAddr EQU 14H ; SCL=PB0, SDA=PB1 14H is PB's port addr SCL_Bit EQU 0 SDA_Bit EQU 1 I2CPORTMASK EQU 03h _IAR EQU [00h] _MP EQU [01h] ; ; fill delay codes to fit specific I2C slaves ; DELAY_tSETUP_START macro ; START Condition Setup Time (600ns HT24C0x) endm DELAY_tHOLD_START macro ; START Condition Hold Time (600ns HT24C0x) endm DELAY_tSETUP_STOP macro ; STOP Condition Setup Time (600ns HT24C0x) endm DELAY_tBUS_FREE macro ; Bus Free Time (1300ns HT24C0x) endm DELAY_tLOW macro ; Clock Low Time (600ns HT24C0x) endm DELAY_tHIGH macro ; Clock High Time (1300ns HT24C0x) endm ;---------------------------------------------------------- ifndef I2C_ASM extern InitI2CBusMaster : near extern _i2c_block_write : near extern _i2c_block_read : near extern SendData : near extern TxmtStartBit : near extern Txmt_Slave_Addr : near extern IsSlaveActive : near extern _Bus_Busy : bit extern _Txmt_Progress : bit extern _Rcv_Progress : bit extern _Txmt_Success : bit extern _Rcv_Success : bit extern _Ack_Error : bit extern _10BitAddr : bit extern _Slave_RW : bit extern _SlaveActive : bit extern DataByte : byte extern SlaveAddr : byte extern tempCount : byte extern TempStore : byte endif ;------------------- ; LOAD_ADDR_8 ;------- LOAD_ADDR_8 macro SLAVE_ADDRESS clr _10BitAddr MOV A,(SLAVE_ADDRESS and 0ffh) MOV SlaveAddr,A endm ;------------------- ; I2C_TEST_DEVICE ;------- I2C_TEST_DEVICE macro call IsSlaveActive endm ;------------------- ; RELEASE_BUS ;------- RELEASE_BUS macro set SDA ; set to hi-impedence set SCL endm ;------------------- ; I2C_WRITE_SUB ;------- I2C_WRITE_SUB macro _BYTES_, _SourcePointer_, _SubAddress_ MOV A,_SubAddress_ MOV TempStore,A MOV A,_BYTES_ ; loop data MOV tempCount,A MOV A,_SourcePointer_ MOV _MP,A call _i2c_block_write endm ;------------------- ; I2C_READ ;------- I2C_READ macro _BYTES_, _DestPointer_ MOV A,_BYTES_-1 MOV tempCount,A MOV A,_DestPointer_ MOV _MP,A call _i2c_block_read endm ;------------------- ; I2C_READ_SUB ;------- I2C_READ_SUB macro _BYTES_, _DestPointer_, _SubAddress_ clr _Slave_RW call TxmtStartBit call Txmt_Slave_Addr MOV A,_SubAddress_ MOV DataByte,A call SendData I2C_READ _BYTES_, _DestPointer_ endm ;************************************************* ;---------------------------------------------------------- ; File Name: TEST.ASM ; Author: Andy Yu ; Date: July 22, 1998 ; Purpose: test i2c routines ;---------------------------------------------------------- include i2c.inc include ht48c50.inc MySlaveAddr EQU 0a2h tdata .section 'data' PageData db 8 dup(?) Addr db ? Add1 db ? PageCount db ? Temp db ? Count db ? main .section at 0 'code' jmp start ; start: call InitI2CBusMaster ; LOAD_ADDR_8 MySlaveAddr ; I2C_TEST_DEVICE snz _SlaveActive jmp Error ; ; write HT24c01 with their address ; clr Addr MOV A,16 ; for PageCount = 16 downto 1 MOV PageCount,A PageWriteLp: call FillPageData ; Fill PageData with address I2C_WRITE_SUB 8, offset PageData, Addr snz _Txmt_Success jmp Error AckPoll: I2C_TEST_DEVICE snz _SlaveActive jmp AckPoll MOV A,8 addm A,Addr ; Addr += 8 sdz PageCount jmp PageWriteLp ; ; read back check ; clr Addr MOV A,16; for PageCount = 16 downto 1 MOV PageCount,A PageReadLp: I2C_READ_SUB 8, offset PageData, Addr snz _Rcv_Success jmp Error MOV a,0a0h MOV add1,a call CheckPageData snz ACC.0 jmp Error MOV a,8 addm A,add1 ; Add1 += 8 sdz PageCount jmp PageReadLp ; jmp $; success Error: jmp $ ; fail FillPageData proc ; PageData=Add,Add+1,...,Add+7 MOV A,offset PageData ; MP0 = offset PageData MOV MP0,A MOV A,0a0h ; Temp = Addr MOV Temp,A MOV A,8 MOV Count,A ; for Count = 8 downto 1 FillLp: MOV A,Temp MOV R0,A MOV PAC,A inc Temp inc MP0 sdz Count jmp FillLp ; end for ret FillPageData endp CheckPageData proc ; PageData must be Addr,Addr+1,...,Addr+7 MOV A,offset PageData ; MP0 = offset PageData MOV MP0,A MOV A,add1 ; Temp = Addr MOV Temp,A MOV A,8 MOV Count,A ; for Count = 16 downto 1 CheckLp: MOV A,R0 XOR A,Temp snz Z ret A,0 inc Temp inc mp0 sdz count jmp checkLp ret A,1 CheckPageData endp ;********************************************** |