📄 i2c.asm
字号:
.include "8515def.inc" ; change if an other device is used
;**** Global viic Constants ****
.equ vscl =4 ; SCL Pin number (port D)
.equ vsda =5
.equ vwe =3
.equ viic_port =portd
.equ viic_pin =pind
.equ viic_ddr =ddrd
.equ read_sbuf =$70
.equ write_sbuf =$80 ; SDA Pin number (port D)
.equ b_dir = 0 ; transfer direction bit in viic_adr
.equ viic_rd = 1
.equ viic_wr = 0
;**** Global Register Variables ****
.def viic_data = r15
.def viic_delay = r16
.def start_address = r17 ; Delay loop variable
; viic data transfer register
.def viic_adr = r18 ; viic address and direction register
.def viic_stat = r19
.def data_number = r20 ; viic bus status register
;**** Interrupt Vectors ****
.org $0000
rjmp RESET ; Reset handle
viic_hp_delay:
ldi viic_delay,2
viic_hp_delay_loop:
dec viic_delay
brne viic_hp_delay_loop
ret
viic_qp_delay:
ldi viic_delay,1
viic_qp_delay_loop:
dec viic_delay
brne viic_qp_delay_loop
ret
viic_rep_start:
sbi viic_ddr,vscl ; force SCL low
cbi viic_ddr,vsda ; release SDA
rcall viic_hp_delay ; half period delay
cbi viic_ddr,vscl ; release SCL
rcall viic_qp_delay ; quarter period delay
viic_start:
mov viic_data,viic_adr ; copy address to transmitt register
sbi viic_ddr,vsda ; force SDA low
rcall viic_qp_delay ; quarter period delay
viic_write:
sec ; set carry flag
rol viic_data ; shift in carry and out bit one
rjmp viic_write_first
viic_write_bit:
lsl viic_data ; if transmit register empty
viic_write_first:
breq viic_get_ack ; goto get acknowledge
sbi viic_ddr,vscl ; force SCL low
brcc viic_write_low ; if bit high
nop ; (equalize number of cycles)
cbi viic_ddr,vsda ; release SDA
rjmp viic_write_high
viic_write_low: ; else
sbi viic_ddr,vsda ; force SDA low
rjmp viic_write_high ; (equalize number of cycles)
viic_write_high:
rcall viic_hp_delay ; half period delay
cbi viic_ddr,vscl ; release SCL
rcall viic_hp_delay ; half period delay
rjmp viic_write_bit
viic_get_ack:
sbi viic_ddr,vscl ; force SCL low
cbi viic_ddr,vsda ; release SDA
rcall viic_hp_delay ; half period delay
cbi viic_ddr,vscl ; release SCL
viic_get_ack_wait:
sbis viic_pin,vscl ; wait SCL high
;(In case wait states are inserted)
rjmp viic_get_ack_wait
clt ; clear carry flag
sbic viic_pin,vsda ; if SDA is high
set ; set carry flag
rcall viic_hp_delay ; half period delay
ret
viic_do_transfer:
sbrs viic_adr,b_dir ; if dir = write
rjmp viic_write ; goto write data
viic_read:
rol viic_stat
clr viic_data ; store acknowledge
; (used by viic_put_ack)
inc viic_data ; data = 0x01
viic_read_bit: ; do
sbi viic_ddr,vscl ; force SCL low
rcall viic_hp_delay ; half period delay
cbi viic_ddr,vscl ; release SCL
rcall viic_hp_delay ; half period delay
clc ; clear carry flag
sbic viic_pin,vsda ; if SDA is high
sec ; set carry flag
rol viic_data ; store data bit
brcc viic_read_bit ; while receive register not full
viic_put_ack:
sbi viic_ddr,vscl ; force SCL low
ror viic_stat ; get status bit
brcc viic_put_ack_low ; if bit low goto assert low
cbi viic_ddr,vsda ; release SDA
rjmp viic_put_ack_high
viic_put_ack_low: ; else
sbi viic_ddr,vsda ; force SDA low
viic_put_ack_high:
rcall viic_hp_delay ; half period delay
cbi viic_ddr,vscl ; release SCL
viic_put_ack_wait:
sbis viic_pin,vscl ; wait SCL high
rjmp viic_put_ack_wait
rcall viic_hp_delay
sbi viic_ddr,vscl
cbi viic_ddr,vsda ; half period delay
ret
viic_stop:
sbi viic_ddr,vscl ; force SCL low
sbi viic_ddr,vsda ; force SDA low
rcall viic_hp_delay ; half period delay
cbi viic_ddr,vscl ; release SCL
rcall viic_qp_delay ; quarter period delay
cbi viic_ddr,vsda ; release SDA
rcall viic_hp_delay ; half period delay
ret
viic_init:
clr viic_stat ; clear viic status register (used
; as a temporary register)
out viic_port,viic_stat ; set viic pins to open colector
out viic_ddr,viic_stat
ret
write_data:
ldi viic_adr,$A0+viic_wr ; Set device address and write
rcall viic_start ; Send start condition and address
mov viic_data,start_address ; Write word address (0x00)
rcall viic_do_transfer
clr xh
ldi xl,write_sbuf
write_loop:
ld viic_data,x ; Execute transfer
rcall viic_do_transfer
inc xl
dec data_number
brne write_loop ; Execute transfer
rcall viic_stop
ret
; Send stop condition
Read_data:
ldi viic_adr,$A0+viic_wr ; Set device address and write
rcall viic_start ; Send start condition and address
mov viic_data,start_address ; Write word address
rcall viic_do_transfer ; Execute transfer
ldi viic_adr,$A0+viic_rd ; Set device address and read
rcall viic_rep_start
clr xh
ldi xl,read_sbuf ; Send repeated start condition and address
read_loop:
clc ; Set no acknowledge (read is followed by a stop condition)
rcall viic_do_transfer
st x,viic_data
inc xl
dec data_number
brne read_loop ; Execute transfer (read)
rcall viic_stop
ret ; Send stop condition - releases bus
RESET:
main:
ldi r16,high(ramend)
out sph,r16
ldi r16,low(ramend)
out spl,r16
ldi r16,$01
clr xh
ldi xl,write_sbuf
set_data:
st x,r16
inc r16
inc xl
cpi r16,$0f
brne set_data
call_loop:
rcall viic_init
ldi start_address,$0
ldi data_number,6 ; initialize viic interface
rcall write_data
ldi start_address,$0
ldi data_number,6
rcall read_data
rjmp call_loop
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -