Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: FT2233H в SPI режиме обеспечивает дуплекс?
Форум разработчиков электроники ELECTRONIX.ru > Интерфейсы > Форумы по интерфейсам > RS232/LPT/USB/PCMCIA/FireWire
misyachniy
В AN 135: http://www.ftdichip.com/Support/Documents/...SPI_Example.pdf,
написано следующее:
Цитата
"Full duplex data transfers can be made up to 30 Mbits/sec with the FT2232H. There is no fixed bit length in
SPI. A generic SPI system consists of the following signals and is illustrated in Figure 1."

В примере есть отдельные функции чтения и записи по SPI.
Обмена в дуплексном режиме я не нашел.
В функции чтения есть возможность передать управляющий поток бит WriteControlBuffer, а затем прочитать ответ устройства на него -ReadDataBuffer.
Цитата
Status = SPI_ReadHiSpeedDevice(ftHandle, &ReadStartCondition, true, false, NUM_93LC56B_CMD_CONTOL_BITS,
&WriteControlBuffer, NUM_93LC56B_CMD_CONTOL_BYTES, true, false, NUM_93LC56B_CMD_DATA_BITS, ReadDataBuffer,
&dwNumDataBytesReturned, &HighPinsWriteActiveStates);

Тут автор корневого поста пишет, что дуплекс есть.
http://www.edaboard.com/thread114333.html
Цитата
Since SPI is a full duplex transfer

Fruity 4 часа пытался организовать дуплекс, но результата не получил.
Цитата
I actually have a similar question about FT2232 ( I am using the FT2232H but the principle is the same ).

I am trying to use the bidirectional feature of SPI.
I want to send one byte via MOSI while receiving one byte via MISO, so all that in 8 SPI CLK.

I have searched and searched for hours, and can't make it work. It is has if everything was always half duplex.


В режме запись/чтение я с этим чипом работал много, почти год. "Лишних байт" не получал и не принимал.
Сейчас понадобился дуплекс. Я пробовал читать с нулевой и ненулевой длиной "WriteControlBuffer"
При чтении с нулевой длиной, читается требуемые мне 6 байт, при добавлении 6 байтной команды - посылка удлиняется в два раза.

Так есть дуплекс или нет?


ReAl
Дуплекс у всех c MPSSE есть.
Ну например — при программировании AVR во время посылки третьего байта команды входа в программирование нужно прочитать назад копию второго байта, служащую признаком успешного входа в программирование.

Но я врукопашную всё делаю, напрямую обращаясь к FTD2XX.DLL / libftd2xx.so

Код
void spi_ftdi_mpsse_t::io(const uint8_t *obuf, uint8_t *ibuf, size_t len)
{
    uint8_t buffer[4 * 4096 + 4];

    buffer[0] = shift_mode | ftdi_chip_t::MPSSE_WRITE_TDI | ftdi_chip_t::MPSSE_READ_TDO;
    buffer[1] = len - 1;
    buffer[2] = (len - 1) >> 8;
    memcpy(buffer + 3, obuf, len);
    buffer[len + 3] = ftdi_chip_t::MPSSE_SEND_IMMEDIATE;

    ft2232_->write(buffer, len + 4); // "send SPI data"
    ft2232_->read(ibuf, len); // "receive SPI data"
}

Код
void  spi_ftdi_mpsse_t::out(const uint8_t *obuf, size_t len)
{
    uint8_t buffer[4096 + 3];

    buffer[0] = shift_mode | ftdi_chip_t::MPSSE_WRITE_TDI;
    buffer[1] = len - 1;
    buffer[2] = (len - 1) >> 8;
    memcpy(buffer + 3, obuf, len);

    ft2232_->write(buffer, len + 3); // "send SPI data"
}

Код
void spi_ftdi_mpsse_t::in(uint8_t *ibuf, size_t len)
{
    uint8_t buffer[] = {
        shift_mode | ftdi_chip_t::MPSSE_READ_TDO,
        len - 1,
        (len - 1) >> 8,
        ftdi_chip_t::MPSSE_SEND_IMMEDIATE
    };

    ft2232_->write(buffer, sizeof (buffer));
    ft2232_->read(ibuf, len);
}
uriy
Как SPI может быть НЕ дуплексным? Мастер формирует тактовые сигналы на CLK и параллельно шлет данные по MOSI при этом на каждый такт CLK слейв выдает по биту данных. Как только вы перестали формировать CLK (и соответсвенно перестали слать данные в слейв) слейв перестает выдавать данные.
_pv
Цитата(uriy @ Jan 13 2012, 21:15) *
Как SPI может быть НЕ дуплексным?

ну всяко бывает sm.gif
в блэкфинах, например, SPI хоть и нормальное, но вот его ДМА про это не знает и работает только в одну сторону либо на приём либо на передачу, посылая при приёме нули и игнорируя принимаемые данные при передаче.
misyachniy
Цитата(ReAl @ Jan 13 2012, 11:32) *
Дуплекс у всех c MPSSE есть.
Ну например — при программировании AVR во время посылки третьего байта команды входа в программирование нужно прочитать назад копию второго байта, служащую признаком успешного входа в программирование.
Но я врукопашную всё делаю, напрямую обращаясь к FTD2XX.DLL / libftd2xx.so


Понятно.
На каждую запись в FTDI формируется ответная посылка байт в буфере и ее нужно вычитывать.
Пример от FTDI считывает иотбрасывает ответные байты.

Примером инициализации врукопашную режима SPI есть желание поделиться?
ReAl
Там всё достаточно «прямоугольно», по описанию.
Понятно, все ft2232_-> заменить на одноимённые вызовы FT_*** c передачей handle и контролем возвращаемого значения. Там везде что-то в духе
Код
void ftdi_chip_ftd2xx_t::set_bit_mode(uint8_t direction, bit_mode_t mode)
{
    FT_STATUS status = FT_SetBitMode(handle_, direction, mode);
    check_fail("set bit mode", status); // а эта штука выбрасывает исключение с сообщением
}

Инициализация (выброшено кое-что avreal-специфическое):
Код
    ft2232_->set_bit_mode(0x00, ftdi_chip_t::BM_MPSSE);
    ft2232_->set_timeouts(5000, 5000);

    uint32_t base_freq = 6000000UL; // FT2232C+

    // Буфер максимально на MPSSE_DIV5* + MPSSE_SET_DIVISOR + MPSSE_SEND_IMMEDIATE
    uint8_t buf[1+3+1];

    int index=0;
    if (ft2232_->ft_type != FT_DEVICE_2232C) {
        // На жаль, зберегти-відновити стан неможливо.
        // Тому тут просто встановлюємо потрібне, а в деструкторі
        // скидаємо в стан == по ввімкненні живлення
        if( freq >= 500000UL ) {
            // додати в буфер команду зняття ділилки на 5
            buf[index++] = ftdi_chip_t::MPSSE_DIV5_DISABLE;
            base_freq = 30000000UL;
        } else {
            buf[index++] = ftdi_chip_t::MPSSE_DIV5_ENABLE;
        }
    }

    uint32_t divisor = (base_freq + freq - 1) / freq;
    if (divisor > 0) --divisor;

    // 1000Hz / 4 = 250Hz, а мінімально можлива - близько 92Гц
    if (divisor > 65535) {
        logger.message(logger_t::error,
                "SCK frequency for FTDI hardware SPI adapter (MPSSE) must be higher than %s\n",
                nice_float( base_freq / 65535.0, freq_Hz )
        );
        throw app_error(E_INVCMD);
    }

    buf[index++] = ftdi_chip_t::MPSSE_SET_DIVISOR;
    buf[index++] = divisor;
    buf[index++] = divisor >> 8;
    buf[index++] = ftdi_chip_t::MPSSE_SEND_IMMEDIATE; // заодно вичистити все, що там завалялося

    ft2232_->write(buf, index);

    os_timer_t timer;
    timer.delay(20);

    ft2232_->purge(ftdi_chip_t::RX);

Направление в set_bit_mode стоит все на вход, так как позже все равно устанавливаются и для DBUS, и для CBUS вызовом
Код
void spi_ftdi_mpsse_t::update_signals()
{
    uint8_t buf[6];

    buf[0] = ftdi_chip_t::MPSSE_SET_LOW_BYTE;
    buf[1] = data_buf;
    buf[2] = dir_buf;
    buf[3] = ftdi_chip_t::MPSSE_SET_HIGH_BYTE;
    buf[4] = data_buf >> 8;
    buf[5] = dir_buf >> 8;

    ft2232_->write(buf, sizeof (buf));
}
В dir_buf у меня набираются маски в том числе для RESET, светодиодов, ... по конфигурации адаптера avreal.

misyachniy
Цитата(ReAl @ Jan 14 2012, 13:24) *
Там всё достаточно «прямоугольно», по описанию.
...
Наверное у нас военное положение и прямой угол равен 100 градусов. :-)

Как посылать байты через FTD2XX.DLL понятною
Не получилось аппаратно управлять выводом CS.
При работе через FTCSPI.DLL вывод CS опускался и поднимался в течении такта.

В документе : url="http://www.ftdichip.com/Support/Documents/AppNotes/AN_108_Command_Processor_for_MPSSE_and_MCU_Host_Bus_Emulation_Modes.pdf"]AN_108_Command_Processor_for_MPSSE_and_MCU_Host_Bus_Emulation_Modes.pdf[/url]
дается пример иницыализации:
Цитата
0x80 Set Data Bits Low Byte
0x08 TCK TDI low, TMS high
0x0B TCK, TDI, TMS output, TDO and GPIOL0-> GPIOL3 input
При передаче байты выталкиваются побитно и тактируются корректно, через перемычку принимаются тоже корректно.
Но сигнал CS не активен.

Я пробовал через Set Data Bits Low Byte управлять сигналом CS, но он заведомо медленее переключается - порядка нескольких миллисекунд.

В указаном выше документе есть TMS Commands, я пробовал их использовать для управления TMS/CS сигналом.
Цитата
index = 0;
Buffer1[index++] = 0x4A;
Buffer1[index++] = 0; // длина посылки -1, младший байт
Buffer1[index++] = 0; // длина посылки -1, старший байт

Buffer1[index++] = 0x31;
Buffer1[index++] = 0; // длина посылки -1, младший байт
Buffer1[index++] = 0; // длина посылки -1, старший байт
Buffer1[index++] = 0x55;

Buffer1[index++] = 0x4A;
Buffer1[index++] = 0; // длина посылки -1, младший байт
Buffer1[index++] = 0xFF; // длина посылки -1, старший байт

if (MPSSE_Write(ftHandleA, &Buffer1[0],index) != true) return false;
Тоже не похоже на работу через FTCSPI.DLL.

Для похожего FT232H (AN_180_FT232H MPSSE Example - USB Current Meter using the SPI interface.pdf) в примере более подробно показано управление CS

Цитата
' Set the required values for the pins
LED_State = LED_Status_On ' Status LED on to indicate MPSSE configured 0x1x xxxx
CS_State = CS_None ' No chip select lines asserted yet xxx1 1xxx
' State of the other SPI lines x1xx x110
Pin_Values = Pin_Defaults Or LED_State Or CS_State ' 0111 1110
SendBuffer(0) = &H80 ' MPSSE Command to set low bits of port
SendBuffer(1) = Pin_Values '
SendBuffer(2) = Pin_Directions ' Defined above as 1011 1011
У меня аналогично управление, но не работает.

Не могу найти где собака порылась.
ReAl
Несколько мс - это разбивка на несколько независимых USB-ных обменов выходит. У меня CS-а то как такового нет, RESET при программировании AVR меняется нечасто и неспеша. Думаю, нужно просто одним FT_Write отправлять и CS, и данные, как-то так:

Код
    index = 0;
    // Активизировать CS - это фрагмент из моего update_signals, которым я CS да светодиоді дергаю
    buffer[index++] = ftdi_chip_t::MPSSE_SET_LOW_BYTE;
    buffer[index++] = LINE_STATE_WITH_CS_ACTIVE; // тут правильные начальные полярности
    buffer[index++] = LINE_DIRECTION;
    // Отправить данные по SPI
    buffer[index++] = shift_mode | ftdi_chip_t::MPSSE_WRITE_TDI | ftdi_chip_t::MPSSE_READ_TDO;
    buffer[index++] = len - 1;
    buffer[index++] = (len - 1) >> 8;
    memcpy(buffer + index, obuf, len);
    index += len;
    // Побыстрее получить ответ
    buffer[index++] = ftdi_chip_t::MPSSE_SEND_IMMEDIATE;
    // Деактивизировать CS
    buffer[index++] = ftdi_chip_t::MPSSE_SET_LOW_BYTE;
    buffer[index++] = LINE_STATE_WITH_CS_PASSIVE;
    buffer[index++] = LINE_DIRECTION;

    ft2232_->write(buffer, index);
    ft2232_->read(ibuf, len);
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.