📄 i2c_avr.asm
字号:
; File Name I2c_avr.asm"
; Support Email Per@hum.au.dk
;* Target : AT90Sxxxx (any AVR device)
; R e v i s i o n H I S T O R Y
; rev. date who why
; ---- -------------- --- ------------------------------------------
; 0.01 May 14, 2001 PB Start with Atmel app. note
; 0.02 May 19, 2001 PB Fixing a few bugs with multi byte reads
; 0.10 May 19, 2001 PB Apperently it works
;* Main I2C functions :
;* 'i2c_start' - Issues a start condition and sends address
;* and transfer direction.
;* 'i2c_rep_start' - Issues a repeated start condition and sends
;* address and transfer direction.
;* 'i2c_do_transfer' - Sends or receives data depending on
;* direction given in address/dir byte.
;* 'i2c_stop' - Terminates the data transfer by issue a
;* stop condition.
;*
;* NOTES
;* The I2C routines can be called either from non-interrupt or
;* interrupt routines, not both.
;*
;* STATISTICS
;* Code Size : 81 words (maximum)
;* Register Usage : 4 High, 0 Low
;* Interrupt Usage : None
;* Other Usage : Uses two I/O pins on port C
;* XTAL Range : N/A
;***************************************************************************
;*
;* FUNCTION
;* i2c_hp_delay
;* i2c_qp_delay
;*
;* DESCRIPTION
;* hp - half i2c clock period delay (normal: 5.0us / fast: 1.3us)
;* qp - quarter i2c clock period delay (normal: 2.5us / fast: 0.6us)
;*
;* SEE DOCUMENTATION !!!
;* Xtal = 2.4576 MHz.
;*
;* USAGE
;* no parameters
;*
;* RETURN
;* none
;*
;***************************************************************************
i2c_hp_delay:
ldi i2cdelay,3
i2c_hp_delay_loop:
dec i2cdelay
brne i2c_hp_delay_loop
i2c_qp_delay:
nop
ret
;***************************************************************************
;*
;* FUNCTION
;* i2c_rep_start
;*
;* DESCRIPTION
;* Assert repeated start condition and sends slave address.
;*
;* USAGE
;* i2cadr - Contains the slave address and transfer direction.
;*
;* RETURN
;* Carry flag - Cleared if a slave responds to the address.
;*
;* NOTE
;* IMPORTANT! : This funtion must be directly followed by i2c_start.
;*
;***************************************************************************
I2c_rep_start:
sbi DDRC,SCLP ; force SCL low
cbi DDRC,SDAP ; release SDA
rcall i2c_hp_delay ; half period delay
cbi DDRC,SCLP ; release SCL
rcall i2c_qp_delay ; quarter period delay
;***************************************************************************
;*
;* FUNCTION
;* i2c_start
;*
;* DESCRIPTION
;* Generates start condition and sends slave address.
;*
;* USAGE
;* i2cadr - Contains the slave address and transfer direction.
;*
;* RETURN
;* Carry flag - Cleared if a slave responds to the address.
;*
;* NOTE
;* IMPORTANT! : This funtion must be directly followed by i2c_write.
;*
;***************************************************************************
I2c_start: mov i2cdata,i2cadr ; copy address to transmitt register
sbi DDRC,SDAP ; force SDA low
rcall i2c_qp_delay ; quarter period delay
;***************************************************************************
;*
;* FUNCTION
;* i2c_write
;*
;* DESCRIPTION
;* Writes data (one byte) to the I2C bus. Also used for sending
;* the address.
;*
;* USAGE
;* i2cdata - Contains data to be transmitted.
;*
;* RETURN
;* Carry flag - Set if the slave respond transfer.
;*
;* NOTE
;* IMPORTANT! : This funtion must be directly followed by i2c_get_ack.
;*
;***************************************************************************
I2c_write: sec ; set carry flag
rol i2cdata ; shift in carry and out bit one
rjmp i2c_write_first
i2c_write_bit:
lsl i2cdata ; if transmit register empty
i2c_write_first:
breq i2c_get_ack ; goto get acknowledge (JRZ)
sbi DDRC,SCLP ; force SCL low
brcc i2c_write_low ; if bit high
nop ; (equalize number of cycles)
cbi DDRC,SDAP ; release SDA
rjmp i2c_write_high
i2c_write_low: ; else
sbi DDRC,SDAP ; force SDA low
rjmp i2c_write_high ; (equalize number of cycles)
i2c_write_high:
rcall i2c_hp_delay ; half period delay
cbi DDRC,SCLP ; release SCL
rcall i2c_hp_delay ; half period delay
rjmp i2c_write_bit
;***************************************************************************
;*
;* FUNCTION
;* i2c_get_ack
;*
;* DESCRIPTION
;* Get slave acknowledge response.
;*
;* USAGE
;* (used only by i2c_write in this version)
;*
;* RETURN
;* Carry flag - Cleared if a slave responds to a request.
;*
;***************************************************************************
i2c_get_ack: sbi DDRC,SCLP ; force SCL low
cbi DDRC,SDAP ; release SDA
rcall i2c_hp_delay ; half period delay
cbi DDRC,SCLP ; release SCL
i2c_get_ack_wait:
sbis PINC,SCLP ; wait SCL high
;(In case wait states are inserted)
rjmp i2c_get_ack_wait
clc ; clear carry flag
sbic PINC,SDAP ; if SDA is high
sec ; set carry flag
rcall i2c_hp_delay ; half period delay
ret
;***************************************************************************
;*
;* FUNCTION
;* i2c_do_transfer
;*
;* DESCRIPTION
;* Executes a transfer on bus. This is only a combination of i2c_read
;* and i2c_write for convenience.
;*
;* USAGE
;* i2cadr - Must have the same direction as when i2c_start was called.
;* see i2c_read and i2c_write for more information.
;*
;* RETURN
;* (depends on type of transfer, read or write)
;*
;* NOTE
;* IMPORTANT! : This funtion must be directly followed by i2c_read.
;*
;***************************************************************************
I2c_do_transfer:
sbrs i2cadr,b_dir ; if dir = write
rjmp i2c_write ; goto write data
;***************************************************************************
;*
;* FUNCTION
;* i2c_read
;*
;* DESCRIPTION
;* Reads data (one byte) from the I2C bus.
;*
;* USAGE
;* Carry flag - If set no acknowledge is given to the slave
;* indicating last read operation before a STOP.
;* If cleared acknowledge is given to the slave
;* indicating more data.
;*
;* RETURN
;* i2cdata - Contains received data.
;*
;* NOTE
;* IMPORTANT! : This funtion must be directly followed by i2c_put_ack.
;*
;***************************************************************************
I2c_read:
rol i2cstat ; store acknowledge
; (used by i2c_put_ack)
ldi i2cdata,0x01 ; data = 0x01
i2c_read_bit: ; do
sbi DDRC,SCLP ; force SCL low
rcall i2c_hp_delay ; half period delay
cbi DDRC,SCLP ; release SCL
rcall i2c_hp_delay ; half period delay
clc ; clear carry flag
sbic PINC,SDAP ; if SDA is high
sec ; set carry flag
rol i2cdata ; store data bit
brcc i2c_read_bit ; while receive register not full
;***************************************************************************
;*
;* FUNCTION
;* i2c_put_ack
;*
;* DESCRIPTION
;* Put acknowledge.
;*
;* USAGE
;* (used only by i2c_read in this version)
;*
;* RETURN
;* none
;*
;***************************************************************************
i2c_put_ack: sbi DDRC,SCLP ; force SCL low
ror i2cstat ; get status bit
brcc i2c_put_ack_low ; if carry goto assert low
cbi DDRC,SDAP ; release SDA
rjmp i2c_put_ack_high
i2c_put_ack_low: ; else
sbi DDRC,SDAP ; force SDA low
i2c_put_ack_high:
rcall i2c_hp_delay ; half period delay
cbi DDRC,SCLP ; release SCL
i2c_put_ack_wait:
sbis PINC,SCLP ; wait SCL high
rjmp i2c_put_ack_wait
rcall i2c_hp_delay ; half period delay
sbi DDRC,SCLP ; force SCL low .... MISSING in original code
cbi DDRC,SDAP ; Release SDA .... MISSING in original code
ret
;***************************************************************************
;*
;* FUNCTION
;* i2c_stop
;*
;* DESCRIPTION
;* Assert stop condition.
;*
;* USAGE
;* No parameters.
;*
;* RETURN
;* None.
;*
;***************************************************************************
i2c_stop: sbi DDRC,SCLP ; force SCL low
sbi DDRC,SDAP ; force SDA low
rcall i2c_hp_delay ; half period delay
cbi DDRC,SCLP ; release SCL
rcall i2c_qp_delay ; quarter period delay
cbi DDRC,SDAP ; release SDA
rcall i2c_hp_delay ; half period delay
ret
;**** End of File ****
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -