ATtiny13 и I2CSlave

Обсуждаем контроллеры компании Atmel.
Ответить
Мучитель микросхем
Сообщения: 421
Зарегистрирован: Сб янв 06, 2018 09:22:43

Сообщение dokoff »

Добрый день, форумчане!
Обычно не обращаюсь за помощью, но тут убил почти неделю на безрезультатный поиск по просторам интернетов.
Есть задача запилить I2c слейв на ATtiny13. Именно на ATtiny13 (26,45,85 - не устраивает по причине большого количества имеющихся уже в наличии 13х).
Задача банальная. Отреагировать согласно протоколу на свой адрес, если чтение: отдать 3-5 байт из массива (ОЗУ), если запись: забрать 3-5 байт от мастера и поместить в массив (ОЗУ). На этом все.
Крайне желательно не использовать INT0 и таймер (хотя он там и не нужен для i2c).
В ATtiny13 нет TWI (USI).
На немецком сайте нашел нужную мне реализацию, но она на асме. Я в асме дуб дубом (хоть когда-то и писал под Z80 :write:).
Если кто-то подкинет стабильную реализацию на C (в любом виде, включая попсовую ардуину).
Пожалуйста, не пинайте... я за 5-8 лет ничего не просил у народа вообще... тут реально нужна подмога :beer:
Реклама
Друг Кота
Аватара пользователя
Сообщения: 15752
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Ежли просто ОЗУ для хранения до 20 байт - можно использовать DS1307 - там даже опция энергонезхависимого хранения прилагается...
:wink:
Реклама
Мучитель микросхем
Сообщения: 421
Зарегистрирован: Сб янв 06, 2018 09:22:43

Сообщение dokoff »

Нет. Не просто ОЗУ. А тиньке декодер дифференцированного манчестер-кода из радиоэфира. Данные складываются в 3-5 байт ОЗУ. После чего их нужно отдать по запросу мастера i2c.
Друг Кота
Аватара пользователя
Сообщения: 7082
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Сообщение Ivanoff-iv »

нашел асм - выложи, если своих мыслей не будет (после праздников о чемто серьёзном думать тяжело) хоть проанализируем...
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Реклама
Эиком - электронные компоненты и радиодетали
Мучитель микросхем
Сообщения: 421
Зарегистрирован: Сб янв 06, 2018 09:22:43

Сообщение dokoff »

АСМ
Спойлер

Код: Выделить всё

; i2c_slave implementation
; needs int0
; needs 2 high and 1 low register and one pointer (z)

.include "tn13def.inc"

.equ	i2c_pin		= PINB
.equ	i2c_port	= PORTB
.equ	i2c_dir		= DDRB

;.equ	i2c_bitSCL	= 0
;.equ	i2c_bitSDA	= 1
.equ	i2c_bitSCL	= 2
.equ	i2c_bitSDA	= 1

.equ	i2c_valSCL	= 1<<i2c_bitSCL
.equ	i2c_valSDA	= 1<<i2c_bitSDA

.def	i2c_data	= r16
.def	i2c_state	= r17
.def	i2c_SREG	= r8

.equ	i2c_slaveAddr	= 0x52

;macros 
.macro i2c_waitSCL_low
i2c_waitSCL_low0:	sbic i2c_pin, i2c_bitSCL
		rjmp i2c_waitSCL_low0
.endm

;macros 
.macro i2c_waitSCL_high
i2c_waitSCL_high0:	sbis i2c_pin, i2c_bitSCL
		rjmp i2c_waitSCL_high0
.endm


.macro i2c_readAddress
	; reads the address into @0
	; this is shorter than readByte, because we do not need to detect a stop condition
	ldi @0, 0x01
i2c_readAddress0:
	i2c_waitSCL_high
	clc
	sbic i2c_pin, i2c_bitSDA
		sec
	rol @0
	i2c_waitSCL_low
	brcc i2c_readAddress0
.endm

.macro i2c_readByte	; returns when scl is low, after last bit
	; reads one byte into @0
	; read the first bit (here could also come a stop condition or a rep-start)
	i2c_waitSCL_high
	in @0, i2c_pin
	andi @0, i2c_valSDA | i2c_valSCL
i2c_readByte2:
	in i2c_state, i2c_pin
	andi i2c_state, i2c_valSDA | i2c_valSCL
	cp i2c_state, @0
	breq i2c_readByte2	; nothing happend
	
	andi i2c_state, i2c_valSCL
	breq i2c_readByte3	; first bit recieved
	
	andi @0, i2c_valSDA
	brne i2c_repStart	; rep-start-condition
	i2c_return		; stop-condition

i2c_readByte3:
	andi @0, i2c_valSDA
	breq i2c_readByte4
		ldi @0, 0x03
i2c_readByte4:
	ori @0, 0x02		; end-mark for finish
i2c_readByte0:
	i2c_waitSCL_high
	clc
	sbic i2c_pin, i2c_bitSDA
i2c_readByte1:
		sec
	rol @0
	i2c_waitSCL_low
	brcc i2c_readByte0
.endm

.macro i2c_writeByte	;returns when scl is low, after last bit
	sec
i2c_writeByte0:
	rol @0
	breq i2c_writeByte3
	brcc i2c_writeByte1
		cbi i2c_dir, i2c_bitSDA
		rjmp i2c_writeByte2
i2c_writeByte1:
		sbi i2c_dir, i2c_bitSDA
		;rjmp i2c_writeByte2
i2c_writeByte2:	;sda = bit now
	i2c_waitSCL_high	; wait one clock pulse
	i2c_waitSCL_low
	clc
	rjmp i2c_writeByte0
i2c_writeByte3:	; transmittion finished
	cbi i2c_dir, i2c_bitSDA
.endm

.macro i2c_getAck	; returns when scl is low, after ack
	i2c_waitSCL_high
	andi @0, 0xFE
	sbis i2c_pin, i2c_bitSDA
		ori @0, 0x01
	i2c_waitSCL_low
.endm

.macro i2c_putAck	; returns if scl is low, after ack
	sbi i2c_dir, i2c_bitSDA
	i2c_waitSCL_high
	i2c_waitSCL_low
	cbi i2c_dir, i2c_bitSDA
.endm

.macro i2c_handleInterrupts	; this must be called between a putWaitState and remWaitState
	; needs a high register for temporary usage
	; remove interrupt-bit from GIFR
	ldi @0, 0x40
	out GIFR, @0
	sei	; switch interrupts to on
	nop	; do nothing
	nop	; max. number of 2 interrupts
	cli	; switch interrupts to off
.endm
.macro i2c_putWaitState
	sbi i2c_dir, i2c_bitSCL
.endm
.macro i2c_remWaitState
	cbi i2c_dir, i2c_bitSCL
.endm

.macro i2c_putByte	; store a recieved byte, could be a call
	; this must be the address -> z-register
	mov zl, @0
	clr zh
.endm

.macro i2c_getByte	; get a byte for transmittion, could be a call
	cpi zl, 10
	brlt i2c_getByte0
		clr zl
		clr zh
i2c_getByte0:
	ld @0, z+
.endm

.macro i2c_addressed	; this device has been addressed, could be a call
			; and take more than only a few clock cycles
.endm

.macro i2c_return	; return from interrupt, restore SREG, restore Interrupts
	ldi i2c_data, 0x40
	out GIFR, i2c_data	; clear interrupt flag
	out SREG, i2c_SREG
	reti
.endm
	

i2c_int_data:
	; only proceed on when start condition happened:
	sbis i2c_pin, i2c_bitSCL
		reti			; the scl line was low -> normal change of sda line
	
	in i2c_SREG, SREG		; the scl line was high -> start condition detected

i2c_repStart:
	i2c_waitSCL_low
	
	; handle the i2c_start_condition
	i2c_readAddress i2c_data		; read the address byte
	
	; decode the address
	mov i2c_state, i2c_data
	andi i2c_state, 0x01
	andi i2c_data, 0xFE
	cpi i2c_data, i2c_slaveAddr
	breq i2c_addressMatch		; if address matches, handle this
		
		i2c_return	; else return and wait for next start condition

i2c_addressMatch:
	; this device has been addressed -> give ack
	i2c_putAck
	i2c_putWaitState
	i2c_addressed
	rjmp i2c_readNextByte1
	
;i2c_write:	; master write mode
;	i2c_putAck
i2c_readNextByte:
	i2c_putWaitState
i2c_readNextByte1:
	i2c_handleInterrupts i2c_data	; handle some interrupts if needed
	
	sbrc i2c_state, 0		; if master-read-mode
		rjmp i2c_read		; read the thing

	i2c_remWaitState		; remove wait-state
					; else master-write
	i2c_readByte i2c_data		; read one byte. this must also detect a stop-condition

	i2c_putAck			; give the ack
	i2c_putWaitState		; put the wait state
	
	i2c_putByte i2c_data		; store the recieved byte internally
	
	i2c_remWaitState
	
	rjmp i2c_readNextByte1		; and wait for next byte

i2c_read:	; master read mode
	i2c_getByte i2c_data		; get the next byte to be read
	
	i2c_remWaitState
	i2c_writeByte i2c_data
	
	i2c_getAck i2c_state

	sbrc i2c_state, 0
		rjmp i2c_readNextByte	; read the next byte
	
	; no more bytes to read, the master didn't acknowled
	i2c_return
	
i2c_init:
	; initialize the peripheral
	cbi i2c_port, i2c_bitSDA
	cbi i2c_port, i2c_bitSCL
	cbi i2c_dir, i2c_bitSDA
	cbi i2c_dir, i2c_bitSCL
	;initialize interrupt
	ldi i2c_data, 0x40
	out GIMSK, i2c_data
	in i2c_data, MCUCR
	andi i2c_data, 0xFC
	;falling edge of int0
	ori i2c_data, 0x02
	out MCUCR, i2c_data
	ret
Реклама
Мудрый кот
Аватара пользователя
Сообщения: 1802
Зарегистрирован: Ср сен 07, 2011 21:40:30

Сообщение Flasher »

В Codevision AVR в визарде есть програмный IIC. Лет 10 назад сам пользовал.
Реклама
Мучитель микросхем
Сообщения: 421
Зарегистрирован: Сб янв 06, 2018 09:22:43

Сообщение dokoff »

[uquote="Flasher",url="/forum/viewtopic.php?p=3276304#p3276304"]В Codevision AVR в визарде есть програмный IIC. Лет 10 назад сам пользовал.[/uquote]
Мастер.
Держит паяльник хвостом
Сообщения: 933
Зарегистрирован: Ср апр 13, 2011 11:09:20
Откуда: Екатеринбург

Сообщение Alkul »

[uquote="dokoff",url="/forum/viewtopic.php?p=3276149#p3276149"]Крайне желательно не использовать INT0[/uquote]
Так не бывает. Можно, конечно, циклически опрашивать линию SCL, но тогда контроллер только этим и будет заниматься.
ВСЕ программные реализации slave I2C используют прерывание INT0 (либо INT1) для того, чтобы контроллер мог еще чем-то осмысленным заниматься.

[uquote="dokoff",url="/forum/viewtopic.php?p=3276149#p3276149"]На немецком сайте нашел нужную мне реализацию, но она на асме.[/uquote]
И она также использует внешнее прерывание.
Если Вам надо использовать внешнее прерывание для декодирования манчестера, используйте PCINT0.
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 370
Зарегистрирован: Ср мар 09, 2016 08:07:41

Сообщение JackSmith »

Так не бывает. Можно, конечно, циклически опрашивать линию SCL, но тогда контроллер только этим и будет заниматься.
ВСЕ программные реализации slave I2C используют прерывание INT0 (либо INT1) для того, чтобы контроллер мог еще чем-то осмысленным заниматься.
есть же PCINT, тоже внешнее прерывание.
возни конечно будет больше, но работать будет. Если удастся в размер вписаться.
Мучитель микросхем
Сообщения: 421
Зарегистрирован: Сб янв 06, 2018 09:22:43

Сообщение dokoff »

[uquote="Alkul",url="/forum/viewtopic.php?p=3276545#p3276545"][uquote="dokoff",url="/forum/viewtopic.php?p=3276149#p3276149"]Крайне желательно не использовать INT0[/uquote]
Так не бывает.[/uquote]
Тут и ежу понятно, что нужно прерывание. Я и написал, что "не желательно использовать [именно] прерывание INT0". Желание это относится не к конкретно данному проекту, а исключительно относительно последующей универсальности такой либы для других проектов. В любом случае это лишь пожелание, а не требование.

Добавлено after 13 minutes 54 seconds:
[uquote="Alkul",url="/forum/viewtopic.php?p=3276545#p3276545"]...для того, чтобы контроллер мог еще чем-то осмысленным заниматься.[/uquote]
Это смотря как посмотреть)) Если Манчестер 1мс TE и пакет относительно редкий, то его вполне можно обрабатывать вн. прерыванием вне всяких циклов в майне. Вся его задача состоит в вычислении разницы таймера, сброса таймера, записи бита в переменную байта, битового сдвига и инкремента счетчика бита. Так что вполне можно обойтись без обработки в основном цикле и сделать все в рамках обработки прерывания.
Я такую схему использовал для декодирования кодов CAME (ворот). Все работало аж бегом. Правда там ТЕ был 340 мс.
Держит паяльник хвостом
Сообщения: 933
Зарегистрирован: Ср апр 13, 2011 11:09:20
Откуда: Екатеринбург

Сообщение Alkul »

[uquote="JackSmith",url="/forum/viewtopic.php?p=3276624#p3276624"]есть же PCINT, тоже внешнее прерывание.[/uquote]
А я о чем написал?
Если Вам надо использовать внешнее прерывание для декодирования манчестера, используйте PCINT0
Человеку надо внешнее прерывание для декодирования манчестера, он пишет для этого программу. Какой смысл изменять отработанную библиотеку I2C под PCINT? Программу для манчестера все равно писать, но зачем еще и писать изменения в готовой библиотеке, если можно без этого обойтись?
PCINT сейчас есть во всех новых контроллерах семейства AVR. Делать библиотеку манчестера под PCINT, а I2C использовать готовую.
[uquote="dokoff",url="/forum/viewtopic.php?p=3276816#p3276816"]В любом случае это лишь пожелание, а не требование.[/uquote]
Можно использовать аппноут AVR302, это готовая библиотека I2C slave. Правда, тоже на ассемблере. Но в чем препятствие? Если вы пишете на С, сделайте эту библиотеку ассемблерной вставкой. Решите только вопрос передачи принятых байт в С-шные функции, но это несложно.
Мучитель микросхем
Сообщения: 421
Зарегистрирован: Сб янв 06, 2018 09:22:43

Сообщение dokoff »

Alkul, ну, если не брать в расчет арбитраж и более функциональный фарш на INT0 (который не хотелось бы тратить на i2c)... то да, безусловно, разницы нет. Для меня АСМ - темный лес со светом в конце тоннеля. Увы.
ЗЫ AVR302 использует TMR0

Я наверно должен пояснить суть своей просьбы. Я не требую кого-то что-то написать. Я вовсе не халявщик из разряда "сделайте мне быстренько". Я лишь прошу поделиться СИшной заготовкой либы, если у вас вдруг таковая есть. С диаграммами I2C у меня свадьбы не случилось еще лет 10 назад... если (вдруг) не найдется либы слейва i2c на СИ, то придется открывать спецификацию и вновь пытаться побороть этот злосчастный для меня i2c. Ну или покорять АСМ .. скорее это уже в другой жизни.
Держит паяльник хвостом
Сообщения: 933
Зарегистрирован: Ср апр 13, 2011 11:09:20
Откуда: Екатеринбург

Сообщение Alkul »

[uquote="dokoff",url="/forum/viewtopic.php?p=3276834#p3276834"]Я лишь прошу поделиться СИшной заготовкой либы[/uquote]
Увы. На С не пишу.
Мудрый кот
Аватара пользователя
Сообщения: 1802
Зарегистрирован: Ср сен 07, 2011 21:40:30

Сообщение Flasher »

А если посчитать?
Тактовая тини13 9,6МГц.
Если I2C 100 кГц, у нас есть 96 тактов на обработку каждого бита. Если прерывание- то около 20 тактов на заход- выход. Итого 70 тактов на обработку одного состояния. Это достаточно мало, но можно влезть. А вот 400 кГц не успеет.
Опытный кот
Аватара пользователя
Сообщения: 781
Зарегистрирован: Сб июн 01, 2013 22:24:21
Откуда: ПФО

Сообщение alex_ »

А чем обусловлен выбор именно протокола I2C?, несколько слейв устройств на шине?
Мучитель микросхем
Сообщения: 421
Зарегистрирован: Сб янв 06, 2018 09:22:43

Сообщение dokoff »

[uquote="alex_",url="/forum/viewtopic.php?p=3277798#p3277798"]А чем обусловлен выбор именно протокола I2C?, несколько слейв устройств на шине?[/uquote]
Да 3 слейва еще на линии. Собственно можно было бы и 1W использовать. Но хотелось бы именно i2c.
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Вы можете любой свой протокол придумать получается? Сделайте например какой-нибудь полудуплексный SPI, мне кажется будет проще.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Опытный кот
Аватара пользователя
Сообщения: 781
Зарегистрирован: Сб июн 01, 2013 22:24:21
Откуда: ПФО

Сообщение alex_ »

Z_h_e писал(а):Вы можете любой свой протокол придумать
У меня почему то такая же идея промелькнула и именно про SPI, потому что прост как три копейки. :))
Друг Кота
Сообщения: 3342
Зарегистрирован: Ср янв 02, 2013 08:37:35

Сообщение АСУ »

[uquote="dokoff",url="/forum/viewtopic.php?p=3276149#p3276149"]Есть задача запилить I2c слейв на ATtiny13.[/uquote]
Если ещё актуально могу попробовать написать нужный код на графическом асме (Algorithm Builder).
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Сообщение Dimon456 »

Меняй контроллер, хотя бы на ATtiny25, у него имеется аппаратный USI.
Вот, поиграйся
Правда скорость всего 100Гц (из-за записи в его EEPROM), но работает, по крайне мере в симуляторе,
хотя если USI-Slave доработать может и можно скорость поднять.
Ответить

Вернуться в «AVR»