Оглавление:

Шина I2C для ATtiny и ATmega: 8 шагов
Шина I2C для ATtiny и ATmega: 8 шагов

Видео: Шина I2C для ATtiny и ATmega: 8 шагов

Видео: Шина I2C для ATtiny и ATmega: 8 шагов
Видео: AVR 48# Аппаратный I2C 2024, Июль
Anonim
Шина I2C для ATtiny и ATmega
Шина I2C для ATtiny и ATmega

Обожаю микроконтроллеры Atmel AVR! С момента создания системы разработки Ghetto, описанной в этом руководстве, у меня было бесконечное удовольствие, экспериментируя с AVR ATtiny2313 и, в частности, с ATmega168. Я даже зашел так далеко, что написал инструкции по использованию переключателей в качестве входных данных и расширил концепцию системы разработки гетто на CPLD. Во время недавнего проекта мне понадобилось несколько переключателей для установки контрольных значений. У AVR не хватало контактов ввода / вывода, поэтому мне пришлось кое-что придумать. Я мог бы попробовать сложную систему ввода с клавиатурой и дисплеем, но у ATtiny2313 не хватило бы ресурсов. К счастью, компания Atmel решила эту проблему, включив интерфейс, который может подключаться к дополнительным микросхемам (например, памяти или портам ввода-вывода) с помощью простого двухпроводного интерфейса. Правильно, используя всего два контакта ввода-вывода на AVR, мы можем получить доступ ко многим дополнительным контактам ввода-вывода, а также к другим ресурсам. Этот двухпроводной интерфейс формально известен как шина Inter-Integrated Circuit или просто шина I2C и был изобретен компанией NXP, когда она еще была Philips Semiconductors. Если вы читаете эту инструкцию, то, вероятно, слышали о шине I2C и, возможно, даже использовали ее на PIC или другом микроконтроллере. Хотя концептуально это очень просто и поддерживается аппаратными ресурсами AVR, программные драйверы по-прежнему необходимы для использования шины I2C. Atmel предоставляет примечания по применению (см. Ресурсы далее в этом Руководстве), но они являются неполными и не показывают каких-либо примеров, кроме связи с другим устройством AVR. Целью данного Руководства не является обучение кого-либо, как создавать драйверы I2C для AVR. Скорее, я предоставлю расширенные версии драйверов Atmel для устройств ATtiny2313 и ATmega168, я объясню требования и ограничения, которые применяются при их использовании, и покажу вам рабочие примеры устройств I2C. После проработки этого руководства вы сможете успешно использовать шину I2C в своих проектах AVR. Очевидно, вы можете игнорировать драйверы для крошечных или MEGA, если вас интересует только один из них. Для тех, кто хочет узнать больше о шине I2C, я дам ссылки на соответствующий материал.

Шаг 1. Что это вообще за штука с I2C?

Что вообще такое про I2C?
Что вообще такое про I2C?
Что вообще такое про I2C?
Что вообще такое про I2C?
Что вообще такое про I2C?
Что вообще такое про I2C?
Что вообще такое про I2C?
Что вообще такое про I2C?

Шина I2C - это простое двухпроводное соединение, которое может связывать несколько устройств вместе и позволять им обмениваться данными. В простейшей форме есть одно ведущее устройство, которое обменивается данными с несколькими ведомыми устройствами. Все устройства подключаются параллельно к двум проводам шины I2C. Эти два провода известны как SCL и SDA. SCL - это линия синхронизации, управляемая ведущим устройством. SDA - это двунаправленная линия данных. Для передачи данных ведущее устройство отправляет адрес ведомого устройства в сочетании с однобитным флагом чтения / записи. Если требуется запись, ведущее устройство будет продолжать отправлять данные адресуемому ведомому устройству. Если запрашивается чтение, ведомое устройство ответит данными. Чтобы координировать транзакции, ведущее и ведомое устройства манипулируют линиями SCL и SDA, чтобы сигнализировать о нескольких условиях. К ним относятся START, STOP, ACK (подтверждение) и NAK (без подтверждения). Подробности этих условий обрабатываются водителями. Настоящие фанаты из числа вас могут узнать все подробности по ссылкам в конце данного Руководства. Требования к электричеству довольно просты. Ведущее устройство и ведомые устройства должны использовать один и тот же уровень для Vcc, заземления должны быть подключены, а линии SCL и SDA должны быть подтянуты к Vcc. Значение подтягивающих резисторов точно определяется расчетом, основанным на общей емкости на шине, но практически может быть практически любым значением от 1,8 кОм до 10 кОм. Я начинаю с 5.1K и использую более низкие значения, пока это не сработает. Обычно это не проблема, если у вас нет большого количества устройств или длинных проводов между устройствами. Номинальная скорость передачи данных на шине I2C составляет 100 Кбит / с. Также возможны скорости 400 Кбит / с, 1 Мбит / с и выше, но они не поддерживаются драйверами в этом Руководстве. Все устройства I2C будут работать со скоростью 100 Кбит / с. ATtiny2313 и ATmega168 реализуют шину I2C по-разному. ATtiny2313 использует оборудование универсального последовательного интерфейса (USI), которое также можно использовать для шины SPI. ATmega168 имеет специальное оборудование для шины I2C, известное как двухпроводной интерфейс (TWI). После написания драйверов эти различия в основном прозрачны для пользователя. Одно существенное отличие заключается в программном обеспечении: драйвер ATmega168 I2C управляется прерываниями, а драйвер ATtiny2313 - нет. Это означает, что программе ATmega168 не нужно ждать передачи данных I2C, а нужно только ждать, прежде чем инициировать другую передачу или пока данные не поступят из операции чтения. Примеры и последующее обсуждение должны прояснить это. Адреса I2C имеют длину 7 бит, поэтому на шине может быть до 127 устройств, если каждое из них имеет уникальный адрес. Как показано на рисунке, этот 7-битный адрес сдвигается на один бит влево, а младший бит используется для отметки чтения или записи устройства по адресу. Таким образом, полный адрес подчиненного устройства составляет 8-битный байт. Фактический адрес частично определяется внутри устройства и не может быть изменен (4 старших бита), а частично определяется битами, которые могут быть подключены к контактам устройства (3 младших бита), которые могут быть привязаны к высокому или низкому уровню для установки. конкретный адрес. Звучит запутанно, но пример прояснит это. Лист данных PCA8574A показывает, что четыре самых старших бита адреса I2C всегда будут 0111. Следующие три бита определяются настройками контактов AD0, AD1 и AD2. Эти контакты могут быть связаны с землей или с источником положительного напряжения (5 вольт), чтобы обозначать 0 или 1 соответственно. Таким образом, диапазон возможных адресов составляет от 38 до 3F в шестнадцатеричном формате, как показано на другом рисунке из таблицы данных PCA8574. Таким образом, изменив настройки адресного бита, к шине I2C одновременно могут подключаться до 8 PCA8574A. Каждый ответит только на свой адрес подчиненного устройства. Если требуется еще больше портов ввода-вывода, можно использовать PCA8574. Единственное различие между PCA8574 и PCA8574A заключается в том, что диапазон адресов ведомого устройства I2C PCA8574 составляет от 20 до 27 шестнадцатеричных чисел. Определение адреса данного устройства может сбивать с толку, поскольку в некоторых таблицах данных бит чтения / записи рассматривается как часть адрес. Внимательно прочтите техническое описание и имейте в виду, что адрес ведомого устройства будет иметь длину 7 бит. Бит чтения / записи следует рассматривать отдельно. Опять же, пример поможет. В таблице данных EEPROM 24C16, с которой мы будем экспериментировать, указано, что первые (наиболее важные) четыре бита адреса подчиненного устройства равны 1010. Следующие три бита могут быть определены с помощью A0, A1 и A2; но обратите внимание, что лист данных также охватывает 24C01 - 24C08, которые представляют собой EEPROM меньшего размера. Рисунок из таблицы данных показывает, что настройки этих адресных битов игнорируются при увеличении размера и полностью игнорируются для 24C16. То есть последние три бита не имеют значения, и 24C16 действительно использует все подчиненные адреса I2C с 50 по 57 в шестнадцатеричном формате. Диапазон адресов ведомых устройств будет фактически адресовать разные разделы в 24C16. Первые 256 байтов находятся по адресу 50h, следующие 256 байтов - по адресу 51h, и так далее до последних 256 байтов по адресу 57h - всего 2 Кбайт. Поскольку адрес RAM PCF8570, с которым мы также экспериментируем, находится в этом диапазоне, 24C16 и PCF8570 не могут использоваться вместе.

Шаг 2. Закажите несколько устройств I2C

Теперь, когда вы немного знаете о шине I2C и хотите ее использовать, почему бы не заказать некоторые устройства I2C для экспериментов сейчас, чтобы они могли быть на пути к вам, пока вы готовите программное обеспечение? Соответствующие устройства включают I / O расширитель интерфейса (мой любимый), статический ОЗУ и EEPROM. Есть еще много чего, но это отличное начало. Мы будем использовать процессоры AVR: ATtiny2313 и Atmega168 (используется в Arduino). Если вы новичок в этом, то взгляните на это замечательное руководство, чтобы узнать о них и построить свою систему развития гетто. Схема ATmega168 в данном руководстве показывает, как реализовать систему разработки Ghetto для этого процессора. Кабель параллельного порта такой же, как и у ATtiny2313. (Я не пробовал USB-версию системы разработки Ghetto, поэтому я не уверен, как на ней осуществляется доступ к шине I2C. То же самое для Arduino.) Вот номера деталей Digikey. Расширитель портов: IC I2C I / O. РАСШИРИТЕЛЬ 568-4236-5-NDRam: IC SRAM 256X8 W / I2C 568-1071-5-NDEEPROM: IC EEPROM SERIAL 16K CAT24C16LI-G-ND

Шаг 3: драйверы I2C

Вот описания функций драйвера для шины I2C. Они были разработаны для начинающих с использованием заметок о приложениях Atmel. Я не смог бы сделать это без них как основы для дальнейшего развития. Разработка велась с использованием WinAVR и компилятора gcc C. Ограничения по тактовой частоте описаны ниже для каждого процессора. Поскольку я не могу протестировать все возможные комбинации вкуса процессора и тактовой частоты, я просто буду придерживаться того, что я действительно могу протестировать, и попытаюсь указать ограничения и ограничения. Вот функции драйвера и способы их использования. Пожалуйста, ознакомьтесь с примерами, чтобы получить более подробную информацию и увидеть функции, используемые в полных программах. Для ATtiny2313: Требования к тактовой частоте: драйверы рассчитаны на тактовую частоту 1 МГц (частота по умолчанию) для ATtiny2313. Если вы хотите работать с другими скоростями, вам придется настроить константы в драйверах. Напишите мне, если вам понадобится помощь в этом. Вы также можете получить некоторые подсказки из примечаний к приложениям Atmel в ссылках на шаге «Ресурсы». USI_TWI_Master_Initialise () Эта функция инициализирует оборудование USI для работы в режиме I2C. Вызовите его один раз в начале вашей программы. Он возвращает void и нет аргументов. USI_TWI_Get_State_Info () Эта функция возвращает информацию об ошибке I2C и используется, если ошибка произошла во время транзакции I2C. Поскольку эта функция возвращает только код ошибки, я использую функцию TWI_Act_On_Failure_In_Last_Transmission (TWIerrorMsg) для мигания светодиода ошибки. Коды ошибок определены в USI_TWI_Master.h. Вот как это назвать: TWI_Act_On_Failure_In_Last_Transmission (USI_TWI_Get_State_Info ()) USI_TWI_Start_Read_Write () Эта функция используется для чтения и записи отдельных байтов в устройства I2C. Он также используется для записи нескольких байтов. Для использования этой функции есть 6 шагов: 1) Объявите в своей программе буфер сообщений, в котором будет храниться адрес подчиненного устройства и байт данных, который должен быть отправлен или получен. unsigned char messageBuf (MESSAGEBUF_SIZE); 2) Поместите адрес ведомого устройства в качестве первого байта в буфер. Сдвиньте его на один бит влево и ИЛИ в бит чтения / записи. Обратите внимание, что бит чтения / записи будет равен 1 для чтения и 0 для записи. Этот пример предназначен для чтения. messageBuf (0) = (TWI_targetSlaveAddress << TWI_ADR_BITS) | (ИСТИНА << TWI_READ_BIT); 3) При выполнении записи поместите байт для записи в следующее место в буфере. 4) Вызовите функцию USI_TWI_Start_Read_Write с буфером сообщений и размером сообщения в качестве аргументов.temp = USI_TWI_Start_Read_Write (messageBuf, 2); 5) возвращаемое значение (в данном случае temp) можно проверить, чтобы увидеть, произошла ли ошибка. Если да, то с этим обращаются, как описано выше. См. Примеры в программах. 6) Если было запрошено чтение, чтение байта будет во втором месте в буфере. Если нужно записать несколько байтов (например, в устройство памяти), можно использовать ту же процедуру. Настройка буфера и вызов подпрограммы немного отличаются. Второй байт в буфере будет начальным адресом памяти для записи. Записываемые данные будут в последующих байтах. Размер сообщения будет размером, включая все действительные данные. Таким образом, если нужно записать 6 байтов, то размер сообщения будет 8 (адрес подчиненного устройства + адрес памяти + 6 байтов данных). USI_TWI_Start_Random_Read () Эта функция используется для чтения нескольких байтов с устройства I2C, обычно это имеет смысл только для какое-то воспоминание. Использование этой процедуры очень похоже на предыдущую, за двумя исключениями. Установка бита чтения / записи не имеет значения. Вызов этой подпрограммы всегда будет вызывать операцию чтения. MessageSize должен быть равен 2 плюс количество байтов для чтения. Если ошибок не произошло, данные будут в буфере, начиная со второго места. Для ATmega168: Clock Requirement: драйверы рассчитаны на тактовую частоту 4 МГц для ATmega168. В примере кода показано, как установить эту тактовую частоту. Если вы хотите работать с другими скоростями, вам придется настроить константы в драйверах. Напишите мне, если вам нужно это сделать. TWI_Master_Initialise () Эта функция инициализирует оборудование TWI для работы в режиме I2C. Вызовите его один раз в начале вашей программы. Он возвращает void и нет аргументов. Обязательно разрешите прерывания, вызвав swi () после инициализации. TWI_Get_State_Info () Эта функция возвращает информацию об ошибке I2C и используется, если ошибка произошла во время транзакции I2C. Поскольку эта функция возвращает только код ошибки, я использую функцию TWI_Act_On_Failure_In_Last_Transmission (TWIerrorMsg) для мигания светодиода ошибки. Коды ошибок определены в TWI_Master.h, но изменены для сигнализации с помощью светодиода ошибки. Подробнее см. В примере кода. Вот как это назвать: TWI_Act_On_Failure_In_Last_Transmission (TWI_Get_State_Info ()) Обратите внимание, что проверка ошибок выполняется путем проверки завершения транзакции I2C (функция описана ниже) и последующего тестирования бита в глобальном слове состояния. две функции работают так же, как соответствующие функции, описанные выше, но с некоторыми исключениями. Они не возвращают никаких значений ошибок. Считанные данные не передаются в буфер. Это будет сделано с помощью функции, описанной далее. При вызове TWI_Start_Random_Read messageSize должен быть количеством запрошенных байтов данных плюс один, а не два. Драйвер I2C для ATmega168 управляется прерываниями. То есть транзакции I2C запускаются и затем выполняются независимо, в то время как основная процедура продолжает выполняться. Когда основной подпрограмме нужны данные из запущенной ею транзакции I2C, она должна проверить, доступны ли данные. То же самое и с проверкой ошибок. Основная процедура должна быть уверена, что транзакция I2C завершена, прежде чем проверять наличие ошибок. Для этих целей используются следующие две функции. TWI_Transceiver_Busy () Вызовите эту функцию, чтобы проверить, завершена ли транзакция I2C, прежде чем проверять наличие ошибок. Примеры программ показывают, как это использовать. TWI_Read_Data_From_Buffer () Вызовите эту функцию для передачи данных из буфера приема драйвера I2C в буфер сообщений. Эта функция проверяет завершение транзакции I2C перед передачей данных. Хотя эта функция возвращает значение, я считаю, что проверка бита ошибки напрямую более надежна. Вот как это назвать. Размер сообщения должен быть на единицу больше, чем желаемое количество битов данных. Данные будут в messageBuf, начиная со второго местоположения.temp = TWI_Read_Data_From_Buffer (messageBuf, messageSize);

Шаг 4: Начнем строить

Строим!
Строим!
Строим!
Строим!
Строим!
Строим!
Строим!
Строим!

Начните с загрузки файла I2C Schematics.zip. Вы можете создать папку I2C в своей рабочей области для хранения схем и файлов примеров программ. Разархивируйте схемы в этот каталог. Вы найдете папку под названием I2C Schematics. Откройте файл с именем tiny I2C.pdf. На этой схеме показана система разработки ATtiny2313 Ghetto и расширитель портов ввода-вывода PCA8574A (вокруг него выделена большая пунктирная рамка). Схема расширителя портов построена на макетной плате. Взгляните на фотографии, чтобы увидеть, как выглядят эти схемы. Они действительно довольно просты. Часть схемы ATtiny2313 - это просто система разработки Ghetto с тремя мигающими лампочками (LED1, 2 и 3, плюс R4, 5 и 6) и подключенной к ней кнопкой (S1) плюс одна дополнительная деталь. Эта деталь - добавление перемычек (JP4, 5 и 6), которые можно удалить, чтобы обеспечить соединение линий SCL и SDA шины I2C. Перемычки должны быть установлены на место для программирования, а затем удалены, чтобы можно было подключить SCL и SDA. На фотографиях показаны перемычки на месте и снятые. Размещение этих перемычек зависит от вас, вам просто нужно установить их в вашу систему разработки гетто, если вы хотите использовать шину I2C. Шину I2C необходимо отключить и установить перемычки для программирования. Обратите внимание, что вам действительно нужно заботиться только о JP4 и JP6 для шины I2C. Вставьте JP5, если вы думаете, что когда-нибудь захотите использовать шину SPI. Макетирование расширителя портов ввода-вывода PCA8574A очень просто. Обеспечьте соединения Vcc (+5 В) и Gnd (земля) и подключите AD0, 1 и 2 к земле (адрес ведомого устройства I2C станет шестнадцатеричным). Затем подключите 4 мигалки и 4 DIP-переключателя. (Если у вас нет DIP-переключателей, вы можете просто использовать провода. Подсоедините к земле или оставьте плавающим для включения или выключения сигнала соответственно.) Наконец, подключите подтягивающие резисторы (R11 и 12) от SDA и SCL к Vcc. Они показаны как 3,3 КБ, но любое значение от 1,8 КБ до 5,1 КБ должно работать (возможно, до 10 КБ, но я этого не пробовал). После того, как вы запрограммировали ATtiny2313, вы можете удалить перемычки и подключить SDA и SCL для тестирования. Теперь для ATmega168. Единственная проблема здесь в том, что вы, возможно, не создали систему разработки Ghetto для этого процессора. Если это так, то предоставленная мной схема (MEGA I2C.pdf) покажет вам, как это сделать. Это просто перестановка версии ATtiny2313. Если вы планируете заранее, вы можете убедиться, что ваш кабель для программирования подходит для обеих систем. Основное отличие - добавление C2 и C3. См. Изображения для их размещения, они должны быть очень близко к микросхеме; один из них на самом деле находится под чипом. Это, в частности, помогает предотвратить попадание шума в аналого-цифровой преобразователь. Вам не нужно устанавливать перемычки, если вы не планируете использовать шину SPI, поскольку они не нужны для шины I2C на этом чипе. Обратите внимание, что макет PCA8754A останется без изменений. Вы просто подключите SDA и SCL, и вперед! Легко, да?

Шаг 5: Давайте закодируем и протестируем

Давайте кодируем и тестируем!
Давайте кодируем и тестируем!
Давайте кодируем и тестируем!
Давайте кодируем и тестируем!
Давайте кодируем и тестируем!
Давайте кодируем и тестируем!

Пришло время собрать драйверы и примеры программ. Мы начнем с только что построенных макетов ATtiny2313 и PCA8574A. Загрузите файл I2C.zip в рабочий каталог I2C и разархивируйте его. У вас появится новая папка под названием I2C. В нем вы найдете USI I2C (для ATtiny2313) и TWI I2C (для ATmega168). В USI I2C вы найдете папку I_O Port. Эта папка содержит код для нашего первого примера программы и драйверы USI I2C. С помощью WinAVR скомпилируйте и загрузите код в ATtiny2313. Сделайте глубокий вдох и включите питание. Вот чего ожидать: при включении питания светодиод 1 на порту PD6 ATtiny2313 мигнет дважды. Больше ничего не произойдет, пока вы не нажмете кнопку (S1). Каждый раз при нажатии кнопки происходит считывание переключателей, и их настройки отображаются на светодиодах, подключенных к PCA8574A. Измените значение переключателей, нажмите кнопку, и светодиоды должны измениться. Продолжайте делать это, пока не перестанете испытывать острые ощущения от того, что это работает. Если (не дай Бог!) Что-то не работает должным образом, внимательно проверьте свою проводку. Об ошибках I2C будет сигнализировать мигание светодиода LED3 (PD4), что, вероятно, означает, что вам нужно проверить, что SDA и SCL подключены к правильным контактам и правильно подтянуты. Если что-то по-прежнему не работает, прочитайте оставшуюся часть этого раздела, чтобы узнать об отладке. А теперь вернитесь и давайте взглянем на код. Откройте файл USI_I2C_Port.c. Это код для примера программы. (USI_TWI_Master.c и USI_TWI_Master.h содержат драйверы - вы можете игнорировать их, если вам не интересно.) Используйте этот пример для руководства своими собственными приложениями I2C. В основном программа показывает вам, как инициализировать и использовать драйверы I2C, включая настройку вверх по адресу подчиненного устройства и остальной части буфера сообщений и извлекать из него данные. Вы также увидите, как я отклоняю кнопку и настраиваю цикл while. Стоит упомянуть несколько деталей программы. Обратите внимание, что данные с переключателей инвертируются перед записью в светодиоды на расширителе портов. Также обратите внимание, что входные порты на расширителе портов должны быть написаны как High, чтобы они работали правильно. Эти подробности описаны в техническом описании PCA8574A. Всегда внимательно читайте таблицы данных! Больший интерес представляет использование условной отладки. Ближе к началу файла программы находится оператор // # define DEBUG, а по всему коду разбросаны операторы #ifdef DEBUG. Пока DEBUG не определен (две косые черты делают строку комментарием и препятствуют ее определению), код в операторах от #ifdef до #endif не будет компилироваться. Но если что-то работает не так, как вы ожидаете, перекомпилируйте и перезагрузите код с #define DEBUG без комментариев. Вы получите намного больше миганий светодиодов, которые вы можете декодировать, чтобы следить за выполнением вашей программы и помогать вам точно определить, где что-то идет не так. На самом деле, я рекомендую вам попробовать это, просто чтобы посмотреть, что произойдет. Вы увидите, что светодиод 2 (на PD5) будет мигать по мере выполнения программы. Значение, считываемое с переключателей, будет мигать на светодиодном индикаторе 1 (PD6), прежде чем оно отобразится на светодиодах расширителя портов. Вы должны иметь возможность отслеживать работу программы с помощью этих светодиодов. Далее мы будем работать с ATmega168; пропустите этот раздел, если вас интересует только ATtiny2313. Все еще со мной? Хороший. Перейдите в папку TWI_I2C, измените рабочий каталог на IO_Port, скомпилируйте и загрузите TWI_I2C_Port.c в ATmega168. Отключите линии SDA и SCL от ATtiny2313 и подключите их к ATmega168. Подключите питание и заземление и включите питание. Операция должна быть такой же! Играйте, пока азарт не утихнет, а затем давайте посмотрим на код. Откройте TWI_I2C_Port.c. Код почти идентичен, за исключением обработки ошибок и размещения драйверов, управляемых прерываниями. Вот различия: Обратите внимание, что для правильной работы шины I2C необходимо установить тактовую частоту 4 МГц. Sei (); Оператор включает прерывания после инициализации драйверов I2C. Чтобы проверить наличие ошибок, тестируется определенный бит состояния. Во время чтения должна быть вызвана функция TWI_Read_Data_From_Buffer для передачи считанных данных в буфер сообщения. Во время записи необходимо использовать while (TWI_Transceiver_Busy ()), чтобы убедиться, что передача завершена, прежде чем проверять наличие ошибок. Эти две последние функции описаны выше в описании драйверов. В остальном код такой же, как у ATtiny2313. DEBUG работает так же, если вы хотите поэкспериментировать с этим.

Шаг 6: Использование памяти I2C

Использование памяти I2C
Использование памяти I2C
Использование памяти I2C
Использование памяти I2C
Использование памяти I2C
Использование памяти I2C
Использование памяти I2C
Использование памяти I2C

Теперь, когда мы научились использовать шину I2C для чтения и записи расширителя портов ввода / вывода, давайте перейдем к использованию памяти I2C, как RAM, так и EEPROM. Основное отличие состоит в том, что несколько байтов могут быть прочитаны или записаны из памяти с помощью одной команды I2C. Чтобы подготовиться к этим экспериментам, нам нужно немного изменить оборудование и построить пару новых схем на макетной плате. Сохраните схему расширителя портов, так как мы будем использовать ее для отображения некоторых значений памяти. Снимите DIP-переключатели с PCA8574A и поместите мигалки на эти контакты. Если вам не хватает мигалок, переместите те, что с P4 по P7, на P0 по P3. (Отображаемые значения достаточно малы.) Теперь посмотрите на схему I2C Ram.pdf и подключите PCF8570 к макету. Посмотрите также на картинку. Обязательно привяжите контакт 7 к Vcc. Проложите провода для SDA и SCL от PCA8574A. Никаких дополнительных подтягивающих резисторов не требуется. Если вас также интересует EEPROM, создайте эту схему, также используя I2C EEPROM.pdf для 24C16, но имейте в виду, что в примере используется ATmega168. Эта схема действительно проста. Как обсуждалось выше, биты адреса следует игнорировать. Просто подключите питание и землю. Пока не подключайте SDA и SCL, поскольку мы еще не закончили эксперименты с Ram. Мы начнем наши эксперименты с памятью с ATtiny2313, подключенного к расширителю портов PCA8574A и к PCF8570 Ram. Программа запишет некоторые числа в RAM, затем прочитает их и отобразит на расширителе портов. Измените ваш рабочий каталог на RAM под USI I2C. Используйте файл make для компиляции и загрузки USI_I2C_RAM.c. Обратите внимание, что файлы драйверов I2C идентичны тем, которые мы использовали ранее. Подключите питание, и вы должны увидеть, как светодиод 1 (PD6) замигает один раз. Данные будут записаны в первые 4 байта памяти. Нажмите кнопку, и два байта будут считаны и отображены. Вы должны увидеть один светодиодный индикатор на расширителе портов (P0), двухсекундную паузу, затем загорятся два светодиода (P0 и P1). Еще две секунды пауза, и светодиоды должны погаснуть. Нажмите кнопку еще раз, чтобы начать последовательность заново. Отладка аналогична описанному выше методу, давайте посмотрим на код. Откройте USI_I2C_RAM.c. Он должен выглядеть очень похоже на предыдущий код. Основные отличия заключаются в деталях чтения и записи памяти. Посмотрите, как загружается буфер сообщений перед вызовом, который фактически выполняет запись. Первый байт - это адрес подчиненного устройства с соответствующим установленным битом чтения / записи. Но следующий байт - это адрес памяти, с которого следует начать запись данных. Затем идут фактические байты данных, которые будут последовательно загружаться в память, начиная с указанного нами адреса. Мы указываем размер сообщения как 6. Итак, мы начинаем запись с адреса 00 и записываем значения 01, 03, 02 и 06 в ячейки памяти с 00 по 03. Чтобы прочитать данные обратно из памяти, мы должны использовать функцию USI_TWI_Start_Random_Read. Буфер сообщений получает адрес подчиненного устройства в первом байте и начальный адрес во втором байте. Затем вызовите функцию с размером сообщения, равным числу байтов для чтения плюс 2. Обратите внимание, что бит чтения / записи не имеет значения, поскольку чтение будет выполнено независимо. Возвращаемые данные будут начинаться со второго места в буфере сообщений. После считывания данных они инвертируются для отображения на расширителе портов и записываются в них по одному байту с паузой между значениями. Наконец, светодиоды расширителя портов погаснут. Запись в расширитель портов идентична тому, что было сделано в предыдущих примерах. Ради интереса вы можете раскомментировать оператор #define DEBUG, как указано выше, и увидеть множество мигающих светодиодов. Залившись от волнения после еще одного успешного эксперимента, давайте перейдем к ATmega168 и EEPROM. Измените свой рабочий каталог на EEPROM в TWI I2C. Используйте файл make для компиляции и загрузки TWI_I2C_EEPROM.c. Обратите внимание, что файлы драйвера I2C идентичны тем, которые мы использовали ранее для PCA8574A. Чтобы протестировать программу, отключите ATtiny2313 и подключите ATmega168. Оставьте шину I2C подключенной к Ram и включите питание. Результаты другие, поскольку теперь мы пишем и читаем больше данных. Светодиод 1 на PD7 должен мигать при инициализации. Нажмите кнопку, и данные будут считаны из памяти и отображены. Светодиоды на PCA8574 должны мигать в следующей последовательности: P1, P0 и P2 (все выключены), P0 и P1, P1 и P2. Наконец, все светодиоды портов должны погаснуть. Нажмите кнопку еще раз, чтобы повторить это. О, но подождите, скажете вы. Разве это программа не для EEPROM? Поскольку мы обращаемся к устройству памяти по одному и тому же адресу I2C, одна и та же программа работает как для оперативной памяти, так и для EEPROM. Выключите питание, переместите SDA и SCL из RAM в EEPROM и снова запустите программу. Он должен работать точно так же. Обратите внимание, что EEPROM и Ram не могут быть подключены к шине I2C одновременно, поскольку они имеют один и тот же адрес. (Самые умные из вас могут подумать об изменении программируемых адресных битов на ОЗУ, но это все равно не сработает. 24C16 использует весь блок адресов, который может быть запрограммирован для ОЗУ.) Хорошо, давайте посмотрим на эту последнюю программу.. Откройте TWI_I2C_EEPROM.c. Первое, на что следует обратить внимание, это то, что я указал, как обращаться ко всей EEPROM 24C16. Доступ к нему можно получить блоками по 256 байт по 8 различным адресам ведомых устройств I2C. Посмотрите, как MEMORY_ADDR определяется как начальный адрес в шестнадцатеричном формате 50; вот почему Ram работал. Если вы хотите получить доступ к другим блокам 24C16, используйте другие адреса, как я указал. Посмотрите, как я настроил запись в память. Сначала в буфер помещается адрес подчиненного устройства с установленным битом чтения / записи, затем начальный адрес 00, затем 16 байтов данных. Функция TWI_Start_Read_Write вызывается для записи данных (как и раньше) с размером сообщения, установленным на 18. Когда кнопка нажата, мы используем TWI_Start_Random_Read и TWI_Read_Data_From_Buffer для обратного чтения данных. Каждый третий байт отображается на светодиодах расширителя портов. Наконец, светодиоды выключаются в ожидании следующего нажатия кнопки. Вы можете спросить, почему я решил записать 16 байт. Если вы внимательно прочитаете лист данных, вы увидите, что 24C16 выполняет цикл записи всякий раз, когда он получает 16 байтов, даже если отправляется больше байтов. Так что это показалось хорошим числом для использования. Если вы решите увеличить это значение, вам придется изменить размер MESSAGEBUF_SIZE. Вам также нужно будет изменить значение TWI_BUFFER_SIZE в TWI_Master.h. Это связано с тем, что драйвер копирует данные из буфера сообщений для использования подпрограммой обслуживания прерывания. Поздравляю! Теперь вы готовы использовать шину I2C в своих проектах!

Шаг 7: Интернет-ресурсы

Вот ссылки на таблицы данных на детали, использованные для экспериментов. Вы обязательно должны получить их, если у вас нет ничего другого. Port ExpanderRamEEPROM Будучи создателем I2C, NXP (Philips) имеет массу отличных вещей. (Они любят использовать квадратные скобки в своих URL-адресах, поэтому я не могу правильно включить их здесь. Извините.] Чтобы перейти в область I2C, выберите «Интерфейс» в списке продуктов. Вы сможете перейти на их сайт I2C и доступ ко всем таблицам данных и примечаниям к приложениям, которые они предлагают. Описание шины I2C и технические детали, в частности, находятся здесь. Получите таблицы данных ATtiny2313 и ATmega168 (книги данных?) от Atmel. Примечания к приложениям Atmel здесь. Посмотрите на AVR310 и AVR315. Также возьмите код. Посмотрите здесь, чтобы узнать больше о I2C.

Шаг 8: Заметки для компьютерных фанатов

Для настоящего компьютерщика, который хочет знать подробности, вот некоторые вещи, которые следует иметь в виду, если вы посмотрите примечания к приложениям Atmel и код драйвера: - Метод адресации и управления устройством I2C не является частью спецификации! За исключением адреса подчиненного устройства и бита чтения / записи, команды, режимы и т. Д. Не указаны и относятся к конкретному устройству. Чтобы прояснить это, обратите внимание, что схема, использованная в примере Atmel, применима только к этому примеру и в значительной степени нестандартна. - Реализация USI отличается от реализации TWI несколькими важными способами. + С USI синхронизация осуществляется программно; с TWI это обеспечивается генератором скорости передачи данных. + Метод USI не использует прерывания; TWI делает. В этом есть определенный смысл, поскольку семейство Mega (использующее TWI) могло бы делать много других вещей и не должно быть захвачено передачами I2C. Версия USI, управляемая прерываниями, безусловно, возможна, но она не реализована в этом руководстве. + Оборудование USI не оптимизировано для I2C и может обрабатывать только 8-битные передачи. Это означает, что для отправки девятого бита требуется две передачи (NACK или ACK). Оборудование TWI обрабатывает это автоматически. Это немного усложняет реализацию драйвера USI. + Обнаружение ошибок TWI осуществляется аппаратно. USI требует обработки в программном обеспечении, что несколько усложняет ситуацию. + Аппаратное обеспечение TWI напрямую контролирует конфигурацию порта. Оборудование USI требует, чтобы биты порта были настроены перед использованием порта. Вы увидите это в подпрограмме Master_Initialize для USI. Атмель утверждает, что можно использовать подтягивание портов AVR для подтягивания шины I2C. Я не нашел способа заставить этот подход работать. Использование двух внешних резисторов кажется довольно простой схемой, поэтому я не тратил на это много времени.

Рекомендуемые: