Вы здесь

AVR320: Программная реализация интерфейса SPI в режиме ведущего (мастера)

SPIПредставленная здесь статья сохранила структуру исходного документа. Основным мотивом написания статьи стало прочтение перевода исходной статьи на сайте gaw.ru, однако, обнаружив много неточностей, я решил написать свой вариант. Любые замечания, дополнения и предложения по улучшению представленного здесь материала приветствуются.


Особенности реализации

  • Скорость до 444 кбайт/сек. при тактовой частоте 10 МГц
  • Поддержка записи больших блоков данных
  • Легко расширяется для работы с несколькими ведомыми SPI-устройствами
  • Работает в режиме 0 интерфейса SPI
  • Код исходно работает с 16-разрядными данными, но легко преобразуется для работы с 8-разрядными данными
  • Не требует использования прерываний
  • Малое число задействованных регистров: всего необходимо три регистра (два в 8-разрядном режиме)
  • Малый размер кода: 35 слов, включая инициализацию
  • Поддержка последовательных ЭСППЗУ AT25xxx производства Atmel

Введение

Стандарт SPI наращивает свою популярность за счет возможности организации более быстродействующей связи по сравнению с двухпроводными интерфейсами, а также за счет простоты реализации на кристалле полупроводника. Хотя большинство старших представителей семейства AVR содержат в своем составе полнофункциональный интерфейс SPI, в младшие версии он не входит. В данном документе описывается набор процедур, написанных на языке низкого уровня, реализующих программно протокол SPI в режиме ведущего (мастера). Данная разработка может использоваться для организации доступа к последовательной памяти ЭСППЗУ семейства 25XXX производства Atmel, а также для связи с другими ведомыми (подчинёнными) периферийными устройствами, например, с контроллером индикатора или другим микроконтроллером.

Пример подключения к AVR-микроконтроллеру подчиненного устройства

Рисунок 1. Пример подключения к AVR-микроконтроллеру подчиненного устройства (последовательное ЭСППЗУ)

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

Рисунок 2. Временная диаграмма интерфейса SPI

Теоретические сведения

Режим 0 интерфейса SPI подразумевает выполнение следующих условий:

  1. Линия SCK в режиме холостого хода (Idle) должна быть установлена в 0.
  2. Линия MOSI должна удерживать свое состояние в течение определенного промежутка времени (tSETUP) перед нарастающим фронтом тактового сигнала SCK.
  3. Линия MISO должна удерживать свое состояние в течение некоторого времени (tVALID) после ниспадающего фронта тактового сигнала SCK.
  4. Первым всегда должен передаваться самый старший бит (MSB).

Рассматриваемые ниже процедуры написаны с учетом этих требований. Особое внимание уделено граничным условиям, таким как tVALID и tSETUP. Эти временные параметры рассмотрены ниже.

Блок-схема алгоритма работы интерфейса SPI в режиме ведущего

Рисунок 3. Блок-схема алгоритма работы интерфейса SPI в режиме ведущего (мастера)

Описание подпрограмм

init_spi

Данная подпрограмма инициализирует линии порта SPI. Изначально предполагается, что под интерфейс SPI отведены линии порта B. Если планируется использовать другой порт, следует отредактировать используемые в процедуре макросы (подробнее смотри раздел "Макросы" ниже в этом документе). При необходимости также можно изменить соответствие между линиями интерфейса SPI и линиями порта ввода/вывода задавая значения EQU для SCK, MOSI, MISO и SS в разделе программы “PORT DEFINITIONS”. Данная подпрограмма не имеет ни входных, ни выходных параметров.

ena_spi

Данная подпрограмма сначала устанавливает линию SCK в 0 (в соответствии с режимом 0 интерфейса SPI), а потом устанавливает линию SS в 0, активируя ведомое устройство). Она не имеет ни входных, ни выходных параметров.

disa_spi

Данная подпрограмма устанавливает линию SS в 1, отключая ведомое устройство. Это необходимо для предотвращения ложного тактирования ведомого устройства. Вызывается после завершения передачи данных. Также не имеет ни входных, ни выходных параметров.

rw_spi

Эта подпрограмма отсылает/принимает 16-ти разрядный блок данных (или 8-ми разрядный, если в исходный код были внесены соответствующие изменения). После возврата управления этой функцией линия SCK установлена в 0. Состояние линии SS не изменяется, что делает возможным передачу большого блока данных просто вызвав эту подпрограмму многократно. Передаваемые данные необходимо до вызова этой подпрограммы поместить в регистр spi_lo (и spi_hi, если используется 16-ти разрядный режим). После завершения работы этой подпрограммы принятые от ведомого устройства данные будут содержаться в этих же регистрах.

Модификация для 8-ми разрядного формата передаваемых данных

При необходимости использования 8-разрядного формата передаваемых данных требуется изменить всего 2 строки программы. Оба изменения касаются подпрограммы rw_spi. Первое – начальное значение счётчика бит необходимо изменить с 16 на 8, второе – строку “rol spi_hi” необходимо закомментировать. Следует отметить, что в этом случае регистр spi_hi не нужен и в дальнейшем этой программой не используется. Его можно задействовать для других целей.

Макросы

Макросы используются для того, чтобы сделать код более читаемым. Исходно предполагается, что для интерфейса SPI будут задействованы линии порта B. Если планируется использовать другой порт, следует самостоятельно изменить имя порта в макросах ss_active, ss_inactive, sck_hi, sck_lo, mosi_hi, mosi_lo, а так же четыре строки в подпрограмме init_spi, в которых используется регистр ddrb, который нужно заменить на соответствующий регистр установки направления данных выбранного вами порта. Например, для порта A вместо регистра ddrb следует указать регистр ddra. Линии порта ввода/вывода, задействованные под четыре сигнала порта SPI, определены в разделе “PORT DEFINITIONS” и могут быть легко изменены.

Макрокоманда функции задержки требует дополнительного разъяснения. Двойное назначение регистра TEMP позволило исключить необходимость применения дополнительных регистров. Регистр TEMP используется для хранения значения 5-разрядного счетчика задержки (младшие 5 разрядов регистра TEMP) и счетчика для задания длительности высокого и низкого уровней сигнала SCK (старшие 3 разряда регистра TEMP). За счет простого увеличения старших трех разрядов и определения переполнения можно задавать временные интервалы, не влияя на младшие 5 разрядов. Обратите внимание, что фактически выполняется операция вычитания вместо сложения. Конечный результат тот же, за исключением того, что флаг переноса C сбрасывается (а не наоборот), когда значение старших трех бит изменяется из 7 в 0.

Временная диаграмма установки и удержания данных

Рисунок 4. Временная диаграмма установки и удержания данных

Время установки данных

Временная задержка с момента установки уровня на линии MOSI до нарастающего фронта на линии SCK является критичным параметром и составляет время установки данных (tSETUP) для подключенного ведомого устройства. В данной подпрограмме длительность времени установки данных составляет 2 цикла при изменении линии MOSI в низкий уровень и 3 цикла при изменении линии MOSI в высокий уровень. При тактовой частоте 10 МГц это время составляет 200-300 нс. Если требуется более длительная задержка, необходимо добавить команды NOP непосредственно перед макрокомандой sck_hi.

Цикл SCK

На линии SCK большую часть времени присутствует логический ноль. Это обусловлено тем, что логический ноль установлен на этой линии во время "накладных расходов" цикла передачи данных.

Если подключенное периферийное устройство может работать на высокой скорости, время высокого уровня (tHILO) может быть уменьшено в соответствии со спецификациями на периферийное устройство и интерфейс SPI. Если значение задержки установлено в 1 (по умолчанию установлено значение 4, смотри параметр макрокоманды set_delay перед меткой time_hi), подпрограмме требуется в среднем 22,5 тактов для передачи одного бита данных. При этом высокий уровень на линии SCK сохраняется в течении 4 тактов. При частоте тактового генератора 10 МГц время пребывания высокого уровня на линии SCK составляет 400 нс, а общая пропускная способность шины будет около 444 килобайт в секунду.

Длительность присутствия низкого уровня на линии SCK (tVALID) определяется требованием периферийного устройства к параметру, который, как правило, называется "SCK fall to MISO (slave data out) Valid". При значении задержки, равной 1 (по умолчанию установлено значение 4, смотри параметр макрокоманды set_delay перед меткой time_lo), эта подпрограмма считает значение на линии MISO, установленное периферийным устройством, через 3 цикла. При той же частоте тактового генератора в 10 МГц эта задержка составит 300 нс. Увеличить время этой задержки можно увеличив значение задержки, передаваемой в качестве параметра макроса set_delay.

Исходный код программы

;**** A P P L I C A T I O N   N O T E   A V R 3 2 0 *****************
;*
;* Title    : Software SPI Master
;* Version    : 1.0
;* Last updated    : 98.04.21
;* Target    : AT90S1200
;* Easily modified for  : Any AVR microcontroller
;*
;* Support E-mail  :avr[dog]atmel.com
;*
;* DESCRIPTION
;*  This is a collection of 8/16-bit word, Mode 0, Master SPI routines.
;*  It simultaneously transmits and receives SPI data in 8- or 16-bit
;*  word format.  Data is sent and received MSB-first.  One pair of
;*  registers is used both to send and to receive; i.e., when one bit
;*  is shifted out (transmitted), the vacated bit position is used to
;*  store the new received bit.  These routines are low-level
;*  interface routines, and do not inherently contain a command
;*  structure; that is dictated by the connected SPI peripheral(s).
;*
;*  Due to having separate Enable/Disable and Read/Write-Word
;*  routines, larger blocks of data can be sent simply by calling
;*  the RW_SPI routine multiple times before disabling /SS.
;*
;* MAJOR ROUTINES:
;*  init_spi: initializes the port lines used for SPI.
;*      No calling requirements, returns nothing.
;*  ena_spi:  forces SCK low, and activates /SS signal.
;*      No calling requirements, returns nothing.
;*  disa_spi: brings /SS signal hi (inactive).
;*      No calling requirements, returns nothing.
;*  rw_spi:   sends/receives a an 8-bit or 16-bit data word.
;*      Must set up data to be sent in (spi_hi,spi_lo)
;*      prior to calling; it returns received data in
;*      the same register pair (if 8-bit, uses only
;*      the spi_lo register).
;*
;* VARIABLES:
;*  The spi_hi and spi_lo variables are the high and low data bytes.
;*  They can be located anywhere in the register file.
;*  
;*  The temp variable holds the bit count, and is also used in timing
;*      the high/low minimum pulse width.  This must be located in an
;*  upper register due to the use of an IMMEDIATE-mode instruction.
;*
;* HISTORY
;*  V1.0  98.04.21 (rgf)  Created
;*    
;***************************************************************************
 
 
 
;**** includes ****
 
.include "1200def.inc"    ;you can change this to any device
 
 
 
 
;***************************************************************************
;*
;* CONSTANTS
;*
;***************************************************************************
 
;**** Revision Codes ****
 
.equ  SW_MAJOR = 1    ; Major SW revision number
.equ  SW_MINOR = 0    ; Minor SW revision number
.equ  HW_MAJOR = 0    ; Major HW revision number
.equ  HW_MINOR = 0    ; Minor HW revision number
 
 
 
;***************************************************************************
;*
;* PORT DEFINITIONS
;*
;***************************************************************************
 
.equ  sck  = 0    ;PB0 pin
.equ  nss  = 1    ;PB1 pin
.equ  mosi  = 2    ;PB2 pin
.equ  miso  = 3    ;PB3 pin
 
 
 
;***************************************************************************
;*
;* REGISTER DEFINITIONS
;*
;***************************************************************************
 
.def  spi_lo  =r0  ;change as needed
.def  spi_hi  =r1  ;  "
.def  temp  =r16  ;misc usage, must be in upper regs for IMMED mode
 
 
 
 
;***************************************************************************
;*
;* MACROS
;*  Program Macros
;*
;* DESCRIPTION
;*  Change the following macros if a port other than PORTB is used.
;*
;***************************************************************************
 
.macro  ss_active
  cbi  portb,nss
.endm
 
 
.macro  ss_inactive
  sbi  portb,nss
.endm
 
 
.macro  sck_hi
  sbi  portb,sck
.endm
 
 
.macro  sck_lo
  cbi  portb,sck
.endm
 
 
.macro  mosi_hi
  sbi  portb,mosi
.endm
 
 
.macro  mosi_lo
  cbi  portb,mosi
.endm
 
 
.macro  addi
  subi  @0, -@1    ;subtract the negative of an immediate value
.endm
 
.macro  set_delay    ;set up the time delay amount, from 1 to 7
  subi  @0, (@1 
Tags: 
AVR, SPI
"Престиж" для семьи семейные пары, няня и няня агенство.