Перейти к содержанию
    

Помогите разобраться с SSP LPC2366 в режиме SLAVE

Есть некое устройство (МАСТЕР) которое каждые 20 мс по SPI (частота SCK = 50кГц) посылает команду состоящую из 4-х байт:

[HEADER = 0x69] [СОСТОЯНИЕ 1] [СОСТОЯНИЕ 2] [КОНТРОЛЬНАЯ СУММА]

 

В моем устройстве, выполненном на LPC2366, эта команда поступает на интерфейс SSP0, который я настроил на режим SLAVE.

    SSP0CPSR = ...;

    SSP0CR0 = 0x107; //8bit, SPI, CPOL=CPHA=0, SCR=1

        install_irq(SSP0_INT, (void*)SSP0Handler, HIGHEST_PRIORITY);

    SSP0CR1 = SSP0CR1_SSE|SSP0CR1_MS;        //SSP enabled in slave mode

        SSP0IMSC = 0x04; // Enable Receive Interrupt (RXIM only)

 

Прерывания от SSP срабатывают, однако сколько бы я не вычитывал SSP0DR, вычитывается только байт HEADER = 0x69, т.е весь массив bySpiData заполняется значениями 0x69

volatile BYTE bySpiData[256];
volatile BYTE bySpiIndex = 0;
volatile DWORD dwSpiReceived = 0;

void SSP0Handler (void) __irq 
{
    while (SSP0MIS_RXMIS & SSP0MIS)
    {    
        bySpiData[bySpiIndex++] = m_SSP0.Read() & 0xFF;
        dwSpiReceived++;
    }
    
    VICVectAddr = 0;            // Acknowledge Interrupt
}

 

Что я делаю не так?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что я делаю не так?

 

Разберитесь с условием while (SSP0MIS_RXMIS & SSP0MIS).

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

 

А вообще как-то стремно: прерывание вызывается для каждого принятого байта отдельно, но внутри прерывания вы пытаетесь вычитать более одного. Разберите более подробно как работает m_SSP0.Read().

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

 

Похоже, что проблема в том, что каждый байт передаваемый МАСТЕРОМ должен стробироваться сигналом SSEL, т.е. после каждого байта необходимо подымать SSEL в высокий, а затем опять ставить его в низкий.

Мне такой режим не подходит, так как МАТЕР выставляет SSEL на время передачи всех 4-х байт и не стробирует каждый из них.

Возможно надо использовать какой-либо другой режим работы SSP0, чтобы он был нечувствителен к стробированию сигналом SSEL?

 

Разберитесь с условием while (SSP0MIS_RXMIS & SSP0MIS).

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

 

А вообще как-то стремно: прерывание вызывается для каждого принятого байта отдельно, но внутри прерывания вы пытаетесь вычитать более одного. Разберите более подробно как работает m_SSP0.Read().

 

А что тут стремного, для SSP есть буфер FIFO, пока я работаю с обработкой одного прерывания, по SSP может уже прийти несколько байт, вот и вычитываю, пока входной буфер не опустеет. Нормальная практика!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Похоже, что проблема в том, что каждый байт передаваемый МАСТЕРОМ должен стробироваться сигналом SSEL, т.е. после каждого байта необходимо подымать SSEL в высокий, а затем опять ставить его в низкий.

Вот это действительно странно. Нет никакой необходимости стробировать с SSEL каждый байт. У вас верно сделано, SSEL на время передачи всех 4-х байт. Приемник обязан принимать. То, что первый байт принимается верно, подтверждает правильность выбранных режимов (там еще те грабли могут быть).

 

А что тут стремного, для SSP есть буфер FIFO, пока я работаю с обработкой одного прерывания, по SSP может уже прийти несколько байт, вот и вычитываю, пока входной буфер не опустеет. Нормальная практика!!!

А вот тут немного не так. На самом деле при SPI тактовой (сколько там у вас? 40 кГц?) принятие символа - очень редкое событие. Это не 2 и не 10 MHz. Попробуйте сделать одно прерывание на один байт.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Похоже, что проблема в том, что каждый байт передаваемый МАСТЕРОМ должен стробироваться сигналом SSEL, т.е. после каждого байта необходимо подымать SSEL в высокий, а затем опять ставить его в низкий.

Мне такой режим не подходит, так как МАТЕР выставляет SSEL на время передачи всех 4-х байт и не стробирует каждый из них.

Возможно надо использовать какой-либо другой режим работы SSP0, чтобы он был нечувствителен к стробированию сигналом SSEL?

 

 

 

А что тут стремного, для SSP есть буфер FIFO, пока я работаю с обработкой одного прерывания, по SSP может уже прийти несколько байт, вот и вычитываю, пока входной буфер не опустеет. Нормальная практика!!!

 

 

Да!!! Так и есть, каждый байт надо обязательно стробировать импульсом CS. Можно ли это отключить - не знаю, перепробовав различные режимы, так и не смог заставить работать как надо. Придется связываться с разработчиком МАСТЕРА, чтобы узнать возможно ли изменить его программу, чтобы каждый передаваемый байт стробировался CS.

Если кто-то знает способ как заставить LPC2366 работать без этой фичи или еще лучше вообще без использования SSEL, буду весьма признателен!!!

 

Вот это действительно странно. Нет никакой необходимости стробировать с SSEL каждый байт. У вас верно сделано, SSEL на время передачи всех 4-х байт. Приемник обязан принимать. То, что первый байт принимается верно, подтверждает правильность выбранных режимов (там еще те грабли могут быть).

 

 

А вот тут немного не так. На самом деле при SPI тактовой (сколько там у вас? 40 кГц?) принятие символа - очень редкое событие. Это не 2 и не 10 MHz. Попробуйте сделать одно прерывание на один байт.

 

Пробовал делать и так и так. Коду в принципе все равно, сколько байт пришло 1 или несколько, примет столько сколько есть в буфере. Когда подключил к своему МАСТЕРУ и начал стробировать данные, все заработало как часы.

Кстати в UserManual тоже нарисовано на графике Fig.93, что каждый байт должен стробироваться CS-ом. Вот засада!!! Кто же знал!?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

while (SSP0MIS_RXMIS & SSP0MIS)

Что я делаю не так?

С чего это Вы наличие данных в FIFO определяете по регистру запросов прерывания??? Он тут вообще не при чём. Наличие данных в FIFO определяется по регистру статуса SSP (и соотв. флагу в нём).

А запрос прерывания надо просто сбросить через регистр сброса в начале ISR.

 

Да!!! Так и есть, каждый байт надо обязательно стробировать импульсом CS. Можно ли это отключить - не знаю, перепробовав различные режимы, так и не смог заставить работать как надо. Придется связываться с разработчиком МАСТЕРА, чтобы узнать возможно ли изменить его программу, чтобы каждый передаваемый байт стробировался CS.

Если кто-то знает способ как заставить LPC2366 работать без этой фичи или еще лучше вообще без использования SSEL, буду весьма признателен!!!

Оставьте разработчика мастера в покое. Всё прекрасно умеет LPC работать в любом режиме.

Единственный косяк с которым сталкивался в slave-SPI LPC - сигнал SSEL необходимо обязательно посадить на GND, даже если он не используется. Ну, или, если мастер выдаёт этот сигнал, подать его на соотв. ногу LPC.

 

PS: Читайте внимательнее мануал на SSP LPC.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Всё прекрасно умеет LPC работать в любом режиме.

В режимах приёмника с CPHA=0 действительно после каждого переданного байта нужно "дрыгать" SSEL через HIGH состояние.

Изменено пользователем GetSmart

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В режимах приёмника с CPHA=0 действительно после каждого переданного байта нужно "дрыгать" SSEL через HIGH состояние.

Разговор идёт о slave-SPI, который по определению не может управлять SSEL.

И в одном из проектов у меня был slave-SPI на LPC (правда LPC17xx, но он совпадает с тем что был в LPC23xx насколько я помню).

Так вот - не помню какой там у меня был CPHA, но SSEL просто посадили на GND и всё (мастер не выдавал CS) и каждый байт ни чем не дрыгали.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так вот - не помню какой там у меня был CPHA, но SSEL просто посадили на GND и всё (мастер не выдавал CS) и каждый байт ни чем не дрыгали.

Не помню - железный аргумент.

PS: Читайте внимательнее мануал на SSP LPC.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И что Вы этим хотели сказать?

Вторая часть поста.

 

"Дрыгать" должен мастер из-за аппаратных особенностей слэйва, работающего в режиме CPHA=0. Если по какой-то причине слэйв не может работать в режиме с CPHA=1. Слово "приёмник" в моём посте следует читать как "слэйв". Слегка ошибся.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...