Yaumen 0 18 августа, 2015 Опубликовано 18 августа, 2015 · Жалоба Есть некое устройство (МАСТЕР) которое каждые 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 } Что я делаю не так? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Gorby 6 18 августа, 2015 Опубликовано 18 августа, 2015 · Жалоба Что я делаю не так? Разберитесь с условием while (SSP0MIS_RXMIS & SSP0MIS). Очевидно же, что следующий байт придет только через достаточно большой интервал времени (относительно скорости процессора). Получается, вы несколько раз считываете один и тот же байт. Убедитесь, что при чтении первого байта сбрасывается флаг готовности. А вообще как-то стремно: прерывание вызывается для каждого принятого байта отдельно, но внутри прерывания вы пытаетесь вычитать более одного. Разберите более подробно как работает m_SSP0.Read(). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Yaumen 0 18 августа, 2015 Опубликовано 18 августа, 2015 · Жалоба Похоже, что проблема в том, что каждый байт передаваемый МАСТЕРОМ должен стробироваться сигналом SSEL, т.е. после каждого байта необходимо подымать SSEL в высокий, а затем опять ставить его в низкий. Мне такой режим не подходит, так как МАТЕР выставляет SSEL на время передачи всех 4-х байт и не стробирует каждый из них. Возможно надо использовать какой-либо другой режим работы SSP0, чтобы он был нечувствителен к стробированию сигналом SSEL? Разберитесь с условием while (SSP0MIS_RXMIS & SSP0MIS). Очевидно же, что следующий байт придет только через достаточно большой интервал времени (относительно скорости процессора). Получается, вы несколько раз считываете один и тот же байт. Убедитесь, что при чтении первого байта сбрасывается флаг готовности. А вообще как-то стремно: прерывание вызывается для каждого принятого байта отдельно, но внутри прерывания вы пытаетесь вычитать более одного. Разберите более подробно как работает m_SSP0.Read(). А что тут стремного, для SSP есть буфер FIFO, пока я работаю с обработкой одного прерывания, по SSP может уже прийти несколько байт, вот и вычитываю, пока входной буфер не опустеет. Нормальная практика!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Gorby 6 18 августа, 2015 Опубликовано 18 августа, 2015 · Жалоба Похоже, что проблема в том, что каждый байт передаваемый МАСТЕРОМ должен стробироваться сигналом SSEL, т.е. после каждого байта необходимо подымать SSEL в высокий, а затем опять ставить его в низкий. Вот это действительно странно. Нет никакой необходимости стробировать с SSEL каждый байт. У вас верно сделано, SSEL на время передачи всех 4-х байт. Приемник обязан принимать. То, что первый байт принимается верно, подтверждает правильность выбранных режимов (там еще те грабли могут быть). А что тут стремного, для SSP есть буфер FIFO, пока я работаю с обработкой одного прерывания, по SSP может уже прийти несколько байт, вот и вычитываю, пока входной буфер не опустеет. Нормальная практика!!! А вот тут немного не так. На самом деле при SPI тактовой (сколько там у вас? 40 кГц?) принятие символа - очень редкое событие. Это не 2 и не 10 MHz. Попробуйте сделать одно прерывание на один байт. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Yaumen 0 18 августа, 2015 Опубликовано 18 августа, 2015 · Жалоба Похоже, что проблема в том, что каждый байт передаваемый МАСТЕРОМ должен стробироваться сигналом 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-ом. Вот засада!!! Кто же знал!? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 241 20 августа, 2015 Опубликовано 20 августа, 2015 · Жалоба while (SSP0MIS_RXMIS & SSP0MIS) Что я делаю не так? С чего это Вы наличие данных в FIFO определяете по регистру запросов прерывания??? Он тут вообще не при чём. Наличие данных в FIFO определяется по регистру статуса SSP (и соотв. флагу в нём). А запрос прерывания надо просто сбросить через регистр сброса в начале ISR. Да!!! Так и есть, каждый байт надо обязательно стробировать импульсом CS. Можно ли это отключить - не знаю, перепробовав различные режимы, так и не смог заставить работать как надо. Придется связываться с разработчиком МАСТЕРА, чтобы узнать возможно ли изменить его программу, чтобы каждый передаваемый байт стробировался CS. Если кто-то знает способ как заставить LPC2366 работать без этой фичи или еще лучше вообще без использования SSEL, буду весьма признателен!!! Оставьте разработчика мастера в покое. Всё прекрасно умеет LPC работать в любом режиме. Единственный косяк с которым сталкивался в slave-SPI LPC - сигнал SSEL необходимо обязательно посадить на GND, даже если он не используется. Ну, или, если мастер выдаёт этот сигнал, подать его на соотв. ногу LPC. PS: Читайте внимательнее мануал на SSP LPC. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 23 августа, 2015 Опубликовано 23 августа, 2015 (изменено) · Жалоба Всё прекрасно умеет LPC работать в любом режиме. В режимах приёмника с CPHA=0 действительно после каждого переданного байта нужно "дрыгать" SSEL через HIGH состояние. Изменено 23 августа, 2015 пользователем GetSmart Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 241 23 августа, 2015 Опубликовано 23 августа, 2015 · Жалоба В режимах приёмника с CPHA=0 действительно после каждого переданного байта нужно "дрыгать" SSEL через HIGH состояние. Разговор идёт о slave-SPI, который по определению не может управлять SSEL. И в одном из проектов у меня был slave-SPI на LPC (правда LPC17xx, но он совпадает с тем что был в LPC23xx насколько я помню). Так вот - не помню какой там у меня был CPHA, но SSEL просто посадили на GND и всё (мастер не выдавал CS) и каждый байт ни чем не дрыгали. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 23 августа, 2015 Опубликовано 23 августа, 2015 · Жалоба Так вот - не помню какой там у меня был CPHA, но SSEL просто посадили на GND и всё (мастер не выдавал CS) и каждый байт ни чем не дрыгали. Не помню - железный аргумент. PS: Читайте внимательнее мануал на SSP LPC. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 241 23 августа, 2015 Опубликовано 23 августа, 2015 · Жалоба Не помню - железный аргумент. И что Вы этим хотели сказать? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 24 августа, 2015 Опубликовано 24 августа, 2015 · Жалоба И что Вы этим хотели сказать? Вторая часть поста. "Дрыгать" должен мастер из-за аппаратных особенностей слэйва, работающего в режиме CPHA=0. Если по какой-то причине слэйв не может работать в режиме с CPHA=1. Слово "приёмник" в моём посте следует читать как "слэйв". Слегка ошибся. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться