сайт для палких паяльників

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

  1. Шина I2C – это двухпроводная шина с линиями SCL, SDA. Теоретически, на одну шину I2C можно параллельно подключить до 112 устройств.
  2. Обе линии шины должны быть через резисторы подключенными к питанию. Рекомендуемый номинал резисторов зависит от скорости и других параметров шины. Обычно мало кто этим озадачивается и ставят резисторы в пределах от 4.7к до 10кОм. Резисторов должно быть по одному на каждую линию.
  3. Если Вы подключаете несколько модулей, а на каждом модуле уже впаяны подтягивающие резисторы, то получается, что резисторы включаются параллельно и их суммарное сопротивление становится меньше. Это не очень хорошо. Но, если вы включаете только два таких модуля и на каждом впаяны резисторы по 10 кОм, тогда суммарное сопротивление будет 5ком, что попадает в пределы допустимой нормы и шины I2C, скорее всего, будет работать. Но повторяю: подключать на каждую линию более одного резистора – не очень хорошая идея.
  4. Каждое устройство на шине I2C имеет отдельный адрес.
  5. На шине I2C может быть только один Master и один или несколько Slave.
  6. Скорость шины может быть разной. Обычно используют два стандарта 100 и 400 КГц. Скорость линии должна определяться по самому медленному устройства на шине. Если Slave не успевает, он может “придержать” шину и все его будут ждать. Такой подход, хотя и является стандартом, но на практике работает не всегда. В случае, когда Master не умеет ждать (этим, например страдают микрокомпьютеры), на шине начинается беспорядок. То есть, некорректная работа одного из устройств на шине I2C (не важно, в каком качестве – Master или Slave) может вызвать проблемы в работе всех устройств.
  7. Если напряжение питания контроллера отличается от напряжения питания датчика, они должны включаться через двунаправленную схему согласования логических уровней.

Рассмотрим пример использования датчика атмосферного давления BMP280. Подключим модуль датчика, как указано на схеме. На модуле датчика есть подтягивающие резисторы для каждой из линий шины I2C, поэтому мы можем подключить его напрямую. Схема подключения:

stm32_bmp280

Настройка шины выполняется следующим образом:

1. Включается тактирование нужной шины I2C. В STM32 их может быть несколько. В нашем микроконтроллере 2 шины I2C.
2. Включается тактирование GPIO порта на котором висят SCL, SDA соответствующей шины I2C.
3. Настраивают GPIO выхода, как альтернативные для работы в качестве SCL, SDA.
4. Включается шина I2C.
5. Настраиваются параметры шины I2C.

Пример:

void I2C1_init(void)
{
    I2C_InitTypeDef  I2C_InitStructure;
    GPIO_InitTypeDef  GPIO_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

    /* Configure I2C_EE pins: SCL and SDA */
    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    /* I2C configuration */
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStructure.I2C_OwnAddress1 = 0x38;
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_InitStructure.I2C_ClockSpeed = 100000;

    /* I2C Peripheral Enable */
    I2C_Cmd(I2C1, ENABLE);
    /* Apply I2C configuration after enabling it */
    I2C_Init(I2C1, &I2C_InitStructure);
}

После чего можно приступать к работе.

Для того, чтобы обратиться к датчику, мы должны знать его адрес. Зная адрес, мы сможем посылать ему данные или команды, или читать с него информацию. Мы можем обратиться к датчику и указать адрес его регистра, с которого мы хотим получить, или в какой хотим записать, информацию. В документации к датчикам указаны адреса регистров и их назначение. Управление датчиками выполняется, как правило, записью в определенный регистр определенного числа (команды). Или отправкой определенной команды на адрес датчика (без указания адреса регистра). Обмен информацией зависит от реализации того или иного датчика. На самом деле это кажется сложным только первый раз. Во многих случаях для различных датчиков функции записи и чтения мало чем отличаются. Например, функция записи байта в регистр выглядит так:

void bmp280WriteByte(unsigned char address, unsigned char data)
{
  I2C_GenerateSTART(I2C1,ENABLE);
  while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

  I2C_Send7bitAddress(I2C1, BMP280_addr, I2C_Direction_Transmitter);
  while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

  I2C_SendData(I2C1,address);
  while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

  I2C_SendData(I2C1,data);
  while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

  I2C_GenerateSTOP(I2C1,ENABLE);

  while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
}
//----------------------------------------

Обычно, для других датчиков она выглядит аналогично. То же касается считывания данных. Различия могут быть в деталях. Например, при считывании более чем 8-битных данных в некоторых датчиках первыми идут старшие разряды, а в других – младшие разряды. Все станет понятнее, когда вы рассмотрите пример. Полный текст программы приводить нет смысла. Проект под названием Example_i2C_Master можно скачать на странице примеров.

Желаю успехов!

Смотри также:

Translate
Архіви

© 2011-2017 Андрій Корягін, Кременчук - Київ, Україна