I2C в Xmega

    С помощью шины I²C XMega может взаимодействовать с другими периферийными устройствами (например, EEPROM, датчиками и т. д.).
    Преимуществом I²C является то, что ему нужны только два провода (SDA и SCL).
    Обычно шина всегда состоит из мастера, и подчиненных (от 0 до максимум 127).
    Шина I²C:
    Прежде чем перейти в программу, я кратко объясню, как работает шина I²C.
    Шина I²C (или Inter-Integrated Circuit) представляет собой двунаправленную двухпроводную шину, что означает, что шина имеет только две сигнальные линии, и нет никакого фиксированного направления для передачи данных (в отличие от UART).
    Он состоит из двух линий, называемых SCL (Serial Clock) и SDA (Serial Data). Выводы SCL и SDA устройства I²C с открытым коллектором, поэтому необходимо вывести шину на определенный уровень с помощью подтягивающих резисторов.
    Каждый пользователь шины имеет свой собственный адрес, который делится на фиксированный базовый адрес и переменный адрес. Поэтому для многих устройств I²C адрес может быть изменен с помощью конкретных контактов адреса, так что несколько микросхем с одним и тем же базовым адресом могут быть подключены к одной шине.
    Обычно адрес имеет длину 7 бит. Кроме того, имеется 8-й бит, который сигнализирует, следует ли считывать I²C или записывать ли данные в I²C регистр.
    Обычно шина имеет ведущего (в основном, микроконтроллер) и до 127 ведомых (EEPROM, датчики и т. д.), Но также возможно реализовать несколько мастеров в одной шине.
    Типичная шина I²C выглядит так:

    XMega как мастер I²C:
    Во-первых, я покажу вам, как настроить I²C в XMega так, чтобы он работал мастером.
В моем примере я использую расширитель портов PCF8574 I²C, и программа включает и выключает светодиод, расположенный на выводе P0 расширителя порта.
    Чтобы настроить I²C XMega, я использую эту функцию:
void TWI_MasterInit(TWI_t *twi)
{
twi->MASTER.BAUD = TWI_BAUDSETTING;
twi->MASTER.CTRLA = TWI_MASTER_ENABLE_bm |
TWI_MASTER_INTLVL_HI_gc |
TWI_MASTER_RIEN_bm |
TWI_MASTER_WIEN_bm;
twi->MASTER.STATUS = TWI_MASTER_BUSSTATE_IDLE_gc;
}
    Первая строка функции копирует желаемую скорость передачи в регистр скорости передачи.
Значение, скопированное в регистр, вычисляется компилятором. Это делается с помощью «#define»:
#define Taktfreuqenz 32000000
#define Takt_TWI 400000
#define TWI_BAUD(F_SYS, F_TWI) ((F_SYS / (2 * F_TWI)) - 5)
#define TWI_BAUDRATE TWI_BAUD(Taktfrequenz, Takt_TWI)

    Во-первых, я определяю переменную «Taktfrequenz» и даю ей текущую частоту микроконтроллера (в моем случае 32 МГц).  Следующая строка определяет переменную «Clock_TWI» и получает значение требуемой тактовой частоты для I²C. В моем примере это значение 400 кГц.  Теперь определена переменная «TWI_BAUD».  Значение этой переменной рассчитывается на основе формулы, приведенной в даташите:  ((F_SYS / (2 * F_TWI)) - 5)
    Переменные «F_SYS» и «F_TWI» являются двумя локальными переменными.
Таким образом, определена функция, которая называется «TWI_BAUD» и которая ожидает два значения в качестве параметров передачи, которые называются «F_SYS» и «F_TWI» внутри функции.
Последняя строка определяет переменную с именем «TWI_BAUDRATE», которая принимает в качестве значения результат функции «TWI_Baud», которая передает значения из переменных «Clock Frequency» и «Clock_TWI».  Это значение затем используется:
twi->MASTER.BAUD = TWI_BAUDRATE;

    Затем XMega переводится в главный режим и активируются оба режима чтения и записи:
twi->MASTER.CTRLA = TWI_MASTER_ENABLE_bm |
TWI_MASTER_INTLVL_HI_gc | TWI_MASTER_RIEN_bm |
TWI_MASTER_WIEN_bm;
    Наконец, шина должна быть переведена в режим ожидания. Это происходит следующим образом:
twi->MASTER.STATUS = TWI_MASTER_BUSSTATE_IDLE_gc;

    Это очень важно, потому что I²C после сброса только в состоянии «Unknown» изменяется и в состоянии «Unknown» может быть прочитано или записано на шине.

    Теперь, когда мастер настроен, я расскажу вам, как вы можете обращаться к ведомому устройству.
    Передача данных на PCF8574:
    Связь между ведущим PCF857  происходит в два этапа.
    Во-первых, адрес передается для адресации соответствующего подчиненного устройства, а затем данные передаются ведомому устройству.
    Адрес PCF8574 у меня есть в начале программы:    #define PCF8574 0x20

    Это всего лишь 7 бит адреса PCF8574. Бит R / W еще не включен. Этот бит будет добавлен позже программой.
    Функция, которая записывает данные в PCF8574, выглядит так:
void PCF8574_send_byte(TWI_t *twi, char Adresse, char byte)
{
Send_Address(twi, Adresse, 0);
_delay_us(500);
twi->MASTER.DATA = byte;
}
    Она получает имя интерфейса I²C, которое будет использоваться в качестве параметра передачи, адрес подчиненного устройства и 1 байт данных для отправки.
Сначала: Send_Address(&TWIF, Adresse, 0);

вызывается другой функцией, которая берет на себя отправку адреса.
Эта функция получает имя используемого интерфейса I²C (& TWIF), адрес PCF8574 (помечен указателем «Адрес»), «0» при записи на ведомый или «1» при чтении с подчиненого.
Давайте подробнее рассмотрим функцию отправки адреса. Она выглядит так:
void Send_Address(TWI_t *twi, char Adresse, char RW)
{
twi->MASTER.ADDR = (Adresse << 1) + RW;
}

    Прежде всего объявляется локальная переменная с именем «Add». Впоследствии это должно иметь полный адрес подчиненного устройства.
    Затем битовая диаграмма адреса, переданного функции, которая находится в переменной «Adress», копируется в переменную «Add». Битовая диаграмма переменной «Add» сдвигается на один бит влево на следующем шаге, а затем проверяется, был ли установлен бит RW.

    Поскольку адрес всегда округлен до 0, последний бит никогда не может быть установлен. Это гарантирует, что бит R / W всегда равен 0 при записи.  И наоборот, команда с 1 гарантирует, что бит всегда установлен.
    Результатом является адрес подчиненного устройства вместе с битом R / W. Затем этот адрес помещается в регистр адресов желаемого интерфейса I²C и затем отправляется.
    Это выглядит так:
twi->MASTER.ADDR = Add;

    После отправки адреса контроллер переходит к первой функции.
   Там программа длится 500 мкс, чтобы дать контроллеру и устройству достаточно времени для обработки данных.
twi->MASTER.DATA = byte;

    Скопируйте переданный байт данных в регистр данных I²C, помеченный указателем «twi», и отправьте байт.

Считывание данных с PCF8574:

     Чтение данных с PCF8574 аналогично записи.  Прежде всего, адрес устройства передается, только на этот раз должен быть установлен бит R / W, т. Е. Адрес увеличивается на единицу.
О функции отправки переданного адреса выглядит так:

Запись: Send_Address (twi, address, 0);
Чтение:  Send_Address (twi, address, 1);

Затем данные считываются с помощью этой функции:
char PCF8574_read_byte(TWI_t *twi, char *Adresse)
{
Send_Address(twi, Adresse, 1);
_delay_us(500);
twi->MASTER.CTRLC = TWI_MASTER_CMD_STOP_gc;
return twi->MASTER.DATA;
}

После передачи адреса чтения PCF8574 выводит один байт данных на шину. Он считываются микроконтроллером и сохраняются в регистре данных.
twi->MASTER.CTRLC = TWI_MASTER_CMD_STOP_gc;

Здесь отправляем условие остановки, так что PCF8574 знает, что передача завершена.
Теперь вы можете использовать строку данных
return twi->MASTER.DATA;
    Blogger Comment
    Facebook Comment

0 коммент.:

Отправить комментарий