Цитата(Cursedsmite @ Jan 24 2013, 21:57)

Я знаю про эту статью. Именно по ней я сейчас пишу свой код на асме. Но всё таки у меня теплиться надежда, что где-то есть уже написанный именно на ассемблере код.
там комментарии достаточно подробные, я по ней и писал...
программа передачи/приема одного байта без признака подтверждения (ACK), при желании допишите его, обмен был сделан для 2-х attiny24 на частоте 115,2кГц с резиторами подтяжки 3кОм
Код
.device ATtiny24
.nolist
.include "C:\Program Files\Atmel\AVR Tools\AvrAssembler2\Appnotes\tn24def.inc"
.list
;====================================================================
;при инициализации в числе прочих определяем вспомогательные регистры шины
;====================================================================
.def stwi =r17 ;определяем регистр состояния шины TWI
;00000000 - шина свободна
;00000001 - флаг "кадр" (идет передача кадра)
;00000010 - флаг "адрес/данные"(0-адрес)
;00000100 - флаг "вывод байта"
;00001000 - флаг "строб"
;00010000 - флаг "сдвиг байта"
;00100000 - флаг "стоп байта"
;01000000 - флаг "освободить шину"
.def atwi =r18 ;регистр адреса кадра TWI с флагами "запись/чтение" (0-запись) и "сброс"
;ХХХХХХ01 - чтение
;ХХХХХХ11 - чтение со сбросом
;ХХХХХХ00 - запись
;ХХХХХХ10 - запись с сохранением в EEPROM
.def dtwi =r19 ;определяем регистр данных кадра TWI
;====================================================================
;таблица векторов прерываний
;====================================================================
rjmp init
reti
reti
reti
reti
reti
rjmp compa
;====================================================================
;настройка таймера 1 на рабочий режим
;====================================================================
ldi temp,0b00000000
out TCNT1H,temp
ldi temp,0b00000000
out TCNT1L,temp
ldi temp,0b00000000 ;включаем таймер 1 в режиме сброс при совпадении
out TCCR1A,temp
ldi temp,0b00001001 ;без деления тактовой
out TCCR1B,temp
ldi temp,0b00000000 ;
out TCCR1C,temp
ldi temp,0b00100010 ;заносим значение 34 (битрейт TWI 115,2кГц) в регистр совпадения
out OCR1AL,temp
ldi temp,0b00000010 ;разрешаем прерывания от таймера 1 по совпадению
out TIMSK1,temp
sei ;общее разрешение прерываний
;====================================================================
;для вывода байта данных в основном цикле загружаем 3 регистра, например так:
;====================================================================
ldi atwi,0b00011100 ;загружаем команду записи регистра 07h без записи в EEPROM
mov dtwi,upor
sbr stwi,0b00000001 ;устанавливаем флаг "кадр"
;====================================================================
;подпрограмма передачи/приема байта от ведомого
;====================================================================
compa: ;прерывание каждые 4,25мкс
sbrs stwi,0 ;если флаг "кадр" не установлен
rjmp impuls ;то переход на вывод импульсов, иначе:
sbrc stwi,2 ;если установлен флаг "вывод байта"
rjmp out_byte ;то переход на подпрограмму вывода байта
sbrc stwi,3 ;если установлен флаг "строб"
rjmp clock ;то переход на подпрограмму формирования строба
sbrc stwi,4 ;если установлен флаг "сдвиг"
rjmp shift ;то переход на подпрограмму формирования сдвига
sbrc stwi,5 ;если установлен флаг "стоп"
rjmp stop ;то переход на подпрограмму формирования стопа
sbrc stwi,6 ;если установлен флаг "освободить шину"
rjmp free_bus ;то переход на подпрограмму освобождения шины
rjmp start ;иначе переход на подпрограмму старта байта
out_compa:
reti ;выход из прерывания
;===================================================================
start:
sbr stwi,0b00000100 ;устанавливаем флаг "вывод байта"
cbi PORTA,6 ;устанавливаем SDA в 0
rjmp out_compa ;и выходим из прерывания
;===================================================================
out_byte:
sbis PINA,4 ;если SCL в 0, значит слейв не готов к обмену и прижал ее
rjmp out_compa ;тогда выходим из прерывания
cbr stwi,0b00000100 ;иначе слейв готов к обмену, сбрасываем флаг "вывод байта"
sbr stwi,0b00001000 ;устанавливаем флаг "строб"
ldi temp,0b11110000 ;сбрасываем флаги и счетчик тактов регистра состояния USI
out USISR,temp
cbi PORTA,4 ;устанавливаем SCL в 0
sbi PORTA,6 ;устанавливаем SDA в 1
sbrc stwi,1 ;проверяем, установлен ли флаг "адрес/данные"
rjmp data ;если установлен, то переходим на передачу данных
out USIDR,atwi ;иначе загружаем адрес в регистр данных TWI
rjmp out_compa ;и выходим из прерывания
data:
sbrs atwi,0 ;если выполняется запись байта
rjmp write_byte ;то переход
cbi DDRA,6 ;иначе переключаем SDA на вход
rjmp out_compa ;и выходим из прерывания
write_byte:
out USIDR,dtwi
rjmp out_compa ;и выходим из прерывания
;==================================================================
clock:
sbi USICR,USITC ;иначе формируем строб
cbr stwi,0b00001000 ;сбрасываем флаг "строб"
sbr stwi,0b00010000 ;устанавливаем флаг "сдвиг"
rjmp out_compa ;и выходим из прерывания
;==================================================================
shift:
sbi USICR,USITC ;формируем сдвиг данных
sbic USISR,USIOIF ;проверяем флаг счетчика тактов
rjmp read_byte ;если переполнен, то переход на конец байта
cbr stwi,0b00010000 ;иначе сбрасываем флаг "сдвиг"
sbr stwi,0b00001000 ;устанавливаем флаг "строб"
rjmp out_compa ;и выходим из прерывания
read_byte:
sbrs stwi,1 ;если флаг "адрес/данные" сброшен
rjmp end_byte ;то переходим на завершение приема байта
in dtwi,USIDR ;иначе читаем байт из регистра данных TWI
end_byte:
sbi USISR,USIOIF ;сбрасываем флаг по переполнению счетчика (можно не делать)
sbi DDRA,6 ;переключаем SDA на выход (на тот случай, когда было чтение)
cbi PORTA,6 ;устанавливаем SDA в 0
cbr stwi,0b00010000 ;сбрасываем флаг "сдвиг"
sbr stwi,0b00100000 ;устанавливаем флаг "стоп"
rjmp out_compa ;и выходим из прерывания
;==================================================================
stop:
sbi USIDR,7 ;освобождаем линию SDA от данных (иначе SDA может не установиться в 1)
sbi PORTA,4 ;устанавливаем SCL в 1
; sbi USIDR,7 ;освобождаем линию SDA от данных (иначе SDA может не установиться в 1)
cbr stwi,0b00100000 ;сбрасываем флаг "стоп"
sbr stwi,0b01000000 ;устанавливаем флаг "освободить шину"
; sbi USIDR,7 ;освобождаем линию SDA от данных (иначе SDA может не установиться в 1)
rjmp out_compa ;и выходим из прерывания
;==================================================================
free_bus:
sbi PORTA,6 ;устанавливаем SDA в 1
sbrc stwi,1 ;если флаг "адрес/данные" установлен
rjmp clr_stwi ;то переходим на сброс
cbr stwi,0b01000000 ;иначе сбрасываем флаг "освободить шину"
sbr stwi,0b00000010 ;устанавливаем флаг "адрес/данные"
rjmp out_compa ;и выходим из прерывания
clr_stwi:
clr stwi ;сбрасываем регистр состояния шины
rjmp out_compa ;и выходим из прерывания
;==================================================================