- Что такое протокол связи I2C?
- Как работает связь I2C?
- Где использовать связь I2C?
- I2C с PIC16F877a с использованием XC8 Compiler
- Программирование с использованием файлов заголовков I2C:
- Моделирование Протея:
Микроконтроллеры PIC - это мощная платформа, предоставляемая микрочипом для встраиваемых проектов, ее универсальный характер позволил найти пути во многие приложения, и эта фаза все еще продолжается. Если вы следовали нашим руководствам по PIC, то вы бы заметили, что мы уже рассмотрели широкий спектр руководств по микроконтроллерам PIC, начиная с самых основ. С этого момента мы рассмотрели основы и можем перейти к более интересным вещам, таким как коммуникационный портал.
В огромной системе встроенных приложений ни один микроконтроллер не может выполнять все действия самостоятельно. На определенном этапе он должен связаться с другими устройствами для обмена информацией, существует множество различных типов протоколов связи для обмена этой информацией, но наиболее часто используемые из них - это USART, IIC, SPI и CAN. У каждого протокола связи есть свои преимущества и недостатки. Давайте сосредоточимся на части IIC, так как это то, что мы собираемся изучить в этом руководстве.
Что такое протокол связи I2C?
Термин IIC расшифровывается как « Inter Integrated Circuits ». Обычно он обозначается как I2C, или я в квадрате C, или даже как протокол 2-проводного интерфейса (TWI) в некоторых местах, но все это означает то же самое. I2C - это протокол синхронной связи, означающий, что оба устройства, которые обмениваются информацией, должны использовать общий тактовый сигнал. У него есть только два провода для обмена информацией, один из которых используется для сигнала петли, а другой - для отправки и приема данных.
Как работает связь I2C?
Связь I2C была впервые представлена Филлипсом. Как было сказано ранее, у него два провода, эти два провода будут подключены к двум устройствам. Здесь одно устройство называется ведущим, а другое - ведомым. Связь должна и всегда будет происходить между двумя ведущим и ведомым. Преимущество связи I2C в том, что к ведущему можно подключить более одного ведомого устройства.
Полная связь осуществляется через эти два провода, а именно последовательные часы (SCL) и последовательные данные (SDA).
Последовательные часы (SCL): разделяет тактовый сигнал, генерируемый ведущим устройством, с ведомым устройством
Последовательные данные (SDA): отправляет данные между ведущим и ведомым.
В любой момент времени только мастер может инициировать обмен данными. Поскольку на шине более одного ведомого устройства, ведущее устройство должно обращаться к каждому ведомому устройству, используя другой адрес. При обращении только мазь с этим конкретным адресом ответит с информацией, в то время как другие продолжат выход. Таким образом, мы можем использовать одну и ту же шину для связи с несколькими устройствами.
Где использовать связь I2C?
Связь I2C используется только для связи на короткие расстояния. Он определенно надежен до некоторой степени, так как он имеет синхронизированный тактовый импульс, что делает его умным. Этот протокол в основном используется для связи с датчиком или другими устройствами, которые должны отправлять информацию мастеру. Это очень удобно, когда микроконтроллер должен взаимодействовать со многими другими подчиненными модулями, используя как минимум только провода. Если вы ищете связь на большие расстояния, вам следует попробовать RS232, а если вы ищете более надежную связь, вам следует попробовать протокол SPI.
I2C с PIC16F877a с использованием XC8 Compiler
Хватит представлений, давайте перейдем к этому и узнаем, как мы можем использовать микроконтроллер для выполнения связи I2C. Прежде чем мы начнем, проясним, что в этом руководстве рассказывается только о I2C в PIC16F877a с использованием компилятора XC8, процесс будет таким же для других микроконтроллеров, но могут потребоваться небольшие изменения. Также помните, что для продвинутых микроконтроллеров, таких как серия PIC18F, сам компилятор может иметь некоторую встроенную библиотеку для использования функций I2C, но для PIC16F877A ничего подобного не существует, поэтому давайте создадим ее самостоятельно. Библиотека, описанная здесь, будет представлена в виде файла заголовка для загрузки внизу, который можно использовать для PIC16F877A для связи с другими устройствами I2C.
Как всегда, лучше всего начать с нашей таблицы данных. Поищите подробную информацию о I2C в таблице данных и проверьте, какие регистры необходимо настроить. Я не собираюсь подробно объяснять, так как таблица уже сделала это за вас. Ниже я объясню различные функции, присутствующие в файле заголовка, и их ответственность в программе.
пусто I2C_Initialize ()
Функция инициализации используется, чтобы сообщить микроконтроллеру, что мы собираемся использовать протокол I2C. Это можно сделать, установив необходимые биты в регистрах SSPCON и SSPCON2. Первым шагом было бы объявить выводы IIC как входные, здесь выводы RC3 и RC4 должны использоваться для связи I2C, поэтому мы объявляем их как входные выводы. Затем мы должны установить SSPCON и SSPCON2, которые являются регистрами управления MSSP. Мы работаем с PIC в режиме ведущего IIC с тактовой частотой FOSC / (4 * (SSPADD + 1)). Обратитесь к номерам страниц таблицы данных, упомянутым в строках комментариев ниже, чтобы понять, почему этот конкретный регистр установлен таким образом.
Итак, теперь мы должны установить тактовую частоту, тактовая частота для разных приложений может отличаться, поэтому мы получаем выбор от пользователя через переменную feq_k и используем ее в наших формулах для установки регистра SSPADD.
void I2C_Initialize (const unsigned long feq_K) // Начинаем IIC как мастер { TRISC3 = 1; TRISC4 = 1; // Установить контакты SDA и SCL как входные SSPCON = 0b00101000; // pg84 / 234 SSPCON2 = 0b00000000; // pg85 / 234 SSPADD = (_XTAL_FREQ / (4 * feq_K * 100)) - 1; // Установка тактовой частоты pg99 / 234 SSPSTAT = 0b00000000; // pg83 / 234 }
Пустота I2C_Hold ()
Следующая важная функция - это функция I2C_hold, которая используется для удержания выполнения устройства до завершения текущей операции I2C. Нам нужно будет проверить, нужно ли удерживать операции I2C, прежде чем начинать любую новую операцию. Это можно сделать, проверив регистры SSPSTAT и SSPCON2. SSPSTAT содержит информацию о состоянии шины I2C.
Программа может показаться немного сложной, поскольку в ней используются операторы «и» и «или». Когда вы сломаете его как
SSPSTAT и 0b00000100 SSPCON2 и 0b00011111
Взаимодействие с другими людьми
Это означает, что мы проверяем , что 2- й бит в SSPSTAT равен нулю, и точно так же биты от 0 до 4 равны нулю в SSPCON2. Затем мы объединяем все это, чтобы проверить нулевой результат. Если результат равен нулю, то программа будет продолжаться, если не будет держать там до тех пор, пока он получает ноль, так как он используется в то время как цикл.
void I2C_Hold () { while ((SSPCON2 & 0b00011111) - (SSPSTAT & 0b00000100)); // проверяем это в регистрах, чтобы убедиться, что IIC не выполняется }
Пустота I2C_Begin () и пустота I2C_End ()
Каждый раз, когда мы пишем или читаем какие-либо данные с помощью шины I2C, мы должны начинать и заканчивать соединение I2C. Чтобы начать коммуникацию I2C, мы должны установить бит SEN, а для завершения коммуникации мы должны установить бит статуса PEN. Перед переключением любого из этих битов мы также должны проверить, занята ли шина I2C, используя функцию I2C_Hold, как описано выше.
void I2C_Begin () { I2C_Hold (); // Удерживать программу, если I2C занят SEN = 1; // Начать IIC pg85 / 234 } void I2C_End () { I2C_Hold (); // Удерживать программу, если I2C занят PEN = 1; // Конец IIC pg85 / 234 }
Пустота I2C_Write ()
Функция записи используется для отправки любых данных из главного модуля в модуль salve. Эта функция обычно используется после функции начала I2C, за которой следует функция конца I2C. Данные, которые должны быть записаны в шину IIC, передаются через переменные данные. Затем эти данные загружаются в буферный регистр SSPBUF, чтобы отправить их по шине I2C.
Обычно перед записью данных адрес записывается, поэтому вам придется использовать функцию записи дважды: один раз для установки адреса, а второй раз для отправки фактических данных.
void I2C_Write (данные без знака) { I2C_Hold (); // Удерживать программу, если I2C занят SSPBUF = data; // pg82 / 234 }
беззнаковый короткий I2C_Read ()
Последняя функция, о которой мы должны знать, - это функция I2C_Read . Эта функция используется для чтения данных, которые в настоящее время находятся на шине I2C. Он используется после запроса ведомого устройства о записи некоторого значения в шину. Полученное значение будет в SSPBUF, мы можем передать это значение любой переменной для нашей операции.
Во время связи I2C подчиненное устройство после отправки данных, запрошенных мастером, отправит другой бит, который является битом подтверждения, этот бит также должен быть проверен мастером, чтобы убедиться, что связь была успешной. После проверки бита ACKDT для подтверждения его следует включить, установив бит ACKEN.
unsigned short I2C_Read (unsigned short ack) { беззнаковый короткий входящий; I2C_Hold (); RCEN = 1; I2C_Hold (); входящий = SSPBUF; // получаем данные, сохраненные в SSPBUF I2C_Hold (); ACKDT = (подтверждение)? 0: 1; // проверяем, получен ли бит подтверждения ACKEN = 1; // стр. 85/234 return incoming; }
То есть этих функций должно быть достаточно для настройки связи I2C и записи или чтения данных с устройства. Также обратите внимание, что существует множество других функций, которые может выполнять связь I2C, но для простоты мы не обсуждаем их здесь. Вы всегда можете обратиться к техническому описанию, чтобы узнать полную работу
Полный код с файлом заголовка для связи PIC16F877A I2C можно скачать по ссылке.
Программирование с использованием файлов заголовков I2C:
Теперь, когда мы узнали, как работает связь I2C и как мы можем использовать созданный для нее файл заголовка, давайте создадим простую программу, в которой мы будем использовать файл заголовка и записывать некоторые значения в строки I2C. Затем мы смоделируем эту программу и проверим, записываются ли эти значения на шину.
Как всегда, программа начинается с установки битов конфигурации и установки тактовой частоты на 20 МГц, как показано ниже.
#pragma config FOSC = HS // Биты выбора осциллятора (генератор HS) #pragma config WDTE = OFF // Бит включения сторожевого таймера (WDT отключен) #pragma config PWRTE = ON // Бит включения таймера включения (PWRT включен) # pragma config BOREN = ON // Бит разрешения сброса пониженного напряжения (BOR включен) #pragma config LVP = OFF // Бит разрешения последовательного программирования низкого напряжения (однополярный) (RB3 - это цифровой ввод / вывод, высокое напряжение включено Для программирования необходимо использовать MCLR) #pragma config CPD = OFF // Бит защиты кода памяти EEPROM данных (защита кода EEPROM данных отключена) #pragma config WRT = OFF // Биты разрешения записи в память программы Flash (защита от записи отключена; вся программная память может быть записано в управление EECON) #pragma config CP = OFF // Бит защиты кода флэш-памяти программы (защита кода выключена) #define _XTAL_FREQ 20000000
Следующим шагом будет добавление файла заголовка, о котором мы только что говорили. Заголовочный файл называется PIC16F877a_I2C.h и может быть загружен по указанной выше ссылке. Убедитесь, что файл заголовка добавлен в файл заголовка вашего списка проектов, структура файла вашего проекта должна выглядеть следующим образом
Убедившись, что файл заголовка добавлен в файл проекта, включите файл заголовка в основной файл C
#включают
Внутри в то время цикла мы начнем с I2C связи записи несколько случайных значений к шине I2C, а затем Завершение I2C связи. Я выбрал случайные значения D0, 88 и FF. Вы можете ввести любые значения, которые хотите. Но запомните эти значения, поскольку мы будем проверять их в нашей симуляции.
пока (1) { I2C_Begin (); I2C_Write (0xD0); I2C_Write (0x88); I2C_Write (0xFF); I2C_End (); __delay_ms (1000); }
Полная программа может быть найдена в нижней части страницы, вы можете использовать его или загрузить полный почтовый файл программы здесь. После получения программы скомпилируйте ее и приготовьтесь к моделированию.
Моделирование Протея:
У Proteus есть хороший инструмент, называемый отладчиком I2C, который можно использовать для чтения данных на шине I2C, поэтому давайте построим схему, используя его, и проверим, успешно ли записываются данные. Полная принципиальная схема показана ниже.
Загрузите шестнадцатеричный файл, созданный нашей программой, двойным щелчком по микроконтроллеру. Затем смоделируйте программу. Вы увидите всплывающее окно, в котором будет отображаться вся информация о шине I2C. Окно нашей программы показано ниже.
Если вы внимательно посмотрите на записываемые данные, вы можете заметить, что они такие же, как мы написали в нашей программе. Значения - D0, 88 и FF. Значения записываются для каждой 1 секунды, поэтому время также обновляется, как показано ниже. Синяя стрелка указывает, что запись передается от ведущего к ведомому, в противном случае она указывала бы в противоположном направлении. Ниже показан более подробный вид отправляемых данных.
Это всего лишь беглое представление о том, что умеет I2C, он также может читать и записывать данные на несколько устройств. Мы расскажем больше о I2C в наших следующих уроках, сопоставляя различные модули, которые работают с протоколом I2C.
Надеюсь, вы поняли проект и узнали из него что-то полезное. Если у вас есть какие-либо сомнения, опубликуйте их в разделе комментариев ниже или воспользуйтесь форумом для получения технической помощи.
Полный код приведен ниже; вы можете скачать файлы заголовков со всем кодом отсюда.