Интерфейс I2C является довольно популярным средством взаимосвязи микроконтроллеров и других электронных устройств. Но некоторые микроконтроллеры могут не поддерживать данный интерфейс. Кроме того, может случиться так, что выводы аппаратного I2C используются в других целях. В связи с этим встает вопрос о необходимости программной эмуляции шины I2C.

Код на языке C с комментариями приведен ниже.
typedef struct
{
unsigned int PIN0:1;
unsigned int PIN1:1;
unsigned int PIN2:1;
unsigned int PIN3:1;
unsigned int PIN4:1;
unsigned int PIN5:1;
unsigned int PIN6:1;
unsigned int PIN7:1;
} PORT;
/* Здесь задан адрес для примера. Его необходимо заменить на требуемый */
#define PORT0 *(volatile PORT *)0x1234
/* Определяем выводы порта для передачи данных и тактирования */
#define I2C_DATA PORT0.PIN0
#define I2C_CLK PORT0.PIN1
#define HIGH 1
#define LOW 0
/* Старт I2C */
void I2C_START(void)
{
/* Эмуляция стартового условия I2C */
I2C_DATA = HIGH;
I2C_CLK = HIGH;
I2C_DATA = LOW;
I2C_CLK = LOW;
}
/* Стоп I2C*/
void I2C_STOP (void)
{
/* Эмуляция стопового условия I2C */
I2C_CLK = LOW;
I2C_DATA = LOW;
I2C_CLK = HIGH;
I2C_DATA = HIGH;
}
/* Режим записи I2C */
void I2C_WRITE(unsigned char data)
{
unsigned char outBits;
unsigned char inBit;
/* 8 бит */
for(outBits = 0; outBits < 8; outBits++)
{
if(data & 0x80)
I2C_DATA = 1;
else
I2C_DATA = 0;
data <<= 1;
/* Синхронизация для 8-битовой передачи данных */
SCLK = HIGH;
SCLK = LOW;
}
/* Синхронизация для ACK */
I2C_CLK = HIGH;
/* Ждем, пока линия синхронизации не перейдет в лог. 1 */
while(I2C_CLK);
/* Синхронизация в лог. 1, подтверждение ACK */
inBit = I2C_DATA;
I2C_CLK = LOW;
}
unsigned char I2C_READ (void)
{
unsigned char inData, inBits;
inData = 0x00;
/* 8 бит */
for(inBits = 0; inBits < 8; inBits++)
{
inData <<= 1;
I2C_CLK = HIGH;
inData |= I2C_DATA;
I2C_CLK = LOW;
}
return inData;
}
/* Пример записи в ведомого (slave) I2C */
void writeI2CSlave (unsigned char data)
{
/* Старт */
I2C_START();
/* Адрес ведомого */
I2C_WRITE(0xAA)
/* Управляющий байт ведомого */
I2C_WRITE(0xBB);
/* Запись данных */
I2C_WRITE(data);
/* Стоп */
I2C_STOP();
}
/* Пример для чтения из ведомого I2C */
unsigned char readI2CSlave(unsigned char data)
{
unsigned char inData;
/* Старт */
I2C_START();
/* Адрес ведомого */
I2C_WRITE(0xAA);
/* Управляющий байт ведомого */
I2C_WRITE(data);
/* Стоп */
I2C_STOP();
/* Старт */
I2C_START();
/* Адрес ведомого + чтение */
I2C_WRITE(0xAA | 1);
/* Чтение */
inData = I2C_READ();
return inData;
}
Перевод © digitrode.ru