我用2个Mega64来做硬件TWI通讯,一个主机读模式,一个从机写模式。主机发出STA信号后能正确得到08码,之后发出SLA+R信号后收不到后续INT置位。
从机方面,每次中断进去后只能得到00码,收不到A8的码。
请各位高手帮忙,已经调了2个星期了。TWI 的2根线在外部加了10k的上拉到5V。
主机部分程序:16M晶振
初始化部分
ldi temp1,0b01111111
out PORTD,temp1
ldi temp1,0b10001011 ;PORTD | . | | | | DO4 | | sda | scl |
out DDRD,temp1
i2c_init:
in temp1,SREG
push temp1
cli
ldi temp1,$00
sts TWCR,temp1
ldi temp1,$48 ;400K twps=0
sts TWBR,temp1
ldi temp1,$00
sts TWSR,temp1
ldi temp1,$84 ;
sts TWCR,temp1
pop temp1
out SREG,temp1
ret
主机主程序部分,用查询INT的方式。
loop: wdr
rcall twi
rjmp loop
;twi子程序
twi: wdr
lds temp1,twiflag
cpi temp1,$00
brne twi2
ldi temp1,$02
sts twiflag,temp1
ldi temp1,(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)
sts TWCR,temp1
twi1exit: ret
twi2: cpi temp1,$02
brne twi3
lds temp1,TWCR
sbrs temp1,TWINT
rjmp twi2exit
lds temp1,TWSR
andi temp1,$f8
cpi temp1,$08 ;$08 已发送了start $10 已重发了start
brne twi2exit ;twi2erro
ldi temp1,$03 ;高7位为地址,最低位1表示读,为0写
sts TWDR,temp1
ldi temp1,(1<<TWINT)|(1<<TWEN)
sts TWCR,temp1
ldi temp1,$03
sts twiflag,temp1
twi2exit: rjmp twi1exit
twi3: cpi temp1,$03
brne twi4
lds temp1,TWCR
sbrs temp1,TWINT
rjmp twi3exit
lds temp1,TWSR
andi temp1,$f8
cpi temp1,$40 ;$38,$40,$48 见p97
brne twi3_2
; call _W1ms
ldi temp1,(1<<TWINT)|(1<<TWEN)
sts TWCR,temp1
ldi temp1,$04
sts twiflag,temp1
twi3exit: rjmp twi1exit
从机的初始化:16M晶振
ldi temp1,0b00001111
out PORTD,temp1
ldi temp1,0b00000011 ;PORTD |GND | GND | GND | GND | XB | XA | SDA | SCL |
out DDRD,temp1
i2c_init:
in temp1,SREG
push temp1
cli
ldi temp1,$00 ;
sts TWCR,temp1
ldi temp1,$03 ;
sts TWAR,temp1
ldi temp1,$c5 ;
sts TWCR,temp1
ldi yh,$00
pop temp1
out SREG,temp1
ret
从机TWI中断:
twi_int: in temp1,SREG ;temp1为中断内临时数据寄存器
push TEMP1
push temp1
push temp2
lds temp1,TWSR
andi temp1,$f8
cpi temp1,$a8 ;sla+r已被接收,ack返回,写入数据
breq twiint_2
cpi temp1,$b8
breq twiint_2
cpi temp1,$00
breq xxy
ldi temp1,(1<<TWINT)|(1<<TWEN)|(1<<TWIE)|(1<<TWEA)
sts TWCR,temp1
jmp twiint_4
xxy: ldi temp1,(1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE)|(1<<TWSTO)
sts TWCR,temp1
jmp twiint_4
twiint_2:
ldi temp1,$05
mul yh,temp1
mov zl,r0
mov zh,r1
subi zh,-$40
twiint_3: cpi yh,$0b
breq twiint_5
inc yh
twiint_40: ldi temp1,(1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE)
sts TWCR,temp1
twiint_4: pop temp2
pop temp1
pop temp1
out SREG,temp1
reti
twiint_5: ldi` yh,$00
ldi temp1,(1<<TWINT)|(1<<TWEN)|(1<<TWIE)|(1<<TWEA)
sts TWCR,temp1
rjmp twiint_4 |