всё это безобразие я оформил ввиде подпрограмм, которые в нужном 
порядке можно вызывать из основной программы

;+подпрограмма инициализации модуля TWI+

TWI_init:
          ldi t1,0x0A           ;при тактовой частоте 8 МГц частота работы
	  out TWBR,t1           ;модуля приблизительно 250 КГц
	  ldi t1,(0b00<<TWPS0)
	  out TWSR,t1
	  ldi t1,(1<<TWEN)
          out TWCR,t1
ret


;+подпрограмма формирования состояния старт на шине TWI+

TWI_start:
          
          ldi temp,0xA4   ;эквивалентно записи (1<<TWINT)|(1<<TWSTA)|(1<<TWEN)
          out TWCR,temp
wait:
          in temp,TWCR    ;ждём установки флага TWINT
          sbrs temp,TWINT ;когда флаг установится идём дальше
rjmp wait

out_st:
          in temp,TWSR    ;проверяем регистр состояния 
	  cpi temp,0x08   ;если 0x08 значит старт сформирован можно выходить
	  breq start_out 

rjmp out_st

start_out:

ret	


;+подпрограмма формирования состояния стоп на шине TWI+

TWI_stop:			 
	 ldi temp,0x94    ;эквивалентно записи (1<<TWINT)|(1<<TWSTO)|(1<<TWEN)
	 out TWCR,temp    ;ну здесь всё понятно
ret


;+подпрограмма формирования состояния повстарт на шине TWI+

TWI_pstart:    

	  ldi temp,0xA4   ;в целом тот же старт, но отличие заключается только
	  out TWCR,temp   ;в значении регистра состояния
wait1:
          in temp,TWCR
          sbrs temp,TWINT
rjmp wait1

pstt:
	  in temp,TWSR
	  cpi temp,0x10
	  breq pstart_out 

rjmp pstt	

pstart_out:   

ret


;+подпрограмма передачи пакета с адресом устройства+
;для перехода модуля в режим ведущий-передатчик необходимо передать по шине
;пакет SLA+W с адресом подчинённого устройства, что мы и делаем
 
master_trans_adress:     
	  
          ldi temp,0x90    ;содержимое пакета зависит от девайса который вы подключаете
	  out TWDR,temp    ;берётся из документации на микросхему у меня пример для DS1621 (0x90)
	  ldi temp,0x84    ;эквивалентно записи (1<<TWINT)|(1<<TWEN)
	  out TWCR,temp
wait2:
          in temp,TWCR     
          sbrs temp,TWINT
rjmp wait2

mtsa:
	  in temp,TWSR     ;здесь проверяется регистр состояния
	  cpi temp,0x18    ;если 0x18 ответ ACK от приёмника пришёл, значит данные приняты
	  breq mt1         ;можно выходить
	  cpi temp,0x20    ;если 0x20 ответ ACK от приёмника не пришёл, формируем состояние стоп
	  breq mt2         ;на линии и выходим
rjmp mtsa

mt1:

ret

mt2:
  rcall i2c_stop
ret


;+подпрограмма передачи пакета с данными+
;после передачи адресного пакета должны быть переданы пактЫ данных
;для этого перед вызовом подпрограммы байт данных записываем в регистр TWDR

ldi temt,0xAA             ;значение для примера
out TWDR,temp

master_trans_data:    
	 
          ldi temp,0x84
	  out TWCR,temp
wait3:
          in temp,TWCR
          sbrs temp,TWINT
rjmp wait3

mtsa1:
          in temp,TWSR
	  cpi temp,0x28
	  breq mt3
	  cpi temp,0x30
	  breq mt4 
rjmp mtsa1

mt3:
ret

mt4:
  rcall i2c_stop
ret


;+подпрограмма приёма пакета с данными+
;для перехода модуля в режим ведущий-приёмник необходимо передать по шине
;пакет SLA+R с адресом подчинённого устройства, что мы и делаем

master_receiver_ad:  
	 
          ldi temp,0x91
	  out TWDR,temp
	  ldi temp,0x84
	  out TWCR,temp
wait5:
          in temp,TWCR
          sbrs temp,TWINT
          rjmp wait5
mtsr:
	  in temp,TWSR
	  cpi temp,0x40
	  breq mt5
	  cpi temp,0x48
	  breq mt6 
rjmp mtsr
mt5:  
          in temp1,TWDR       ;принятый байт сохраняем в регистр temp1
ret

mt6: rcall i2c_stop
ret     

P.S. Ну вот так легко это всё и организовывается
На последок приведу пример с описанными подпрограммами для работы с датчиком DS1621/

Инициализация датчика

ds1621_init:
	 
         rcall TWI_start	
	 rcall master_trans_adress
	 ldi temp,0xEE
	 out TWDR,temp
	 rcall master_trans_data
	 rcall TWI_stop
ret 

чтение данных из датчика

ds1621_read: 
     
	 rcall TWI_start
	 rcall master_trans_adress
	 ldi temp,0xAA
	 out TWDR,temp
	 rcall master_trans_data
	 rcall TWI_pstart
	 rcall master_receiver_ad
wait6:
         in temp,TWCR
         sbrs temp,TWINT

rjmp wait6
	 
         ldi temp,0xC4
	 out TWCR,temp
mtsr8:
	 in temp,TWSR
	 cpi temp,0x50
	 breq mt8

rjmp mtsr8

mt8:  
         in temp1,TWDR             ;старший бай данных     
wait7:
         in temp,TWCR
         sbrs temp,TWINT
rjmp wait7
	 
         ldi temp,0x84
	 out TWCR,temp
mtsr9:
	 in temp,TWSR
	 cpi temp,0x58
	 breq mt9
rjmp mtsr9	 

mt9: 
         in temp2,TWDR            ;младший байт данных
         rcall i2c_stop
ret

Вот так это выглядит.Все вопросы в личку или аську 476243579
