Avr i2c. Использование интерфейса I2C (TWI) в микроконтроллерах AVR: подробное руководство

Что такое интерфейс I2C. Как работает шина I2C в микроконтроллерах AVR. Как настроить и использовать I2C в AVR. Примеры подключения устройств по I2C к AVR. Какие преимущества дает использование I2C.

Содержание

Что такое интерфейс I2C и зачем он нужен

I2C (Inter-Integrated Circuit) — это последовательный протокол связи, разработанный компанией Philips в начале 1980-х годов. Его основное предназначение — обеспечить простое и эффективное соединение между различными микросхемами на одной печатной плате.

Основные преимущества I2C:

  • Использует всего 2 линии для подключения множества устройств
  • Поддерживает режим с несколькими ведущими устройствами
  • Простая адресация устройств
  • Встроенный механизм подтверждения передачи данных
  • Низкое энергопотребление

Благодаря этим особенностям I2C широко применяется для соединения микроконтроллеров с различными датчиками, EEPROM памятью, часами реального времени, АЦП/ЦАП и другими периферийными устройствами.


Принцип работы шины I2C

I2C использует две двунаправленные линии связи:

  • SDA (Serial Data) — линия для передачи данных
  • SCL (Serial Clock) — линия тактового сигнала

Обе линии подтягиваются к питанию через резисторы (обычно 4.7 кОм). Устройства на шине могут быть ведущими (master) или ведомыми (slave). Ведущее устройство инициирует передачу данных и генерирует тактовый сигнал.

Основные этапы передачи данных по I2C:

  1. Формирование состояния СТАРТ
  2. Передача 7-битного адреса устройства
  3. Передача бита направления передачи (чтение/запись)
  4. Получение подтверждения (ACK) от ведомого
  5. Передача/прием данных побайтно
  6. Формирование состояния СТОП

Такой механизм обеспечивает надежную адресацию и передачу данных между устройствами на шине.

Настройка I2C в микроконтроллерах AVR

В микроконтроллерах AVR интерфейс I2C реализован аппаратно и называется TWI (Two Wire Interface). Для его настройки необходимо выполнить следующие шаги:

  1. Настроить выводы SDA и SCL как входы с подтяжкой к питанию
  2. Установить скорость передачи данных в регистре TWBR
  3. Настроить предделитель в регистре TWSR
  4. Включить TWI установкой бита TWEN в регистре TWCR

Пример базовой инициализации I2C для ATmega328P:



#define F_CPU 16000000UL
#define SCL_FREQ 100000L

DDRC &= ~((1<<4)|(1<<5));  // SDA и SCL как входы
PORTC |= (1<<4)|(1<<5);    // Подтяжка к питанию

TWBR = ((F_CPU/SCL_FREQ)-16)/2; // Установка скорости
TWSR = 0; // Предделитель 1

TWCR = (1<<TWEN); // Включение TWI

После этого интерфейс I2C готов к работе и можно выполнять операции передачи и приема данных.

Основные функции для работы с I2C

Для удобной работы с I2C удобно реализовать следующие базовые функции:

  • i2c_start() — формирование состояния СТАРТ
  • i2c_stop() — формирование состояния СТОП
  • i2c_write() — передача байта данных
  • i2c_read() — прием байта данных
  • i2c_readNak() — прием последнего байта данных без подтверждения

Пример реализации функции передачи байта:


uint8_t i2c_write(uint8_t data)
{
  TWDR = data;
  TWCR = (1<<TWINT) | (1<<TWEN);
  
  while (!(TWCR & (1<<TWINT)));
  
  if ((TWSR & 0xF8) != TW_MT_DATA_ACK)
    return 1;
  
  return 0;
}

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


Подключение и использование EEPROM памяти по I2C

Одно из самых распространенных применений I2C — работа с внешней EEPROM памятью. Рассмотрим пример подключения и использования микросхемы AT24C256:

  1. Подключите выводы SDA и SCL микросхемы к соответствующим выводам микроконтроллера
  2. Подтяните линии к питанию через резисторы 4.7 кОм
  3. Подключите выводы A0, A1, A2 к земле для задания адреса устройства 0x50

Пример записи байта в EEPROM:


void eeprom_write_byte(uint16_t addr, uint8_t data)
{
  i2c_start();
  i2c_write(0x50 << 1);     // Адрес 0x50, режим записи
  i2c_write(addr >> 8);     // Старший байт адреса
  i2c_write(addr & 0xFF);   // Младший байт адреса
  i2c_write(data);          // Данные для записи
  i2c_stop();
  
  _delay_ms(5);  // Задержка для завершения записи
}

Пример чтения байта из EEPROM:


uint8_t eeprom_read_byte(uint16_t addr)
{
  uint8_t data;
  
  i2c_start();
  i2c_write(0x50 << 1);     // Адрес 0x50, режим записи
  i2c_write(addr >> 8);     // Старший байт адреса
  i2c_write(addr & 0xFF);   // Младший байт адреса
  
  i2c_start();              // Повторный СТАРТ
  i2c_write((0x50 << 1) | 1); // Адрес 0x50, режим чтения
  data = i2c_readNak();     // Чтение байта
  i2c_stop();
  
  return data;
}

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


Работа с датчиком температуры DS1621 по I2C

Еще один распространенный пример использования I2C — подключение различных датчиков. Рассмотрим работу с цифровым термометром DS1621:

  1. Подключите выводы SDA и SCL датчика к микроконтроллеру
  2. Подтяните линии резисторами 4.7 кОм к питанию
  3. Подключите выводы A0, A1, A2 к земле (адрес 0x48)

Инициализация датчика:


void ds1621_init()
{
  i2c_start();
  i2c_write(0x90);  // Адрес 0x48, режим записи
  i2c_write(0xAC);  // Команда доступа к конфигурации
  i2c_write(0x02);  // Continuous conversion
  i2c_stop();
  
  i2c_start();
  i2c_write(0x90);  // Адрес 0x48, режим записи
  i2c_write(0xEE);  // Команда запуска преобразования
  i2c_stop();
}

Чтение температуры:


int16_t ds1621_read_temp()
{
  uint8_t msb, lsb;
  
  i2c_start();
  i2c_write(0x90);        // Адрес 0x48, режим записи
  i2c_write(0xAA);        // Команда чтения температуры
  
  i2c_start();            // Повторный СТАРТ
  i2c_write(0x91);        // Адрес 0x48, режим чтения
  msb = i2c_read(1);      // Чтение старшего байта
  lsb = i2c_readNak();    // Чтение младшего байта
  i2c_stop();
  
  return (msb << 8) | lsb;  // Объединение в 16-битное значение
}

Такой подход позволяет легко получать данные о температуре, используя всего два провода для подключения датчика.


Преимущества использования I2C в проектах на AVR

Применение интерфейса I2C в проектах на базе микроконтроллеров AVR дает ряд существенных преимуществ:

  • Экономия выводов микроконтроллера — подключение множества устройств по двум линиям
  • Простота расширения системы — легко добавлять новые устройства на шину
  • Стандартизация — большой выбор совместимых микросхем от разных производителей
  • Надежность передачи данных благодаря встроенному механизму подтверждений
  • Возможность организации мультимастерных систем
  • Низкое энергопотребление по сравнению с параллельными интерфейсами

Эти особенности делают I2C отличным выбором для создания компактных и энергоэффективных устройств на базе AVR микроконтроллеров.

Типичные ошибки при работе с I2C и их устранение

При использовании интерфейса I2C могут возникать различные проблемы. Рассмотрим наиболее распространенные из них и способы их решения:

  • Отсутствие подтягивающих резисторов — всегда проверяйте наличие резисторов 4.7 кОм на линиях SDA и SCL
  • Неправильная адресация — убедитесь, что используете корректный адрес устройства
  • Конфликт на шине — проверьте, что устройства не пытаются одновременно управлять линиями
  • Несоответствие скоростей — настройте одинаковую скорость для всех устройств на шине
  • Ошибки синхронизации — добавьте небольшие задержки между операциями для стабильной работы

При возникновении проблем полезно использовать осциллограф для анализа сигналов на линиях SDA и SCL. Это поможет выявить источник неполадок.



AVR Интерфейс TWI (I2C) | Программирование микроконтроллеров

&nbsp

&nbsp

&nbsp

 

Урок 16

Часть 1

 

 

 

Опыт нашей предыдущей работы с микроконтроллерами AVR показал то, что мы уже многому научились, в том числе общаться с внешними устройствами типа ПК. Теперь, я думаю, все понимают, что этого недостаточно. Есть масса устройств и датчиков, которые нам хочется подключить к микроконтроллера и, мало того, ещё ими и поуправлять, забрать у них какие-то данные. Только данные девайзы подключаются к МК с помощью проводов и существует несколько видов подключений. Один из таких видов — шина

I2C. Данный интерфейс является авторской разработкой компании Phillips и поэтому Atmel, чтобы не нарушать авторские права, немного изменила наименование данной шины и назвала её TWI (Two-wire Serial Interface).

Вот мы сегодня и заёмёмся изучением данного интерфейса, а также в данном уроке мы попробуем его как-то и использовать, что-то к нему подключить и с этим чем-то по общаться под интерфейсу TWI.

Как мы уже поняли, данный интерфейс предаёт данные по проводам. Причем именно по двум проводам

 

 

Как мы видим из данной блок-схемы, у нас есть два провода или контакта — SDA и SCL, подсоединённые к контроллеру к его соответствующим ножкам, а затем к этим проводам мы ещё подключаем какое-нибудь устройство или несколько устройств. Теоретически мы можем подключить до 127 устройств, впоследствии мы поймём, почему именно столько. Ножка SDA отвечает за передачу и приём данных по данной шине, а ножка SCL — это ножка тактирования, таким образом шина I2C является синхронной, что увеличивает стабильность и гарантированность передачи данных по ней. Также в данной блок-схеме мы наблюдаем то, что ещё к данным ножкам необходимо подтянуть резисторы на шину питания, причём как правило в каких-то модулях или устройствах данные резисторы уже подтянуты, и. если мы подключим их несколько, то у нас получится ряд параллельно подключенных подтягивающих резисторов, что будет очень нехорошо и придется оставить их в каком-то одном усторйстве, а в других выпаять.

Всё это происходит потому, что есть ограничение на номинал данных резисторов в зависимости от определенных условия

 

 

Как показала практика, данные резисторы не должны быть сопротивлением более 10 килоом и менее 4,7 килоом.

Также, само собой, сигналы должны быть толерантными к логическим уровням нашего МК, поэтому подключенные устройства должны быть соответствующим образом запитаны, а также общий провод устройств и контроллера также должен быть объединён.

Хочу подчеркнуть, что данный интерфейс в микроконтроллрах AVR реализован на аппаратном уровне. Можно также организовывать его и программным способом, путём включение в определённое время двух любых ножек портов в определенные логические состояния, но само собой, аппаратная организация всегда лучше по всем показателям. Программная реализация как правило используется, если не хватит одной шины, но как правило хватает, так как мы выше уже видели, что устройств можно к одной шине подключить несколько. Таким образом, мы будем рассматривать именно аппаратную реализацию — на уровне регистров контроллера.

 

 

В сдедующей блок-схеме мы видим следующие регистры интерфейса TWI в контроллере Atmega8

 

 

Давайте с ними кратко ознакомимся.

Регистр TWBR — это регистр, в котором мы устанавливаем значения для обеспечения определённой скорости шины. Устройства, которые мы подключаем по I2C требуют определённой скорости ну или определённого диапазона скоростей. Расчитывается эта скорость или битрейт по следующей формуле

 

 

Как мы видим, в данной формуле для расчета частоты шины участвует частота тактирования контроллера, значение регистра TWBR, а также значение TWPS, судя по формуле представляющий собой предделитель, то есть, чем он больше, тем больше будет коэффициент деления, так как в степерь значения данного регистра мы возводим цифру 4.

Причем TWPS — это не отдельный регистр, а совокупность всего лишь двух битов статусного регистра TWSR, в котором помимо этих битов есть ещё и другие, посредством которых мы будем отслеживать определенные состояния или ошибки обмена данными. Есть перечень кодов статуса, по которым мы и будем узнавать, удачно ли прошла команда или что-то не так.

Также само собой существует ещё и управляющий регистр TWCR, с помощью установки в соответствующее состояния битов которого мы будем определённым образом настраивать нашу шину.

Есть ещё адресный регистр TWAR, с помощью которого, если мы настраиваем контроллер ведущим устройством, мы передаем ведомому устройству 7-битный адрес (отсюда и 127 максимально устройств на шине), по которому-то как раз и будет обращение именно к определённому устройству из всех навешанных на наши два провода. А восьмой бит к адресу будет добавляться для того, чтобы передать, читаем мы данные или пишем. А если у нас контроллер будет настроен как ведомое устройство, то в данном регистре мы будем получать от ведущего адрес и сравнивать его с определённым, чтобы понять, обратился ведущий именно к нам или к кому-то другому.

Ну, само собой, есть и регистр данных, в который мы в случае ведущего устройства записываем данные для передачи по шине, а в случае ведомого считываем пришедшие по шине данные.

Вот, вообщем, вкратце о регистрах так.

В следующей части занятия мы продолжим подробнее заниматься с данной шиной.

 

Предыдущий урок Программирование МК AVR Следующая часть

 

Программатор и модуль RTC DS1307 с микросхемой памяти можно приобрести здесь:

Программатор (продавец надёжный) USBASP USBISP 2.0

Модуль RTC DS1307 с микросхемой памяти

 

 

Смотреть ВИДЕОУРОК (нажмите на картинку)

 

Post Views: 1 644

Decada

Автор: WildCat

IIC (I2C) — это сокращение от Inter-IC. I2C — разработка компании Philips, начатая в 80-х годах. В наши дни бытовая техника сделала резкий скачок в сторону усложнения схемотехники. В одном устройстве встречается множество микросхем. Как следствие — запутанная разводка и плотный монтаж печатных плат. Philips решила, что неплохо было бы использовать простую последовательную шину. Вместо широких параллельных шин можно было бы использовать всего два проводника. В такой шине один провод отвечает за данные, а второй — за тактовые импульсы, SDA и SCL соответственно.
I2C стандарт 1992 года использует семибитные адреса, что позволяет одновременное подключение до 128 ИС к одной шине.
Более подробно про этот протокол можно почитать в спецификации I2C.

Адресация в I2C

Число микросхем на одной шине ограничено 128, потому что каждому чипу соответствует 7-битный адрес. Сравните это, например, с домами на одной улице. Если у нескольких домов будет один и тот же номер, то почтальон придет в замешательство, не зная, куда бросить извещение о посылке с деталями.
Адреса задаются частично аппаратно в микросхеме, частично их можно задавать вручную путем подключения соответствующих выводов к питанию/земле. Это позволяет независимо подключать несколько одинаковых микросхем к одной шине.
Для примера рассмотрим известную PCF8574P. Это восьмибитный расширитель портов общего назначения. В нем аппаратно установлен адрес 0100 A2 A1 A0. Часть 0100 уже прошита в чипе, а часть A2 A1 A0 можно задать вручную. Мы можем сделать это, подключая соответствующие выводы к + питания или земле:

Вот тут микросхема слева имеет адрес 0100100, а справа — 0100000.

Стандарты I2C

Изначально стандарт I2C работал с тактовой частотой до 100кГц. В 1992 году был добавлен Быстрый режим с максимальной частотой 400кГц. Также в этом варианте была реализована 10-битная адресация. В 1998 году появился Высокоскоростной режим с максимальной скоростью 3,4 Мбит/с. (вероятно, Philips сочла Мбит/с более удобной величиной, чем килогерцы) Быстрый и высокоскоростной режимы одинаково хорошо работают с частотой и 100кГц.

Подробнее про стандарт

Philips обладает патентом на I2C. Это значит, что любая компания, желающая выпускать микросхемы с поддержкой I2C должна заплатить за это и подписать соглашение.
Большинство микроконтроллеров AVR обладают двухпроводным интерфейсом (угадайте, что это), по крайней мере, так сказано в документации. Это, конечно же, пресловутый I2C. Видимо, эта терминология используется из жадности и нежелания платить деньги Philips за то, чем все и так прекрасно пользуются.

Стандарт I2C предусматривает подтягивающие резисторы на SDA и SCL. Это одна из наиболее распространенных ошибок. Забудьте про подтягивание, и ваша схема будет безупречно не работать. Как правило, хватает резистора в 10кОм. Иногда, при достижении максимальной скорости обмена, можно импользовать более низкие значения. Проверьте даташиты микроконтроллера и вашей микросхемы.

Иногда можно встретить резисторы 100-330 Ом в линиях. Это делается для уменьшения взаимного влияния.
Длина шины I2C не ограничена. Единственное, что общая емкость линии с подключенными устройствами не должны превышать 400 пФ.

Устройство, начинающее передачу, называется Ведущим (Master, мастер), а устройство, к которому оно обращается, — Ведомым (соответственно, Slave, мазохист раб). Во всех наших примерах AT90S2313 выступает в роли ведущего устройства. Ведомое устройство молчит всегда, пока его не спросит ведущее. Тактовые импульсы на SCL тоже обеспечивает ведущее устройство. Мастер отвечает за временные интервалы в передаче. Если ведомое устройство должно вернуть какие-то значения мастеру, он также должен отвечать за все временные интервалы. I2C позволяет работу нескольких ведущих устройств на одной шине, однако во всех наших примерах только один «мастер» и один или несколько «рабов».

Что можно учинить с I2C?

Главное преимущество стандарта — это использование всего двух ног контроллера, что актуально для небольших МК. Конечно, за такое удобство придется платить — передача одного байта займет время передачи 8 бит + время начала/окончания передачи. Поэтому I2C безусловно медленнее параллельной шины. Однако, если вы не гонитесь за мегибитами, I2C — идеальный вариант.

Многие изготовители выпускают занятные микросхемы с I2C. Philips, как изобретатель, лидирует в этом деле. Иногда можно встретить целые модули с I2C интерфейсом (ТВ-тюнеры, дисплеи…).

Что же делать?

Вот что мы решили препарировать:
— Philips PCF8574
— TI PCF8574
— On-Semi JLC1562B
— Philips PCF8591
— Natsem LM76
— Philips graphics display LPH7653
— Linear Technology LT6904

PCF8574 — это восьмибитный расширитель портов общего назначения. Он добавляет 8 дополнительных пинов ввода/вывода. Используйте его для подключения светодиодов, реле или клавиш/клавиатуры. У него есть выход прерывания, на котором появляется низкий уровень после любого изменения состояния входов. После чтения состояния портов его уровень автоматически возвращается в высокий. Это очень удобный способ вызова прерывания при вводе. Контроллер тут же читает что изменилось и принимает решение.

Заметка: Philips выпускает две модификации чипа: PCF8574 и PCF8574A. Они отличаются только адресом!

PCF8574: 0100. A2 A1 A0
PCF8574A: 0111. A2 A1 A0

Изучите эти мелочи подробнее в даташите.
Если вам нужно больше портов ввода/вывода, используйте PCF8575 той же Philips. Это уже 16-битный расширитель портов.
Texas Instruments выпускает одноименные чипы, одинаковые по характеристикам (и корпусам).

On-Semi JLC1562B так же восьмибитный расширитель общего назначения, но у него есть кое-что еще: 6-битный ЦАП и компаратор на младших пяти разрядах. Однако у него нет выхода прерывания. Компаратор совместно с ЦАП и некоторым программным кодом может таинственно превращаться в 6-битный АЦП.

PCF8591 от Philips имеет один 8-битный ЦАП и четыре 8-битных АЦП. Аналоговые входы можно настроить как одиночные, так и на сложение и вычитание сигналов. Вот вам датаshit для ковыряния.

Компания National Semiconductor выпускает микросхему термометра LM76. Сами они заявляют, что назначение этих чипов — ‘оценка’ температуры, так что не надейтесь на космическую точность. В общем, подробнее в очередном связанном документе. В чипе находится температурный датчик и 12-битный АЦП (+ знаковый разряд).

LPH7653 от Philips — это маленький графический дисплей, вероятно, выдранный из старого телефона. Даташита на него никто никогда не видел, но говорят, что кто-то знает, как управлять им.

LT6904 от Linear Technology — волшебный чип-синтезатор частоты от 1 кГц до 64 МГц.

Конечно, этот список — всего лишь маленький пример того, что нам доступно для экспериментирования. На самом деле в природе существует гораздо больше хороших микросхем, ищите их на сайтах ведущих производителей по запросу I2C.

Стандартные команды чтения/записи

Команды чтения и записи I2C работают с одним байтом за раз. Стандартная процедура записи такая:


I2cstart
I2cwbyte ICaddress
I2cwbyte Bytetosend
I2cwbyte ...
I2cstop

I2cstart производит сброс линии и заставляет все устроства внимательно слушать. Затем отправляется адрес интересующей нас микросхемы. Она начинает обмен, в это время остальные молчат. Теперь по I2cwbyte отправляются один или несколько байтов. Прием каждого байта подтверждается микросхемой. Наконец, I2cstop освобождает линию.

Стандартная процедура чтения:


I2cstart
I2cwbyte ICaddress
I2crbyte Bytetoread, Ack
I2crbyte Bytetoread, Nack
I2cstop

Так же, как и в первом случае, I2cstart сбрасывает линию. Все устройства начинают слушать. Затем опять передается адрес интересующей микросхемы. Теперь по I2crbyte принимаются один или несколько байтов. После переменной, в которую происходит считываение, стоит ключевое слово Ack или Nack. Ack сообщает, что нужно считать еще байт, Nack — что этот принятый байт был последним. Об этом подробнее рассказано в документации Philips по I2C, о которой говорилось выше.

Ошибки I2C

В BASCOM зарезервирована переменная Err типа Bit. Если происходит ошибка I2C, в нее помещается 1. Правда никому не известно, что с ней делать. На самом деле, что? Обычно ошибки возникают из-за аппаратных проблем, поэтому вряд ли пользователь сможет что-то сделать.

Простая светодиодная мигалка

Давайте забацаем простую мигалку, используя PCF8574. Соберите на макетной плате схедующую несложную схему:

Затем наберите такую программу:


$regfile = "2313def.dat"
$crystal = 4000000

Config Sda = Portd.5
Config Scl = Portd.4
Config I2cdelay = 10

Config Pind.6 = Output

Const Pcf8574write = &h50
Const Pcf8574read = &h51

Set Portd.6
Waitms 1000
Reset Portd.6
Waitms 1000

Do
  Set Portd.6
  I2cstart
  I2cwbyte Pcf8574write
  I2cwbyte 255
  I2cstop
  Waitms 500
  Reset Portd.6
  I2cstart
  I2cwbyte Pcf8574write
  I2cwbyte 0
  I2cstop
  Waitms 500
Loop

End

Две ножки порта D зарезервированы под I2C. I2Cdelay задает скорость шины в 200кГц. Pind.6 настроен на выход, к нему подключен светодиод.

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

Если вы хотите использовать выводы PCF8574 на вход, вам нужно установить на них высокий уровень, записав 1. Затем, используя кнопку, дергать их на землю (и читать с них 0) или не дергать (и соответственно, читать 1). Но это мы рассмотрим позже.

Скорость I2C

Bascom использует стандартную частоту обмена для I2C в 200 кГц. С помощью параметра I2CDelay можно задать и другую.


Config I2Cdelay = 10

Этот код задаст частоту в 100 кГц. Используйте 5 для 200 кГц (по умолчанию). Соответственно, 2 задаст частоту в 500 кГц, а 1 в 1 МГц. Используйте значения 10 или более для низкоскоростных приложений. Иногда при использовании длинных проводов (большая емкость!) нужно понизить скорость обмена, чтобы избежать ошибок.
С другой стороны, большинство микросхем с I2C могут работать на гораздо больших скоростях, чем указано в даташите. Но нет гарантии, что они будут работать в таком режиме при любых условиях, так что несколько раз проверьте работу устройства.

Использование I2cinit

Лапки AVR, используемые с I2C, конфигурируются словами Config SDA/SCL. После подачи питания на контроллер, на них установится логический ноль. Но после команды Portx или после изменения направления input/output, на них могут оказаться непредсказуемые уровни. Поэтому нужно написать:


I2cinit

чтобы насильно установить на них низкий уровень перед началом или продолжением I2C обмена.

Считываем состояние выключателя через PCF8574

Соберем следующую схему:

И зальем в наш контроллер следующую программу:
i2c-pcf8574-switch.bas


$regfile = "2313def.dat"
$crystal = 4000000

Config Sda = Portd.5
Config Scl = Portd.4
Config I2cdelay = 10

Config Pind.6 = Output

Const Pcf8574write = &h50
Const Pcf8574read = &h51

Const Shortwait = 50
Const Longwait = 250

Const Switchbit = 0

Dim Ledwait As Byte
Dim Pcf8574port As Byte

'Поместим на все ножки PCF8574 единицу и будем проверять
I2cstart
I2cwbyte Pcf8574write
I2cwbyte 255
I2cstop

Do
  'Read Pcf8574 port
  I2cstart
  I2cwbyte Pcf8574read
  I2crbyte Pcf8574port , Nack
  I2cstop
  'Determine state of Switchbit bit
  If Pcf8574port.switchbit = 1 Then
    Ledwait = Shortwait
  Else
    Ledwait = Longwait
  End If

  Set Portd. 6
  Waitms Ledwait
  Reset Portd.6
  Waitms Ledwait
Loop

End

Константы определяют длинную и короткую продолжительности вспышки светодиода.
Константа SwitchBit определяет состояние выключателя на Pin 0 (bit 0) PCF8574.
Две переменные типа Byte задают продолжительность вспышки светодиода и состояние порта PCF8574.
Программа начинается с установки всех ножек порта PCF8574 в высокий уровень, так что их можно использовать как входы.
В цикле Do Loop состояние порта PCF8574 определяется так: сначала отсылается I2cstart, затем PCF8574 читает адрес, а затем I2crbyte используется для получения текущего значения порта PCF8574. I2cstop прекращает обмен.

Скомпилируйте программу и отправьте в контроллер. Проследите за её работой — теперь, когда выключатель разомкнут, светодиод моргает часто, если замкнут — редко.

Использование прерываний PCF8574

Программа, описанная выше, достаточно глупая. Время опроса выключателя зависит от состояния переменной Ledwait (пока отрабатывается задержка, контроллер больше ничего не делает). Это плохой пример программирования. Но мы с вами умные и воспользуемся прерываниями от PCF8574. Если вы еще не знаете, что это такое, то срочно прочитайте статью о прерываниях перед тем, как мы продолжим.
Как было сказано ранее, PCF8574 будет генерировать сигнал прерывания (низкий уровень) каждый раз, когда поменяется состояние на его входах.
Соберем такую схему:

И запишем такую программу:
i2c-pcf8574-switch-int.bas


$regfile = "2313def.dat"
$crystal = 4000000

Config Sda = Portd.5
Config Scl = Portd.4
Config I2cdelay = 10

Config Pind.6 = Output
Config Pind.2 = Input
Config Int0 = Falling

Const Pcf8574write = &h50
Const Pcf8574read = &h51

Const Shortwait = 50
Const Longwait = 250

Const Switchbit = 0

Dim Ledwait As Byte
Dim Pcf8574port As Byte

Ledwait = Shortwait

On Int0 Pcfint

Enable Interrupts
Enable Int0

I2cstart
I2cwbyte Pcf8574write
I2cwbyte 255
I2cstop

Do
  Set Portd. 6
  Waitms Ledwait
  Reset Portd.6
  Waitms Ledwait
Loop

'PCF8574 interrupt routine
Pcfint:
  'debounce wait time
  Waitms 10
  'read the input pins
  I2cstart
  I2cwbyte Pcf8574read
  I2crbyte Pcf8574port , Nack
  I2cstop
   'Determine state of Switchbit bit
  If Pcf8574port.switchbit = 1 Then
    Ledwait = Shortwait
  Else
    Ledwait = Longwait
  End If
  Gifr = 64
Return
End

Теперь у нас в конфигурации появилась новая строка: Config Int0 = Falling. Это означает, что только спады сигнала на входе Int0 будут вызывать прерывание программы
Также, Int0 на Portd.2 у нас настроен как вход.
В переменную Ledwait изначально кладется значение константы Shortwait.
Когда произойдет прерывание, программа перейдет на метку Pcfint.
Прерывания включены глобально, отдельно включено прерывание Int0.
Программа будет зацикленно моргать светодиодом, пока не случится прерывание. В подпрограмме обработки первым делом выполняется задержка 10 мс, чтобы исключить ложные срабатывания от дребезга контактов. После этого считывается состояние порта PCF8574, а точнее одного бита, помеченного как Switchbit. Если полученное значение — 1, то то переменную Ledwait приравниваем к Shortwait, иначе к Longwait.

Компилируем программу, загружаем в чип. Наблюдаем, что светодиод мигает часто. Замыкаем выключатель и видим, что он стал мигать медленнно. Вместо выключателя можно использовать кнопку.

Обработка данных с оптического энкодера через PCF8574

AVR можно научить читать значения напрямую с энкодера, об этом есть отдельная одноименная глава под номером 18. Но может случиться так, что вам будет не хватать свободных пинов. Тогда на помощь к нам приходит все тот же расширитель PCF8574.
Рассмотрим (значит, соберем на макетной плате!) схему:

И откроем в BASCOM следующую программу:
i2c-pcf8574-int-encoder. bas


$regfile = "2313def.dat"
$crystal = 4000000

Config Sda = Portd.5
Config Scl = Portd.4
'default I2C speed
Config I2cdelay = 5
Config Pind.6 = Output     'Тут будет светодиод
Config Pind.2 = Input      'Прерывание от PCF8574 на вход Int0
Config Int0 = Falling
Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Portb.4 , Db5 = Portb.5 , Db6 = Portb.6 , Db7 = Portb.7 , E = Portb.3 , Rs = Portb.2
Config Lcdmode = Port

Const Pcf8574write = &h50
Const Pcf8574read = &h51
Const Optencmask = &B00000011   'Энкодер AB подключен к младшим двум битам
Const Optencbmask = &B000000001 'Удерживаем B-бит

Dim Pcf8574input As Byte
Dim Encoderval As Byte
Dim Encounter As Integer
Dim Oldbval As Byte

Encounter = 0
Oldbval = 0
Cls
Lcd "encounter:"

On Int0 Pcfint

'Настроим расширитель на вход
I2cstart
I2cwbyte Pcf8574write
I2cwbyte Optencmask
I2cstop

Enable Interrupts
Enable Int0


'Сообщим положение энкодера
'Следим за светодиодом на Portd. 6 : Если он постоянно включен или выключен,
'то вероятно, срабатывает слишком много  прерываний
Do
  Set Portd.6
  Waitms 5
  Locate 1 , 12
  Lcd Encounter ; "      "
  Reset Portd.6
  Waitms 5
Loop

Pcfint:
  'read the input pins
  I2cstart
  I2cwbyte Pcf8574read
  I2crbyte Pcf8574input , Nack
  I2cstop
  Encoderval = Pcf8574input And Optencmask
  If Oldbval = 1 Then
    Encoderval = Encoderval + 4
  End If
  If Encoderval < 2 Then
    Decr Encounter
  Elseif Encoderval > 5 Then
    Decr Encounter
  Else
    Incr Encounter
  End If
  Oldbval = Pcf8574input And Optencbmask
Return

End

Config Lcdpin используется для задания портов для работы с ЖКИ (в данном случае они совпадают со значениями по умолчанию).
Optencmask используется для установки двух младших битов на энкодере. Optencbmask используется для задания только бита «B».
В основном цикле светодиод на Portd.6 мигает, а на экран выводится положение энкодера. В подпрограмме прерывания считывается байт с I2C порта, из него извлекаются состояния битов на энкодере и определяется его положение, которое обновляется.

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

Использование ON Semi JLC1562B вместо PCF8574

У JLC1562B нет выхода прерываний, однако есть 6-битный ЦАП, напряжение на нем можно изменять в 64 уровнях, от 0 до 4 вольт, с шагом 0,0625. На входах JLC1562B есть компаратор. На младших 5 битах можно установить порог компаратора («B») как на половину питающего напряжения, так и на выход ЦАП. Старшие три бита компаратора («A») всегда настоены на порог в половину питающего напряжения.
По сравнению с PCF8574, в JLC1562B DAC имеет другие режимы чтения и записи. Это нужно знать, чтобы использовать его вместо PCF8574, а также грамотно настроить ЦАП и управлять порогом компаратора. Если используется JLC1562B, как замена PCF8574, последовательность работы с I2C не изменится.
Если вы хотите настроить ЦАП:

— Отправьте JLC1562B адрес записи
— Отправьте байт состояния входов/выходов
— Отправьте 6-битное значение ЦАП (0-63) в младшие 6 бит
— В двух старших битах шестой задает порог компаратора: 0 задает порог в половину питающего напряжения,
1 задает порог значением выхода АЦП, 7 бит управляет «защелкой»,
0 защелкивает данные после команды чтения,
1 защелкивает данные, когда компаратор B переключается из 0 в 1

Чтобы использовать ЦАП, соберите следующую схему:

И наберите следующую программу:
i2c-jlc1562b-dac. bas


$regfile = "2313def.dat"
$crystal = 4000000

Config Sda = Portd.5
Config Scl = Portd.4
Config I2cdelay = 10
Config Pind.6 = Output

Const Jcl1562bwrite = &H70

Dim Dacval As Byte

Do
  Set Portd.6
  For Dacval = 0 To 63
    I2cstart
    I2cwbyte Jcl1562bwrite
    I2cwbyte 0
    I2cwbyte Dacval
    I2cstop
  Next Dacval
  Reset Portd.6
Loop

End

Адрес для записи в JLC1562B установлен в 70 (в шестнадцатеричной системе). Сверяйтесь с даташитом!
В цикле Do Loop включается светодиод, а в JLC1562B записывается 0 в первый байт, а во второй пишется значение счетчика от 0 до 63 для ЦАП. В этом втором байте старшие биты (порог компаратора и защелкивание) остаются равными 0.

Ловкими и отточенными движениями отправляем скомпилированную прошивку в контроллер. Наблюдаем на выходе ЦАП (13 нога) пилообразный сигнал:

JLC1562B в роли 6-битного АЦП

Вы можете настроить компаратор JLC1562 так, чтобы он использовал в качестве источника опорного напряжения выход ЦАП. Если мы установим выход ЦАП, скажем, в 2 вольта и приложим чуть меньшее напряжение к ногам D0..D4, то считанное значение будет равно 0. Если чуть поднять напряжение, то считываться будет уже 1. Так что любой из выводов D0..D4 можно заставить исполнять функции «сыроватого» 6-битного АЦП, если изменять напряжение на ЦАП за 64 шага и считывать значение компаратора после каждого шага.
Соберём следующую схему:

И, как обычно, наберем программу:
i2c-jlc1562b-adc.bas


$regfile = "2313def.dat"
$crystal = 4000000

Config Sda = Portd.5
Config Scl = Portd.4
Config I2cdelay = 10
Config Pind.6 = Output

Const Jcl1562bwrite = &H70
Const Jcl1562bread = &H71
'mask out all but the lower six dac bits
Const Jcl1562bcompon = &B11000000
'make this pin high to use it as input
Const Jclmask = &B00000001

Dim Dacval As Byte
Dim Dacwrite As Byte
Dim Jclinput As Byte

Cls
Do
  Reset Portd. 6
  For Dacval = 0 To 63 Step 1
    Dacwrite = Dacval Or Jcl1562bcompon
    I2cstart
    I2cwbyte Jcl1562bwrite
    I2cwbyte Jclmask
    I2cwbyte Dacwrite
    I2cstop
    I2cstart
    I2cwbyte Jcl1562bread
    I2crbyte Jclinput , Nack
    I2cstop
    Jclinput = Jclinput And Jclmask
    If Jclinput = Jclmask Then
      Exit For
    End If
  Next Dacval
  Locate 1 , 1
  Lcd Dacval ; "    "
Loop

End

В данном примере производится операция ИЛИ: Dacwrite = Dacval Or Jcl1562bcompon, так что оба бита — бит выбора источника опорного напряжения для компаратора B и бит защелки — устанавливаются в 1.
Jlcmask используется, чтобы установить бит 0 на порту JLC1562B в единицу, чтобы он работал как вход.
В цикле Do Loop включается светодиод, в течение следующих шагов значение Dacval возрастает от 0 до своего максимума 63 (0..63 * 0. 0625 = приблизительно 4 вольта). После каждого увеличения считывается значение компаратора. Если при этом оно изменилось (стало 1), считается что компаратор сработал. Тогда цикл прерывается, а значение Dacval выводится на ЖКИ.

АЦП/ЦАП Philips PCF8591

PCF8591 имеет на борту один 8-битный ЦАП и четыре 8-битных АЦП. Чтобы они заработали, вывод EXT нужно подключить к земле. Тогда на выводе OSC появится нечто, похожее на тактовые импульсы 1 МГц:

Вы можете также использовать внешний тактовый генератор (0.75 — 1.25 МГц), подключив его к выводу OSC. Тогда вывод чипа EXT нужно подключить к плюсу питания.

PCF8591 управляется тремя незамысловатыми байтами:
— байт адреса
— байт команды
— байт значения ЦАП
Байт управление выглядит следующим образом:

7 6 5 4 3 2 1 0 (позиция бита)
0 a p p 0 i c c (управляющие биты)

Где:
a = 1 для включения аналогового выхода (но также нужно включить, если планируется использование АЦП)
pp = конфигурация АЦП, нужно выставить 00 для 4 независимых входов A0, A1, A2, A3. Другие значения изучите в даташите самостоятельно!
i = 1 для включения автоувеличения каналов АЦП. Увеличивает значение сс после каждого чтения.
cc = номер канала АЦП, 0, 1, 2 или 3.

Соберём следующую схему:

Для проверки ЦАП введём следующую программу:
i2c-pcf8591-dac-triangle.bas


$regfile = "2313def.dat"
$crystal = 4000000

Config Sda = Portd.5
Config Scl = Portd.4
Config I2cdelay = 10

Config Pind.6 = Output

Const Pcf8591write = &H90
Const Pcf8591read = &H91

Const Pcf8591dacconfig = &B01000000
'                           |
'                           -------- включаем аналоговый выход
'                                    (также нужно и для АЦП)
Dim Dacout As Byte

Set Portd.6
Waitms 1000
Reset Portd.6
Waitms 1000

Do

  Set Portd.6
  For Dacout = 1 To 255 Step 1
    I2cstart
    I2cwbyte Pcf8591write
    I2cwbyte Pcf8591dacconfig
    I2cwbyte Dacout
    I2cstop
  Next Dacout
  Reset Portd. 6
  For Dacout = 255 To 1 Step -1
    I2cstart
    I2cwbyte Pcf8591write
    I2cwbyte Pcf8591dacconfig
    I2cwbyte Dacout
    I2cstop
  Next Dacout

Loop

End

В константе Pcf8591dacconfig установлен 6 бит, включающий аналоговый выход.
В цикле Do Loop, For Next цикл меняет значение Dacout от 1 до 255 и отсылает Dacout как третий управляющий байт.
Затем For Next цикл меняет значение Dacout в обратном порядке, от 255 до 1.

На выводе 15 (Aout) можно наблюдать треугольный сигнал:

Изменение Config I2cdelay с 10 до 1 ускоряет процесс:

Конечно, все эти наши приколы ограничены частотой в 100 КГц, это максимальная частота, поддерживаемая PCF8591.
Но тем не менее, программу можно переделать, чтобы получать более высокие частоты:
i2c-pcf8591-triangle-faster.bas


$regfile = "2313def.dat"
$crystal = 4000000

Config Sda = Portd. 5
Config Scl = Portd.4
Config I2cdelay = 10

Config Pind.6 = Output

Const Pcf8591write = &H90
Const Pcf8591read = &H91

Const Pcf8591dacconfig = &B01000000

Dim Dacout As Byte

Set Portd.6
Waitms 1000
Reset Portd.6
Waitms 1000

I2cstart
I2cwbyte Pcf8591write
I2cwbyte Pcf8591dacconfig

Do

  For Dacout = 1 To 255 Step 1
    I2cwbyte Dacout
  Next Dacout
  For Dacout = 255 To 1 Step -1
    I2cwbyte Dacout
  Next Dacout

Loop

End

Теперь первые два управляющий байта отсылаются перед циклом Do Loop.
В самом цикле лишь происходит запись значения Dacout в чип PCF8591.

Обратите внимание: в этой программе нет команды I2cstop! В реальной же программе такой поворот событий маловероятен, потому что наверняка будут происходить какие то другие процессы с шиной I2C.

Посмотрим на выходной сигнал теперь:

Но мы опять ускорим программу, заменив, как и обешано, I2cdelay на 1:

И по идее можно добиться ещё большего ускорения, установив в схему кварц на 10 МГц, благополучно не сказав об этом Bascom. Тогда результат будет таким:

Разумеется, грамотный читатель никогда не будет делать таких ужасных вещей при разработке коммерческих продуктов. Но домашнее применение подразумевает попирание всех правил, но и подразумевает возможные последствия.

Температурный сенсор National Semiconductor LM76

LM76 — это одна из кучи микросхем для измерения температуры, с I2C интерфейсом. У большинства крупных производителей такой чип непременно есть в «портфолио». LM76 не предполагает высокой точности, и поэтому позорно называется «оценщик температуры». На самом деле она дает точность измерений около одного градуса Цельсия. В общем, почитайте даташит на досуге.
В этом чипе 6 регистров. Регистр, из которого нужно читать температуру, выбирается по умолчанию после включения питания. Подробнее об этих регистрах я расскажу позже. LM76 меряет и запоминает температуру с точностью 0.0625oC. Температура хранится как 16-битное слово, считывается как два байта:

D0-D2 не определены. D15 — бит знака, само значение температуры лежит в D3-D14. Температура хранится в обычном двоичном представлении. Это значит, что положительные числа хранятся как есть, с битом знака равным 0. Отрицательные числа хранят 1 в бите знака, сам модуль числа записан в инвертированном виде и увеличен на 1. Если вы предполагаете использовать датчик для измерения только плюсовых температур, забудьте про эти махинации со знаками и просто считывайте биты D3-D14. Однако если вы из мест не столь отдаленных, вас наверняка заинтересует метод считывания отрицательных значений. Для этого я приготовил вам следующий код:


...
Dim Tempint as Word
Dim Tempbytelo as Byte
Dim Tempbytehi as Byte
...
'считаем два байта из lm76. Это просто, как два байта переслать =)
. ..
Tempint = Makeint(Tempbytelo, Tempbytehi)
Tempsign = Tempbytehi And &B1000000
If Tempsign = &B10000000 Then
  Tempint = Not Tempint
  Tempint = Tempint + 1
End If
Shift Tempint, Right, 3
...

Makeint объединяет принятые два байта в одно 16-битное слово и кладет в переменную Tempint. Затем, путем откусывания самого старшего (левого) бита, извлекается знак числа. Если бит равен 1, нам нужно инвертировать все биты в Tempint (убрав тем самым бит знака) и увеличить результат на 1. Наконец, все биты в Tempint нужно сдвинуть вправо на 3 разряда, убрав тем самым бесполезные биты D0-D2. Теперь в Tempint хранится модуль температуры с точностью 0.0625oC, а в Tempsign лежит знак температуры. Все проще некуда.
Посему соберем следующую интересную схему:

И введём следующую интересную программу:
i2c-lm76.bas


$regfile = "2313def.dat"
$crystal = 4000000

Config Sda = Portd. 5
Config Scl = Portd.4
Config I2cdelay = 100
Config Pind.6 = Output

Const Lm76write = &H90
Const Lm76read = &H91

Dim Tempint As Integer At $80
Dim Tempbytelo As Byte At $80 Overlay
Dim Tempbytehi As Byte At $81 Overlay
Dim Templong As Long

Cls

Do
  Set Portd.6
  I2cstart
  I2cwbyte Lm76write
  'указатель на регистр температуры.
  'хоть и установлен по умолчанию, он здесь просто для примера.
  I2cwbyte 0
  I2cstart
  I2cwbyte Lm76read
  I2crbyte Tempbytehi , Ack
  I2crbyte Tempbytelo , Nack
  I2cstop
  Cls
  Lcd Tempbytehi ; " " ; Tempbytelo
  Lowerline
  Shift Tempint , Right , 3
  Templong = Tempint * 65
  Lcd Tempint ; " " ; Templong
  Reset Portd.0.6
  Wait 1
Loop

End

В этом примере игнорируется знак температуры. Поэтому нужно привести еще один, более продвинутый пример, который будет показывать нам температуру сразу в градусах Цельсия:
i2c-lm76-fusing. bas


$regfile = "2313def.dat"
$crystal = 4000000

Config Sda = Portd.5
Config Scl = Portd.4
Config I2cdelay = 100
Config Pind.6 = Output

Const Lm76write = &H90
Const Lm76read = &H91
Const Lm76resolution = 0.0625

Dim Tempint As Word
Dim Tempbytelo As Byte
Dim Tempbytehi As Byte
Dim Temperature As Single
Dim Tempstring As String * 4
Dim Tempsign As Byte
Dim Flashnumber As Byte
Dim Flashloop As Byte
Dim Flashtime As Word

Do
  Set Portd.6
  Wait 1
  Cls
  I2cstart
  I2cwbyte Lm76read
  I2crbyte Tempbytehi , Ack
  I2crbyte Tempbytelo , Nack
  I2cstop
  Lcd Tempbytehi ; " " ; Tempbytelo ; " "
  Tempint = Makeint(tempbytelo , Tempbytehi)
  Tempsign = Tempbytehi And 128
  If Tempsign = 128 Then
    Tempint = Not Tempint
    Tempint = Tempint + 1
   End If
  Shift Tempint , Right , 3
  Lcd Tempint ; " "
  Temperature = Tempint * Lm76resolution
  Lowerline
  Lcd Temperature ; " "
  Tempstring = Fusing(temperature , "##. #")
  If Tempsign = 128 Then Lcd "-"
  Lcd Tempstring
  Reset Portd.6
  Wait 1
Loop

End

Эта программа использует операции с плавающей точкой. Для этого подгружаются специальные библиотеки. Хоть программа и очень маленькая, она займет 99% памяти в вашем AT90S2313 (а в ATTINY2313 даже не влезет)!
При работе с маленькими контроллерами следует избегать операций с плавающими точками, где это возможно. Следующая программа покажет, как сделать это, используя переменные типа Integer. Она также будет работать намного быстрее:
i2c-lm76-usingintegers.bas


$regfile = "2313def.dat"
$crystal = 4000000

Config Sda = Portd.5
Config Scl = Portd.4
Config I2cdelay = 100
Config Pind.6 = Output

Const Lm76write = &H90
Const Lm76read = &H91
Const Lm76resolution = 625

Dim Tempint As Word
Dim Tempbytelo As Byte
Dim Tempbytehi As Byte
Dim Tempall As Long
Dim Temprem As Long
Dim Temptemp As Long
Dim Tempdeg As Long
Dim Tempsign As Byte
Dim Tempdigit As Integer

Do
  Cls
  Set Portd. 6
  I2cstart
  I2cwbyte Lm76read
  I2crbyte Tempbytehi , Ack
  I2crbyte Tempbytelo , Nack
  I2cstop
  Lcd Tempbytehi ; Tempbytelo ; " "
  Tempint = Makeint(tempbytelo , Tempbytehi)
  Tempsign = Tempbytehi And 128
  If Tempsign = 128 Then
    Tempint = Not Tempint
    Tempint = Tempint + 1
   End If
  Shift Tempint , Right , 3
  Lcd Tempint ; " "
  Tempall = Tempint * Lm76resolution
  Lcd Tempall ; " "
  Tempdeg = Tempall / 10000
  Temptemp = Tempdeg * 10000
  Temprem = Tempall - Temptemp
  Lowerline
  Lcd Tempdeg ; " " ; Temprem ; " "

  Tempdigit = Temprem / 1000
  Temptemp = Tempdigit * 1000
  Temprem = Temprem - Temptemp

  If Temprem > 499 Then Tempdigit = Tempdigit + 1
  If Tempdigit > 9 Then
    Tempdigit = 0
    Tempdeg = Tempdeg + 1
  End If

  If Tempsign = 128 Then Lcd "-"
  Lcd Tempdeg ; "." ; Tempdigit

Loop

End

В этой программе больше строк, но, как ни странно, она занимает всего 85% в памяти контроллера, оставляя место для некоторых других функций.

Управление графическим дисплеем Philips LPH7653

Дисплей Philips LPH7653 вероятно был разработан для мобильных телефонов ранних поколений. Он имеет разрешение 97×35 пикселей.
Информацию по нему можно найти тут.
Прочитайте это описание (хоть оно и на английском, просто посмотрите картинки)! Наверняка вам придется подбирать напряжения питания и регулировки контрастности, чтобы суметь что-то прочитать на нем. Светодиодную подсветку можно питать стандартным напряжением +5 вольт.

LP7653 — чисто графический дисплей. Он не имеет знакогенератора, это значит, что вам придется самим рисовать символы, если вы хотите выводить текст. Но это не так сложно, как может показаться.
Дисплей имеет ширину в 97 пикселей, однако судя по всему, видеопамять у него рассчитана на 101 пиксель. Каждая строка из 8 пикселей имеет индивидуальную адресацию:

В программном плане это выглядит так:


I2cstart
I2cwbyte lph7653writeaddress '(7Ahex)
I2cwbyte linenumber          '(60, 61, 62, 63 or 64hex для строк 0, 1, 2, 3 и 4)
I2cwbyte pixelcolumn         '(00. ..60hex для столбцов 0...97)
I2cwbyte pixelbyte           '(младший бит - сверху)
I2cwbyte pixelbyte           '(pixelcolumn/linenumber идёт pixelcolumn 64hex)
I2cwbyte ...
I2cstop

Для очистки экрана вы можете записать 5×101 нулевых байтов начиная с первой строки и первого столбца. Если вы планируете использовать дисплей только для вывода текста, разумно было бы использовать его как четырёхстрочный. Тогда вы можете использовать символы высотой в 8 пикселей. Вы можете выводить стандартные символы 7×5 как символы 7×6. Таким образом, нижний ряд пикселей будет пустым, создавая отступ между строками текста. Пятая строка доступна для вывода, но отображаться будут только верхние три ряда пикселей (35 — (4 x 8)).
Для проверки соберём следующую схему:

И введём следующую программу:
i2c-lph7653-75.bas для символов 7×5
или i2c-lph7653-75prop.bas для символов 7×6
(листинги здесь не приводятся, так как там много скучных и неинтересных строк)

Программа i2c-lph7653-76prop. bas использует символы 7×6, поэтому каждая строка Data хранит 6 байтов.

Если вы хотите использовать дисплей для вывода графики, вам нужно представить изображение в виде 8-битных столбцов пикселей. Это немного отличается от метода вывода на дисплей Toshiba T6963, для которого в Bascom есть утилита конвертирования изображений.
Если вы просто хотите «слить» изображение на дисплей, лучше всего привести его к разрешению 101×35 и выводить видимую часть 97×32 начиная с левого верхнего края. Конечно, вы можете выводить и меньшие изображения, но тогда внимательно следите за тем, как меняется адресация.
Для преобразования изображений в блок данных есть небольшая утилита на Delphi. Она считывает черно-белое изображение BMP и выводит в виде текста, который вы можете скопировать и вставить в программу. Исходные коды прилагаются!
Вот вам пример работы:

Загружаем первый битмап в утилиту и видим следующее:

Вы можете загрузить и переконвертировать все изображения по очереди, а затем вставить полученный код в нужное место вашей программы на Bascom.

Управление синтезатором частоты Linear Technology LT6904

LT6904 — это чип от Linear Technology, выполняющий функцию синтезатора частоты. Его собрат LT6903 имеет SPI интерфейс, но LT6904 использует I2C. Еще есть чипы LT1799, LT6900, LT6902 и LT6905, в которых частота задается внешним переменным резистором.
LT6904 управляется следующим путем (согласно даташиту):

где OCT — четырёхбитное и DAC — десятибитные слова. Также еще два бита применяются для конфигурирования выходов. Убедитесь, что вы отключили неиспользуемый выход (читайте даташит!) В итоге мы отсылаем 16 бит в таком порядке:
Oct3, Oct2, Oct1, Oct0, DAC9, DAC8…DAC0, Cfg1, Cfg0.
Соберём такую схему:

Обратите внимание, даташит утверждает, что напряжение питание может быть от 2.7 до 5.5 вольт. Однако была замечена неприятная вещь — при питании 5 вольт, выход сигнала LT6904 «пропадает». Такая особенность поведения пропала после понижения питания до 3.3 вольта.
Загрузим для самостоятельного изучения следующую программу:
i2c-lt6904.bas Автор оригинала не предоставил код. Пусть это будет на его совести!

У нас возникает небольшая проблема: Bascom говорит, что программа займет 162% программной памяти. Очевидно, что эта программа жирновата для AT90S2313. Пора обратиться к более мощным контроллерам. Об этом будет рассказано в следующих главах.

 

Atmega i2c

Subscribe to comments with RSS. Доброго здоровья после праздников! Идея состоит в том, что бы мастер опрашивал N подчинённых выбирая по усмотрению прог-мы данные, обрабатывал их и при получении аварийного отправлял на все подчинённые свои рекомендации. Если имеется готовый проект приблизительно в эту тему буду очень благодарен. Спасибо за Ваше участие.


Поиск данных по Вашему запросу:

Atmega i2c

Схемы, справочники, даташиты:

Прайс-листы, цены:

Обсуждения, статьи, мануалы:

Дождитесь окончания поиска во всех базах.

По завершению появится ссылка для доступа к найденным материалам.

Содержание:

  • как написать функцию чтения avr I2C
  • AVR Урок 16. Интерфейс TWI (I2C). Часть 6
  • Что произойдет, если я опустил резисторы подтягивания на линиях I2C?
  • Работа с TWI (I2C) в ATmega8
  • ATMEGA TWI/I2C Slave — Как реализовать растяжение часов?
  • Передача данных по шине I2C
  • AVR Урок 16. Интерфейс TWI (I2C). Часть 1
  • Использование протокола I2C

ПОСМОТРИТЕ ВИДЕО ПО ТЕМЕ: I2C Bus Communication Protocol Tutorial with Example

как написать функцию чтения avr I2C


В простой системе I2C может быть один ведущий и несколько ведомых. Ведущий — это устройство, которое инициирует передачу данных и вырабатывает сигналы синхронизации. При этом любое адресуемое устройство считается ведомым по отношению к ведущему. SDA и SCL являются двунаправленными линиями и подключаются к источнику питания через оттягивающий резистор.

В большинстве случаев ведущим устройством выступает микроконтроллер, а ведомыми могут быть часы реального времени и датчики температуры, например, DS и DS от www. После каждой передачи данных выполняется условие остановки. Длина данных, передаваемых по линии SDA, всегда равна 8 битам включая команды чтения и записи.

Каждый байт должен оканчиваться битом подтверждения. Старший бит MSB передается первым. Подтверждение при передаче данных обязательно. Приемник должен удерживать линию данных в течение подверждения в стабильно Низком состоянии. Приёмник, которому были адресованы данные, обязан генерировать подтверждение после каждого принятого байта, исключая те случаи, когда посылка начинается с адреса CBUS.

После этого ведущий может выдать сигнал СТОП для прерывания пересылки данных. Ведущий может в любое время остановить передачу данных. Допустим, у нас есть ведомое устройство с адресом , и ведущий хочет, чтобы он выступал в роле приемника. После этого ведущий может начать передачу данных или остановить ее условием СТОП. Ведомый может начать передачу данных после потверждения от ведущего, он также может прекратить прием данных, создав условие СТОП.

Этот пример показывает, как настроить чтение с датчика температуры DS Схема подключения DS Код программы представлен ниже. Отметим, что используемые команды в этом примере можно найти в документации к DS Bascom AVR имеет встроенный компилятор, который преобразует программы, написанные на языке Basic, в шестнадцатеричный код, который, в свою очередь, можно запрограммировать прошить в микроконтроллер. Краткий обзор команд.

I2cwbyte Записывает один байт в I2C. I2crbyte Считывает один байт из I2C. I2csend Записывает количество байт, I2C. I2creceive Читает количество байтов от I2C. Практика Ниже показано, как реализовать I2C. В схеме использeтся контроллер Mega88 как мастер.


AVR Урок 16. Интерфейс TWI (I2C). Часть 6

Обратите внимание, что я пропустил оба подтягивающих резистора. Оба режима работают нормально, один из них работает уже более 3 месяцев. Как это возможно? В любом случае, я хотел знать:. Не хватает ли pullups, чтобы повредить любой из этих двух микросхем на моей плате?

Урок 16 Часть 6 Интерфейс TWI (I2C) В занятия уже продолжили свою работу с отправкой значений в память микросхемы EEPROM по.

Что произойдет, если я опустил резисторы подтягивания на линиях I2C?

Модуль предназначен для организации обмена данными между микросхемами, подключенными к двухпроводной шине. Соображения, по которым Atmel использует другое названия, видимо связано с нежеланием платить Philips за лицензию. В этом материале мы разберемся с основами двухпроводного последовательного интерфейса, а в следующих перейдем к работе с TWI модулем AVR. Далее я буду опираться на даташит atmega16 и спецификацию I2C. Обе линии подтянуты через резисторы к плюсу питания. Устройства на шине подразделяются на ведущих master и ведомых slave. Ведущие запускают и завершают передачу данных, ведомые — отвечают на запросы. Одни — начальники, другие — подчиненные. Микроконтроллеры могут совмещать в себе обе эти функции.

Работа с TWI (I2C) в ATmega8

В простой системе I2C может быть один ведущий и несколько ведомых. Ведущий — это устройство, которое инициирует передачу данных и вырабатывает сигналы синхронизации. При этом любое адресуемое устройство считается ведомым по отношению к ведущему. SDA и SCL являются двунаправленными линиями и подключаются к источнику питания через оттягивающий резистор.

Используется для соединения низкоскоростных периферийных компонентов. Название является аббревиатурой слов Inter-Integrated Circuit.

ATMEGA TWI/I2C Slave — Как реализовать растяжение часов?

Статья про I2С должна была появиться уже давно. Для обмена данными с периферией существуют различные интерфейсы, например мы уже ранее рассматривали SPI. Его недостаток — для обмена данными используются четыре ножки, если задействовано несколько устройств, то ножку CS — chip select нужно тянуть для каждого устройства отдельную. Таким образом, если используются три внешних устройства, то у микроконтроллера будет задействовано шесть ножек. Ножки это важный ресурс и высокая скорость, которой обладает SPI не всегда нужна, поэтому альтернативой является интерфейс I2C, который работает со скоростью до кГц и обладает 7 битным адресным пространством и теоретически позволяет подключать до ведомых устройств. Ну и самое главное, для передачи данных используется всего две ножки микроконтроллера и не важно сколько у вас сидит устройств на шине данных 1, 2 или

Передача данных по шине I2C

Некоторые современные микроконтроллеры серии ATmega аппаратно поддерживают подключение к стандартной двухпроводной шине I2C , которая часто используется в приборах и бытовой технике. Atmel называет эту шину two-wire interface, сокращенно TWI. Изначально эта шина получила название I2C от фирмы Philips, но это название избегают использовать в документации Atmel из-за патентных проблем. Примечание: полное описание протокола I2C см. Все устройства на шине соединены друг с другом параллельно, используя драйверы с открытым стоком для формирования на шине логических уровней сигналов 0 и 1. По этой причине на шине обязательно присутствуют два верхних нагрузочных подтягивающих резистора pull-up, на рисунке это резисторы R PU , подключенные к плюсу питания VDD. Нагрузочные резисторы должны иметь достаточно малый номинал для используемой тактовой частоты, чтобы быстро заряжать емкость сигналов SDA и SCL и давать короткие фронты нарастания уровня лог.

Схема моих часов без подтягивающих резисторов на линиях I2C Возможно, у вас есть внутренние подтягивания, включенные на ATmega. Из того, что.

AVR Урок 16. Интерфейс TWI (I2C). Часть 1

Atmega i2c

Например здесь: TWI по русски. Так же инфа есть тут: ApNotes. Может оказаться что проще взять готовое оттуда, а не использовать Procyon AVRlib, который давно не обновляется.

Использование протокола I2C

Описание тега atmega Описание тега Вопросы с тегом. Arduino if утверждение всегда верно Я создаю программу для моего мега Arduino с моторным щитом LD и модулем Bluetooth на контакте rx для моего автомобильного проекта arduino rc. Я хочу знать, как я могу преобразовать USB из режима устройства в режим хоста. Может ли кто-нибудь помочь мне? Как сделать один секундный таймер с atmega8? Я хочу сделать таймер на одну секунду с atmega8 и timer0.

Про шину IIC я писал уже неоднократно. Вначале было описание протокола , потом пример работы в лоб , а недавно камрад Ultrin выложил пример работы с i 2 c на базе блока USI.

Работает вообще, мастер может отправлять и считывать данные с ведомого устройства. Все идет нормально. Я хотел бы использовать растяжение часов, чтобы заставить хозяина ждать, пока данные не будут готовы. Это полезно, если тактовая частота, установленная мастером, слишком велик для ведомого устройства, или ведомому устройству требуется дополнительное время для обработки между передачами данных. Это именно то, что я хочу, но я не понимаю, как реализовать это на уровне драйвера. Я не вижу способа указать ведомому аппарату I2C, что он не должен немедленно активировать ACK, но вместо этого вытащить SCL в течение определенного периода времени.

При проектировании устройств и их починке приходится сталкиваться с этой шиной. Рассмотрим ее поподробнее. Шина I2C была спроектирована компанией Philips в начале х и предназначена для низкоскоростной передачи данных по двум сигнальным проводникам, SDA для данных и SCL для тактирования. Для успешного обмена данными на шине обязательно присутствие одного ведущего устройства master device , которое производит тактирование и одного или более ведомых устройств slave device.


Пример использования двухпроводного интерфейса (TWI)

Некоторые новые устройства серии ATmega содержат встроенную поддержку интерфейса микроконтроллера с двухпроводной шиной, называемой TWI. По сути, это то же самое, что Philips называет I2C, но этот термин избегается в документации Atmel из-за проблем с патентованием.

Для получения дополнительной документации см.:

http://www.nxp.com/documents/user_manual/UM10204.pdf

Двухпроводной интерфейс состоит из двух сигнальных линий с именами SDA (последовательные данные) и SCL (последовательные часы) (плюс линия заземления, конечно). Все устройства, участвующие в шине, соединены вместе с помощью схемы драйвера с открытым стоком, поэтому провода должны быть оконцованы соответствующими подтягивающими резисторами. Подтяжки должны быть достаточно малы, чтобы пополнить емкость линии за достаточно короткое время по сравнению с желаемой максимальной тактовой частотой, но достаточно велики, чтобы все драйверы не были перегружены. В техпаспорте есть формулы, которые помогают подобрать подтягивания.

Устройства могут действовать на шине как ведущие (т. е. инициировать передачу) или как ведомые (действуют только при вызове ведущим). Шина может работать с несколькими ведущими, и конкретная реализация устройства может действовать как ведущее или ведомое устройство в разное время. Устройства адресуются с использованием 7-битного адреса (координируемого Philips), который передается как первый байт после так называемого условия запуска. Младший бит этого байта равен R/~W, т.е. е. он определяет, будет ли запрос к ведомому устройству читать или записывать данные в течение следующих циклов. (Есть также возможность использовать устройства с 10-битными адресами, но это не рассматривается в этом примере.)

Аппаратное обеспечение ATmega TWI поддерживает как ведущее, так и ведомое устройство. Этот пример только демонстрирует, как использовать микроконтроллер AVR в качестве ведущего устройства TWI. Реализация остается простой, чтобы сконцентрироваться на шагах, которые требуются для связи с ведомым устройством TWI, поэтому вся обработка выполняется в режиме опроса, ожидая, когда интерфейс TWI укажет, что следующий шаг обработки должен быть выполнен (путем установки бит прерывания TWINT). Если желательно, чтобы вся коммуникация TWI происходила в «фоновом режиме», все это можно реализовать способом, управляемым прерываниями, когда извне процедуры обработки прерывания необходимо инициировать только условие запуска.

Существует множество ведомых устройств, которые можно подключить к шине TWI. Для этого примера было выбрано устройство EEPROM из стандартной серии 24C xx (где xx может быть одним из 01 , 02 , 04 2 , 800 21 или 16 ), которые можно приобрести у различных поставщиков. Выбор был почти произвольным, в основном вызванным тем фактом, что с устройством EEPROM говорят в обоих направлениях, читая и записывая ведомое устройство, поэтому пример продемонстрирует детали обоих.

Обычно нет особой необходимости добавлять больше EEPROM в систему ATmega таким образом: наименьшим из возможных устройств AVR, предлагающих аппаратную поддержку TWI, является ATmega8 с 512 байтами EEPROM, что эквивалентно устройству 24C04. ATmega128 уже поставляется с вдвое большим объемом EEPROM, чем может предложить 24C16. Единственным исключением может быть использование съемного устройства EEPROM, подключенного извне; е. грамм. Память SDRAM для ПК поставляется со встроенной TWI EEPROM, которая содержит информацию о конфигурации RAM.

Исходный файл: twitest.c

Примечание [1]

Файл заголовка содержит некоторые определения макросов для символических констант, используемых в регистре состояния TWI. Эти определения соответствуют именам, используемым в таблице данных Atmel, за исключением того, что все имена имеют префикс TW_ .

Примечание [2]

Часы используются в расчетах таймера, выполняемых компилятором, для скорости передачи UART и тактовой частоты TWI.

Примечание [3]

Адрес, назначенный для EEPROM 24Cxx, состоит из 1010 в старших четырех битах. Следующие три бита обычно доступны в качестве подчиненных подадресов, что позволяет использовать более одного устройства одного типа на одной шине, где фактический подадрес, используемый для каждого устройства, настраивается аппаратной привязкой. Однако, поскольку следующий пакет данных после выбора устройства позволяет использовать только 8 бит, которые используются в качестве адреса EEPROM, устройства, которым требуется более 8 бит адреса (24C04 и выше), «воруют» биты подадреса и используют их для адреса ячейки EEPROM. бит 9до 11 по мере необходимости. В этом примере просто предполагается, что все биты подадреса равны 0 для меньших устройств, поэтому входы E0, E1 и E2 24Cxx должны быть заземлены.

Примечание [3a]

ЭСППЗУ типа 24C32 и выше больше не могут быть адресованы даже с использованием битового трюка подадреса. Таким образом, они требуют, чтобы старшие биты адреса передавались по шине отдельно. При активации определения WORD_ADDRESS_16BIT алгоритм реализует эту передачу байта вспомогательного адреса.

Примечание [4]

Для медленных часов включите множитель тактовой частоты 2 x U[S]ART, чтобы уменьшить ошибку скорости передачи. Это позволит осуществлять связь на скорости 9600 бод с использованием стандартного калиброванного RC-генератора с частотой 1 МГц. См. также таблицы скоростей передачи в технических описаниях.

Примечание [5]

В техническом описании объясняется, почему минимальное значение TWBR, равное 10, должно поддерживаться при работе в ведущем режиме. Таким образом, для системных часов ниже 3,6 МГц мы не можем запустить шину с предполагаемой тактовой частотой 100 кГц, но должны соответственно замедлиться.

Примечание [6]

Эта функция используется стандартными средствами вывода, используемыми в этом примере для целей отладки и демонстрации.

Примечание [7]

Чтобы сократить объем данных, отправляемых по шине TWI, EEPROM 24Cxx поддерживают передачу нескольких байтов данных в одном запросе, поддерживая внутренний счетчик адресов, который обновляется после каждого данных. байт успешно передан. При чтении данных один запрос может прочитать всю память устройства, если это необходимо (счетчик зациклится и начнет с 0 при достижении конца устройства).

Примечание [8]

При чтении EEPROM первый выбор устройства должен быть сделан с намерением записи (бит R/~W установлен в 0, что указывает на операцию записи), чтобы передать адрес EEPROM для запуска чтение из. Это называется режимом главного передатчика . Каждое завершение определенного шага связи TWI обозначается установленным битом TWINT в TWCR. (Если разрешено, будет сгенерировано прерывание.) После выполнения любых действий, необходимых для следующего шага связи, условие прерывания должно быть сброшено вручную с помощью установка бита TWINT. В отличие от многих других источников прерываний, это может потребоваться даже при использовании истинной процедуры прерывания, поскольку, как только повторно устанавливается TWINT, начинается следующая шинная транзакция.

Примечание [9]

Так как шина TWI может работать с несколькими ведущими, существует вероятность конфликта на шине, когда один ведущий начинает доступ к шине. Обычно блок интерфейса шины TWI обнаруживает эту ситуацию и не инициирует условие запуска, пока шина занята. Однако в случае, если два мастера запускались в одно и то же время, как работает арбитраж шины, всегда есть шанс, что один мастер может потерять арбитраж шины во время любой операции передачи. Протокол требует от мастера, проигравшего арбитраж, немедленно прекратить разговор по шине; в частности, он не должен инициировать условие остановки, чтобы не повредить текущую передачу от активного мастера. В этом примере при обнаружении условия проигрыша арбитража вся передача будет перезапущена. Это приведет к инициации нового условия запуска, которое обычно откладывается до тех пор, пока активный в данный момент мастер не освободит шину.

Примечание [10]

Затем ведомое устройство будет повторно выбрано (используя так называемое условие повторного запуска, которое должно гарантировать, что арбитраж шины останется на текущем ведущем устройстве) с использованием того же адрес подчиненного устройства (SLA), но на этот раз с намерением чтения (бит R/~W установлен в 1), чтобы запросить подчиненное устройство начать передачу данных от подчиненного устройства к ведущему в следующем пакете.

Примечание [11]

Если устройство EEPROM все еще занято записью одной или нескольких ячеек после предыдущего запроса на запись, оно просто оставит свои драйверы интерфейса шины с высоким импедансом и никак не отреагирует на выбор. Мастер, выбирающий устройство, увидит высокий уровень в SDA после передачи пакета SLA+R/W в качестве NACK на его запрос выбора. Таким образом, процесс выбора просто запускается заново (фактически вызывая повторяющееся условие запуска) до тех пор, пока устройство в конце концов не ответит. Эта процедура опроса рекомендуется в техническом описании 24Cxx, чтобы свести к минимуму время ожидания при записи. Обратите внимание, что если устройство сломано и никогда не отвечает на выбор (например, поскольку его вообще больше нет), это вызовет бесконечный цикл. Таким образом, максимальное количество итераций, выполняемых до тех пор, пока устройство не будет объявлено как не отвечающее вообще, и не будет возвращена ошибка, будет ограничено MAX_ITER.

Примечание [12]

Это называется режимом ведущего приемника : ведущее устройство шины по-прежнему поставляет часы SCL, но ведомое устройство управляет линией SDA с соответствующими данными. После 8 битов данных мастер отвечает битом ACK (SDA установлен на низкий уровень), чтобы запросить еще одну передачу данных от ведомого, или он может оставить линию SDA на высоком уровне (NACK), указывая ведомому, что он собирается остановиться. передача сейчас. Подтверждение ACK обрабатывается установкой бита TWEA в TWCR при запуске текущей передачи.

Примечание [13]

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

Примечание [14]

За исключением случая проигрыша арбитража, все транзакции шины должны быть должным образом завершены мастером, инициирующим условие остановки.

Примечание [15]

Запись в устройство EEPROM проще, чем чтение, так как требуется только передача режима ведущего передатчика. Обратите внимание, что первый пакет после выбора SLA+W всегда считается адресом EEPROM для следующей операции. (Этот пакет точно такой же, как тот, что был отправлен перед началом чтения устройства.) адрес. Внутренний указатель адреса будет увеличиваться после каждой операции записи.

Примечание [16]

Устройства 24Cxx могут быть защищены от записи путем привязки их вывода ~WC к высокому логическому уровню. (Оставлять его неподключенным явно разрешено и представляет собой логический низкий уровень, т. е. отсутствие защиты от записи.) В случае устройства, защищенного от записи, все попытки передачи данных будут отвергнуты устройством. Обратите внимание, что некоторые устройства могут не реализовать это.

avr — разъяснение I2C

Изменено 2 года, 8 месяцев назад

Просмотрено 87 раз

\$\начало группы\$

Этот вопрос в основном для того, чтобы проверить, правильно ли я понял протокол i2c и оборудование. Поскольку режимы пинов меня немного сбивают с толку, я просто новичок.

  1. Линии I2C SDA и SCL подключены к высокому уровню с помощью подтягивающего резистора. В моем случае я использую резистор 4k.
  2. Мастер замыкает линию SDA на землю и после этого начинает синхронизацию на линии SCL, и это называется условием запуска.
  3. Мастер отправляет подчиненному адрес и бит чтения/записи.

Вот что меня смущает.

  1. Мастер перенастраивает контакт SDA в режим ввода для получения бита ACK, в то время как подчиненный перенастраивает свой входной контакт на выходной контакт и подключает линию SDA к земле для отправки и бита ACK.

И то же самое повторяется с остальными байтами до тех пор, пока не будет выполнено условие остановки. Вопрос в том, действительно ли вывод перенастроен с выхода на вход на мастере, чтобы прочитать бит ACK, или есть какие-то другие механизмы, о которых я не знаю?

Из того, что я прочитал на форумах AVR, я могу сделать следующее: В случае, если мой контакт SDA находится на PB0, чтобы сделать его высоким, я бы переключил PB0 на вход без внутреннего подтягивания (оставляет его плавающим). Чтобы сделать контакт низким, я бы установил его на низкий уровень вывода. Пока я в режиме ввода, я также могу считывать ввод с того же вывода.

Пожалуйста, поправьте меня, если я ошибаюсь.

  • авр
  • i2c

\$\конечная группа\$

\$\начало группы\$

I²C имеет два состояния на линиях SCL/SDA. Слабый высокий уровень и сильный низкий уровень. Чтобы добиться этого с помощью битового удара, установите выходной регистр в низкий уровень и оставьте его в покое позже.

Всегда переключайте регистр направления данных SCL/SDA только между входом/слабым высоким уровнем и выходом/сильным низким уровнем.

Для SCL вы должны сделать то же самое, что и для SDA, потому что ведомое устройство может выбрать низкий уровень на линии SCL для увеличения тактовой частоты. Вы должны отпустить часы, а затем проверить, отпустил ли их ведомый. Отсутствие должной поддержки растяжения тактовой частоты является ошибкой, обнаруженной даже в профессиональных хостах I²C, реализованных на аппаратном уровне.

Большинство контроллеров AVR имеют встроенный аппаратный контроллер хоста/устройства I²C, и это один из немногих правильно реализованных контроллеров. Вам не нужно битить I²C на этих контроллерах. Проверьте техническое описание.

\$\конечная группа\$

3

\$\начало группы\$

I2C в качестве стандартного протокола будет иметь специальные аппаратные блоки, которые будут использоваться для синхронизации битов и соответствия протоколу.

Кажется, вы немного качаете протокол I2C вручную. Для высокого импеданса, как вы сказали, сделать вход без внутренних подтягиваний и понижений — это нормально.

  • I2C — это сложный протокол, который необходимо реализовать вручную, но при этом он поддерживает все необходимые функции

  • Если ведомые контроллеры представляют собой простое устройство (датчик или дисплей), то будет проще

  • Сценарий с несколькими мастерами и некоторые известные состояния ошибок являются проблемами, будут ограничениями

  • Пожалуйста, также сделайте сброс ведомого устройства, если это возможно

\$\конечная группа\$

1

\$\начало группы\$

Вот хороший ресурс — https://learn. sparkfun.com/tutorials/i2c. Там вы можете увидеть, что выходов с открытым стоком входов ) соединены параллельно в так называемое проводное ИЛИ .

\$\конечная группа\$

2

Твой ответ

Зарегистрируйтесь или войдите в систему

Зарегистрируйтесь с помощью Google

Зарегистрироваться через Facebook

Зарегистрируйтесь, используя электронную почту и пароль

Опубликовать как гость

Электронная почта

Требуется, но никогда не отображается

Опубликовать как гость

Электронная почта

Требуется, но не отображается

Нажимая «Опубликовать свой ответ», вы соглашаетесь с нашими условиями обслуживания, политикой конфиденциальности и политикой использования файлов cookie

I2C Register Описание : Arduino / ATmega328p

Примечание

Эта статья является частью Arduino / ATmega328p Embedded C Firmware Programming Tutorial . Подумайте о том, чтобы изучить домашнюю страницу курса и найти статьи на похожие темы.

Учебное пособие по Arduino. Мастер-класс Arduino на уровне встроенного регистра C

Также посетите страницу выпуска .0324 .

Введение

Аппаратное обеспечение двухпроводного последовательного интерфейса (TWI) I2C в микроконтроллере ATmega48A/PA/88A/PA/168A/PA/328/P использует регистры TWBR, TWCR, TWSR, TWDR, TWAR и TWAMR для настроить аппаратное обеспечение и для передачи и получения данных. Ниже приведены описания регистров. Atmel использует термин TWI/двухпроводной интерфейс для избежания лицензионных конфликтов. TWI совместим с протоколом I2C.

Конфигурация регистра AVR I2C

Что вы узнаете

  • Что такое регистры I2C в Arduino?
  • Что такое регистры I2C в AVR ATmega328p?
  • Какие регистры AVR управляют и настраивают I2C/TWI/двухпроводной интерфейс?
  • Какова функция регистров AVR I2C?

TWBR – TWI Bit Rate Register

Bit 7 6 5 4 3 2 1 0
0xB8 TWBR7 TWBR6 TWBR5 TWBR4 TWBR3 TWBR2 TWBR1 SPR0
Read/Write R/W R/W R/W R/W R/W R/W R/W R/W
Initial Value 0 0 0 0 0 0 0 0

• Биты 7…0 – Регистр скорости передачи данных TWI
TWBR выбирает коэффициент деления для генератора скорости передачи данных. Генератор битрейта представляет собой делитель частоты, который генерирует тактовую частоту SCL в режимах Master.
SCL Частота = тактовая частота CPU / (16 + 2 * TWBR * PRESCALERVALUE)

TWCR — TWI Control Register

BIT 7 6 5 7 6 5 7 6 5 6 5 7 6 5 7 6 5 7 1 0
0xBC TWINT TWEA TWSTA TWSTO TWWC TWEN TWIE
Read/Write R/W R/W R/ W R/W R/W R/W R/W R/W
Initial Value 0 0 0 0 0 0 0 0

TWCR используется для управления работой I2C/TWI. Он используется для включения I2C/TWI, для инициирования доступа Master путем применения к шине условия START, для генерации подтверждения Receiver, для генерации условия STOP и для управления коллизиями шины.

• Бит 7 — TWINT: флаг прерывания TWI
Этот бит устанавливается аппаратно, когда TWI завершил свою текущую работу и ожидает ответа прикладного программного обеспечения. Когда флаг TWINT установлен, период SCL LOW растягивается. Флаг TWINT должен быть очищен программой путем записи в него логической единицы. Этот флаг не сбрасывается аппаратно автоматически при выполнении процедуры обработки прерывания. Сброс этого флага возобновляет работу TWI.

• Бит 6 – TWEA: Бит подтверждения включения TWI
Бит TWEA управляет генерацией импульса подтверждения. Если бит TWEA записан в единицу, импульс ACK формируется на шине TWI при выполнении следующих условий:
1. Принят собственный адрес ведомого устройства
2. Принят общий вызов, при этом бит TWGCE в TWAR установлен
3. Байт данных был получен в режиме ведущего приемника или ведомого приемника
Записав бит TWEA в ноль, устройство может быть временно отключено от 2-проводной последовательной шины.

• Бит 5 – TWSTA: бит условия запуска TWI
Прикладному программному обеспечению необходимо записать бит TWSTA в единицу, когда оно хочет стать ведущим на 2-проводной последовательной шине. Аппаратное обеспечение TWI генерирует состояние START на шине, если она свободна. Если шина не свободна, TWI ждет, пока не будет обнаружено состояние STOP, а затем генерирует новое условие START, чтобы заявить о статусе мастера шины. TWSTA должен быть очищен программным обеспечением, когда было передано условие START.

• Бит 4 – TWSTO: Бит условия STOP TWI
Когда бит TWSTO установлен, аппаратное обеспечение TWi генерирует состояние STOP на 2-проводной шине. Когда на шине выполняется условие STOP, бит TWSTO автоматически сбрасывается. В ведомом режиме установка бита TWSTO используется для восстановления после состояния ошибки. Это переводит линии SCL и SDA в состояние высокого импеданса.

• Бит 3 — TWWC: флаг конфликта записи TWI
Бит TWWC устанавливается при попытке записи в регистр данных TWI — TWDR, когда TWINT имеет низкий уровень. Этот флаг очищается записью в регистр TWDR, когда TWINT имеет высокий уровень.

• Бит 2 — TWEN: Бит включения TWI
Бит TWEN включает работу I2C/TWI и активирует интерфейс TWI. Если этот бит равен нулю, TWI выключается и все передачи TWI прекращаются, независимо от текущей операции.

• Бит 1 – зарезервировано
Этот бит зарезервирован и всегда будет считываться как ноль.

• Бит 0 – TWIE: Разрешение прерывания TWI
Когда этот бит равен единице, а I-бит в SREG установлен, прерывание TWI разрешено.

TWSR – TWI Status Register

Bit 7 6 5 4 3 2 1 0
(0xB9) TWS7 TWS6 TWS5 TWS4 TWS3 TWPS1 TWPS0
Read/Write R R R R R R R/W R/W
Initial Value 1 1 1 1 1 1 1 1

• Bits 7 :3 – TWS: Состояние TWI
Эти 5 бит отражают состояние логики TWI и 2-проводной последовательной шины.

• Бит 2 – зарезервировано
Этот бит зарезервирован и всегда будет считываться как ноль.

• Биты 1:0 – TWPS: Биты 9 предварительного делителя TWI0324
These bits can be read and written, and control the bit rate Prescaler

.0355 Bit
TWPS1 TWPS0 Prescaler Value
0 0 1
0 1 4
1 0 16
1 1 64
64
64
64
64 7 6 5 4 3 2 1 0
(0xBB) TWD7 TWD6 TWD5 TWD4 TWD3 TWD2 TWD1 TWD0
Read/Write R/W R/W R/W R/W R/W R/W R/W Ч/З
Начальное значение 1 1 1 1 1 1 1 1
1 1
1 1
. В режиме приема TWDR содержит последний полученный байт. Данные могут быть записаны, когда флаг прерывания TWI (TWINT) установлен аппаратно. Данные в TWDR остаются стабильными, пока установлен TWINT. В то время как данные перемещаются по шине. В случае потери арбитража шины данные не теряются при переходе от ведущего к ведомому. Обработка бита ACK автоматически контролируется логикой TWI, ЦП не может получить прямой доступ к биту ACK.

• Биты 7:0 – TWD: Регистр данных TWI
Эти восемь битов составляют следующий байт данных, который должен быть передан, или последний байт данных, полученный по 2-проводной последовательной шине.

TWAR – TWI (Slave) Address Register

Bit 7 6 5 4 3 2 1 0
(0xBA) TWA6 TWA5 TWA4 TWA3 TWA2 TWA1 TWA0 TWGCE
Read/Write R/W R/W R/W R/W R/W R/W R/W R/W
Initial Value 1 1 1 1 1 1 1 0

The TWAR should be loaded с 7-битным адресом ведомого (в семи старших битах TWAR), на который будет реагировать TWI, когда он запрограммирован как ведомый передатчик или приемник, и не требуется в режимах ведущего. В
мультимастер-системы, необходимо установить TWAR.

• Биты 7:1 – TWA: регистр адреса TWI (подчиненного)
Эти семь бит составляют адрес подчиненного устройства TWI.


• Бит 0 – TWGCE: Бит разрешения общего распознавания вызова TWI
Если установлен, этот бит разрешает распознавание общего вызова, переданного по 2-проводной последовательной шине.

TWAMR – Регистр маски адреса TWI (подчиненный)

.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Бит 7 6 5 4 3 2 1 0
(0xBA) TWAM6 TWAM5 TWAM4 TWAM3 TWAM2 TWAM1 TWAM0
Read/Write R/W R/W R/W R/W R/W R/W R/W R/W
Исходное значение 0 0 0 0 0 0