ATmega328: SPI Печать
Добавил(а) microsin   

Здесь приведен перевод даташита по микроконтроллеру ATmega328 (ATmega48, ATmega88, ATmega168), касающиеся аппаратного блока интерфейса SPI.

Основные возможности интерфейса:

• Полнодуплексная, трехпроводная, синхронная передача данных
• Возможность работы в режиме Master или Slave
• Передача данных с разным порядком следования бит - сначала LSB или сначала MSB
• 7 программируемых скоростей передачи
• Флаг прерывания, сигнализирующим об окончании передачи
• Флаг защиты от коллизии записи
• Возможность пробуждения из режима сна (Idle Mode)
• Режим Master SPI удвоенной скорости (CK/2)

[Описание основных возможностей SPI]

Последовательный периферийный интерфейс (Serial Peripheral Interface, SPI) позволяет осуществлять высокоскоростной обмен данными между микроконтроллерами ATmega48A/PA/88A/PA/168A/PA/328/P и периферийными устройствами, либо с другими устройствами на основе микроконтроллерах (AVR, ARM, STM32 и т. п.). Интерфейс USART может тоже использоваться в режиме Master SPI, см. раздел "USART в режиме SPI". Бит PRSPI в регистре PRR (Power Reduction Register) должен быть записан в 0, чтобы мог работать блок SPI.

Как следует из своего названия, регистр PRR предназначен для управления снижением энергопотребления микроконтроллера за счет отключения некоторых аппаратных блоков микроконтроллера - TWI (I2C), Timer/Counter2, Timer/Counter0, Timer/Counter1, SPI, USART0, ADC. По умолчанию (после сброса или включения питания) все биты в регистре PRR обнулены, что разрешает работу вышеперечисленного оборудования, в том числе и SPI.

PRSPI: Power Reduction Serial Peripheral Interface. Бит PRSPI в регистре PRR позволяет отключить интерфейс SPI (если записать в этот бит лог. 1) и тем самым снизить общее энергопотребление. Если используется встроенный аппаратный режим отладки (debugWIRE On-chip Debug System), этот бит должен быть записан в лог. 1. Запись в лог. 1 этого бита выключает SPI путем остановки тактирования этого модуля. Когда SPI снова выйдет из сна, он должен быть заново переинициализирован, чтобы обеспечить свое корректное функционирование.

Ниже показана диаграмма внутреннего устройства блока SPI.

AVR SPI block diagram

Рис. 19-1. Блок-диаграмма SPI.

ATmega328 DIP28 SPI pinout

Рис. 19-1a. Расположение (цоколевка) выводов микроконтроллера ATmega328P, задействованных под функцию SPI (SCK, MISO, MOSI, ~SS) для корпуса DIP28.

Примечание: цоколевку выводов SPI для других корпусов и других микроконтроллеров AVR см. даташит на соответствующий микроконтроллер. Для ATmega328 см. [4].

Как соединяются друг с другом устройства процессоры в режимах Master и Slave, показано на рис. 19-2. Система состоит их 2 регистров сдвига, и генератора тактов интерфейса, работающего на стороне устройства Master. SPI Master инициирует цикл обмена, когда переводит вывод выборки подчиненного устройства (Slave Select, ~SS) в лог. 0. Устройства Master и Slave подготавливают данные для отправки в их соответствующих регистрах сдвига, и Master генерирует на выводе SCK тактовые импульсы, необходимые для обмена данными. Данные всегда передаются в направлении от Master к Slave через вывод MOSI (Master Out – Slave In), и в обратном направлении всегда через вывод MISO (Master In – Slave Out). После передачи каждого пакета данных Master осуществляет синхронизацию устройства Slave путем перевода в лог. 1 вывода ~SS.

AVR SPI Master Slave interconnection

Рис. 19-2. Взаимодействие SPI Master - SPI Slave.

Master. Когда интерфейс SPI сконфигурирован в режиме Master, то нет автоматического управления состоянием сигнала ~SS. Это должно быть обработано программно кодом пользователя перед тем, как может начаться обмен данными. Когда линия ~SS сконфигурирована (соответствующее устройство Slave выбрано), запись байта в регистр данных SPI запустит генерацию тактов SPI, и аппаратура интерфейса выдвигает 8 бит и передает их устройству Slave. После того, как байт выдвинут, генератор тактов SPI останавливается, и установится флаг окончания передачи (SPIF). Если разрешено прерывание SPI (установкой бита SPI Interrupt Enable, SPIE в регистре SPCR, то будет выставлен запрос на прерывание. Master может продолжить передавать другие байты путем записи в регистр SPDR, или сигнализировать об окончании пакета переводом в лог. 1 вывода ~SS. Последний пришедший байт будет сохранен в буферном регистре для последующего использования.

Slave. Когда устройство сконфигурировано как Slave, интерфейс SPI будет оставаться в режиме сна, когда вывод MISO находится в третьем (отключенном) состоянии, пока вывод ~SS удерживается в лог. 1. В этом состоянии программа может обновить содержимое регистра данных (SPI Data Register, SPDR), но данные не будут передаваться наружу по тактам SCK, пока вывод ~SS не будет переведен в лог. 0. Как только один байт полностью сдвинут, будет установлен флаг окончания передачи SPIF. Если установлен бит разрешения прерывания (SPI Interrupt Enable bit, SPIE) в регистре SPCR, то будет выставлен запрос на прерывание. Slave может продолжить размещать новые данные для отправки в регистр SPDR перед чтением приходящих данных. Последний пришедший байт будет сохранен в буферном регистре для последующего использования.

В системе есть одиночная буферизация в направлении передачи и двойная буферизация в направлении приема. Это означает, что передаваемые байты не могут быть записаны в регистр данных SPI (SPI Data Register, SPDR), пока не будет осуществлен полный цикл сдвига текущего передаваемого байта. Однако когда принимаются данные, принятый символ должен быть прочитан из регистра данных SPI (SPDR) до того, как следующий байт будет вдвинут в интерфейс, иначе последний уже принятый байт будет потерян. В режиме SPI Slave управляющая логика будет отслеживать приходящий сигнал на выводе SCK. Чтобы гарантировать правильную работу этого сигнала, требуется выполнить условия для минимально допустимых длительностей тактового сигнала:

Длительность лог. 0 должна быть больше длительности 2 тактов ядра CPU.
Длительность лог. 1 должна быть больше длительности 2 тактов ядра CPU.

Когда SPI разрешен, направление работы сигналов выводов is MOSI, MISO, SCK и ~SS переназначается в соответствии с таблицей 19-1. Подробнее про автоматическое переназначение функций выводов см. "Альтернативные функции выводов порта" в статье [4].

Таблица 19-1. Как меняют свою функцию выводы SPI в зависимости от режима работы Master/Slave(1).

Вывод
Направление, Master SPI Направление, Slave SPI
MOSI Определяется пользователем (DDRxn) Вход
MISO Вход Определяется пользователем (DDRxn)
SCK Определяется пользователем (DDRxn) Вход
~SS Определяется пользователем (DDRxn) Вход

Примечание (1): для пунктов таблицы "Определено пользователем" направление работы выводов SPI зависит от настройки выводов порта B и их альтернативных функций (см. "Альтернативные функции выводов порта" в статье [4]).

В следующем коде показано, как инициализировать SPI в режиме Master, и как выполнить простую передачу. DDR_SPI в примерах заменяется действительным регистром, определяющим направление данных ножки вывода (это зависит от микроконтроллера, и может быть, к примеру DDRB, если применяется ATmega328). DD_MOSI, DD_MISO и DD_SCK должны быть заменены соответствующими номерами бит, определяющими ножки микроконтроллера. Например, если MOSI находится на ножке порта PB3 (как это у микроконтроллера ATmega328 [4]), то замените DD_MOSI на имя номера ножки порта DDB3 и замените DDR_SPI на имя регистра DDRB.

Пример кода на ассемблере:

SPI_MasterInit:
; Настройка MOSI и SCK как выход, все остальные сигналы как вход:
   ldi r17,(1 << DD_MOSI)|(1 << DD_SCK)
   out DDR_SPI,r17
; Разрешить работу SPI, режим Master, установить скорость тактов fck/16:
   ldi r17,(1 << SPE)|(1 << MSTR)|(1 << SPR0)
   out SPCR,r17
   ret
   
SPI_MasterTransmit:
; Запуск передачи данных (r16):
   out SPDR,r16
Wait_Transmit:
; Ожидание завершения передачи
   in r16, SPSR
   sbrs r16, SPIF
   rjmp Wait_Transmit
   ret

Пример кода на языке C:

void SPI_MasterInit(void)
{
   /* Настройка MOSI и SCK как выход,
      все остальные сигналы как вход: */
   DDR_SPI = (1 << DD_MOSI)|(1 << DD_SCK);
   /* Разрешить работу SPI, режим Master,
      установить скорость тактов fck/16: */
   SPCR = (1 << SPE)|(1 << MSTR)|(1 << SPR0);
}
 
void SPI_MasterTransmit(char cData)
{
   /* Запуск передачи данных: */
   SPDR = cData;
   /* Ожидание завершения передачи: */
   while(!(SPSR & (1 << SPIF)));
}

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

Для регистров ввода/вывода, находящихся в расширенной области адресного пространства AVR (extended I/O map), инструкции IN, OUT, SBIS, SBIC, CBI и SBI должны быть заменены на инструкции, которые позволяют получить доступ в эту область. Обычно инструкции LDS и STS комбинируются с SBRS, SBRC, SBR и CBR.

Следующие примеры кода показывают инициализацию SPI в режиме Slave, и показывают как выполнить простейший прием данных.

Пример кода на ассемблере:

SPI_SlaveInit:
; Настройка ножки порта MISO как выход,
; все остальные сигналы как вход:
   ldi r17,(1 << DD_MISO)
   out DDR_SPI,r17
; Разрешить работу SPI:
   ldi r17,(1 << SPE)
   out SPCR,r17
   ret
   
SPI_SlaveReceive:
; Ожидание завершения приема:
   in r16, SPSR
   sbrs r16, SPIF
   rjmp SPI_SlaveReceive
; Чтение принятых данных и возврат:
   in r16,SPDR
   ret

Пример кода на языке C:

void SPI_SlaveInit(void)
{
   /* Настройка ножки порта MISO как выход,
      все остальные сигналы как вход: */
   DDR_SPI = (1 << DD_MISO);
   /* Разрешить работу SPI: */
   SPCR = (1 << SPE);
}
 
char SPI_SlaveReceive(void)
{
   /* Ожидание завершения приема: */
   while(!(SPSR & (1 << SPIF)));
   /* Чтение принятых данных и возврат: */
   return SPDR;
}

[Функциональность вывода ~SS]

Slave Mode (подчиненное устройство SPI). Когда SPI сконфигурирован в режиме Slave, вывод порта для сигнала Slave Select (~SS) всегда автоматически настраивается как вход. Когда ~SS находится в лог. 0, активируется блок SPI, и вывод MISO становится выходом (выходит из третьего состояния, или из состояния входа), если это было ранее сконфигурировано пользователем настройкой битов регистра DDRx. Все другие сигналы SPI остаются входами. Когда ~SS находится в лог. 1, то все выводы становятся входами, и блок SPI переходит в пассивное состояние, т. е. он не будет принимать данные. Обратите внимание, что логика SPI будет сброшена, когда сигнал ~SS переводится в лог. 1.

Вывод ~SS полезно использовать для синхронизации пакета / байта, чтобы сохранить соответствие между счетчиком бит подчиненного устройства SPI и генератором тактов фрейма главного устройства SPI. Когда ~SS переводится в лог. 1, подчиненное устройство SPI немедленно сбросит логику передачи и приема, и все частично принятые данные в регистре сдвига будут отброшены.

Master Mode (главное устройство SPI). Когда SPI сконфигурирован в режиме Master (установлен бит MSTR в регистре SPCR), пользователь может определить направление работы вывода ~SS (вход это будет или выход).

Если ~SS сконфигурирован как выход, то вывод становится обычным выходом GPIO, работа которого никак аппаратно не связано с блоком SPI. Обычно этим выводом можно программно управлять состоянием входного сигнала ~SS подчиненного устройства SPI.

Если ~SS сконфигурирован как вход, он должен удерживаться в состоянии лог. 1, чтобы мог работать Master SPI. Если вывод ~SS будет переведен в лог. 0 периферийными схемами, когда SPI сконфигурирован в режиме Master с ~SS работающим как вход, то блок SPI интерпретирует это состояние так, что другое главное устройство заняло шину SPI и начинает передавать данные подчиненному устройству. Эта ситуация относится к сценарию, когда на шине SPI имеется несколько главных устройств (Master), и они конкурируют друг с другом на доступ к подчиненному устройству SPI (Slave). Чтобы избежать коллизии на шине, блок SPI предпринимает следующие действия:

1. Бит MSTR в регистре SPCR очищается, и система SPI переходит в режим Slave. В результате устройство SPI переходит в режим Slave, и выводы MOSI и SCK становятся входами.
2. Устанавливается флаг SPIF в регистре SPSR, и если разрешено прерывание SPI, и I-бит в регистре SREG установлен (глобально разрешены прерывания), то запустится обработчик прерывания SPI.

Таким образом, если передача SPI в режиме Master работает под управлением прерываний, и есть возможность изменения входного лог. уровня сигнала ~SS, то прерывание должно всегда проверять, установлен ли все еще бит MSTR. Если бит MSTR был очищен выборкой подчиненного устройства, то он должен быть установлен программой пользователя, чтобы снова разрешить работу режима SPI Master.

[Режимы формата данных]

Имеется 4 возможные комбинации фазы и полярности SCK по отношению к последовательным данным, что управляется битами CPHA и CPOL регистра SPCR. Форматы передачи данных SPI показаны на рис. 19-3 и 19-4. Биты данных выдвигаются наружу и захватываются при приеме на противоположных перепадах сигнала SCK, что гарантирует достаточное количество времени для стабильной передачи сигналов данных. Форматы фрейма данных показаны на рис. 19-3 и 19-4, в соответствии с таблицей 19-2.

Таблица 19-2. Форматы данных SPI.

SPI mode Настройка Начальный перепад Конечный перепад
0 CPOL=0, CPHA=0 Выборка сигнала (нарастание уровня) Установка сигнала (спад уровня)
1 CPOL=0, CPHA=1 Установка сигнала (нарастание уровня) Выборка сигнала (спад уровня)
2 CPOL=1, CPHA=0 Выборка сигнала (спад уровня) Установка сигнала (нарастание уровня)
3 CPOL=1, CPHA=1 Установка сигнала (спад уровня) Выборка сигнала (нарастание уровня)

AVR SPI data format CPHA0

Рис. 19-3. Формат передачи SPI, когда CPHA = 0.

AVR SPI data format CPHA1

Рис. 19-4. Формат передачи SPI, когда CPHA = 1.

[Описание регистров]

Регистр управления SPI.

AVR SPCR

Bit 7 – SPIE: SPI Interrupt Enable

Этот бит, если он установлен в 1, разрешает выполниться обработчику прерывания SPI (если установился бит SPIF в регистре SPSR, и если разрешены глобальные прерывания установкой I-бита в регистре SREG).

Bit 6 – SPE: SPI Enable

Когда бит SPE установлен в лог. 1, то работа SPI разрешена.

Bit 5 – DORD: Data Order

Когда в бит DORD записана лог. 1, то первым будет передан младший бит (Least Significant Bit, LSB) 8-битного слова данных. Когда DORD сброшен в лог. 0 (состояние по умолчанию), сначала будет передаваться старший бит (Most Significant Bit, MSB).

Bit 4 – MSTR: Master/Slave Select

Этот бит выберет режим Master SPI, когда в него записана лог. 1, и режим Slave SPI, когда в него записан лог. 0. Если ~SS сконфигурирован как вход и подтянут к лог. 0, когда установлен в лог. 1 бит MSTR, то бит MSTR сбросится в лог. 0, и установятся бит SPIF в регистре SPSR. Для того, чтобы снова заработал режим Master, пользователь должен программно установить бит MSTR.

Bit 3 – CPOL: Clock Polarity

Когда этот бит записан в лог. 1, SCK находится на уровне лог. 1 в состоянии ожидания. Когда в CPOL записан лог. 0, то SCK в состоянии ожидания будет на уровне лог. 0. См. рис. 19-3 и 19-4 для примера. Функциональность CPOL показана в таблице ниже:

Таблица 19-3. Как работает CPOL.

CPOL Начальный перепад Конечный перепад
0 Нарастание уровня Спад уровня
1 Спад уровня Нарастание уровня

Bit 2 – CPHA: Clock Phase

Установка бита фазы (CPHA) определяет, как будет считываться бит данных - по начальному (первому) или по завершающему (последнему) перепаду уровня SCK. См. рис. 19-3 и 19-4 для примера. Функциональность CPHA показана в таблице ниже:

Таблица 19-3. Как работает CPOL.

CPHA Начальный перепад Конечный перепад
0 Считывание уровня данных Установка уровня данных
1 Установка уровня данных Считывание уровня данных

Bits 1, 0 – SPR1, SPR0: выбор скорости следования тактов SPI

Эти два бита управляют частотой следования импульсов SCK, когда устройство сконфигурировано как Master. SPR1 и SPR0 не оказывают никакого влияния, когда устройство сконфигурировано как Slave. Зависимость частоты тактов SCK и частоты генератора тактов системы (Oscillator Clock frequency, fOSC) показана в таблице:

SPI2X SPR1 SPR0 Частота SCK
0 0 0 fOSC/4
0 0 1 fOSC/16
0 1 0 fOSC/64
0 1 1 fOSC/128
1 0 0 fOSC/2
1 0 1 fOSC/8
1 1 0 fOSC/32
1 1 1 fOSC/64

Регистр состояния SPI.

AVR SPSR

Bit 7 – SPIF: SPI Interrupt Flag

Когда завершена передача фрейма данных, устанавливается флаг SPIF. Если бит SPIE в регистре SPCR установлен, и разрешены глобальные прерывания, то запустится обработчик прерывания. Если ~SS настроен как вход в режиме SPI Master, и вход ~SS переведен в лог. 0, то это событие также установит флаг SPIF. SPIF очищается аппаратно, когда выполнится соответствующий обработчик прерывания. Альтернативно бит SPIF очищается первым чтением регистра состояния SPSR, когда бит SPIF установлен, и последующим доступом к регистру данных SPI (SPDR).

Bit 6 – WCOL: Write COLlision Flag

Бит WCOL установится, если в регистр данных SPI (SPDR) записаны данные в тот момент, когда осуществляется передача. Бит WCOL (и вместе с ним бит SPIF) очистятся первым чтением регистра состояния SPI с установленным битом WCOL, и последующим доступом к регистру данных SPI (SPDR).

Bit [5:1] – Reserved

Эти биты зарезервированы в ATmega48A/PA/88A/PA/168A/PA/328/P и всегда читаются как 0.

Bit 0 – SPI2X: Double SPI Speed Bit

Когда в этот бит записана лог. 1, то скорость SPI (т. е. частота тактов SCK) удваивается, когда SPI работает в режиме Master (см. таблицу 19-5). Это означает, что минимальный период SCK составит 2 такта ядра CPU. Когда SPI сконфигурирован как Slave, работа SPI гарантируется на частотах fOSC/4 или ниже.

Также интерфейс SPI микроконтроллеров ATmega48A/PA/88A/PA/168A/PA/328/P используется для последовательного внутрисхемного программирования (ISP), так что с помощью внешнего программатора ISP можно записать и прочитать память программ (FLASH), энергонезависимую память (EEPROM) и фьюзы (подробности см. в даташите на микроконтроллер).

Регистр данных SPI.

AVR SPDR

Регистр данных SPI предназначен для чтения / записи принимаемых и передаваемых данных. Регистр SPDR расположен в области файла регистров AVR, и служит для обмена данными с регистрами сдвига SPI. Запись в SPDR инициализирует данные для передачи. Чтение SPDR выполняет чтение буфера регистра сдвига SPI.

[Ссылки]

1. AVR151: настройка и использование SPI.
2. Интерфейс SPI.
3. ATmega328: USART в режиме SPI.
4. GPIO и альтернативные функции порта.