В приведенных ниже примерах вывод SCL I2C устройства подключен к выводу RB2 pic-контроллера,
вывод SDA - к RB3.
  Процедуры написаны на ассемблере и могут быть встроены в код С-компиллятора (как это сделано
в примерах - для C2C). Проверялась работа процедур с частотой кварца 4МГц. При
более высоких частотах возможно потребуется вводить временные задержки для корректного обмена
по шине I2C.
/*--------- начало примера-----------
Требуется 2 байта ОЗУ - i2c_byte - в него помещается байт,
который необходимо вывести на шину, в нем оказывается байт,
считанный с шины; tmp - счетчик, используемый в цикле. */
char i2c_byte; /* рабочий регистр */
char tmp; /* счетчик */
void i2c_start() {
asm {
bcf STATUS, RP0
bsf PORTB, 2 ; SCL - 1
bsf PORTB, 3 ; SDA - 1
bcf PORTB, 3 ; SDA - 0
bcf PORTB, 2 ; SCL - 0
}
}
void i2c_stop() {
asm {
bcf STATUS, RP0
bcf PORTB, 3 ; SDA - 0
bsf PORTB, 2 ; SCL - 1
bsf PORTB, 3 ; SDA - 1
}
}
void i2c_write() {
asm {
movlw 0x08
movwf _tmp
bsf STATUS, RP0
bcf TRISB, 3 ; SDA - вывод
bcf STATUS, RP0
bcf PORTB, 2 ; SCL - 0
send_bit bsf PORTB, 3 ; выводим 1 на SDA
btfss _i2c_byte, 7 ; бит данных - 1 ?
bcf PORTB, 3 ; нет - выводим 0 на SDA
bsf PORTB, 2 ; SCL - 1
rlf _i2c_byte, F ; сдвигаем влево байт данных
bcf PORTB, 2 ; SCL - 0
decfsz _tmp, F ; конец цикла ?
goto send_bit ; нет - переход
bsf PORTB, 3 ; осв. SDA
bsf PORTB, 2 ; SCL - 1, получаем ACK-бит и игнорируем его (!)
bcf PORTB, 2 ; SCL - 0
}
}
void i2c_read() {
asm {
movlw 0x08
movwf _tmp
bsf STATUS, RP0
bsf TRISB, 3 ; SDA - на ввод
bcf STATUS, RP0
bcf PORTB, 2 ; SCL - на 0
read_bit rlf _i2c_byte, F ; сдвигаем байт влево
bsf PORTB, 2 ; SCL - up
bsf _i2c_byte, 0 ; устанавливаем бит в 1
btfss PORTB, 3 ; SDA - 1?
bcf _i2c_byte, 0 ; нет - устанавливаем бит в 0
bcf PORTB, 2 ; SCL - 0
decfsz _tmp, F ; конец цикла ?
goto read_bit ; нет - переход
bsf STATUS, RP0
bcf TRISB, 3 ; SDA - на вывод
bcf STATUS, RP0
}
}
/*------------- окончание примера ------------ */
*/------------начало примера----------------
вывод содержимого памяти на COM-порт */
void outAllData() {
for (i = 0; i < 32767; i++) {
i2c_start();
i2c_byte = 0xA0; // control байт с битом WR
i2c_write();
asm {
movfw _i+1
movwf _i2c_byte ; старший байт адреса памяти
}
i2c_write();
asm {
movfw _i
movwf _i2c_byte ; младший байт адреса памяти
}
i2c_write();
i2c_start();
i2c_byte = 0xA1; // control байт с битом RD
i2c_write();
i2c_read();
i2c_stop();
putchar(i2c_byte);
}
}
/* запись в 24LC256 числа 1Fh по адресам от 00h по FFh */
for (temp = 0; temp <= 0xFF; temp++) {
i2c_start();
i2c_byte = 0xA0; //control байт с битом WR
i2c_write();
i2c_byte = 0; // старший байт адреса памяти
i2c_write();
i2c_byte = temp; // младший байт адреса памяти
i2c_write();
i2c_byte = 0x1F; // записываемые данные
i2c_write();
i2c_stop();
}
/*------------окончание примера---------------*/