Интерфейс spi и arduino

Введение

Без преувеличения можно сказать, что встроенные системы в настоящее время используются везде. Простой пример встроенной системы – специальная компьютерная система, входящая в состав более крупной системы, предназначенная для мониторинга и контроля служб этой системы. Типовые встроенные системы после своего включения запускают специальные приложения, а после отключения – закрывают эти приложения. В сущности, все электронные устройства, которые проектируются и производятся в настоящее время, можно назвать встроенными системами. Краткий список примеров встроенных систем:

– Будильники

– Автоответчики

– Мобильные телефоны

– Принтеры

– Контроллеры противоблокировочных тормозных систем

– Печи СВЧ

– Системы инерциального наведения ракет

– Проигрыватели DVD

– Карманные компьютеры (PDA)

– Программируемые логические контроллеры (PLC) для автоматизации и контроля промышленного производства

– Портативные музыкальные проигрыватели

– Возможно, даже тостеры…

Встроенные системы могут содержать различные устройства, включая микропроцессоры, микроконтроллеры, ЦОС, ОЗУ, память EPROM, программируемые вентильные матрицы (FPGA), ЦАП, АЦП и схемы входа/выхода. Эти различные устройства, как правило, обмениваются данными друг с другом и с внешними устройствами по параллельным шинам. Однако в настоящее время все больше стандартных блоков, используемых во встроенных системах, заменяются блоками с последовательными шинами. Это обусловлено следующими причинами:

– Для передачи меньшего количества сигналов требуется меньше пространства

– Низкие затраты

– Низкое энергопотребление

– Меньше контактов

– Встроенные тактовые генераторы

– Разностные сигналы обеспечивают большую помехозащищенность

– Доступность компонентов со стандартными последовательными интерфейсами

Хотя последовательные шины обладают рядом преимуществ, их использование создает определенные проблемы для разработчиков встроенных систем, связанных с тем, что информация передается последовательно, а не параллельно. В данном примечании по использованию описаны общие проблемы проектирования встроенных систем и показано, как их решить с помощью функциональных возможностей новых цифровых осциллографов Tektronix серии DPO4000.

3Стандартная библиотека для работы по интерфейсу SPI

Для Arduino написана специальная библиотека, которая реализует протокол SPI. Она устанавливается вместе со средой разработки Arduino IDE. Подключается она так: в начале программы добавляем #include SPI.h.

Чтобы начать работу по протоколу SPI, нужно задать настройки и затем инициализировать протокол с помощью процедуры SPI.beginTransaction(). Можно выполнить это одной инструкцией: SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE0))

Это значит, что мы инициализируем протокол SPI на частоте 14 МГц, передача данных идёт, начиная с MSB (наиболее значимого бита), в режиме SPI_MODE0.

После инициализации выбираем ведомое устройство, переводя соответствующий пин SS в состояние LOW. Затем передаём ведомому устройству данные командой SPI.transfer(). После передачи возвращаем SS в состояние HIGH.

Временная диаграмма работы интерфейса SPI

Работа с протоколом завершается командой SPI.endTransaction().

Желательно минимизировать время выполнения передачи между инструкциями SPI.beginTransaction() и SPI.endTransaction(), чтобы не возникло накладок, если другое устройство попробует инициализировать передачу данных, используя другие настройки.

Если вы планируете в своём скетче использовать стандартные пины Arduino, можно не описывать их в начале программы, т.к. они уже определены в самой библиотеке и имеют следующие имена:

#define PIN_SPI_SS    (10)
#define PIN_SPI_MOSI  (11)
#define PIN_SPI_MISO  (12)
#define PIN_SPI_SCK   (13)

Данные пины определены в файле pins_arduino.h , который находится по пути %programfiles%\arduino-(версия)\hardware\arduino\avr\variants\ (если вы устанавливали программу в стандартное расположение). То есть, например, чтобы опустить пин выбора ведомого в состояние «0», можно написать:

digitalWrite(PIN_SPI_SS, LOW);

Data Structure Documentation

struct ARM_DRIVER_SPI

Access structure of the SPI Driver.

The functions of the SPI driver are accessed by function pointers exposed by this structure. Refer to for overview information.

Each instance of a SPI interface provides such an access structure. The instance is identified by a postfix number in the symbol name of the access structure, for example:

  • Driver_SPI0 is the name of the access struct of the first instance (no. 0).
  • Driver_SPI1 is the name of the access struct of the second instance (no. 1).

A middleware configuration setting allows connecting the middleware to a specific driver instance Driver_SPIn. The default is , which connects a middleware to the first instance of a driver.

(*  )(void)
  Pointer to : Get driver version.
 
(*  )(void)
  Pointer to : Get driver capabilities.
 
int32_t(*  )( cb_event)
  Pointer to : Initialize SPI Interface.
 
int32_t(*  )(void)
  Pointer to : De-initialize SPI Interface.
 
int32_t(*  )( state)
  Pointer to : Control SPI Interface Power.
 
int32_t(*  )(const void *data, uint32_t num)
  Pointer to : Start sending data to SPI Interface.
 
int32_t(*  )(void *data, uint32_t num)
  Pointer to : Start receiving data from SPI Interface.
 
int32_t(*  )(const void *data_out, void *data_in, uint32_t num)
  Pointer to : Start sending/receiving data to/from SPI.
 
uint32_t(*  )(void)
  Pointer to : Get transferred data count.
 
int32_t(*  )(uint32_t control, uint32_t arg)
  Pointer to : Control SPI Interface.
 
(*  )(void)
  Pointer to : Get SPI status.
 

Field Documentation

(* GetVersion)(void)

Pointer to : Get driver version.

(* GetCapabilities)(void)

Pointer to : Get driver capabilities.

int32_t(* Initialize)( cb_event)

Pointer to : Initialize SPI Interface.

int32_t(* Uninitialize)(void)

Pointer to : De-initialize SPI Interface.

int32_t(* PowerControl)( state)

Pointer to : Control SPI Interface Power.

int32_t(* Send)(const void *data, uint32_t num)

Pointer to : Start sending data to SPI Interface.

int32_t(* Receive)(void *data, uint32_t num)

Pointer to : Start receiving data from SPI Interface.

int32_t(* Transfer)(const void *data_out, void *data_in, uint32_t num)

Pointer to : Start sending/receiving data to/from SPI.

uint32_t(* GetDataCount)(void)

Pointer to : Get transferred data count.

int32_t(* Control)(uint32_t control, uint32_t arg)

Pointer to : Control SPI Interface.

(* GetStatus)(void)

Pointer to : Get SPI status.

struct ARM_SPI_CAPABILITIES

SPI Driver Capabilities.

A SPI driver can be implemented with different capabilities. The data fields of this structure encode the capabilities implemented by this driver.

Returned by:

ARM_SPI_GetCapabilities

Data Fields
uint32_t simplex: 1 supports Simplex Mode (Master and Slave)

Reserved (must be zero)
uint32_t ti_ssi: 1 supports TI Synchronous Serial Interface
uint32_t microwire: 1 supports Microwire Interface
uint32_t event_mode_fault: 1 Signal Mode Fault event: .
uint32_t reserved: 28 Reserved (must be zero)
struct ARM_SPI_STATUS

SPI Status.

Structure with information about the status of the SPI. The data fields encode busy flag and error flags.

Returned by:

ARM_SPI_GetStatus

Data Fields
uint32_t busy: 1 Transmitter/Receiver busy flag.
uint32_t data_lost: 1 Data lost: Receive overflow / Transmit underflow (cleared on start of transfer operation)
uint32_t mode_fault: 1 Mode fault detected; optional (cleared on start of transfer operation)
uint32_t reserved: 29

Пример программной реализации

Ниже представлен пример программной реализации SPI мастера на языке Си. Линия CS (chip select, выбор микросхемы) должна быть активирована (в большинстве случаев — притянута к низкому уровню), перед тем, как начнётся обмен данными, и деактивирована после окончания обмена. Большинство устройств требуют несколько сеансов передачи с активной линией CS. Эта функция может быть вызвана несколько раз, пока линия активна.

unsigned char SPIBitBang8BitsMode0(unsigned char byte)
{       
    unsigned char bit;

    for (bit = ; bit < 8; bit++) {
        /* записать MOSI по спаду предыдущего тактового импульса */
        if (byte & 0x80)
            SETMOSI();
        else
            CLRMOSI();
        byte <<= 1;

        /* ждём половину тактового периода, перед тем как сгенерировать фронт */
        SPIDELAY(SPISPEED2);
        SETCLK();

        /* ждём половину тактового периода, перед тем как сгенерировать спад */
        SPIDELAY(SPISPEED2);

        /* читаем MISO на спаде */
        byte |= READMISO();
        CLRCLK();
    }

    return byte;
}

Механизмы доступа к Flash ROM и защита записи

В общем случае, для инициирования операций стирания или перезаписи микросхемы
BIOS, программа должна выполнить четыре действия:

  1. Настроить регистры «южного моста» чипсета, управляющие размещением
    микросхемы BIOS в адресном пространстве для обеспечения доступа к полному
    объему микросхемы.
  2. Выключить режим защиты записи BIOS, реализуемый средствами «южного моста»
    чипсета.
  3. Выключить режим защиты записи BIOS, реализуемый средствами микросхемы
    Flash ROM.
  4. Передать команду стирания или записи микросхеме Flash ROM.

Рассмотрим подробнее эти процедуры, механизмы защиты, препятствующие их
несанкционированному выполнению и, конечно, уязвимости этих механизмов.

Как было сказано выше, при выполнении операций записи и стирания, программный
доступ к микросхеме SPI Flash осуществляется посредством регистров контроллера
SPI, без использования диапазона адресов, в котором доступен образ микросхемы
BIOS. Поэтому перенастройка чипсета для доступа к диапазону FFF00000h-FFFFFFFFh
в данном примере не потребуется.

Защита записи, реализуемая «южным мостом» Intel ICH8 построена по такой же
схеме, как и в платформах предыдущих поколений, отличаются только адреса
регистров. Следовательно, процедура снятия этой защиты подобна процедуре
рассмотренной в предыдущих публикациях. Доступом к микросхеме BIOS управляет
8-битный регистр BIOS_CNTL (его координаты в конфигурационном пространстве
Bus=0, Device=1Fh, Function=0, Register=DCh). Бит 0 этого регистра (бит BIOSWE,
BIOS Write Enable) управляет разрешением записи в микросхему BIOS, 0=запрещена,
1=разрешена. Бит 1 того же регистра (бит BLE, BIOS Lock Enable) обеспечивает
перехват несанкционированного выключения защиты. Если бит BLE=1, то при попытке
установить бит BIOSWE=1 будет генерироваться прерывание SMI (System Management
Interrupt) с вызовом специальной процедуры, входящей в состав BIOS. Причем, если
BIOS при старте установит бит BLE=1, программно обнулить его чипсет не
позволяет, режим перехвата будет выключен только после аппаратного сброса (по
сигналу RESET). Подробности в .

Практика показывает, что данный механизм «защиты от снятия защиты» обычно не
активируется разработчиками BIOS. Во всех материнских платах, исследованных
автором, бит BLE=0, поэтому для снятия защиты записи достаточно установить бит
BIOSWE=1, эта операция не будет перехвачена.

Микросхема Intel ICH8 также поддерживает защиту содержимого микросхемы BIOS,
путем задания адресных диапазонов, защищенных от чтения и (или) записи.
Теоретически, на базе данного механизма можно реализовать эффективную защиту,
так как запрет программно включается процедурами BIOS при старте платформы, и
может быть снят только при аппаратном сбросе. Но и этот механизм обычно не
активируется разработчиками BIOS.

(Продолжение следует)

Description

Driver API for SPI Bus Peripheral (Driver_SPI.h)

The Serial Peripheral Interface Bus (SPI) implements a synchronous serial bus for data exchange. In microcontroller (MCU) applications, the interface is often used to connect peripheral components at board (PCB) level. SPI devices can operate as Master (SCLK and SS are outputs) or Slave (SCLK and SS are inputs). Wikipedia offers more information about the Serial Peripheral Interface Bus.

Block Diagram

The SPI Driver API defines a SPI interface for middleware components. The SPI Driver supports multiple slaves, but if only one slave is connected, then the Slave Select signal can be omitted.

SPI Master connected to a single slave

SPI Master connected to 3 slaves

The SPI Driver functions control the following SPI signal lines.

Signal Name Description
SS Slave Select (active low) Selects the slave. This signal can be part of the SPI peripheral or implemented using a GPIO pin.
MOSI Master Out, Slave In MOSI output of the Master connects to MOSI input of the Slave.
SCLK Serial Clock Serial clock output from Master. Controls the transfer speed and when data are sent and read.
MISO Master In, Slave Out MISO input of the Master connects to MISO output of the Slave.

SPI API

The following header files define the Application Programming Interface (API) for the SPI interface:

Driver_SPI.h : Driver API for SPI Bus Peripheral

The driver implementation is a typical part of the Device Family Pack (DFP) that supports the peripherals of the microcontroller family.

Driver Functions

The driver functions are published in the access struct as explained in

ARM_DRIVER_SPI : access struct for SPI driver functions

Example Code

The following example code shows the usage of the SPI interface.

#include «Driver_SPI.h»

#include «cmsis_os.h»

void mySPI_Thread(void const *argument);
osThreadId tid_mySPI_Thread;

extern Driver_SPI0;

void mySPI_callback(uint32_t event)
{
switch (event)
{
case :

osSignalSet(tid_mySPI_Thread, 0x01);
break;
case :

__breakpoint(0);

break;
case :

__breakpoint(0);

break;
}
}

const uint8_t testdata_out = { 0, 1, 2, 3, 4, 5, 6, 7 };
uint8_t testdata_in ;

void mySPI_Thread(void const* arg)
{
* SPIdrv = &Driver_SPI0;
osEvent evt;

#ifdef DEBUG

version;
drv_capabilities;

version = SPIdrv->();
if (version. < 0x200)

{

return;
}

drv_capabilities = SPIdrv->();
if (drv_capabilities. == 0)
{

return;
}
#endif

SPIdrv->(mySPI_callback);

SPIdrv->();

SPIdrv->( | | | | (8), 10000000);

SPIdrv->(, );

while (1)
{

SPIdrv->(, );

SPIdrv->(testdata_out, sizeof(testdata_out));

evt = osSignalWait(0x01, 100);
if (evt.status == osEventTimeout) {
__breakpoint(0);

}

SPIdrv->(, );

SPIdrv->(, );

SPIdrv->(testdata_in, 8);
evt = osSignalWait(0x01, 100);
if (evt.status == osEventTimeout) {
__breakpoint(0);

}

SPIdrv->(, );
}
}

Прием и передача данных в SPI


Типичная структура связей и линий интерфейса SPI

Передача осуществляется пакетами. Длина пакета, как правило, составляет 1 байт (8 бит), при этом известны реализации SPI с иной длиной пакета, например, 4 бита.
Ведущее устройство инициирует цикл связи установкой низкого уровня на выводе выбора подчиненного устройства (SS) того устройства, с которым необходимо установить соединение.
При низком уровне сигнала SS:

  • схемотехника ведомого устройства находится в активном состоянии;
  • вывод MISO переводится в режим «выход»;
  • тактовый сигнал SCLK от ведущего устройства воспринимается ведомым и вызывает считывание на входе MOSI значений передаваемых от ведущего битов и сдвиг регистра ведомого устройства.

Подлежащие передаче данные ведущее и ведомое устройства помещают в сдвиговые регистры. После этого ведущее устройство начинает генерировать импульсы синхронизации на линии SCLK, что приводит к взаимному обмену данными. Передача данных осуществляется бит за битом от ведущего по линии MOSI и от ведомого по линии MISO. Передача осуществляется, как правило, начиная со старших битов, но некоторые производители допускают изменение порядка передачи битов программными методами. После передачи каждого пакета данных ведущее устройство, в целях синхронизации ведомого устройства, может перевести линию SS в высокое состояние.

3Стандартная библиотека для работы по интерфейсу SPI

Для Arduino написана специальная библиотека, которая реализует протокол SPI. Она устанавливается вместе со средой разработки Arduino IDE. Подключается она так: в начале программы добавляем #include SPI.h.

Чтобы начать работу по протоколу SPI, нужно задать настройки и затем инициализировать протокол с помощью процедуры SPI.beginTransaction(). Можно выполнить это одной инструкцией: SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE0))

Это значит, что мы инициализируем протокол SPI на частоте 14 МГц, передача данных идёт, начиная с MSB (наиболее значимого бита), в режиме SPI_MODE0.

После инициализации выбираем ведомое устройство, переводя соответствующий пин SS в состояние LOW. Затем передаём ведомому устройству данные командой SPI.transfer(). После передачи возвращаем SS в состояние HIGH.

Временная диаграмма работы интерфейса SPI

Работа с протоколом завершается командой SPI.endTransaction().

Желательно минимизировать время выполнения передачи между инструкциями SPI.beginTransaction() и SPI.endTransaction(), чтобы не возникло накладок, если другое устройство попробует инициализировать передачу данных, используя другие настройки.

Если вы планируете в своём скетче использовать стандартные пины Arduino, можно не описывать их в начале программы, т.к. они уже определены в самой библиотеке и имеют следующие имена:

#define PIN_SPI_SS    (10)
#define PIN_SPI_MOSI  (11)
#define PIN_SPI_MISO  (12)
#define PIN_SPI_SCK   (13)

Данные пины определены в файле pins_arduino.h , который находится по пути %programfiles%\arduino-(версия)\hardware\arduino\avr\variants\ (если вы устанавливали программу в стандартное расположение). То есть, например, чтобы опустить пин выбора ведомого в состояние «0», можно написать:

digitalWrite(PIN_SPI_SS, LOW);

3Программа «Реализация SPI с помощью микросхем FTDI»

«SPI via FTDI» версии 1 (разворачивается)

Представляю вашему вниманию программу «Реализация SPI с помощью микросхем фирмы FTDI» или «SPI via FTDI» – программное обеспечение, написанное под .NET и предназначенное для передачи данных из ПК и приёма данных в ПК с помощью микросхем фирмы FTDI (семейства FT22xx, FT23xx, FT42xx) по последовательному интерфейсу SPI. Это ПО позволит вам организовать обмен данными с устройствами, которые работают по интерфейсу SPI.

Микросхемы FT2ххx и FT3xxx работают только в режиме ведущего устройства SPI (master).

С помощью данной программы вы сможете оперативно протестировать вашу микросхему в разных режимах работы. Подключившись логическим анализатором к выводам SK, DO, DI и CS микросхемы, можно наглядно увидеть, как влияют разные настройки на способ передачи данных.

Системные требования

  • Операционная система Windows XP и выше, в т.ч. Windows 10. Программа работает как с x86, так и с x64 операционными системами.
  • .NET Framework версии 3.5 SP1.
  • Наличие USB порта.

Установка и настройка программы «SPI с помощью микросхем FTDI»

Если программа запускается на компьютере с ОС Windows XP, необходимо убедиться в наличии установленной .NET Framework и, при её отсутствии, установить.

Скачать .NET Framework 3.5 SP1. После установки .NET Framework компьютер следует перезагрузить.

В Windows Vista, Windows 7 и 10 библиотеки .NET версии 3.5 присутствуют по умолчанию. Для установки на Windows 8 потребуется произвести дополнительные операции, а именно вручную включить возможность установки среды .NET.

Установка программы осуществляется копированием исполняемого файла с установочного носителя в нужное расположение.

При первом запуске программа проверит наличие необходимых для работы с микросхемами динамических библиотек D2XX.dll и FTCSPI.dll и, при их отсутствии, запишет их на компьютер в директорию C:\Temp.

Возможности программы

  • Передача данных из файла или введённого вручную массива байтов из ведущего устройства (микросхемы FTDI) к ведомому устройству,
    реализующему интерфейс SPI.
  • Приём данных от ведомого устройства.
  • Циклический приём данных заданное количество раз и в бесконечном цикле.
  • Изменение настроек работы SPI, а также частотно-временных характеристик приёма и передачи «на ходу». Реализация различных режимов работы интерфейса SPI.
  • Сохранение принятых данных в файл (текстовый или двоичный).

Работа с программой «SPI via FTDI»

При запуске программа определяет наличие подключённых к системе поддерживаемых устройств FTDI и создаёт для каждого устройства свою вкладку. Если после запуска программы были подключены новые устройства FTDI, можно обновить список устройств, нажав кнопку с синей стрелкой (Обновить).

Внешний вид главного окна программы «SPI с помощью FTDI»

Выбор настроек осуществляется выбором желаемых параметров в левой панели главного окна программы. Каждое устройство конфигурируется независимо.

Подключение к устройству FTDI осуществляется нажатием на кнопку в заголовке вкладки. Отключение – нажатием на ту же кнопку. Возможно одновременное подключение к нескольким устройствам.

Передача данных возможна тремя способами: выбором файла (кнопка с иконкой папки), отправкой произвольной последовательности байтов (в поле Преамбула при активном флажке), а также отправка преамбулы, а затем выбранного файла, если выбраны оба варианта. Передача данных осуществляется нажатием на кнопку Записать.

Приём данных от ведомого устройства осуществляется нажатием на кнопку Прочитать. Если в поле справа от кнопки введено число, отличное от 1, приём будет осуществлён соответствующее число раз; если указан «0», то чтение будет продолжаться бесконечно (до принудительной остановки).

При чтении все принятые данные автоматически сохраняются в файл (текстовый или двоичный, по выбору пользователя) в директорию с программой. Открытие файла происходит по нажатию на кнопку Открыть.

Данная программа использует только базовые возможности микросхем FTDI. Например, вы не сможете назначить несколько пинов Chip Select (используется только первый CS, см. таблицы выше), не сможете использовать выводы GPIOH. Т.е., сможете подключить только одно ведомое устройство SPI.

spi.setup()¶

Set up the SPI configuration.
Refer to for details regarding the clock polarity and phase definition.

Calling will route the HSPI signals to the related pins, overriding previous configuration and control by the module. It is possible to revert any pin back to gpio control if its HSPI functionality is not needed, just set the desired for it. This is recommended especially for the HSPI /CS pin function in case that SPI slave-select is driven from a different pin by — the SPI engine would toggle pin 8 otherwise.

Parameters

  • SPI ID number: 0 for SPI, 1 for HSPI
  • select master or slave mode

    • — not supported currently
  • clock polarity selection
  • clock phase selection
  • number of bits per data item 1 — 32
  • SPI clock divider, f(SPI) = 80 MHz / , 1 .. n (0 defaults to divider 8)
  • duplex mode

    • (default when omitted)

6«Бегущая волна» из светодиодов

Светодиоды загораются по очереди, и мы наблюдаем бегущую «волну» из огоньков. Управление светодиодами осуществляется с помощью сдвигового регистра, к которому мы подключились по интерфейсу SPI. В результате для управления 8-ю светодиодами задействованы всего 3 вывода Arduino. Если бы мы подключали светодиоды напрямую к цифровым портам Arduino, нам бы потребовалось для каждого светодиода использовать отдельный порт.

Мы изучили самый простой пример работы Arduino с шиной SPI. Более подробно рассмотрим работу нескольких сдвиговых регистров при независимом и каскадном подключениях в отдельной статье.

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

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

Adblock
detector