|
Отправляю пакет пр SPI |
|
|
|
 |
Ответов
(1 - 9)
|
May 9 2006, 16:55
|

Мастер
   
Группа: Свой
Сообщений: 730
Регистрация: 18-02-06
Из: Москва
Пользователь №: 14 474

|
Насколько я понял, SPI замкнут сам на себя.
У меня тоже есть подобная проблема, но я пока грешу на передатчик. В чем дело у меня, отпределю уже только на работе (дома ни осциллоскопа, ни даже мультиметра). Но симптомы похожие: при приеме пропадает первый бит данных (MSB), количество бит и их положение в байте корректные (пробовал и опрос в цикле, и по DMA).
Все-таки поддерживаю GetSmart, конкретизируйте немного, как настроен SPI, как подключен.
--------------------
شامل
|
|
|
|
|
May 9 2006, 18:32
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Даю вырезки для работы с SPI LPC213x. Подойдёт и ко многим другим. С AT91 не знаком, так что немного переделаете. Вообще, процедуры написаны так, чтобы максимально использовать скорость процессора. То есть во время передачи байта можно выполнять другие действия.
Процедуры инициализации:
#define PCLKFREQ 14745600*4
void LPC213xInitSPI0Master() { PINSEL0 = (PINSEL0 & ~0xff00) | 0x1500; // for SCK0, MISO, MOSI, SSEL- SPCCR0 = PCLKFREQ / 921600; // скорость = 0.6912 MHz (~80 КБ/сек) SPCR0 = 0x20; if (SPSR0) {}; // просто чтение для сброса флага SPIF SPDR0 = '!'; // это чтобы изначально бит SPIF (TDRE) установился }
void txByteSPI0(long byte) { if (SPSR0) {} // просто чтение для сброса флага SPIF SPDR0 = byte; }
long rxtxByteSPI0(long byte) { for(uInt i=0; i<0x10000; i++) // 1/50 sec - это на всякий случай. Всё бывает на свете! if (SPSR0_bit.SPIF) // это бит завершения передачи байта в мастере (и приёма в слэйве) { long j = SPDR0; if (byte >= 0) SPDR0 = byte; return(j); } LPC213xInitSPI0Master(); return(0); }
Рабочие процедуры:
void READ_ADS1218(uInt cmd, uInt cnt, uByte *ptr) { _ON_CS_ADS1218; txByteSPI(cmd); rxtxByteSPI(cnt-1); _WAIT(_50Tosc); rxtxByteSPI(0); while (cnt--) if (cnt) *ptr++ = rxtxByteSPI(0); else *ptr = rxtxByteSPI(-1); // завершение передачи _OFF_CS_ADS1218; }
Пояснение: В моей схеме был режим мастер, а вывод SSEL вообще не использовался. Сначала вручную сбрасывается сигнал ~CS на нужное внешнее устройство. Затем вызывается процедура передачи первого байта без анализа флагов (txByteSPI0(long byte)). После сколько угодно раз процедуру уже анализирующую флаги (rxtxByteSPI0(long byte)). Однако в конце нужно вызывать её же с параметром (-1). Она при этом ничего не передаёт, а просто ждёт завершения передачи последнего байта. После этого уже можно обратно вручную устанавливать вывод ~CS в еденицу (_OFF_CS_ADS1218).
Если не выжимать из процессора максимум скорости, то можно было бы сделать немного попроще. Но мне так больше нравится.
Если нужно просто выкинуть в SPI 6 байт то вот пример:
void Write6bytesSPI(uByte *ptr) { _ON_CS_ADS1218; txByteSPI(*ptr++); for (uInt i=0; i<5; i++) // здесь выкинуть именно 5, а не 6 байт. т.к. один уже выкинут rxtxByteSPI(*ptr++); rxtxByteSPI(-1); // завершение передачи _OFF_CS_ADS1218; }
Кстати, процедура (rxtxByteSPI0(long byte)) передаёт новый байт в SPI, но возвращает как бы предыдущий принятый байт. Осторожно!
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
May 10 2006, 19:26
|

Мастер
   
Группа: Свой
Сообщений: 730
Регистрация: 18-02-06
Из: Москва
Пользователь №: 14 474

|
Итак, я провел анализ на работе, у меня, как и предполагалось, "виноват" передатчик. SAM'овский SPI отрабатывает на прием все как задумано. Могу привести свои исходники, но они для Slave-режима и только на прием (без передачи). Вряд ли Вам будет это интересно. Однако для справки могу сказать, что когда писал свою программу, ориентировался на пример отсюда. Скорректировал под себя, разумеется (пришлось подробно ознакомиться с даташитом), но заработало с первого раза (SPI под ARM вообще делаю первый раз  ).
--------------------
شامل
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|