Ну и пока ставим USITC в 0, чтобы интерфейс пока ничем не дергал.
Также нельзя забывать о конфигурации ног SCL и SDA на выход. С этого
момента старший бит регистра USIDR присутствует в виде уровня на ноге
SDA! Обе линии находятся в исходном состоянии (в единице).
Теперь опишем процедуры для задания состояний СТАРТ и СТОП.
•
Состояние СТАРТ — это изменение уровня SDA с высокого на низкий
при высоком уровне линии SCL
•
Состояние СТОП — это изменение уровня SDA с низкого на высокий
при высоком уровне линии SCL
Я перестраховался с этими состояниями, поэтому код несколько избыточен и
в тоже время прост как пробка и нагляден:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void i2c_start(void)
{ // Генерируем состояние Старт (или ПовСтарт)
sbi(sdaport,sda); // на всякий случай выставляем в исходное
состояние sda
sbi(sclport,scl); // тоже с SCL
cbi(sclportd,scl); // ВАЖНО!!! отключаем SCL от
выходного буфера интерфейса
USISR = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|(0x0<<USICNT0);
cbi(sdaport,sda); // переводим SDA в 0 пока SCL в 1
dummyloop(USI_DELAY); // тупим нашу задержку
sbi(sclportd,scl); // ВАЖНО!!! подключаем SCL обратно к
выходному буферу интерфейса
cbi(sclport,scl); // переводим SCL в 0
sbi(sdaport,sda); // освобождаем линию SDA для
последующей передачи/приема данных
dummyloop(USI_DELAY); // еще раз тупим
задержку
return();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
void i2c_stop(void) {// Генерируем состояние Стоп
cbi(sclport,scl); // необязательная подготовка
dummyloop(USI_DELAY);
cbi(sdaport,sda);
dummyloop(USI_DELAY);
sbi(sclport,scl); // перевод SCL в 1
dummyloop(USI_DELAY);
sbi(sdaport,sda); // перевод SDA в 1
dummyloop(USI_DELAY);
USISR|=(1<<USIPF); //сброс флага детекции
состояния Стоп в USISR
return ();
}