50405

Особенности работы с SPI на микроконтроллерах Миландр. Эхо между двумя платами К1986ВЕ92QI (К1986ВЕ92FI, К1986ВЕ92F1I, К1986ВЕ94GI)

Автор статьи: Лампадов Илья Александрович (Инженер)
Дата последнего изменения: 29.11.2023 13:49:24
Материал из настоящей статьи, относящийся к микросхеме К1986ВЕ92QI, распространяется в том числе на микроконтроллеры К1986ВЕ92FI, К1986ВЕ92F1I и К1986ВЕ94GI
В рамках данной статьи рассмотрим особенности работы с блоком SSP, который интегрируется в микроконтроллеры разработки компании Миландр, при этом выполним подключение двух демонстрационных плат К1986ВЕ92QI между собой и наладим эхо-сигнал.

Блок SSP в микроконтроллерах компании Миландр может работать в трёх режимах: SPI фирмы Motorola, SSI фирмы Texas Instruments и Microwire фирмы National Semiconductor. Наибольшее распространение получил именно режим SPI от фирмы Motorola из-за его гибкости при формировании диаграмм обмена, что позволяет соединить между собой большее количество устройств. Несмотря на то, что и в данной статье будет рассмотрена работа с режимом SPI, два других режима могут быть полезны при подключении специфичных изделий.

Вся теория по SPI в данной статье рассматриваться не будет, с ней можно ознакомиться из статьи ресурса Wikipedia. Обозначим лишь тезисно ключевые моменты, включая особенности используемого компанией Миландр блока SSP:

- Архитектурно SPI представляет из себя сдвиговый регистр. Для полного понимания механики работы интерфейса важно усвоить, что из этого вытекает то, что если мы что-то отправляем, то мы обязательно что-то получаем в ответ;

- Для обмена в SPI используются четыре линии: MOSI (выход мастера, вход ведомого), MISO (вход мастера, выход ведомого), SCLK (тактовый сигнал) и FSS (сигнал выбора ведомого или кадровой синхронизации - в различной литературе может также обозначаться как nCS);

- Все транзакции на шине инициирует строго мастер, то есть ведущее устройство. Это значит, что тактовый сигнал или сигнал синхронизации SCLK на шину для обмена вводит именно мастер, ведомый (или ведомые) не управляет тактовым сигналом;

- Говоря о гибкости интерфейса SPI, в первую очередь мы говорим о том, что есть достаточно большая вариативность построения диаграмм обмена, которая зависит от двух параметров: SPH (фаза сигнала) и SPO (полярность сигнала).

Если SPO = 0, то исходное состояние сигнала синхронизации SCLK - низкий уровень;
Если SPO = 1, то исходное состояние сигнала синхронизации SCLK - высокий уровень;
Если SPH = 0, то выборка данных будет производиться по переднему фронту сигнала синхронизации SCLK;
Если SPH = 1, то выборка данных будет производиться по заднему фронту сигнала синхронизации SCLK

Для большего понимания обращаем Ваше внимание на рисунок 1, на котором можно увидеть работу всех возможных режимов SPI.

Рисунок 1 - Режимы работы интерфейса SPI
Соответственно, если в Вашем проекте появляется необходимость связаться по шине SPI с некоторым периферийным устройством, которое в системе будет ведомым, то необходимо открыть документацию на данное изделие и посмотреть на его диаграммы обмена. При детальном рассмотрении можно будет установить, что это одна из четырех комбинаций параметров SPO и SPH
- Сигнал выбора ведомого или кадровой синхронизации FSS. Данный сигнал имеет активный уровень ноль, и его на шине SPI выставляет ведущее устройство в начале транзакции. Сигнал выделяет передаваемое слово из общего потока данных, при этом он обязательно необходим в режимах с SPH = 0, потому что по фронту первого тактового импульса в посылке уже будет производиться чтение линии. Поэтому предварительное падение линии FSS в логический ноль показывает ведомому, что начинается обмен, и ему следует выдать свои данные на MISO. 

В качестве справки приведем на рисунке 2 диаграмму обмена по SPI с SPH = 0 из документа спецификации на микроконтроллер К1986ВЕ92QI с некоторыми примечаниями:

Рисунок 2 - Работа SPI в режиме с SPH = 0

Резюмируем: в режимах с SPH = 0 без использования сигнала FSS не обойтись, он обязательно должен быть подключен к ведомому устройству со стороны ведущего. Более того, при непрерывном обмене этот сигнал должен включаться/выключаться между пересылкой каждого слова данных (в отличие от режимов с SPH = 1, о чем пойдет речь далее) - данный аппаратный блок учитывает эту особенность и переключает сигнал FSS соответствующим образом.

Далее необходимо обратить внимание, что сигнал TX находится в 3-м состоянии, когда FSS = 1. И только когда FSS = 0, то линия TX выходит из 3-го состояния, и по ней возможна передача данных. Это важно помнить, когда используется режим без линии FSS, то есть когда используется SPI с 3-мя линиями. Для этого необходимо использовать режим с SPH = 1, как показано на рисунке 3.

Рисунок 3 - Работа SPI в режиме с SPH = 1

Как видно из картинки, сигнал FSS здесь не так важен, и переключать его нет необходимости. Поэтому сигнал FSS со стороны ведомого обычно просто подключают к шине "Общий" (GND), а FSS со стороны ведущего не выводят на внешний пин. Вариант такого подключения представлен на рисунке 4.

Рисунок 4 - Подключение устройств по шине SPI без использования сигнала FSS

При таком включении видно, что сигнал SCLK является входом для ведомого, и именно по сигналам на нем ведомый будет выдавать свои данные. В случае соединения двух демонстрационных плат, чем мы займемся далее, важно, чтобы ведомый не начал выдавать свои данные, пока ведущий, например, инициализируется. Если ведущий контроллер еще не успел настроить SPI на своей стороне, то линия SCLK будет в 3-м состоянии. На ней появятся наводки и утечки, которые ведомый может воспринять как такты обмена, если сигнал помех превысит уровень логического нуля. Ведомый может выдать часть своих данных, а когда начнется настоящий обмен, то данные будут уже некорректными. В случае использования сигнала FSS этого бы не случилось, поскольку сигнал FSS синхронизирует посылки, тем не менее, вариант такого использования очень популярен (парировать подобную проблему позволит включение внутренней подтяжки к шине "Общий" (GND) сигнала SCLK на стороне ведомого - в проекте из данной статьи этот момент будет учтен, чтобы Вы смогли более предметно протестировать возникновение ошибок при данной конфигурации). Более того, в непрерывном режиме обмена с использованием SPH = 1, аппаратный сигнал FSS со стороны мастера будет в активном уровне (уровне логического нуля) на протяжении выдачи всех данных (при одиночном обмене сигнал FSS будет отрабатывать аналогичным образом с SPH = 0), в отличие от режима обмена с SPH = 0, где между пересылкой каждого слова сигнал FSS будет переключаться из активного уровня в неактивный.

Такой подход, когда нет переключения сигнала FSS на время выдачи данных (то есть это либо жесткое заземление на стороне ведомого в режиме с SPH = 1, либо в этом же режиме выполняется подключение линии FSS со стороны ведущего к ведомому, но работа ведётся в непрерывном режиме), может быть полезен при организации взаимодействия с изделиями, которые принимают данные по SPI, например, порциями по 32 бита. Поскольку аппаратный блок SSP в микроконтроллере К1986ВЕ92QI может выдавать за раз на шину слово максимум до 16 бит (настраивается при конфигурации блока, при этом здесь важно отметить, что в микроконтроллере К1986ВК025 появилась возможность установить слово данных размером до 32 бит - то есть блок был улучшен), то потребуется две последовательных транзакции по 16 бит. При этом, поскольку сигнал FSS не будет переводиться из активного уровня в неактивное между передачей двух слов данных, ведомое устройство сможет успешно зафиксировать принятые 32 бита.
Всё это время речь шла о сигнале FSS, который формирует микроконтроллер аппаратно. Однако, здесь важно помнить, что аппаратный сигнал FSS на стороне блока SSP микроконтроллера всего лишь один, а ведомых устройств на шине SPI может быть несколько. Чтобы корректно управлять несколькими ведомыми на шине SPI, можно на стороне ведущего устройства настроить несколько портов общего назначения, подключить данные линии к ведомым устройствам и выставлять в активный уровень (уровень логического нуля) требуемый программный сигнал FSS перед началом транзакции SPI.
- Частота работы блока SSP. Первостепенно на блок SSP подводится частота, сформированная в блоке тактовых частот (RST_CLK) с точностью до делителя BRG. Это значит, что при делителе BRG = 1 на блок SSP в микроконтроллере К1986ВЕ92QI может прийти частота максимум 80 МГц. Назовем частоту, приходящую на блок SSP - частотой SSPCLK. При дальнейших выкладках пускай частота SSPCLK будет равна максимальной частоте работы микроконтроллера, то есть 80 МГц.

В самом блоке SSP имеется два делителя: CPSR (значение от 2 до 254) и SCR (значение от 0 до 255). Именно эти два делителя будут определять финальную рабочую частоту блока SSP по следующей формуле: 

Speed = SSPCLK / (CPSR*(1+SCR))

Теперь переходим к самому главному: отношение частоты SSPCLK, приходящей на блок SSP, к частоте Speed (которая учитывает делители CPSR и SCR), которую мы хотим использовать в качестве рабочей, в режиме ведущего устройства должно составлять 2 (данное соотношение обеспечивается автоматически из-за того, что минимальное значение делителя CPSR составляет 2). Что это значит для человека, работающего с блоком? Это значит, что при максимальной частоте работы микроконтроллера К1986ВЕ92QI в 80 МГц и при делителе BRG = 1 можно обеспечить частоту работы блока SSP максимум 40 МГц (на практике это невозможно из-за ограничения портов GPIO, которые не могут переключаться с такой скоростью, тем не менее, это теоретический предел работы блока SSP для режима ведущего).

Для ведомого аналогичное соотношение должно составлять уже 12. Это связано с тем, что для сэмплирования входного сигнала требуется 12 тактов частоты. То есть для получения максимальной рабочей частоты блока SSP в режиме ведомого необходимо выставить делители CPSR и SCR в значения, что они будут делить частоту SSPCLK на 12. Таким образом для максимальной частоты работы микроконтроллера в 80 МГц в режиме ведомого мы можем получить рабочую частоту SSP максимум в 80 МГЦ / 12 = 6.66 МГц

Очевидно, что при увеличении значений делителей CPSR и SCR мы можем закономерно уменьшать рабочую частоту блока SSP, однако, этот механизм было важно описать для получения максимальных частот.

Как покажет практика, установить обмен на двух демонстрационных платах К1986ВЕ92QI по SPI удастся на максимальной возможной частоте в 6.66 МГц (то есть это максимальная частота ведомого при SSPCLK = 80 МГц, и хоть микроконтроллер, являющийся ведущим, потенциально мог бы работать и на частоте 10 МГц, но ведущий и ведомый должны оба иметь одну частоту Speed), о чем пойдет речь далее.

Подключение двух демонстрационных плат К1986ВЕ92QI по SPI и запуск примера

Говоря о подключении двух плат между собой, важно помнить, что требуется общая земля для сигналов. Достигается это подключением провода по линии "Общий" (GND) от одной платы к другой. Чем лучше будет земля, тем стабильнее будет обмен (в этом случае объединить по линии "Общий" (GND) платы можно двумя проводами). Сигналы TX должны подключаться на сигналы RX.

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

В рассматриваемом примере оба микроконтроллера будут использовать для работы один и тот же набор выводов:

PF0 - SSP1_TXD (19 пин разъема XP14);
PF1 - SSP1_CLK (20 пин разъема XP14);
PF2 - SSP1_FSS (21 пин разъема XP14);
PF3 - SSP1_RXD (22 пин разъема XP14);
Шина "Общий" (GND) (29 или 30 пин разъема XP14).


На рисунке 5 продемонстрировано подключение двух плат К1986ВЕ92QI по данным линиям. При этом важно выполнить отключение LCD-дисплея с платы, поскольку одна из используемых линий SPI сопряжена с разъемом для подключения дисплея:

Рисунок 5 - Подключение двух отладочных плат К1986ВЕ92QI по SPI

Рабочий проект доступен для загрузки в конце статьи. Код является универсальным, выбор ведущего или ведомого осуществляется директивой #define. Если требуется, чтобы микроконтроллер был ведущим, то необходимо определить в рамках #define значение "MASTER", при этом для ведомого необходимо определить значение "SLAVE". Указанные определения сделают активными только те участки кода, которые требуются для корректной работы в выбранном режиме.

Микроконтроллеры в примере настраиваются на работу на частоте 80 МГц, эта же частота приходит на блок SSP (SSPCLK). Далее делитель CPSR выставляется в значение 12, а делитель SCR - в значение 0, что даёт общий делитель частоты SSPCLK равный 12. Рабочая частота SSP = 6.66 МГц - это максимальная частота обмена при работе с данными микроконтроллерами, если исходить из ограничения на соотношение частоты SSPCLK к частоте Speed, описанного ранее.

Логика работы примера заключается в следующем: пока нажата кнопка "SELECT" на плате ведущего устройства SPI, в сторону ведомого отправляется постоянный поток инкрементированных данных от нуля до 0xFF (слово данных для SPI настроено на 8 бит). Ведомый, в свою очередь, при получении слова данных, кладёт его в буфер FIFO со значением "data + 1", чтобы ведущий получил в рамках транзакции отправленное значение (вспоминаем о том, что при отправке данных по SPI, мы обязательно получаем данные в ответ). Ведущий ведёт подсчёт отправленных пакетов, при этом происходит верификация принятых данных с тем, что было отправлено. Как только кнопка "SELECT" на стороне ведущего устройства отпускается, то мы, имея переменную key = 1 в качестве подобия семафора, открываем доступ к обработке отправленных и полученных данных, и если все то, что мы отправили, было получено в том же виде обратно, то зажигаются оба светодиода на плате ведущего устройства, при этом если во время обмена, пока была нажата кнопка "SELECT", произошли какие-либо ошибки (самый простой пример - разрыв шины "Общий" (GND) между платами во время обмена), то зажжется только один светодиод.

Пример позволяет провести тестирование SPI во всех возможных режимах SPH и SPO. Для режимов с SPH = 1, когда линия FSS со стороны ведущего устройства может не выводиться, а на стороне ведомого устройства может быть подтянута к шине "Общий" (GND), предусмотрено определение "PULLDOWN_CLK_SLAVE", которое обеспечивает подтяжку сигнала SCLK на стороне ведомого к шине "Общий" (GND) для избежания фиксации невалидных данных в силу наводок и утечек по данному выводу (особенность описывалась выше в статье).

На что важно обратить внимание

Структурно рассматриваемый в статье пример выполнен достаточно просто: ведущий отправляет данные, а ведомый фиксирует приём и сразу же отправляет данные обратно. Из-за того, что ведомый успевает быстро подготовить данные для отправки, мы никогда не столкнемся с ситуацией, что буфер FIFO передатчика в режиме ведомого будет заполнен. Однако, такая ситуация на практике в режиме ведомого может произойти, и зачастую требуется, чтобы передача данных ведущему велась сразу с заданных слов, не допуская при этом отправки ранее загруженных в FIFO данных. Для этого необходимо очистить буфер FIFO передатчика на стороне ведомого устройства.

Очистить буфер FIFO передатчика можно, отправив все данные наружу, после чего будет выставлен флаг опустошения FIFO - поле TFE в регистре SR. SPI в режиме ведущего может самостоятельно опустошить FIFO фактом выдачи всех данных, когда как в режиме ведомого такой возможности нет, поскольку передача инициируется ведущим. В таком случае для очистки FIFO передатчика потребуется:

1. Отключить SPI от линии (перенастроить порты GPIO, чтобы данные не выводились в линию - например, в аналоговый режим работы);

2. Установить SPI в режим ведущего и разрешить работу приёмопередатчика (регистр CR1, поле MS = 0 и SSE = 1);

3. Дождавшись опустошения буфера (поле TFE = 1 в регистре SR, а также поле BSY = 0 - модуль закончил передачу), вернуть настройки в исходное состояние.

Сохранить статью в PDF

Файлы для скачивания

Документация

Теги

Была ли статья полезной?