Софтовый I2C

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
Родился
Аватара пользователя
Сообщения: 19
Зарегистрирован: Пн окт 13, 2008 20:24:05
Откуда: LbtCity

Сообщение KVorb »

Понадобился мне софтовый I2C. Взял пример из апноты avr300.asm
Отправка данных мастером работает, чтение одного байта тоже работает.
А вот при попытке прочитать два байта, в первом есть данные, а второй всегда равен 0x00 :( Во втором байте точно должен быть не 0, проверял с аппаратным I2C на Mega8.

Вот сам код:

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

;Адрес I2C + write и 	Старт	
ldi  	i2cadr,0b10011110+i2cwr	
rcall	i2c_start					
	
;Адрес ячейки и Отправка
ldi  	i2cdata,$A2			 
rcall	i2c_do_transfer				

;Адрес I2C + read и Повторный старт
ldi  	i2cadr,0b10011110+i2crd	
rcall	i2c_rep_start				

;Чтение
;Этот байт читается, после него ACK 
rcall	i2c_do_transfer				
mov  	r18,i2cdata	
	
sec							 
;Чтение
;В этом байте всегда 0x00 ( почему? ), после него NACK	
rcall	i2c_do_transfer				
mov  	r19,i2cdata

;STOP
rcall	i2c_stop					
Проверял и на макетке и в протеусе, везде одинаково.
Контактная информация:
Реклама
Родился
Аватара пользователя
Сообщения: 19
Зарегистрирован: Пн окт 13, 2008 20:24:05
Откуда: LbtCity

Сообщение KVorb »

Разобрался :))

Оказывается в апноте есть ошибка. Она приводит к тому, что при чтении все байты, кроме первого (после адреса слейва) читаются как 0x00. Это связано с тем, что при выдачи мастером ACK в ответ на чтение 1-го байта линия SDA засаживается контроллером на "0" и остается в этом состоянии на протяжении всех последующих чтений.

Оригинальный код:

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

i2c_read:
	rol	i2cstat			; store acknowledge
					; (used by i2c_put_ack)
	ldi	i2cdata,0x01		; data = 0x01
i2c_read_bit:				; do
	sbi	DDRD,SCLP		; 	force SCL low
	rcall	i2c_hp_delay		;	half period delay

	cbi	DDRD,SCLP		;	release SCL
	rcall	i2c_hp_delay		;	half period delay

	clc				;	clear carry flag
	sbic	PIND,SDAP		;	if SDA is high
	sec				;		set carry flag

	rol	i2cdata			; 	store data bit
	brcc	i2c_read_bit		; while receive register not full
Поменять на:

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

i2c_read:
	rol	i2cstat			; store acknowledge
						; (used by i2c_put_ack)
	ldi	i2cdata,0x01		; data = 0x01
i2c_read_bit:				; do
	sbi	DDRC,SCLP		; 	force SCL low
;******** Добавлено******************************
    nop; даем время опуститься SCL (300ns)
    nop
    nop
    nop
    nop
    cbi    DDRC,SDAP; отпускаем SDA
;******** ***************************************
	rcall	i2c_hp_delay		;	half period delay

	cbi	DDRC,SCLP		;	release SCL
	rcall	i2c_hp_delay		;	half period delay

	clc				;	clear carry flag
	sbic	PINC,SDAP		;	if SDA is high
	sec				;		set carry flag

	rol	i2cdata			; 	store data bit
	brcc	i2c_read_bit		; while receive register not full
Спасибо тем кто очень хотел, но не успел помочь :)))
Контактная информация:
Реклама
Модератор
Аватара пользователя
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Сообщение ploop »

KVorb, это вам спасибо, следил за темой. Реально скоро пригодится.
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»