Рейтинг@Mail.ru
Плата с микросхемой FT2232HL
Плата с микросхемой FT2232HL

Реализация SPI с помощью микросхем фирмы FTDI

автор:
17 comments Программирование
Print Friendly, PDF & Email

Рассматриваются основные этапы программной реализации работы в режиме последовательного интерфейса SPI микросхем семейств FT2xx и FT4xx фирмы FTDI. А также предлагается готовое бесплатное программное обеспечение, которое реализует этот режим (а также I2C, 1-Wire, uWire). С помощью данной программы можно читать (и записывать) информацию с множества датчиков и прочих устройств, которые работают по интерфейсам SPI, I2C, OneWire, MicroWire.

1Микросхемы фирмы FTDI

Мы уже не раз обсуждали работу с интерфейсом SPI, реализуя его с помощью Arduino. На этот раз рассмотрим этот интерфейс на примере работы с микросхемами фирмы FTDI, а именно FT2232 и FT4232, которые пользуются огромной популярностью среди разработчиков радиоэлектронной аппаратуры из-за своей дешевизны, надёжности и хорошей поддержки со стороны производителя.

FTDI выпускает микросхемы с суффиксом H (например, FT2232H) – высокоскоростные, с суффиксом D (FT2232D) – низкоскоростные.

Для работы с микросхемами нам понадобится отладочная или любая другая плата с микросхемой FTDI и всей необходимой «обвязкой». Для примера на фотографии приведены несколько плат, которые я использую в различных проектах, в том числе, описанных на этом сайте.

Отладочная плата с микросхемой FT2232D
Отладочная плата с микросхемой FT2232D
Отладочная плата с микросхемой FT2232H
Отладочная плата с микросхемой FT2232H

С помощью платы с микросхемой FTDI вы сможете читать данные со всевозможных датчиков и конфигурировать их, передавать данные различным устройствам, читать из памяти и записывать в память, а также делать многое-многое другое. Потенциал у микросхемы FT2232 поистине огромный. Ниже в статье я приведу несколько реальных примеров использования этих микросхем.

Для тестов вы можете купить готовую плату у наших китайских друзей или сделать плату самому, используя типовое решение, приведённое в техническом описании (datasheet) на данные микросхемы. Вот ещё один прекрасный образец такой платы:

Отладочная плата с микросхемой FT2232HL
Отладочная плата с микросхемой FT2232HL

Заказать такую плату можно на этом сайте.

На двух иллюстрациях ниже, взятых из технических описаний, приводится назначение ножек микросхем FT2232D (низкоскоростной) и FT2232H (высокоскоростной) при работе в разных режимах, в том числе SPI (см. столбец MPSSE). Микросхема FT4232 также имеет два канала, поддерживающих режим MPSSE. Хотя общее число каналов у неё – четыре.

Ножки микросхем, обозначенные GPIOL («нижние» порты ввода-вывода GPIO), могут работать в качестве выбора ведомого (Chip Select), т.е., как видно, к микросхемам FT2232D и FT2232H можно подключить до 5 ведомых устройств SPI к одному каналу.

Назначение выводов микросхемы FT2232D при работе в разных режимах
Назначение выводов микросхемы FT2232D при работе в разных режимах

Доступны также «верхние» порты ввода-вывода GPIOH: 4 у микросхемы FT2232D и 8 – у микросхемы FT2232H. Эти ножки также можно использовать в качестве чип-селекта, или для иных целей.

Назначение выводов микросхемы FT2232H при работе в разных режимах
Назначение выводов микросхемы FT2232H при работе в разных режимах

2Библиотеки для работы с микросхемами FTDIFTCSPI.dll и FTD2XX.dll

Если вы хотите реализовать программное обеспечение, использующее микросхемы FTDI для работы по интерфейсу SPI, нужно зайти на сайт производителя и скачать динамически подключаемые библиотеки FTD2XX.dll и FTCSPI.dll. Первая из них – общего назначения – и входит в состав пакета драйверов FTDI WHQL Certified. Includes VCP and D2XX. Вторая предназначена исключительно для работы по SPI, и найти её можно на странице FTC SPI. Для работы с обеими библиотеками есть прекрасные подробные инструкции для программистов (Programmers Guide), которые любезно выложены на том же сайте фирмы FTDI. Они обязательны для прочтения, если вы будете разрабатывать ПО, работающее с микросхемами FTDI.

Указанный драйвер FTDI WHQL Certified должен быть установлен в любом случае, прежде, чем вы начнёте работать с микросхемами FTхххх.

Дальнейшая последовательность действий такая: вы создаёте проект в Visual Studio или в той IDE, в которой пишете свои программы. Размещаете обе библиотеки в папке проекта. Импортируете нужный функционал в свой проект через директивы [DllImport]. Например, для проектов на VB.NET импорт функции FT_Open из библиотеки ftd2xx.dll будет выглядеть так:

<DllImport("c:\Temp\ftd2xx.dll", SetLastError:=True, CallingConvention:=CallingConvention.StdCall)> _
Private Shared Function FT_Open(ByVal deviceNumber As Integer, ByRef pHandle As Integer) As Integer
End Function

Public Shared Sub OpenDevice(ByVal deviceNumber As Integer, ByRef pHandle As Integer)
   Dim r As Integer = FT_Open(deviceNumber, pHandle)
   If r <> FT_OK Then
        Throw New Exception(r)
    End If
End Sub

То же самое на C#:

[DllImport("c:\Temp\ftd2xx.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
private static extern int FT_Open(int deviceNumber, ref int pHandle);

public static void OpenDevice(int deviceNumber, ref int pHandle)
{
    int r = FT_Open(deviceNumber, ref pHandle);
    if (r != FT_OK) 
    {
	throw new Exception(r);
    }
}

Собственно, метод FT_Open импортируется как закрытый в первых двух строках кода, а следом объявляется открытый метод с теми же (или другими, если это удобно) входными параметрами для обращения к нему из других классов сборки. В принципе, можно сразу объявлять метод как открытый и обращаться к нему напрямую из других классов вашей сборки, но более правильно объявлять методы, обращающиеся к нативному неуправляемому коду, закрытыми, а внутри .NET приложения использовать открытые управляемые методы.

Импортировать все функции из DLL не нужно. Внимательно изучите Programmers Guide и выберите только те функции и структуры, которые понадобятся вам для решения вашей задачи.

Как правильно и какие типы импортировать? Поможет замечательный инструмент PInvoker, о котором мы уже писали, или любой другой аналогичный. Ну и конечно же, заголовочные h-файлы из скачанного архива с драйвером, а также руководство программиста.

Далее представлена часть кода, реализующая режим SPI. Другая часть кода, в частности базовый класс MpsseBase, представлены в статье, посвящённой I2C.

Код класса MpsseSpi (разворачивается)
Imports System.Diagnostics
Imports System.Runtime.InteropServices

Namespace Ftdi

    ''' <summary>
    ''' Работа в режиме SPI с помощью библиотеки LibMPSSE.
    ''' </summary>
    Public Class MpsseSpi
        Inherits MpsseBase

#Region "READ-ONLY PROPS, CONST"

        Public Const HISPEED_MAX_CLOCK As Integer = 60000000
        Public Const FULLSPEED_MAX_CLOCK As Integer = 12000000
        Public Const MAX_SPI_FREQUENCY As Integer = 30000000
        Public Const SPI_MAX_READ_DATA_BITS_BUFFER As Integer = 524288
        Public Const SPI_MAX_READ_DATA_BYTES_BUFFER As Integer = SPI_MAX_READ_DATA_BITS_BUFFER \ 8
        Public Const SPI_MAX_WRITE_DATA_BYTES_BUFFER As Integer = SPI_MAX_READ_DATA_BYTES_BUFFER

        ''' <summary>
        ''' Режим работы устройства MPSSE - SPI.
        ''' </summary>
        Public Overrides ReadOnly Property DeviceMode As DeviceWorkingMode = DeviceWorkingMode.Spi

#End Region '/READ-ONLY PROPS, CONST

#Region "CTOR"

        ''' <summary>
        ''' Подключается к устройству с заданным индексом в режиме SPI.
        ''' </summary>
        ''' <param name="index">Индекс устройства в системе, начиная с 0.</param>
        ''' <param name="openNow">Открывать ли сразу устройство.</param>
        Public Sub New(index As Integer, Optional openNow As Boolean = True)
            MyBase.New(index)
            Dim ci As FT_DEVICE_LIST_INFO_NODE = GetChannelInfo(index)
            SetNameReadable(ci.Description)
            SetSerialNumber(ci.SerialNumber)
            SetDeviceType(ci.Type)
            If openNow Then
                SetDevHandle(OpenChannel(index))
            End If
        End Sub

#End Region '/CTOR

#Region "ИНФО"

        <DllImport(DLL_MPSSE_PATH, SetLastError:=True, CallingConvention:=CallingConvention.Cdecl)>
        Private Shared Function SPI_GetChannelInfo(index As Integer, ByRef chanInfo As FT_DEVICE_LIST_INFO_NODE) As Integer
        End Function

        ''' <summary>
        ''' Возвращает информацию об устройстве (канале) по его индексу в системе.
        ''' </summary>
        ''' <param name="index">Индекс канала, начиная с 0 до <see cref="GetNumSpiChannels()"/> - 1.</param>
        Public Overloads Shared Function GetChannelInfo(index As Integer) As FT_DEVICE_LIST_INFO_NODE
            Dim info As New FT_DEVICE_LIST_INFO_NODE()
            Dim r As Integer = SPI_GetChannelInfo(index, info)
            CheckStatus(r)
            Return info
        End Function

        ''' <summary>
        ''' Возвращает информацию о текущем устройстве (канале).
        ''' </summary>
        Public Overrides Function GetChannelInfo() As FT_DEVICE_LIST_INFO_NODE
            Return GetChannelInfo(DeviceIndex)
        End Function

        ''' <summary>
        ''' Пересчитывает реальную частоту по желаемой заданной.
        ''' </summary>
        ''' <param name="desiredFrequency"></param>
        Protected Function GetRealClockFrequency(desiredFrequency As Integer) As Integer
            Dim maxClk As Integer = HISPEED_MAX_CLOCK 
            If (Not IsHighSpeedDevice) Then
                maxClk = FULLSPEED_MAX_CLOCK
            End If
            Dim divisor As Double = Math.Floor(maxClk / (desiredFrequency * 2) - 1)
            Debug.WriteLine(divisor)
            Return GetClockFrequencyByDivisor(CInt(divisor))
        End Function

        ''' <summary>
        ''' Возвращает частоту, заданную делителем.
        ''' </summary>
        ''' <param name="divisor"></param>
        Protected Function GetClockFrequencyByDivisor(divisor As Integer) As Integer
            Dim maxClk As Integer = HISPEED_MAX_CLOCK 'если устройство 2232D, то 12 МГц, если 2232H - 60 МГц.
            If (Not IsHighSpeedDevice) Then
                maxClk = FULLSPEED_MAX_CLOCK
            End If
            Dim freq As Integer = CInt(maxClk / ((1 + divisor) * 2))
            Return freq
        End Function

#End Region '/ИНФО

#Region "INIT"

        ''' <summary>
        ''' Последняя заданная конфигурация.
        ''' </summary>
        Private LastConfig As SpiConfig

        <DllImport(DLL_MPSSE_PATH, SetLastError:=True, CallingConvention:=CallingConvention.Cdecl)>
        Private Shared Function SPI_InitChannel(handle As Integer, ByRef config As SpiConfig) As Integer
        End Function

        ''' <summary>
        ''' Инициализирует канал заданными параметрами.
        ''' </summary>
        ''' <param name="devHandle">Дескриптор устройства.</param>
        ''' <param name="config">Конфигурация канала.</param>
        Public Shared Function InitChannel(devHandle As Integer, config As SpiConfig) As SpiConfig
            Dim r As Integer = SPI_InitChannel(devHandle, config)
            CheckStatus(r)
            Return config
        End Function

        ''' <summary>
        ''' Инициализирует канал заданными параметрами.
        ''' </summary>
        ''' <param name="conf">Конфигурация канала.</param>
        Public Function InitChannel(conf As SpiConfig) As SpiConfig
            If IsOpened Then
                LastConfig = conf
                Return InitChannel(DeviceHandle, conf)
            End If
            Return Nothing
        End Function

        ''' <summary>
        ''' Устанавливает последнюю заданную конфигурацию.
        ''' </summary>
        Public Function ReInitChannel() As SpiConfig
            Return InitChannel(DeviceHandle, LastConfig)
        End Function

        <DllImport(DLL_MPSSE_PATH, SetLastError:=True, CallingConvention:=CallingConvention.Cdecl)>
        Private Shared Function SPI_ChangeCS(handle As Integer, configOption As SPI_CONFIG_OPTION) As Integer
        End Function

        ''' <summary>
        ''' Изменяет пин CS.
        ''' </summary>
        ''' <param name="configOption"></param>
        Public Sub ChangeCS(configOption As SPI_CONFIG_OPTION)
            Dim s As Integer = SPI_ChangeCS(DeviceHandle, configOption)
            CheckStatus(s)
        End Sub

#End Region '/INIT

#Region "OPEN, CLOSE CHANNEL"

        <DllImport(DLL_MPSSE_PATH, SetLastError:=True, CallingConvention:=CallingConvention.Cdecl)>
        Private Shared Function SPI_OpenChannel(ByVal index As Integer, ByRef handle As Integer) As Integer
        End Function

        ''' <summary>
        ''' Открывает устройство режиме SPI и возвращает его дескриптор.
        ''' </summary>
        ''' <param name="index">Индекс устройства в системе.</param>
        Private Overloads Shared Function OpenChannel(ByVal index As Integer) As Integer
            Dim devH As Integer = 0
            Dim r As Integer = SPI_OpenChannel(index, devH)
            CheckStatus(r)
            If (devH = 0) Then
                Throw New SystemException("Устройство не открыто.")
            End If
            Return devH
        End Function

        ''' <summary>
        ''' Открывает канал, если это не было сделано при создании экземпляра.
        ''' </summary>
        Public Overrides Sub OpenChannel()
            If (Not IsOpened) Then
                SetDevHandle(OpenChannel(DeviceIndex))
                RaiseConnectionStateChanged(True)
            End If
        End Sub

        <DllImport(DLL_MPSSE_PATH, SetLastError:=True, CallingConvention:=CallingConvention.Cdecl)>
        Private Shared Function SPI_CloseChannel(ByVal handle As Integer) As Integer
        End Function

        ''' <summary>
        ''' Закрывает устройство (если оно открыто).
        ''' </summary>
        Public Overrides Sub CloseChannel()
            If IsOpened Then
                Dim r As Integer = SPI_CloseChannel(DeviceHandle)
                CheckStatus(r)
                SetDevHandle(CLOSED_HANDLE)
                RaiseConnectionStateChanged(False)
            End If
        End Sub

#End Region '/OPEN, CLOSE CHANNEL

#Region "SPI READ, WRITE"

        <DllImport(DLL_MPSSE_PATH, SetLastError:=True, CallingConvention:=CallingConvention.Cdecl)>
        Private Shared Function SPI_IsBusy(handle As Integer, <MarshalAs(UnmanagedType.Bool)> ByRef state As Boolean) As Integer
        End Function

        ''' <summary>
        ''' Проверяет, не занято ли устройство.
        ''' </summary>
        Public Function IsBusy() As Boolean
            Dim state As Boolean
            CheckStatus(SPI_IsBusy(DeviceHandle, state))
            Return state
        End Function

        ''' <remarks>
        ''' FTDI_API FT_STATUS SPI_ReadWrite( FT_HANDLE handle, uint8 *inBuffer, uint8 *outBuffer, uint32 sizeToTransfer, uint32 *sizeTransferred, uint32 transferOptions);
        ''' </remarks>
        <DllImport(DLL_MPSSE_PATH, SetLastError:=True, CallingConvention:=CallingConvention.Cdecl)>
        Private Shared Function SPI_ReadWrite(handle As Integer, rxBuffer As Byte(), txBuffer As Byte(),
                                              sizeToTransfer As UInteger, ByRef sizeTransferred As UInteger, options As UInteger) As Integer
        End Function

        ''' <summary>
        ''' Одновременные запись и чтение SPI.
        ''' </summary>
        ''' <param name="txBuffer">Передаваемый буфер.</param>
        ''' <param name="sizeToRead">Число байтов для чтения.</param>
        ''' <param name="options">Параметры передачи.</param>
        Public Overridable Function ReadWriteSim(txBuffer As Byte(), sizeToRead As Integer,
                                     Optional options As SPI_TRANSFER_OPTIONS = SPI_TRANSFER_OPTIONS.SIZE_IN_BYTES Or SPI_TRANSFER_OPTIONS.CHIPSELECT_ENABLE Or SPI_TRANSFER_OPTIONS.CHIPSELECT_DISABLE) As Byte()
            Dim len As Integer = txBuffer.Length
            Dim rxBuffer() As Byte = New Byte(sizeToRead - 1) {}
            If ((options And SPI_TRANSFER_OPTIONS.SIZE_IN_BITS) = 1) Then 
                len *= 8
                ReDim rxBuffer(sizeToRead \ 8 - 1)
            End If
            Dim transferred As UInteger = 0
            Dim r As Integer = SPI_ReadWrite(DeviceHandle, rxBuffer, txBuffer, CUInt(len), transferred, CUInt(options))
            CheckStatus(r)
            Return rxBuffer
        End Function

        ''' <summary>
        ''' Последовательные запись и чтение SPI.
        ''' </summary>
        ''' <param name="txBuffer">Передаваемый буфер.</param>
        ''' <param name="sizeToRead">Число байтов для чтения.</param>
        ''' <remarks>Используется не стандартная функция <see cref="SPI_ReadWrite"/> библиотеки, 
        ''' а комбинация записи и чтения с разными параметрами <see cref="SPI_TRANSFER_OPTIONS"/>.</remarks>
        Public Function ReadWrite(txBuffer As Byte(), sizeToRead As Integer) As Byte()
            Dim transferred As Integer = 0
            SPI_Write(DeviceHandle, txBuffer, txBuffer.Length, transferred, SPI_TRANSFER_OPTIONS.CHIPSELECT_ENABLE Or SPI_TRANSFER_OPTIONS.SIZE_IN_BYTES)
            Dim rxData As Byte() = Read(sizeToRead, SPI_TRANSFER_OPTIONS.CHIPSELECT_DISABLE Or SPI_TRANSFER_OPTIONS.SIZE_IN_BYTES)
            Return rxData
        End Function

        <DllImport(DLL_MPSSE_PATH, SetLastError:=True, CallingConvention:=CallingConvention.Cdecl)>
        Private Shared Function SPI_Read(handle As Integer, buffer() As Byte, sizeToTransfer As Integer, ByRef sizeTransfered As Integer, options As Integer) As Integer
        End Function

        ''' <summary>
        ''' Запрашивает заданное число байтов (или битов - в зависимости от параметра options) из ведомого SPI.
        ''' </summary>
        ''' <param name="devHandle">Дескриптор устройства (канала).</param>
        ''' <param name="sizeToRead">Число байтов или битов для чтения.</param>
        ''' <param name="options">Параметры передачи.</param>
        Public Shared Function Read(devHandle As Integer, sizeToRead As Integer,
                                    Optional options As SPI_TRANSFER_OPTIONS = SPI_TRANSFER_OPTIONS.SIZE_IN_BYTES Or SPI_TRANSFER_OPTIONS.CHIPSELECT_ENABLE Or SPI_TRANSFER_OPTIONS.CHIPSELECT_DISABLE) As Byte()
            Dim buffer() As Byte = New Byte(sizeToRead - 1) {}
            Dim received As Integer = 0
            Dim r As Integer = SPI_Read(devHandle, buffer, sizeToRead, received, options)
            CheckStatus(r)
            ReDim Preserve buffer(received - 1)
            Return buffer
        End Function

        ''' <summary>
        ''' Запрашивает заданное число байтов (или битов - в зависимости от параметра <paramref name="options"/>) из ведомого устройства.
        ''' </summary>
        ''' <param name="sizeToRead">Число байтов или битов для чтения.</param>
        ''' <param name="options">Параметры передачи.</param>
        Public Function Read(sizeToRead As Integer, Optional options As SPI_TRANSFER_OPTIONS = SPI_TRANSFER_OPTIONS.SIZE_IN_BYTES Or SPI_TRANSFER_OPTIONS.CHIPSELECT_ENABLE Or SPI_TRANSFER_OPTIONS.CHIPSELECT_DISABLE) As Byte()
            Return Read(DeviceHandle, sizeToRead, options)
        End Function

        <DllImport(DLL_MPSSE_PATH, SetLastError:=True, CallingConvention:=CallingConvention.Cdecl)>
        Private Shared Function SPI_Write(handle As Integer, buffer As Byte(), sizeToTransfer As Integer, ByRef sizeTransfered As Integer,
                                          Optional options As SPI_TRANSFER_OPTIONS = SPI_TRANSFER_OPTIONS.SIZE_IN_BYTES Or SPI_TRANSFER_OPTIONS.CHIPSELECT_ENABLE Or SPI_TRANSFER_OPTIONS.CHIPSELECT_DISABLE) As Integer
        End Function

        ''' <summary>
        ''' Передаёт в ведомое устройство заданный массив байтов.
        ''' </summary>
        ''' <param name="devHandle">Дескриптор устройства (канала).</param>
        ''' <param name="buffer">Массив байтов для записи.</param>
        ''' <param name="options">Параметры передачи.</param>
        Public Shared Sub Write(devHandle As Integer, buffer As Byte(), Optional options As SPI_TRANSFER_OPTIONS = SPI_TRANSFER_OPTIONS.SIZE_IN_BYTES Or SPI_TRANSFER_OPTIONS.CHIPSELECT_ENABLE Or SPI_TRANSFER_OPTIONS.CHIPSELECT_DISABLE)
            Dim buf As Byte() = buffer
            Dim transferred As Integer = 0
            Dim r As Integer = SPI_Write(devHandle, buf, buf.Length, transferred, options)
            CheckStatus(r)
        End Sub

        ''' <summary>
        ''' Передаёт в ведомое устройство заданный массив байтов.
        ''' </summary>
        ''' <param name="buffer">Массив байтов для записи.</param>
        ''' <param name="options">Параметры передачи.</param>
        Public Sub Write(buffer As Byte(), Optional options As SPI_TRANSFER_OPTIONS = SPI_TRANSFER_OPTIONS.SIZE_IN_BYTES Or SPI_TRANSFER_OPTIONS.CHIPSELECT_ENABLE Or SPI_TRANSFER_OPTIONS.CHIPSELECT_DISABLE)
            Write(DeviceHandle, buffer, options)
        End Sub

#End Region '/SPI READ, WRITE

#Region "СТРУКТУРЫ И ПЕРЕЧИСЛЕНИЯ"

        ''' <summary>
        ''' Конфигурация устройства (канала) SPI.
        ''' </summary>
        <StructLayout(LayoutKind.Sequential)>
        Public Structure SpiConfig

            ''' <summary>
            ''' Значение тактовой частоты шины SPI, в Гц. 
            ''' Значения в диапазоне от 0 до 30 МГц.
            ''' </summary>
            Public ClockRate As Integer

            ''' <summary>
            ''' Значение таймера задержек, в мс. Действительные значения 0...255. 
            ''' Рекомендуются диапазоны:
            ''' - для full-speed устройств (FT2232D): 2...255;
            ''' - для Hi-speed устройств (FT232H, FT2232H, FT4232H): 1...255.
            ''' </summary>
            Public LatencyTimer As Byte

            ''' <summary>
            ''' <list>
            ''' <item>Биты 1..0 - задают режим SPI:
            ''' - 00 - <see cref="SPI_CONFIG_OPTION.MODE0"/> - data are captured on rising edge and propagated on falling edge;
            ''' - 01 - <see cref="SPI_CONFIG_OPTION.MODE1"/> - data are captured on falling edge and propagated on rising edge;
            ''' - 10 - <see cref="SPI_CONFIG_OPTION.MODE2"/> - data are captured on falling edge and propagated on rising edge;
            ''' - 11 - <see cref="SPI_CONFIG_OPTION.MODE3"/> - data are captured on rising edge and propagated on falling edge.
            ''' </item>
            ''' <item>Биты 4..2 - задают, какие линии выбора ведомого CS будут использоваться:
            ''' - 000 - xDBUS3 <see cref="SPI_CONFIG_OPTION.CS_DBUS3"/>;
            ''' - 001 - xDBUS4 <see cref="SPI_CONFIG_OPTION.CS_DBUS4"/>;
            ''' - 010 - xDBUS5 <see cref="SPI_CONFIG_OPTION.CS_DBUS5"/>;
            ''' - 011 - xDBUS6 <see cref="SPI_CONFIG_OPTION.CS_DBUS6"/>;
            ''' - 100 - xDBUS7 <see cref="SPI_CONFIG_OPTION.CS_DBUS7"/>.
            ''' </item>
            ''' <item>Бит 5 - задаёт, каким уровнем будет осуществляться выбор ведомого:
            ''' - 0 - CS активен высоким;
            ''' - 1 - CS активен низким - <see cref="SPI_CONFIG_OPTION.CS_ACTIVELOW"/>.
            ''' </item>
            ''' <item>Биты 6..31 - резерв.</item>
            ''' </list>
            ''' </summary>
            ''' <remarks>
            ''' Обозначение xDBUS0..xDBUS7 соответствует линиям:
            ''' - ADBUS0..ADBUS7 - если используется первый канал MPSSE;
            ''' - BDBUS0..BDBUS7 - если используется второй MPSSE канал (если он есть).
            ''' </remarks>
            Public ConfigOptions As SPI_CONFIG_OPTION

            ''' <summary>
            ''' Определяет направления и значения выводов.
            ''' <list>
            ''' <item># bit 7..0 - Direction of the lines after <see cref="InitChannel(Integer, SpiConfig)"/> is called (1 = OUTPUT, 0 = INPUT)</item>
            ''' <item># bit 15..8 - Value of the lines after <see cref="InitChannel(Integer, SpiConfig)"/> is called (1 = HIGH, 0 = LOW)</item>
            ''' <item># bit 23..16 - Direction of the lines after <see cref="CloseChannel"/> is called (1 = OUTPUT, 0 = INPUT)</item>
            ''' <item># bit 31..24 - Value of the lines after <see cref="CloseChannel"/> is called (1 = HIGH, 0 = LOW)</item>
            ''' </list>
            ''' </summary>
            ''' <remarks>
            ''' Note that the directions of the SCLK, MOSI and the specified chip select line will be overwritten to 1 
            ''' and the direction of the MISO like will be overwritten to 0 irrespective of the values passed by the user application.
            ''' </remarks>
            <CLSCompliant(False)>
            Public Pin As UInteger

            ''' <summary>
            ''' Резерв.
            ''' </summary>
            <CLSCompliant(False)>
            Public Reserved As UShort

        End Structure

        ''' <summary>
        ''' Конфигурация SPI - режимы и CS.
        ''' </summary>
        <Flags()>
        Public Enum SPI_CONFIG_OPTION As Integer

            ''' <summary>
            ''' Биты 0..1: MODE.
            ''' </summary>
            MODE0 = &H;0

            ''' <summary>
            ''' Биты 0..1: MODE.
            ''' </summary>
            MODE1 = &H;1

            ''' <summary>
            ''' Биты 0..1: MODE.
            ''' </summary>
            MODE2 = &H;2

            ''' <summary>
            ''' Биты 0..1: MODE.
            ''' </summary>
            MODE3 = &H;3

            ''' <summary>
            ''' Биты 2..4: CS.
            ''' </summary>
            CS_DBUS3 = &H;0

            ''' <summary>
            ''' Биты 2..4: CS.
            ''' </summary>
            CS_DBUS4 = &H;4

            ''' <summary>
            ''' Биты 2..4: CS.
            ''' </summary>
            CS_DBUS5 = &H;8

            ''' <summary>
            ''' Биты 2..4: CS.
            ''' </summary>
            CS_DBUS6 = &H;C

            ''' <summary>
            ''' Биты 2..4: CS.
            ''' </summary>
            CS_DBUS7 = &H;10

            ''' <summary>
            ''' Бит 5: Линия CS активна в состоянии LOW?
            ''' </summary>
            CS_ACTIVELOW = &H;20

        End Enum

        ''' <summary>
        ''' Настройки передачи.
        ''' </summary>
        <Flags()>
        Public Enum SPI_TRANSFER_OPTIONS As Integer

            ''' <summary>
            ''' BIT 0: Счёт передаваемых данных - в байтах.
            ''' </summary>
            SIZE_IN_BYTES = 0

            ''' <summary>
            ''' BIT 0: Счёт передаваемых данных - в битах.
            ''' </summary>
            SIZE_IN_BITS = 1

            ''' <summary>
            ''' BIT 1: Если задано, линия CS выставляется до начала передачи.
            ''' </summary>
            CHIPSELECT_ENABLE = 2

            ''' <summary>
            ''' BIT 2: Если задано, линия CS убирается после окончания передачи.
            ''' </summary>
            CHIPSELECT_DISABLE = 4

        End Enum

#End Region '/СТРУКТУРЫ И ПЕРЕЧИСЛЕНИЯ

    End Class '/MpsseSpi

End Namespace
    

3Программа «Реализация SPI с помощью микросхем FTDI»

"SPI via FTDI" версии 1, устаревшая (разворачивается)

Представляю вашему вниманию программу «Реализация SPI с помощью микросхем фирмы FTDI» или "SPI via FTDI" – программное обеспечение, написанное под .NET и предназначенное для передачи данных из ПК и приёма данных в ПК с помощью микросхем фирмы FTDI (семейства FT22xx, FT23xx, FT42xx) по последовательному интерфейсу SPI. Это ПО позволит вам организовать обмен данными с устройствами, которые работают по интерфейсу SPI.

Микросхемы FT2ххx и FT3xxx работают только в режиме ведущего устройства SPI (master).

С помощью данной программы вы сможете оперативно протестировать вашу микросхему в разных режимах работы. Подключившись логическим анализатором к выводам SK, DO, DI и CS микросхемы, можно наглядно увидеть, как влияют разные настройки на способ передачи данных.

Системные требования

  • Операционная система Windows XP и выше, в т.ч. Windows 10. Программа работает как с x86, так и с x64 операционными системами.
  • .NET Framework версии 3.5 SP1.
  • Наличие USB порта.

Установка и настройка программы «SPI с помощью микросхем FTDI»

Если программа запускается на компьютере с ОС Windows XP, необходимо убедиться в наличии установленной .NET Framework и, при её отсутствии, установить.

Скачать .NET Framework 3.5 SP1. После установки .NET Framework компьютер следует перезагрузить.

В Windows Vista, Windows 7 и 10 библиотеки .NET версии 3.5 присутствуют по умолчанию. Для установки на Windows 8 потребуется произвести дополнительные операции, а именно вручную включить возможность установки среды .NET.

Установка программы осуществляется копированием исполняемого файла с установочного носителя в нужное расположение.

При первом запуске программа проверит наличие необходимых для работы с микросхемами динамических библиотек D2XX.dll и FTCSPI.dll и, при их отсутствии, запишет их на компьютер в директорию C:\Temp.

Возможности программы

  • Передача данных из файла или введённого вручную массива байтов из ведущего устройства (микросхемы FTDI) к ведомому устройству, реализующему интерфейс SPI.
  • Приём данных от ведомого устройства.
  • Циклический приём данных заданное количество раз и в бесконечном цикле.
  • Изменение настроек работы SPI, а также частотно-временных характеристик приёма и передачи «на ходу». Реализация различных режимов работы интерфейса SPI.
  • Сохранение принятых данных в файл (текстовый или двоичный).

Работа с программой "SPI via FTDI"

При запуске программа определяет наличие подключённых к системе поддерживаемых устройств FTDI и создаёт для каждого устройства свою вкладку. Если после запуска программы были подключены новые устройства FTDI, можно обновить список устройств, нажав кнопку с синей стрелкой (Обновить).

Внешний вид главного окна программы «SPI с помощью FTDI»
Внешний вид главного окна программы «SPI с помощью FTDI»

Выбор настроек осуществляется выбором желаемых параметров в левой панели главного окна программы. Каждое устройство конфигурируется независимо.

Подключение к устройству FTDI осуществляется нажатием на кнопку в заголовке вкладки. Отключение – нажатием на ту же кнопку. Возможно одновременное подключение к нескольким устройствам.

Передача данных возможна тремя способами: выбором файла (кнопка с иконкой папки), отправкой произвольной последовательности байтов (в поле Преамбула при активном флажке), а также отправка преамбулы, а затем выбранного файла, если выбраны оба варианта. Передача данных осуществляется нажатием на кнопку Записать.

Приём данных от ведомого устройства осуществляется нажатием на кнопку Прочитать. Если в поле справа от кнопки введено число, отличное от 1, приём будет осуществлён соответствующее число раз; если указан "0", то чтение будет продолжаться бесконечно (до принудительной остановки).

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

Данная программа использует только базовые возможности микросхем FTDI. Например, вы не сможете назначить несколько пинов Chip Select (используется только первый CS, см. таблицы выше), не сможете использовать выводы GPIOH. Т.е., сможете подключить только одно ведомое устройство SPI.

Скачать программу "SPI via FTDI"

Скачать программу можно по любой из ссылок ниже. Пишите свои замечания и отзывы о работе с программой в комментариях или мне на электронную почту.

"SPI via FTDI" версии 2

По сравнению с первой версией, программа была полностью переписана. Теперь она использует другую динамически загружаемую библиотеку – libMPSSE.dll. Эта библиотека позволяет управлять микросхемами FTDI, поддерживающими режим MPSSE – Multi-Protocol Synchronous Serial Engine.

Кроме того, программа приобрела несколько новых, весьма полезных, возможностей. Среди них:

  • поддержка интерфейсов SPI, I2C, 1-Wire и μWire;
  • поддержка переключаемых профилей;
  • переключение между оригинальной и модифицированной библиотеками (об этом ниже);
  • сканер шины I2C и 1-Wire;
  • полезные инструменты: генератор прямоугольных импульсов, частотомер, управление выводами общего назначения (GPIO);
  • технические описания (datasheet) на микросхемы FT2232H и FT2232D всегда под рукой.

Главное окно программы SPI via FTDI (в режиме SPI) выглядит так:

Главное окно программы «SPI via FTDI»
Главное окно программы «SPI via FTDI»

Как видно, пользовательский интерфейс программы претерпел небольшие изменения. Главное окно по-прежнему состоит из двух частей: левая содержит панели настройки режима, записи и чтения, а правая – список вкладок, где каждая отвечает за своё устройство MPSSE.

Если кликнуть правой кнопкой мыши на заголовке вкладки, откроется контекстное меню, через которое можно подключиться к устройству FTDI (или отключиться), а также просмотреть краткую информацию о нём.

Контекстное меню для устройства MPSSE
Контекстное меню для устройства MPSSE

Возможность подключиться к устройству FTDI и отключиться от устройства продублирована в главном меню программы, пункт Устройство. Это действует для текущего активного устройства. Также для подключения/отключения удобно использовать горячие клавиши Ctrl+C.

Информацию об устройстве содержит такие данные как тип микросхемы, текстовое описание, сохранённое в ПЗУ микросхемы FTDI, её серийный номер, идентификатор и флаги.

Окно с краткими сведениями об устройстве MPSSE
Окно с краткими сведениями об устройстве MPSSE
Выбор режима работы, интерфейса SPI или I2C, версии библиотеки

Главное меню программы SPI via FTDI выглядит так:

Главное меню программы «SPI via FTDI»: Устройство
Главное меню программы «SPI via FTDI»: Устройство

Если вы подключили устройства FTDI после того, как была запущена программа, выберите пункт Обнаружить устройства или нажмите сочетание клавиш Ctrl+F. Все доступные устройства FTDI, которые поддерживают режим MPSSE, будут обнаружены и добавлены в соответствующие вкладки.

В главном меню можно выбрать интерфейс, по которому мы хотим работать с устройством: SPI, I2C или 1-Wire. Программа запоминает последний использовавшийся интерфейс.

Программа «SPI via FTDI» позволяет работать одновременно только в одном режиме для всех устройств. Если вам нужно, к примеру, с одним устройством работать в режиме SPI, а с другим – в I2C, можно запустить два экземпляра программы и настроить режим для каждого устройства индивидуально.

Также в главном меню можно выбрать, с какой библиотекой работать: с оригинальной, которую можно скачать с сайта FTDI Chip, или с модифицированной. В оригинальной библиотеке в режиме SPI после того, как закончилась передача данных и деактивируется сигнал выбора ведомого CS, присутствует задержка около 2 мс. Это сделано разработчиками библиотеки libMPSSE.dll намеренно для исключения возможных проблем при сопряжении с медленными устройствами. В модифицированной мной версии библиотеки эта задержка убрана.

В оригинальной библиотеке libMPSSE.dll между окончанием передачи данных и деактивацией CS присутствует задержка
В оригинальной библиотеке libMPSSE.dll между окончанием передачи данных и деактивацией CS присутствует задержка

Если вы планируете обмен данными с высокоскоростными устройствами SPI на тактовых частотах в десять и более мегагерц, показанные задержки будут существенно снижать общую скорость передачи. Для таких скоростей рекомендуется использовать модифицированную библиотеку.

Выбор библиотеки libMPSSE.dll
Выбор библиотеки libMPSSE.dll

Программа запоминает, какую версию библиотеки следует использовать. При переключении библиотеки необходимо перезапустить программу.

Обновление 2023-04. Разработчики FTDI Chip наконец-то услышали глас общественности, который на протяжении почти 10-ти лет просил их сделать это. А именно – убрать пресловутую задержку. В обновлённой программе "SPI via FTDI" версии 2.2 используется новая библиотека, в которой нет этих задержек. Поэтому исчезли и соответствующие пункты в меню программы. Кроме того, путь к библиотекам изменился. При первом запуске программа пытается записать их в системную директорию. Если это не получается (отказ в правах доступа), библиотека располагается радом с исполняемым файлом программы.

В меню Справка можно ознакомиться с кратким описанием программы SPI via FTDI, а также прочитать datasheet на микросхемы FT2232H и FT2232D.

Главное меню программы «SPI via FTDI»: Справка
Главное меню программы «SPI via FTDI»: Справка

В версии 2.2 программы в справку добавились стандартные схемы подключения в режимах SPI, 1-Wire, I2C.

Работа с профилями SPI и I2C

Теперь программа SPI via FTDI поддерживает работу с профилями. Например, вы настроили режим работы, ввели команды и параметры записи в журнал для какого-то устройства. Чтобы быстро восстановить все эти настройки существуют профили. Новый профиль создаётся через меню Устройство — Запомнить конфигурацию или с помощью нажатия горячих клавиш Ctrl+S. Программа предложит ввести произвольное имя и сохранит профиль в конфигурационный файл.

Все сохранённые профили хранятся в одном файле и вызываются через меню Устройство — Восстановить конфигурацию или с помощью нажатия горячих клавиш Ctrl+O. При этом откроется окно со списком доступных конфигураций. Если выделить конфигурацию и нажать на кнопку "ОК", то программа восстановит настройки, присущие этой конфигурации.

Контекстное меню в окне доступных конфигураций программы "SPI via FTDI"
Контекстное меню в окне доступных конфигураций программы "SPI via FTDI"

Если кликнуть правой кнопкой мыши на какой-либо конфигурации, то откроется контекстное меню с дополнительными действиями. Так, можно переименовать или удалить конфигурацию, экспортировать в отдельный файл или импортировать из файла.

Если в программе выбран режим SPI, то будут отображены только профили для режима SPI. Аналогично – для режима I2C и 1-wire.

Работа в режиме I2C

Программа поддерживает режим I2C. Вы можете выбрать одну из стандартных скоростей обмена из выпадающего списка, но также можете и ввести произвольную, там же в выпадающем списке. Значения скоростей приводятся в герцах и соответствуют режимам I2C:

  • Standard mode (100 000 Гц);
  • Fast mode (400 000 Гц);
  • Fast mode plus (1 000 000 Гц);
  • High speed mode (3 400 000 Гц).
Выбор скорости обмена по IIC
Выбор скорости обмена по IIC

Интересной особенностью является то, что в программе имеется сканер шины I2C. После нажатия на кнопку сканирования программа пытается обнаружить все подключённые ведомые устройства. Как мы знаем, на одной шине IIC могут находиться до 128-ми ведомых устройств (на самом деле меньше, т.к. 12 адресов являются зарезервированными). Программа пытается провести чтение или запись по каждому из адресов, и если на каком-то адресе получает ответ, то добавляет его в список найденных адресов. Рекомендую начинать работу со сканирования шины I2C.

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

Обратите внимание на схему подключения микросхем FTDI в качестве ведущего к шине I2C. Как видно из приведённой иллюстрации, выводы DI и DO микросхемы FTDI необходимо закоротить между собой:

Схема подключения FTDI и ведомых устройств к шине IIC
Схема подключения FTDI и ведомых устройств к шине IIC

В остальном процедуры чтения и записи аналогичны таковым в режиме SPI.

Работа в режиме 1-Wire

В режиме 1-Wire программа позволяет отправлять стандартные сигналы RESET, SKIP ROM, SEARCH ROM, MATCH ROM, а также осуществляет поиск устройств на шине. Через интерфейс программы можно обращаться ко всем устройствам сразу или к конкретному устройству по его уникальному номеру. Поддерживается как стандартный, так и ускоренный (overdrive) скоростные режимы. Разумеется, с помощью программы можно реализовать и собственные команды для обмена с устройствами One-wire.

Вид программы в режиме 1-Wire
Вид программы в режиме 1-Wire

Пример использования программы в режиме 1-Wire можно посмотреть в этой статье (последний раздел).

Работа в режиме UART

Программа позволяет работать с портами микросхем FTDI в режиме UART. Поддерживается передача, приём данных в виде ASCII текста или байтовых массивов.

Чтение и запись данных (SPI/I2C)

Программа позволяет как передавать данные ведомым устройствам, так и запрашивать данные от них.

Микросхема FTDI всегда «мастер».

При записи можно выбрать файл, который будет передаваться (кнопка с папкой), можно ввести команду (массив байтов в hex), а можно скомбинировать эти две возможности: если указана команда и выбран файл, то сначала отправится команда, а затем файл. Важным параметром является размер буфера записи. По умолчанию он задан 64 кб – размер максимально возможного аппаратного буфера микросхемы FT2232H. Если объём передаваемых данных превышает размер буфера, то данные будут передаваться частями. Если вы зададите размер буфера "1", то данные будут передаваться по одному байту, если укажете "10" – по десять байт. Каждая порция данных будет отправляться под своим «чип селектом».

Можно задать число повторов чтения. Если задано "0", то чтение будет повторяться бесконечно до принудительной остановки. Любые другие положительные значения определяют число повторений как есть.

При чтении задаётся размер буфера чтения. По сути, он равен числу байтов, которые нужно прочитать из ведомого устройства. Также имеется возможность отправки команды, которая задаётся как hex-массив. Некоторые устройства (как SPI, так и I2C), ожидают команды, прежде чем начнут отправлять данные. Например, это может быть адрес регистра, содержимое которого мы собираемся читать. Число повторов задаётся аналогично, как при записи.

Для просмотра принимаемых данных можно нажать кнопку с изображением таблицы, которая находится в поле чтения. Она обновляется при появлении новых данных в буфере, но не чаще, чем задано периодом обновления. Это ограничение введено для случаев, когда данные льются большим потоком: обновлять таблицу чаще нескольких раз в секунду бессмысленно.

В таких случаях принимаемые данные необходимо сохранять в текстовый и/или двоичный файлы. Для этого имеются флажки под полем команды в разделе чтения. При сохранении принимаемых данных программа всегда создаёт файл с неизменным названием (таким же, как название канала). Для переименования файла вручную можно воспользоваться соответствующим пунктом контекстного меню поля журнала. Переименовывать файл можно только после окончания записи.

В меню Файлы можно найти несколько полезных функций по работе с записанными данными.

Главное меню программы «SPI via FTDI»:  Файлы
Главное меню программы «SPI via FTDI»: Файлы

Для текстового файла можно задать число байтов, которые будут записаны в одну стоку. Это удобно, если, например, вы принимаете пакеты фиксированной длины. Тогда каждый пакет будет начинаться с новой строки. Выставление этого параметра – через кнопку с шестерёнкой в поле параметров чтения.

Специфика записи такова, что сначала программа пишет данные в свой программный буфер в памяти, и потом порциями сохраняет на диск. При этом приём данных продолжается. Сохранение может занимать значительное время, особенно если был принят большой объём данных (десятки или сотни мегабайт). Необходимо дождаться оповещения об окончании сохранения, прежде чем переименовывать файл или закрывать программу. Такое решение используется для того, чтобы не терять данные при высоких скоростях обмена и больших объёмах данных. Например, возможны ситуации, когда вы должны непрерывно принимать данные в потоковом режиме на скорости 20 МГц на протяжении многих минут или часов. Программа позволяет использовать её в таком режиме.

Примеры использования программы SPI via FTDI

Давайте рассмотрим несколько примеров, как использовать программу для чтения различных устройств с поддержкой интерфейсов SPI и I2C. Я показываю только часть программы, где видны настройки, используемые в данных примерах.

Чтение по IIC датчика давления BMP280

Первый пример – чтение по интерфейсу I2C регистра ID нашего старого знакомого – датчика давления BMP280. Здесь стоит обратить внимание на адрес устройства 119 (0x77) и на часть, относящуюся к чтению. Видно, что нужно поставить галку «Команда» и ввести в поле команды "D0". Как мы помним, это адрес регистра ID. Также следует задать размер буфера равным 1. Нажав кнопку «Прочитать», мы запишем в датчик BMP280 адрес регистра ID и затем запросим у датчика один байт из этого регистра.

Чтение регистра ID датчика BMP280
Чтение регистра ID датчика BMP280 с помощью FTDI

Некоторые устройства позволяют выполнять запись команды и чтение ответа не в едином цикле, как мы только что сделали, а разделять команду и ответ. Например, в данном случае можно было отправить команду "D0" в поле записи, нажав на кнопку «Записать», а в поле чтения команду не выставлять. Нажав на кнопку «Прочитать», мы бы получили точно такой же результат.

Чтение по I2C таймера DS3231

Следующий пример – чтение содержимого регистров таймера реального времени DS3231. На сей раз адрес ведомого равен 104 (0x68), команда равна "00", а запрашиваем мы 18 байтов: именно такого размера буфер у данного устройства.

Чтение содержимого регистров часов реального времени DS3231
Чтение содержимого регистров часов реального времени DS3231 с помощью FTDI
Чтение по SPI АЦП ADT7411

Для чтения показаний аналого-цифрового преобразователя ADT7411 по SPI после включения необходимо подать самую первую команду трижды. Это требуется, чтобы перевести АЦП в режим SPI, т.к. по умолчанию он работает по I2C. Команда не важна, важен выбор ведомого, полученный устройством 3 раза. После этого можно передавать команды и читать ответы. Запросим, например карту регистров АЦП adt7411, которая состоит из 64-х байтов. Для этого сначала запишем команду 90h-00h. Здесь код 0x90 сообщает АЦП, что мы хотим осуществить запись в его регистры. Далее следует 0x00 – записываемые данные – адрес регистра.

После этого необходимо прочитать 64 байта. Но начать чтение необходимо с команды 91h, которая сообщает АЦП, что мы хотим прочитать из него.

Чтение по SPI содержимого регистров АЦП ADT7411
Чтение по SPI содержимого регистров АЦП ADT7411

Прочитаем также 3 регистра Device ID, Manufacturer's ID, Silicon Revision (идентификатор чипа, производителя, версия чипа):

Чтение по SPI содержимого регистров АЦП ADT7411
Чтение по SPI содержимого регистров АЦП ADT7411
Чтение по I2C ПЗУ 24C04

Ещё один пример с интерфейсом I2C – запись данных в ПЗУ 24C04 и чтение из него. Первым действием – из поля «Запись» – мы записываем в ячейку по адресу 0xF0 число 0xEE. Размер буфера здесь можно было задать 2, но можно оставить и так: всё равно будет передано только 2 байта. Далее в поле «Чтение» мы запрашиваем 256 байтов (полный размер данного ПЗУ), начиная с адреса "0". Обратите внимание, что в ячейке с адресом 0xF0 должно находиться число 0xEE, которое мы только что туда записали.

Чтение и запись данных в EEPROM 24C04 с помощью FTDI
Чтение и запись данных в EEPROM 24C04 с помощью FTDI
Чтение по SPI акселерометра ADXL345

Следующий пример с интерфейсом SPI – чтение содержимого регистров цифрового акселерометра ADXL345 с помощью программы SPI via FTDI.

Чтение содержимого регистров цифрового акселерометра ADXL345
Чтение содержимого регистров цифрового акселерометра ADXL345 с помощью FTDI
Чтение по SPI ПЗУ 23LC1024

Последний пример – запись и чтение ПЗУ 23LC1024 по интерфейсу SPI. Сначала (см. поле записи) мы запишем в ПЗУ команду "02 00 00 00 01". Здесь "02" – код команды «Запись» согласно даташиту, далее 3 нулевых байта – адрес ячейки памяти, и последний байт – "01" – значение, которое мы записываем в данную ячейку.

Чтение и запись данных в EEPROM 23LC1024 с помощью FTDI
Чтение и запись данных в EEPROM 23LC1024 с помощью FTDI

В поле чтения мы отправляем команду "03 00 00 00" и вычитываем буфер размером в 1 байт. Команда означает следующее: "03" – код команды «Чтение» согласно даташиту, далее 3 нулевых байта – адрес начальной ячейки, с которой начинаем читать. Но так как мы запрашиваем только 1 байт, то нам и вернётся значение, хранящееся по этому адресу, которое мы только что записали сюда и которое должно быть равно "01".

Управление портами общего назначения GPIO микросхемы FTDI (FT2232 и т.д.)

В меню Инструменты можно найти несколько полезных инструментов. В частности, для управления портами ввода и вывода общего назначения (GPIO). Правда, только «верхними». В документации разработчика они обозначаются как GPIOH (GPIO High). В частности, двухканальная микросхема FT2232 имеет 16 таких ножек GPIO, по 8 на канал.

Виджет управления портами общего назначения GPIO микросхемы FTDI
Виджет управления портами общего назначения GPIO микросхемы FTDI

Управление заключается в том, что можно прочитать текущее состояние выводов, а можно записать в него значение. Данный инструмент работает только в режиме SPI.

Соблюдайте осторожность, когда записываете данные в порт, если к нему подключено какое-либо устройство, т.к. подача высокого уровня на ножку, не предназначенную для этого, может повредить либо подключённому устройству, либо самой микросхеме FTDI.

Генератор прямоугольных импульсов, реализованный на микросхеме FTDI (FT2232 и т.п.)

Ещё одним полезным инструментом программы SPI via FTDI является генератор прямоугольных импульсов. Импульсы генерируются на выводе MOSI (DO) в режиме SPI. Можно настроить собственно частоту и скважность. По умолчанию используется частота 1000 Гц и скважность 0,5. Также можно поставить ограничение на число импульсов: если задано "0", то генерация происходит непрерывно до принудительной остановки, а если задать конкретное число, то генератор выдаст именно это число прямоугольных импульсов.

Настройки генератора прямоугольных импульсов в программе SPI via FTDI
Настройки генератора прямоугольных импульсов в программе SPI via FTDI

В основе работы генератора частоты лежит такая идея. Зная частоту шины SPI, мы можем рассчитать время передачи заданного числа 8-битных чисел. Пусть это будет периодом импульсов. А скважность мы будем задавать, передавая столько битов, равных "1", чтобы в отношении к общему числу передаваемых битов это равнялось значению скважности. Поясню на примере.

Будем использовать передачу 4-ёх байтов как один период. Тогда нам нужно выставить частоту шины SPI такой, чтобы эти 4 байта передались за время, равное одному периоду генератора. Так, если мы хотим получить частоту генератора 1 кГц, нужно выставить частоту SPI равной 1000(Гц)×4(байта)×8(бит)=32000 Гц.

Допустим, мы хотим получить скважность 0,5. Для этого мы будем передавать из этих четырёх байтов 2 равными 0xFF, а два других – нулевыми. В двоичном виде это будет 11111111_11111111_00000000_00000000. Последовательность единиц и будет нашим прямоугольным импульсом. Рисунок ниже иллюстрирует этот пример.

Генератор прямоугольных импульсов с помощью чипа FTDI
Генератор прямоугольных импульсов с помощью чипа FTDI

Здесь на линии DO частота генератора (1 кГц) со скважностью 0,5, а на линии SCL – частота шины SPI (32 кГц).

Данная функция хорошо работает до частоты примерно 5 кГц. На более высоких частотах генератор не держит частоту постоянной именно из-за программной природы своей реализации, т.к. небольшие задержки вносят существенный вклад в конечный результат. Также необходимо использовать модифицированную библиотеку libMPSSE.dll, о которой было написано выше.

Частотомер, реализованный на микросхеме FTDI (FT2232 и т.п.)

В версии 2.2 программы добавился такой инструмент как измеритель частоты в диапазоне от 0 до примерно 500 кГц. Активируется также через меню «Инструменты» в режиме SPI.

На иллюстрации показан пример работы с частотомером. С генератора сигнала поступает периодический сигнал (меандр, пила, синус) на вход DI микросхемы, программа определяет его частоту и выводит на экран.

Частотомер в программе SPI via FTDI
Частотомер в программе "SPI via FTDI"

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

Работа в режиме Micro-Wire

В версии программы 2.2 добавилась поддержка интерфейса MicroWire.

Microwire по сути – предшественник SPI с более жёсткими ограничениями. Так, выбор ведомого осуществляется только высоким логическим уровнем, тактовая частота более низкая, а кадр информации имеет регламентированную структуру.

Программа "SPI via FTDI" в режиме μWire
Программа "SPI via FTDI" в режиме μWire

Пользователю доступен ряд команд: чтение (READ), запись по адресу (WRITE), запись по всем адресам (WRAL), стирание по адресу (ERASE), стирание по всем адресам (ERAL), разрешение записи или стирания (WEN), запрет записи и стирания (WDS).

Поля, отмеченные зелёным фоном – обязательные для заполнения пользователем. Поля, отмеченные серым фоном также можно изменить, но, как правило, это не требуется.

Над кнопками READ, WRITE, ERASE работает прокрутка колёсиком мыши; при прокрутке изменяется адрес в ту или иную сторону.

Перед записью или стиранием необходимо выдать команду WEN (при этом зелёный значок замка изменится на открытый оранжевый замок). Далее записываем или стираем столько адресов, сколько нужно. Затем выдаём команду WDS для запрета записи. При пакетной записи программа сама выставляет разрешение записи.

Чтение и запись ППЗУ 93C66 по MicroWire

Пример микросхемы, которая работает по интерфейсу µWire – перезаписываемая память 93C66. Обратившись к техническому описанию на данный чип, увидим, что он может иметь организацию памяти в байтах (8 бит) или словах (16 бит). В данном случае микросхема подключена в режиме слов. При этом следует также указать разрядность адреса – 8 бит. Далее выбираем файл, размером меньше объёма ПЗУшки, и нажимаем «Записать». Проверить успех записи можно, нажав кнопку «Прочитать». В данном примере записаны только 32 байта.

Чтение EEPROM 93C66 программой "SPI via FTDI" в режиме μWire
Чтение EEPROM 93C66 программой "SPI via FTDI" в режиме μWire

Если выбранный файл больше, чем объём памяти, программа по кругу перезапишет память его содержимым. Это, естественно, приведёт к порче информации в ППЗУ.

Где скачать

Скачать программу можно с SourceForge или по ссылкам в конце статьи.

Last modified onСреда, 13 Ноябрь 2024 19:34 Read 23641 times

Поблагодарить автора:

Поделиться

Print Friendly, PDF & Email

17 comments

  • Дмитрий
    Дмитрий Пятница, 21 May 2021 16:48 Ссылка на комментарий

    Добрый день.
    Очень хорошо пишете, доходчиво, обстоятельно, подробно и... очень мне понравилось!! Большущее спасибо!

    А теперь вопрос. А вопрос по скриптам. Задумка весьма и весьма хорошая, а вот как пользоваться... Я так понял, что в xml-файл конфигурации пишется "лог" действий пользователя. Конечно, отредактировать его в принципе можно, но неудобно. Да и по привычке - скрипт это "нечто" просто редактируемое в текстовом редакторе. Вот если бы Вы доработали эту часть Вашей прекрасной программы - цены бы ей не было!
    Есть устройства, которые инициируются несколькими посылками команд, данных и т.п. - не мне Вам объяснять, Вы всё прекрасно знаете. Вот и хотелось бы наполнять этот скрипт вручную, с командами задержек ,м.б. даже с подключением файлов внешних данных (шрифтов и т.п.), но это уже так, фантазии. )) Подумайте, м.б. эта идея заинтересует Вас? В принципе - достаточно было бы просто редактировать тело скрипта и возможность выставлять задержки выполнения команд.
    Большое спасибо за Ваш труд! )

  • aave1
    aave1 Пятница, 21 May 2021 19:03 Ссылка на комментарий

    Дмитрий, большое спасибо за отзыв и за идею!
    На самом деле эта задумка в планах имеется, и даже есть её рабочая "альфа" версия. К сожалению, нет достаточного количества времени для качественной доработки, поэтому дело движется медленно, а показывать в сыром виде не хочется. Но эту идею я обязательно завершу, и в следующей версии программы скрипты обязательно появятся! Но по срокам не могу ничего конкретного обещать.

  • Дмитрий
    Дмитрий Суббота, 22 May 2021 16:11 Ссылка на комментарий

    Большое спасибо, что не оставляете такой хороший и нужный нам, простым пользователям, проект!
    Желаю Вам успехов во всех Ваших начинаниях и делах! ))

  • Александр
    Александр Пятница, 09 Сентябрь 2022 19:42 Ссылка на комментарий

    Здравствуйте!
    Большое спасибо за статью.
    Скажите пожалуйста, можно ли пере-собрать программу SPI via FTDI ver.2 для Windows XP (т.е. Win32)?
    И второй вопрос: где можно скачать модифицированную вами библиотеку libMPSSE.dll ?

  • aave613
    aave613 Пятница, 09 Сентябрь 2022 20:14 Ссылка на комментарий

    Александр, добрый день! Программа SPI via FTDI работает под WinXP, только в ОС нужно установить .NET Framework 3.5 SP1. Модифицированная библиотека присутствует в самой программе, чтобы её активировать просто в меню выберите Устройство - Библиотека - Модифицированная. Программа запишет библиотеку в директорию C:\Temp. После этого нужно перезапустить программу, и она будет использовать модифицированную библиотеку.

  • Александр
    Александр Суббота, 10 Сентябрь 2022 20:04 Ссылка на комментарий

    Большое спасибо за разъяснение. Действительно, с .NET 3.5 SP1 программа нормально запустилась под WinXP. По поводу записи библиотеки в директорию c:\Temp - может вам будет полезна информация о том, что программа записывает библиотеку в эту директорию только если там уже имеется одноименный файл (т.е. переписывает его). По крайней мере в моей XP происходит так. Не может создать файл?

  • aave613
    aave613 Суббота, 10 Сентябрь 2022 21:26 Ссылка на комментарий

    Я проверю это. Если так, добавлю в новую версию такую возможность. Относительно скоро (до Нового года, думаю) планирую загрузить новую версию программы с новым функционалом, в ней учту Ваше замечание. Спасибо за обратную связь!)

  • Александр
    Александр Среда, 21 Сентябрь 2022 10:43 Ссылка на комментарий

    Прошу прощения за глупый вопрос: а с шиной SMBus ваша замечательная программа не работает? Сами устройства на этой шине она видит (функция "Сканер устройств на шине").

  • aave2
    aave2 Суббота, 24 Сентябрь 2022 05:56 Ссылка на комментарий

    Александр, я не проверял, но по идее должна на малых скоростях до 100 кГц.

  • Максим
    Максим Вторник, 14 Март 2023 12:43 Ссылка на комментарий

    Доброго незлого дня
    Пробую вычитать 25QUxxx через Tigard (https://github.com/tigard-tools/tigard), на любых настройках - 0 эмоций, читает нули
    Через flashrom в Linux все отменно
    Драйвера стоят, программатор определяется
    куда копать не подскажете?

  • aave1
    aave1 Вторник, 14 Март 2023 19:21 Ссылка на комментарий

    Максим,
    Если возвращаются нули, скорее всего микросхема не отвечает. Тут следует проверить, что во-первых всё правильно подключено, а во-вторых, что вы работаете на тех же логических уровнях, что и читаемая память. Это что в голову пришло, я не работал с Tigard. Может быть ещё что-то с библиотеками .dll, есть ли какие-то диагностические сообщения? Кстати, если я правильно понял из описания, этот девайс работает по UART, попробуйте включить в настройках драйвера виртуальный порт VCP. Ещё вот что: возможно, для чтения дампа памяти микросхеме нужно отправить какую-то команду? Надо внимательно почитать даташит.

  • Владимир
    Владимир Понедельник, 24 Апрель 2023 17:55 Ссылка на комментарий

    Огромное вам спасибо за проделанную работу.
    Очень меня выручили.
    Смог отредактировать еепром ЭБУ двигателя приора.
    Удалил иммобилайзер не теряя остальных настроек.

  • aave1
    aave1 Вторник, 25 Апрель 2023 05:44 Ссылка на комментарий

    Владимир, рад помочь) на днях планирую загрузить новую версию программы с поддержкой интерфейса MicroWire.

  • Витя
    Витя Пятница, 16 Июнь 2023 20:06 Ссылка на комментарий

    поправьте в статье ошибочку выделил этими знаками , что предложение вставлено в слово.
    На двух иллюстрациях ниже, взятых из технических описаний, приводится назна чение ножек микросхем FT2232D (низкоскоростной) и FT2232H (высокоскоростной) при работе в разных режимах, в том числе SPI (см. столбец MPSSE). Микросхема FT4232 также имеет два канала, поддерживающих режим MPSSE. Хотя общее число каналов у неё – четыре.

  • aave1
    aave1 Суббота, 17 Июнь 2023 13:09 Ссылка на комментарий

    Витя, спасибо за обратную связь и замечание. Действительно, не заметил. Исправил.

  • Рашид
    Рашид Суббота, 19 Октябрь 2024 01:00 Ссылка на комментарий

    Приветствую вас
    Спасибо за труд

    Нахожусь в поисках разгадки для своей проблемы

    Буду очень рад , если ознакомитесь с моим вопросом и что-то посоветуете
    Имеется микросхема FTDI (FT232R). Стоит задача изменить ее сериал_нумбер с дефолтного (A50285BI) на конфигурируемый. Иными словами на какой-то другой, а не дефолтный

    Как водится пошел по пути наименьшего сопротивления : FT_PROG.
    Поправив значение упомянутого поля в интерфейсе FT_PROG, можно нажать на исполнение. Затем возникает лог о результативном завершении , ну и после , по логике, нужно переподключить девайс. Что и было выполнено. Но ожидаемого результата, а именно изменённого значения сериал_нумбер, достичь так и не удалось. Пробовал раз 20 с разными изменениями в последовательности действий и тд, но результат одинаковый ...

    Стал искать и нашел ваше видео. Пришел на этот ваш сайт: https://soltau.ru/index.php/themes/dev/item/421-realizatsiya-spi-s-pomoshchyu-mikroskhem-firmy-ftdi

    Но как скачать и установит SPI via FTDI , если честно, не до конца понятно

    Если бы вы смогли подсказать почему у меня не получилось с FT_PROG и второй вопрос - это как скачать любезно предлагаемую вами SPI via FTDI?

    И ещё третье: вы не знаете - получилось ли, пользуясь мощностями вашего приложения , поправить значения в (FT232R) так, чтобы они сохранились на плате ?
    Заранее большое спасибо )

  • Aavex
    Aavex Понедельник, 21 Октябрь 2024 08:23 Ссылка на комментарий

    Рашид, добрый день!
    Ссылки на скачивание программы приведены в конце статьи.
    Но, боюсь, вам моя программа тоже не поможет поменять серийный номер. Скорее всего, на вашей плате нет внешней памяти, поэтому используется номер, зашитый непосредственно в микросхему. Он неизменяемый.