Программирование интерфейса SPI
Рекомендации по применению 8/16-разрядных микроконтроллеров MB89XXX / MB90XXX семейств F2MC-8L/16LX
Введение
SPI (последовательный интерфейс периферийных устройств) – простой способ обмена данными между двумя цифровыми устройствами. В связи с отсутствием жестких требований и наличия различных форматов, реализация SPI-интерфейса на практике может вызвать ряд затруднений.
В данном руководстве описано большинство общих форматов SPI-интерфейса и методы их реализации на основе 16-разрядных микроконтроллеров.
1 Форматы SPI
В данном разделе описываются большинство общих форматов SPI.
1.1 Общие определения SPI-интерфейса
SPI – последовательный синхронный интерфейс между одним мастером (главное устройство) и одним помощником (подчиненное устройство). Каждый передаваемый бит данных в любом из направлений имеет собственный тактовый импульс. Поэтому, SPI использует по крайней мере три различных сигнала:
- SCK – тактирование последовательной связи (синхронизация)
- SI – последовательный ввод (данные от «помощника» к «мастеру»)
- SO – последовательный вывод (данные от «мастера» к «помощнику»)
В некоторых конфигурациях SPI использует четвертый сигнал “Выбор микросхемы ” (CS), который используется для разрешения последовательной связи мастером. Данный сигнал может иметь активный уровень как низкий, так и высокий.
1.2 Сигнал тактирования SPI (SCK)
В связи с отсутствием общих технических требований к SPI-интерфейсу временная диаграмма тактового сигнала зависима от устройства (микросхемы), поскольку каждый производитель использует собственную временную диаграмму. Для большинства SPI протоколов можно выделить четыре типа настроек, которые обычно задаются внутренними установками "мастера" шины SPI: CPOL (полярность тактового сигнала) и CPHA (фаза тактового сигнала).
CPOL определяет активное состояние сигнала тактирования последовательной связи SPI и, следовательно, является отметочным уровнем.
CPHA определяет фазу тактового сигнала относительно бита данных на линии SO.
Не существует общей классификации SPI-протоколов и SPI-устройств, которая определяла бы установки CPOL и CPHA относительно собственно протокола. Поэтому в этом документе установки определяются следующим образом:
CPOL = 0 : тактовый сигнал имеет отметочный уровень “1”
CPOL = 1 : тактовый сигнал имеет отметочный уровень “0”
CPHA = 0 : тактовый сигнал синхронен битам данных на линии SO
CPHA = 1 : тактовый сигнал задержан на полпериода передачи бита данных относительно бита данных на линии SO
1.3 Направление данных
В большинстве SPI-форматов первым передается старший разряд (MSB).
1.4 Скорость связи
Скорость передачи данных SPI-интерфейса задается аппаратно. Максимальная скорость ограничивается временными диаграммами установки и удержания сигналов.
SPI используется в широком диапазоне скоростей связи, начиная с нескольких кбит/с до нескольких Мбит/с.
1.5 SPI - протоколы
В данном разделе описываются главные отличия временных диаграмм различных протоколов SPI.
1.5.1 CPOL = 0, CPHA = 0
Данный SPI-формат соответствует стандартному синхронному формату. Временная диаграмма иллюстрируется ниже:
Рисунок 1 – Тактовый сигнал в фазе с данными (отметочный уровень = “1”)
1.5.2 CPOL = 1, CPHA = 0
Данный SPI-формат соответствует стандартному синхронному формату, но с инвертированным тактовым сигналом
Рисунок 2 – Тактовый сигнал в фазе с данными (отметочный уровень = “0”, инвертированный)
1.5.3 CPOL = 0, CPHA = 1
В этом SPI-формате тактовый сигнал задержан на полпериода передачи бита данных по отношению к стандартному синхронному формату.
Рисунок 3 - Тактовый сигнал задержан на половину длительности передачи бита данных (отметочный уровень = “1”)
Обратите внимание, что в этом формате первый бит данных устанавливается на SO перед возникновением первого тактового импульса.
1.5.4 CPOL = 1, CPHA = 1
В этом SPI-формате тактовый сигнал задержан на полпериода передачи бита данных по отношению к стандартному синхронному формату и инвертирован тактовый сигнал.
Рисунок 4 - Тактовый сигнал задержан на половину длительности передачи бита данных (отметочный уровень = “0”, инвертированный)
Обратите внимание, что в этом формате первый бит данных устанавливается на SO перед возникновением первого тактового импульса.
2 Реализация SPI-интерфейса
В данном разделе описано как реализовать различные конфигурации SPI-интерфейса
2.1 Реализация форматов SPI с CPHA = 0
2.1.1 SPI с CPHA = 0 и CPOL = 0
Этот SPI-формат реализован на всех интерфейсах последовательного ввода-вывода Fujitsu. УАПП (устройство асинхронной приемо-передачи) Fujitsu с синхронным режимом также поддерживают данный формат.
2.1.2 SPI с CPHA = 0 и CPOL = 1
Данный формат поддерживается во всех интерфейсах последовательного ввода-вывода Fujitsu, которые выполняют инверсию тактового сигнала (бит NEG). УАПП Fujitsu с синхронным режимом и инверсией тактового сигнала также поддерживают данный формат (биты NEG или SCES).
2.2 Реализация форматов SPI с CPHA = 1
Данный формат поддерживается у LIN-UART, начиная с серии MB90340. Для его реализации программист должен использовать синхронный режим и SCDE = 1 (разрешение задержки тактового сигнала) и SCES = x (выбор тактового фронта для задания полярности CPOL = x). Для всех остальных интерфейсов последовательного ввода-вывода и УАПП должны быть учтены некоторые особенности.
2.2.1 SPI на основе последовательного ввода-вывода (SIO) c CPHA = 1, CPOL = 0
Последовательный ввод-вывод может поддерживать только SPI-форматы с CPHA = 0 в его нормальном режиме работы. При выборе режима внешнего тактирования сдвигового регистра последовательный ввод-вывод может тактироваться переключением порта относительно его вывода SCK.
Недокументированная особенность состоит в том, что последовательный ввод-вывод может быть также синхронизирован переключением бита NEG в регистре SES (выбор фронта). Поэтому, есть возможность установить первый бит данных на SO перед генерацией тактового сигнала на выводе порта.
Следующий Си-код показывает пример реализации данного метода. Обратите внимание, что максимальная скорость связи зависит от времени выполнения инструкции (тактовой частоты МК), а функция SPI_Byte не должна прерываться на обработку запроса на прерывание:
Пример Си-кода с использованием последовательного ввода-вывода (SIO) и CPHA = 1, CPOL = 0
void InitSIO (void)
{
PDR4 = 0x80; // порт SCK2 – 47-выв. у серии MB90540
DDR4 = 0x80; // SCK2 установить к "1"
SMCS_SOE = 1; // Разрешение последовательного вывода
SMCS_SCOE = 0; // Выключение внутреннего последовательного тактирования
SES2_NEG = 1; // Инвертирование тактирования
SMCS_STOP = 0; // Сброс останова (STOP)
SMCS_SMD = 0x05; // Режим внешнего тактирования сдвига
SMCS_BDS = 1; // Установка передачи старшего разряда первым
}
unsigned char SPI_Byte(data)
{
SDR = data; // Записать данные в сдвиговый регистр
SMCS_STRT = 1; // Разрешение начала связи
SES2_NEG = 0; // Генерация импульса "внутреннего тактирования"
SES2_NEG = 1; // для установки первого бита данных на SOT2
PDR4_P47 = 0; // генерация 8 тактовых импульсов на SCK2
PDR4_P47 = 1;
PDR4_P47 = 0;
PDR4_P47 = 1;
PDR4_P47 = 0;
PDR4_P47 = 1;
PDR4_P47 = 0;
PDR4_P47 = 1;
PDR4_P47 = 0;
PDR4_P47 = 1;
PDR4_P47 = 0;
PDR4_P47 = 1;
PDR4_P47 = 0;
PDR4_P47 = 1;
PDR4_P47 = 0;
PDR4_P47 = 1;
SES2_NEG = 0; // "внутренний тактовый импульс" для выполнения
SES2_NEG = 1; // последовательной связи
data = SDR; // чтение сдвигового регистра
return data;
}
Прим.: Сигнал CS можно легко реализовать с помощью любого другого вывода порта.
2.2.2 SPI с последовательным вводом-выводом и CPHA = 1, CPOL = 1
Методика для CPOL = 1 аналогична описанной выше в 2.2.1. Следующий Си-код показывает пример реализации методики. Обратите внимание, что максимальная скорость связи также зависит от времени выполнения инструкции (тактовой частоты МК), а функция SPI_Byte не должна прерываться для обработки запроса на прерывание:
Пример Си-кода с использованием последовательного ввода-вывода (SIO) и CPHA = 1, CPOL = 1
void InitSIO (void)
{
PDR4 = 0x00; // порт SCK2 – 47 выв. у серии MB90540
DDR4 = 0x80; // установка "0" на SCK2
SMCS_SOE = 1; // Разрешение последовательного вывода
SMCS_SCOE = 0; // Выключение внутренней последовательной синхронизации
SES2_NEG = 0; // Нормальная синхронизация
SMCS_STOP = 0; // Сброс останова (STOP)
SMCS_SMD = 0x05; // Режим внешней синхронизации сдвига
SMCS_BDS = 1; // Выбор передачи старшего разряда первым
}
unsigned char SPI_Byte(data)
{
SDR = data; // Запись данных в сдвиговый регистр
SMCS_STRT = 1; // Запуск последовательной связи
SES2_NEG = 1; // Генерация импульса "внутренней синхронизации"
SES2_NEG = 0; // для установки первого бита даны на SOT2
PDR4_P47 = 1; // генерация 8-ми тактовых на SCK2
PDR4_P47 = 0;
PDR4_P47 = 1;
PDR4_P47 = 0;
PDR4_P47 = 1;
PDR4_P47 = 0;
PDR4_P47 = 1;
PDR4_P47 = 0;
PDR4_P47 = 1;
PDR4_P47 = 0;
PDR4_P47 = 1;
PDR4_P47 = 0;
PDR4_P47 = 1;
PDR4_P47 = 0;
PDR4_P47 = 1;
PDR4_P47 = 0;
SES2_NEG = 1; // импульс "внутренней синхронизации " для выполнения
SES2_NEG = 0; // последовательной связи
data = SDR; // чтение сдвигового регистра
return data;
}
Прим.: Сигнал CS можно легко реализовать с помощью любого другого вывода порта.\
2.2.3 SPI на основе УАПП в синхронном режиме и CPHA = 1, CPOL = 0
Данный метод реализации SPI (CPHA = 1 и CPOL = 0) на основе УАПП в синхронном режиме подобен методу с использованием последовательного ввода-вывода. В данном примере синхронизация УАПП генерируется внутренне с использованием переключения бита NEG и генерируется "внешне" через соответствующий вывод SCK.
Обратите внимание, что этот пример работает только с УАПП, у которого имеются синхронный режим и предделитель, нет перезагружаемого счетчика. Эти УАПП идентифицируются регистром CDC (управление делением тактовой частоты).
Пример Си-кода с CPHA = 1, CPOL = 0 и использованием синхронного режима УАПП
void InitUART(void)
{
SMR1_MD1 = 1; // Выбор синхронного режима
SMR1_MD0 = 0;
SMR1_CS2 = 1; // Выбор источника внешней синхронизации
SMR1_CS1 = 1;
SMR1_CS0 = 1;
SMR1_SCKE = 0; // Внешняя синхронизация
SMR1_SOE = 1; // Разрешение последовательного вывода
SES1_NEG = 1; // Инверсия синхронизации
SCR1_TXE = 1; // Разрешение передачи
PDR4 = 0x10; // Порт SCK1 – 44 выв. у серии MB90540
DDR4 = 0x10; // Установка "1" на SCK1
}
unsigned char SPI_Byte(data)
{
SODR1 = data; // Запись данных в регистр передачи
DI(); // Запрет всех прерываний
SES1_NEG = 0; // Генерация импульса "внутренней синхронизации"
SES1_NEG = 1; // для установки первого бита данных на SOT1
PDR4_P44 = 0; // генерация 8 тактовых импульсов на SCK1
PDR4_P44 = 1;
PDR4_P44 = 0;
PDR4_P44 = 1;
PDR4_P44 = 0;
PDR4_P44 = 1;
PDR4_P44 = 0;
PDR4_P44 = 1;
PDR4_P44 = 0;
PDR4_P44 = 1;
PDR4_P44 = 0;
PDR4_P44 = 1;
PDR4_P44 = 0;
PDR4_P44 = 1;
PDR4_P44 = 0;
PDR4_P44 = 1;
SES1_NEG = 0; // импульс "внутренней синхронизации" для выполнения
SES1_NEG = 1; // последовательной задачи
EI(); // Разрешение всех прерываний (опционально)
data = SIDR; // чтение данных из регистра приема
return data;
}
Прим.: Сигнал CS можно легко реализовать с помощью любого другого вывода порта.
2.2.4 SPI на основе УАПП в синхронном режиме и CPHA = 1, CPOL = 1
Данная методика реализации SPI (CPHA = 1 и CPOL = 1) на основе УАПП в синхронном режиме подобна описанной выше (2.2.3).
Пример Си-кода с CPHA = 1, CPOL = 1 и использованием синхронного режима УАПП
void InitUART(void)
{
SMR1_MD1 = 1; // Выбор синхронного режима
SMR1_MD0 = 0;
SMR1_CS2 = 1; // Выбор внешней синхронизации
SMR1_CS1 = 1;
SMR1_CS0 = 1;
SMR1_SCKE = 0; // Внешняя синхронизация
SMR1_SOE = 1; // Разрешение последовательного вывода
SES1_NEG = 0; // Нормальная синхронизация
SCR1_TXE = 1; // Разрешение передачи
PDR4 = 0x00; // порт SCK1 44 выв. у серии MB90540
DDR4 = 0x10; // установка на SCK1 "0"
}
unsigned char SPI_Byte(data)
{
SODR1 = data; // Запись данных в регистр передачи
DI(); // Запрет всех прерываний
SES1_NEG = 1; // Генерация импульса внутренней синхронизации
SES1_NEG = 0; // для установки первого бита данных на SOT1
PDR4_P44 = 1; // генерация 8 тактовых импульсов на линии SCK1
PDR4_P44 = 0;
PDR4_P44 = 1;
PDR4_P44 = 0;
PDR4_P44 = 1;
PDR4_P44 = 0;
PDR4_P44 = 1;
PDR4_P44 = 0;
PDR4_P44 = 1;
PDR4_P44 = 0;
PDR4_P44 = 1;
PDR4_P44 = 0;
PDR4_P44 = 1;
PDR4_P44 = 0;
PDR4_P44 = 1;
PDR4_P44 = 0;
SES1_NEG = 1; // импульс "внутренней синхронизации " для выполнения
SES1_NEG = 0; // последовательной задачи
EI(); // Разрешение всех прерываний (опционально)
data = SIDR; // чтение из приемного регистра
return data;
}
Прим.: Сигнал CS можно легко реализовать с помощью любого другого вывода порта.
Ваш летний отдых в Адлере - гостиницы, санатории
|