С помощью шины 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 расширителя порта.
Значение, скопированное в регистр, вычисляется компилятором. Это делается с помощью «#define»:
Теперь, когда мастер настроен, я расскажу вам, как вы можете обращаться к ведомому устройству.
Передача данных на PCF8574:
Связь между ведущим PCF857 происходит в два этапа.
Во-первых, адрес передается для адресации соответствующего подчиненного устройства, а затем данные передаются ведомому устройству.
Адрес PCF8574 у меня есть в начале программы: #define PCF8574 0x20
Это всего лишь 7 бит адреса PCF8574. Бит R / W еще не включен. Этот бит будет добавлен позже программой.
Функция, которая записывает данные в PCF8574, выглядит так:
Сначала: Send_Address(&TWIF, Adresse, 0);
вызывается другой функцией, которая берет на себя отправку адреса.
Эта функция получает имя используемого интерфейса I²C (& TWIF), адрес PCF8574 (помечен указателем «Адрес»), «0» при записи на ведомый или «1» при чтении с подчиненого.
Давайте подробнее рассмотрим функцию отправки адреса. Она выглядит так:
Затем битовая диаграмма адреса, переданного функции, которая находится в переменной «Adress», копируется в переменную «Add». Битовая диаграмма переменной «Add» сдвигается на один бит влево на следующем шаге, а затем проверяется, был ли установлен бит RW.
Поскольку адрес всегда округлен до 0, последний бит никогда не может быть установлен. Это гарантирует, что бит R / W всегда равен 0 при записи. И наоборот, команда с 1 гарантирует, что бит всегда установлен.
Результатом является адрес подчиненного устройства вместе с битом R / W. Затем этот адрес помещается в регистр адресов желаемого интерфейса I²C и затем отправляется.
Это выглядит так:
Там программа длится 500 мкс, чтобы дать контроллеру и устройству достаточно времени для обработки данных.
Считывание данных с PCF8574:
Чтение данных с PCF8574 аналогично записи. Прежде всего, адрес устройства передается, только на этот раз должен быть установлен бит R / W, т. Е. Адрес увеличивается на единицу.
О функции отправки переданного адреса выглядит так:
Запись: Send_Address (twi, address, 0);
Чтение: Send_Address (twi, address, 1);
Затем данные считываются с помощью этой функции:
Теперь вы можете использовать строку данных
Преимуществом 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_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, выглядит так:
Она получает имя интерфейса I²C, которое будет использоваться в качестве параметра передачи, адрес подчиненного устройства и 1 байт данных для отправки.void PCF8574_send_byte(TWI_t *twi, char Adresse, char byte)
{
Send_Address(twi, Adresse, 0);
_delay_us(500);
twi->MASTER.DATA = byte;
}
Сначала: 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.
Результатом является адрес подчиненного устройства вместе с битом R / W. Затем этот адрес помещается в регистр адресов желаемого интерфейса I²C и затем отправляется.
Это выглядит так:
twi->MASTER.ADDR = Add;После отправки адреса контроллер переходит к первой функции.
Там программа длится 500 мкс, чтобы дать контроллеру и устройству достаточно времени для обработки данных.
twi->MASTER.DATA = byte;Скопируйте переданный байт данных в регистр данных I²C, помеченный указателем «twi», и отправьте байт.
Чтение данных с 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;
0 коммент.:
Отправить комментарий