PIC Урок 22. MSSP. I2C. Slave. Соединяем два микроконтроллера. Часть 1



Попытаемся теперь настроить наш модуль MSSP в режиме I2С, но уже в качестве ведомого устройства. Возможно, что когда-то мы встретимся с ситуацией, когда нужно будет к контроллеру PIC16 подключить какой-нибудь датчик, контроллер будет собирать и обрабатывать данные с этого датчика, а затем передавать на более мощный контроллер, который будет потом уже обрабатывать также эти данные, сравнивать с чем-то, затем передавать куда-то по сети. И вообщем-то, это не совсем фантастическая ситуация, в моей практике такое случалось очень часто. И здесь мы, соответственно, начинаем впадать в расстройство, а как же это сделать, какой интерфейс применить, и очень часто бывает целесообразно именно воспользоваться шиной I2C, так как она часто бывает свободна и больших скоростей нам не надо. Вот тут-то и помогает нам режим ведомого устройства. А, как правило, за плечами у нас нет знаний, а как же это сделать, и как этот ведомый режим применить. На многочисленных форумах существует очень много нерешенных вопросов по этой теме, но мне всё же освоить такой режим удалось. Признаться, очень сильно помогает логический анализ, и в основном вся путаница происходит из-за битов подтверждения, ну и, конечно же, из-за ожиданий установок различных флагов там, где это вовсе не нужно, и, наоборот, отсутствия таких ожиданий там, где они жизненно необходимы. А у меня (вы, конечно же, будете смеяться), проблема очень долго не решалась, из-за того, что я не подключил подтягивающие резисторы с ножек I2C к питанию, так как привык, что всё всегда уже подключено.

Также важность ведомого режима подчёркивается ещё тем, что он в официальной технической документации на PIC16 находится на первом месте, а уж потом ведущий (MASTER).

Так же, как и в режиме ведущего устройства, в ведомом режиме ножки SDA и SCL должны быть первоначально настроены на вход.

При работе в режиме ведомого устройства, если контроллер, работающий в таком режиме узнал адрес, а точнее его узнал модуль MSSP, сравнив пришедший адрес со значением, заранее занесённом в регистр SSPADD, то в таком случае модуль на выходе сформирует бит подтверждения ACK, то есть такой бит генерируется аппаратно. Бывают некоторые условия, при которых бит подтверждения может не сгенерироваться, как то переполнение буфера в данный момент, также взведенный бит BF, который, в принципе гласит приблизительно о том же. Думаю, у нас таких ситуаций не возникнет. Само собой также разумеется, что перед всем этим ведомый обязан заметить сформировавшееся условие СТАРТ на шине, иначе он даже не будет обращать внимание на пришедший байт адреса. Если перед этим контроллеры не общались, то по заднему фронту восьмого такта сигнала SCL значение в регистре SSPSR (а именно 7 старших его битов) начнёт сравниваться с содержимым аналогичных битов регистра SSPADD. И, если эти биты вдруг совпадут, то значение регистра SSPSR перепишется в буфер SSPBUF, бит BF установится в 1, сгенерируется подтверждение (ACK), и установится флаг SSPIF. Также в этом случае сгенерируется прерывание, если же оно, конечно, будет разрешено. Прерывание это сгенерируется также на заднем фронте шины SCK, но уже её 9 такта.

Всё это достоверно именно для 7-битной адресации. Для 10-битной ситуация аналогична, но несколько отличается. В рамках данного занятия использование 10-битной адресации не предусмотрено, так как мы её использовать в ближайшем будущем не планируем.

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

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

В качестве ведомого устройства (SLAVE) у нас будет использоваться наш постоянный контроллер PIC16F877A, расположенный на плате от Waveshare, а в качестве ведущего (MASTER) — контроллер PIC16F876A, с которым мы работали раньше, находящийся на макетной плате вместе с четырехразрядным индикатором, с которым мы последний раз работали, когда изучали подобный режим на шине SPI. Он также у нас выступал в роли ведущего устройства. Я данную плату не разбираю, и, оказывается, что не зря. Она зачастую нам требуется.

Ну, давайте с неё и начнём.

На схеме мы ничего не меняем, так как все эти вещи мы уже проделали в уроке по SPI, правда за исключением подтягивающих резисторов.

Подключим провода для соединения по шине I2С к соответствующим ножкам контроллера. Ножки мы используем вот такие

 

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

 

 

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

Поэтому подключим также к нашей плате и программатор

 

 

Подключим также программатор к ПК и начнём работать наконец-то с проектом.

 

 

Проект для прототипа мы возьмём из урока 18 с именем SPI_MASTER и дадим ему опять же говорящее имя I2C_MASTER.

Откроем наш проект в MPLAB X и сделаем его главным.

Откроем файл main.c и удалим из него вот этот макрос

 

#define cs RA5

 

Удалим также функции SPI_init, SPI_SendByte, и SPI_Receive_byte вместе с телами.

Из функции main() удалим объявление вот этой переменной

 

unsigned char bt;

 

А там, где объявлена переменная i, добавим ещё переменную n

 

 

Также удалим настройку порта C

TRISC = 0x00;
PORTC = 0x00;

Ну и также удалим вызов функции инициализации SPI

SPI_init();

И из бесконечного цикла удалим тело цикла for, сам цикл оставим. После этого наш бесконечный цикл примет вот такой вид

 

 

Теперь настроим шину I2C.

 

 

Настройки шины точь в точь такие же, как и в уроке 19.

 

 

Над функцией main() добавим несколько служебных функций для работы с шиной I2C, которыми мы уже пользовались в предыдущих уроках по данной шине

 

 

Также ниже добавим функцию передачи байта по адресу устройства

 

 

Такой функцией мы пользовались в прошлом занятии.

Также сегодня нам будет нужна функция приёма байта, в которой мы будем принимать байт без подтверждения, как мы принимали последний байт в уроке 19

 

 

В бесконечном цикле передадим байт ведомому и подождём некоторое время

 

Затем примем байт от ведомого устройства, покажем его на индикаторе и ещё немного подождём

 

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

Сначала нам его необходимо подключить к ведущему.

На ведомом устройстве значения пришедших байтов мы будем демонстрировать в двоичном виде с помощью зажжённых светодиодов, поэтому поставим перемычки, которые их задействуют, на место

Подключим провода, идущие от ведущего устройства к соответствующему разъёму

Подключим также к плате логический анализатор. Подключить можно к разъёму SPI, так как те же ножки там есть (соответствие SCL — SCK, SDA — SDI). Также подключим анализатор к ПК

Подключим также и программатор, и тоже его подключим к ПК

Проект в качестве основы мы будем использовать из урока 19 с именем AT24C.X, присвоив ему новое имя I2C_SLAVE.

Откроем наш проект в MPLAB X, сделаем его главным, зайдём в настройки и убедимся, что контроллер будет питаться от программатора.

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

 

 

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

 

Купить программатор (неоригинальный) можно здесь: PICKit3

Купить программатор (оригинальный) можно здесь: PICKit3 original

Отладочную плату PIC Open18F4520-16F877A можно приобрести здесь: PIC Open18F4520-16F877A

Семисегментный чертырехразрядный индикатор красный с общим анодом 10 шт

Логический анализатор 16 каналов можно приобрести здесь

 

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

 

PIC I2C. Slave. Соединяем два микроконтроллера

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

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

*