Próbuję wykorzystać sprzętowe I2C zawarte w Atmedze16. Poniżej kod:
Adres jest wysyłany poprawnie. Po jego wysłaniu pojawia się ACK. Wysłanie pierwszego bajtu danych też kończy się powodzeniem i odebraniem ACK. Przy drugim wysyłanym bajcie dochodzi do zapętlenia w podprogramie "I2C_gotowosc". Rezystory podciągające dla SDA i SCL wstawiłem 5,6KΩ.
.nolist
.include "m16def.inc" ;dołączenie listy stałych
.list
.cseg
;konfiguracja I2C
.EQU TWBR_ = 10 ;TWI Bit Rate Register
.EQU TWPS_ = 3 ;TWI Prescaler Bits
;status I2C
.EQU START = 0x08 ;sygnał startowy - wysłany
.EQU MT_SLA_ACK = 0x18 ;SLSA+W wysłany, ACK odebrany
.EQU MT_DATA_ACK = 0x28 ;dane wysłane, ACK odebrany
;adresy urządzeń slave I2C
.EQU ADR_TSA6057 = 0xC4
;dane dla TSA6057
.EQU SUBADRESS = 0x03
.EQU DB0 = 0x63 ;DB0...DB2 - komórki RAM
.EQU DB1 = 0x64
.EQU DB2 = 0x65
.EQU DB3 = 0x00
;prowizoryczne stałe
.EQU FM_AM = 1
.EQU FM_AM_OPAMP = 1
.EQU CP_ = 0
.EQU REF1 = 0 ;1Khz step
.EQU REF2 = 0
.EQU BS = 0
.EQU DIVIDER = 0x6AA4 ;27300*1KHz=27,3MHz
.EQU DB0_ = ((DIVIDER & 0x7F) << 1) + CP_
.EQU DB1_ = ((DIVIDER & 0x7F80) >> 7)
.EQU DB2_ = ((DIVIDER & 0x18000) >> 15) + 4*BS + 16*FM_AM_OPAMP + 32*FM_AM + 64*REF2 + 128*REF1
.org 0x0000 rjmp RESET
I2C_start:
ldi r16, (1<<TWINT) | (1<<TWSTA) | (1<<TWEN)
out TWCR, r16
ret
I2C_gotowosc:
in R16, TWCR
sbrs R16, TWINT
rjmp I2C_gotowosc
ret
I2C_status:
;R17 sprawdzany status
in R16, TWSR
andi R16, 0xF8
cp R16, R17
brne ERROR
ret
ERROR:
;błąd I2C
ret
I2C_adres_SLA_W:
;R16 adres urządzenia SLAVE I2C
out TWDR, R16
ldi R16, (1<<TWINT) | (1<<TWEN)
out TWCR, R16
rcall I2C_gotowosc
ret
I2C_dane:
;R16 wysyłany bajt danych do urządzenia SLAVE I2C
out TWDR, R16
ldi R16, (1<<TWINT) | (1<<TWEN)
out TWCR, R16
rcall I2C_gotowosc
ret
I2C_stop:
ldi R16, (1<<TWINT) | (1<<TWEN) | (1 << TWSTO)
out TWCR, R16
ret
wyslij_dane_TSA6057:
rcall I2C_start
ldi R17,START
rcall I2C_status
ldi R16,ADR_TSA6057
rcall I2C_adres_SLA_W
ldi R17,MT_SLA_ACK
rcall I2C_status
ldi R16,SUBADRESS
rcall I2C_dane
ldi R17,MT_DATA_ACK
rcall I2C_status
lds R16,DB0
rcall I2C_dane
ldi R17,MT_DATA_ACK
rcall I2C_status
lds R16,DB1
rcall I2C_dane
ldi R17,MT_DATA_ACK
rcall I2C_status
lds R16,DB2
rcall I2C_dane
ldi R17,MT_DATA_ACK
rcall I2C_status
ldi R16,DB3
rcall I2C_dane
ldi R17,MT_DATA_ACK
rcall I2C_status
rcall I2C_stop
ret
RESET:
ldi R18,low(RAMEND)
out SPL,R18
ldi R18,high(RAMEND)
out SPH,R18
;ustawienie f dla SCL
ldi R16,TWBR_
out TWBR,R16
in R16,TWSR
ori R16,TWPS_
out TWSR,R16
ldi R16,DB0_
sts DB0,R16
ldi R16,DB1_
sts DB1,R16
ldi R16,DB2_
sts DB2,R16
rcall wyslij_dane_TSA6057
stop:
rjmp stop
Adres jest wysyłany poprawnie. Po jego wysłaniu pojawia się ACK. Wysłanie pierwszego bajtu danych też kończy się powodzeniem i odebraniem ACK. Przy drugim wysyłanym bajcie dochodzi do zapętlenia w podprogramie "I2C_gotowosc". Rezystory podciągające dla SDA i SCL wstawiłem 5,6KΩ.