SPI

32-разрядные микроконтроллеры разработки АО "НИИЭТ"

Модераторы: ea, dav, bkolbov, Alis, pip, _sva_

Аватара пользователя
atom
Сообщения: 11
Зарегистрирован: 26 фев 2016, 11:03
Предприятие: Алмаз-Фазотрон
Откуда: Саратов

SPI

Сообщение atom »

Здравствуйте!
Пытаюсь настроить SPI в режиме Slave. Пересылки идут пачками по 16 бит.
Настройки SPI:

Код: Выделить всё

    
    GPIO_Init_TypeDef GPIO_InitStruct;
    GPIO_StructInit(&GPIO_InitStruct);

    /* A2 - TXD */
    GPIO_InitStruct.GPIO_AltFunc = GPIO_AltFunc_2;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AltFunc;
    GPIO_InitStruct.GPIO_Out = GPIO_Out_En;
    GPIO_InitStruct.GPIO_Dir = GPIO_Dir_Out;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;
    GPIO_Init(NT_GPIOA, &GPIO_InitStruct);

    /* Перенастройка PB0-PB2 для последующей нормальной настройки SPI1 (errarta п.6) */
    GPIO_InitStruct.GPIO_AltFunc = GPIO_AltFunc_3;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;
    GPIO_Init(NT_GPIOB, &GPIO_InitStruct);

    /* E8 - FSS */
    /* E9 - CLK */
    GPIO_InitStruct.GPIO_AltFunc = GPIO_AltFunc_3;
    GPIO_InitStruct.GPIO_Out = GPIO_Out_Dis;
    GPIO_InitStruct.GPIO_Dir = GPIO_Dir_In;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
    GPIO_Init(NT_GPIOE, &GPIO_InitStruct);

    /* G2 - RXD */
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;
    GPIO_Init(NT_GPIOG, &GPIO_InitStruct);

    /* Обратное подключение JTAG */
    GPIO_InitStruct.GPIO_AltFunc = GPIO_AltFunc_1;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;
    GPIO_Init(NT_GPIOB, &GPIO_InitStruct);
    
    /* Настройка SPI */
    NT_SPI_TypeDef *spi = NT_SPI1;
    SPI_DeInit(spi);

    RCC_SPIClkSel(spi, RCC_SPIClk_SYSCLK);
    RCC_SPIClkDivConfig(spi, 2, ENABLE);
    RCC_SPIClkCmd(spi, ENABLE);

    SPI_Init_TypeDef SPI_InitStruct;
    SPI_StructInit(&SPI_InitStruct);

    SPI_InitStruct.SPI_CPSDVSR    = 2;
    SPI_InitStruct.SPI_SCR        = 0;
    SPI_InitStruct.SPI_Mode       = SPI_ModeSlave;
    SPI_InitStruct.SPI_SPH        = SPI_SPH_1Edge;
    SPI_InitStruct.SPI_SPO        = SPI_SPO_Low;
    SPI_InitStruct.SPI_WordLength = SPI_WordLength16b;
    SPI_InitStruct.SPI_FRF        = SPI_FRF_SPI_Motorola;
    SPI_InitStruct.SPI_TX_Slave   = SPI_TX_Slave_Disable;
    SPI_Init(spi, &SPI_InitStruct);

    SPI_Cmd(spi, ENABLE);
При этом при считывании данных наблюдаю сдвижку данных в каждом кадре на 1 бит влево, т.е например когда установлен только младший бит считывается 0х0002 (а не 0х0001), когда установлены все биты - считывается 0xFFFE (вместо 0xFFFF).
Подскажите, пожалуйста, в чём может быть проблема и как её исправить?
Диаграмма работы SPI | Показать
SCR02.PNG
SCR02.PNG (21.65 КБ) 9439 просмотров
Драйвер SPI | Показать
niietcm4_spi.c
(8.43 КБ) 164 скачивания
hgost
Сообщения: 61
Зарегистрирован: 14 дек 2015, 12:07
Предприятие: АО НИИЭТ
Откуда: НИИЭТ
Контактная информация:

Re: SPI

Сообщение hgost »

atom писал(а): 28 ноя 2017, 10:40 Здравствуйте!
Пытаюсь настроить SPI в режиме Slave. Пересылки идут пачками по 16 бит.
Добрый день.
Мы с SPI никаких проблем не наблюдали. Временная диаграмма в Вашем сообщении выглядит нормально. Попробуйте поэкспериментировать:
- А что за устройство передает данные, может проблема в мастере?
- Режимы работы обоих устройств идентичны? (протокол, полярности и фазы CLK)
- Попробовать другой режим работы или другую размерность данных
- Соблюдается ли ограничение по частоте Fspi_clk ≤ SysCLK/12 ?
Аватара пользователя
atom
Сообщения: 11
Зарегистрирован: 26 фев 2016, 11:03
Предприятие: Алмаз-Фазотрон
Откуда: Саратов

Re: SPI

Сообщение atom »

Проблема решена, данные стали читаться корректно. Проблема была в низкой частоте работы блока SPI. Для корректной работы в коде выше нужно заменить строчку

Код: Выделить всё

RCC_SPIClkDivConfig(spi, 2, ENABLE);
на

Код: Выделить всё

RCC_SPIClkDivConfig(spi, 0, ENABLE);
Аватара пользователя
atom
Сообщения: 11
Зарегистрирован: 26 фев 2016, 11:03
Предприятие: Алмаз-Фазотрон
Откуда: Саратов

Re: SPI

Сообщение atom »

Ещё один вопрос: как настроить чтение данных из SPI в массив при помощи DMA?
Я пытаюсь делать так:
1. Разрешаю формирование запросов DMA для обслуживания буфера FIFO приёмника SPI:

Код: Выделить всё

SPI_DMACmd(spi, SPI_DMA_RXE, ENABLE);
2. Инициализирую DMA:

Код: Выделить всё

#define NWORD_MAX           32

DMA_ConfigData_TypeDef DMA_CONFIGDATA __attribute__ ((aligned (1024)));
uint16_t dataControl[NWORD_MAX];

/*******************************************
 * Инициализация режима DMA для SPI1
 ******************************************/
void SPI1_DMA_Initialization(void) {
    /* Reset all DMA settings */
    DMA_DeInit();

    /* Базовый указатель */
    DMA_BasePtrConfig((uint32_t)(&DMA_CONFIGDATA));

    /* Инициализация канала */
    DMA_ChannelInit_TypeDef DMA_ChannelInitStruct;
    DMA_ChannelStructInit(&DMA_ChannelInitStruct);
    DMA_ChannelInitStruct.DMA_SrcDataEndPtr        = (uint32_t *)(&(NT_SPI1->SPI_DR));
    DMA_ChannelInitStruct.DMA_DstDataEndPtr        = (uint32_t *)(&dataControl[NWORD_MAX - 1]);
    DMA_ChannelInitStruct.DMA_SrcDataInc           = DMA_DataInc_Disable;
    DMA_ChannelInitStruct.DMA_DstDataInc           = DMA_DataInc_16;
    DMA_ChannelInitStruct.DMA_SrcDataSize          = DMA_DataSize_16;
    DMA_ChannelInitStruct.DMA_DstDataSize          = DMA_DataSize_16;
    DMA_ChannelInitStruct.DMA_Mode                 = DMA_Mode_Basic;
    DMA_ChannelInitStruct.DMA_TransfersTotal       = NWORD_MAX;
    DMA_ChannelInitStruct.DMA_ArbitrationRate      = DMA_ArbitrationRate_1;
    DMA_ChannelInitStruct.DMA_SrcProtect.PRIVELGED = ENABLE;
    DMA_ChannelInitStruct.DMA_DstProtect.PRIVELGED = ENABLE;
    DMA_ChannelInit(&DMA_CONFIGDATA.PRM_DATA.CH[0], &DMA_ChannelInitStruct);

    /* Инициализация контроллера */
    DMA_Init_TypeDef DMA_InitStruct;
    DMA_StructInit(&DMA_InitStruct);
    DMA_InitStruct.DMA_Channel       = DMA_Channel_0;
    DMA_InitStruct.DMA_HighPriority  = ENABLE;
    DMA_InitStruct.DMA_UseBurst      = DISABLE;
    DMA_InitStruct.DMA_ChannelEnable = ENABLE;
    DMA_Init(&DMA_InitStruct);
    DMA_MasterEnableCmd(ENABLE);
}
При этом в массиве dataControl данные не появляются. Подскажите, пожалуйста, что я делаю не так и как получить данные при помощи DMA?
Обновленный драйвер SPI | Показать
niietcm4_spi.h
(16.27 КБ) 167 скачиваний
niietcm4_spi.c
(8.54 КБ) 160 скачиваний
Аватара пользователя
atom
Сообщения: 11
Зарегистрирован: 26 фев 2016, 11:03
Предприятие: Алмаз-Фазотрон
Откуда: Саратов

Re: SPI

Сообщение atom »

atom писал(а): 29 ноя 2017, 18:17 Подскажите, пожалуйста, что я делаю не так и как получить данные при помощи DMA?
Неправильно был выбран канал DMA. Вместо нулевого нужно выбирать канал 21, на который приходит запрос от буфера приёмника SPI1, т.е. в коде выше нужно заменить 2 строчки:

Код: Выделить всё

DMA_ChannelInit(&DMA_CONFIGDATA.PRM_DATA.CH[0], &DMA_ChannelInitStruct);
и 
DMA_InitStruct.DMA_Channel       = DMA_Channel_0;
на

Код: Выделить всё

DMA_ChannelInit(&DMA_CONFIGDATA.PRM_DATA.CH[21], &DMA_ChannelInitStruct);
и 
DMA_InitStruct.DMA_Channel       = DMA_Channel_SPI1_RX;
соответственно.
Роман
Сообщения: 28
Зарегистрирован: 26 янв 2018, 12:01
Предприятие: ВНИИЭМ

SPI master

Сообщение Роман »

Добрый день, немного длинное вступление:
Контроллер осваиваю на плате MBS-К1921ВК01Т от мехатроники. Плата выполнена в формате ezdsp tms320f2812 - под которую мы когда-то делали базовую плату, на которой используется spi расширитель портов (подключен к McBSP). MBS-К1921ВК01Т пришлось чуть переделать для совместимости.
Расширитель портов - два max7301 один за другим, т.е длина одного слова spi 32 бита, слова д.б. разделены переходом cs в 1, по которому max7301 защёлкивает данные. Длина разового пакета 5 слов. В случае использования с TI все просто (фифо 16 слов шириной до 32 бит, длительность cs определяется шириной слова, полностью задаваемый уровень прерываний): записал всю посылку в передающий фифо, и, по прерыванию, забрал ответ из приёмного.

С ВК01 обмен пока получился только по прерываниям в 8 битном режиме. В передающий буфер приходится писать данные по 32 бита и ждать окончания отправки (т.к. cs переходит в 1 когда нет передачи, прерывания по окончанию отправки нет, а по приёму только по 4-м элементам в фифо).
В принципе конечно работает, но в следующих контроллерах хотелось бы:
1. Возможность альтернативного управления CS, т.е. CS может управляться так как сейчас либо в зависимости размера передаваемого кадра.
2. Более гибкое управление прерываниями, по крайней мере полностью задаваемый уровень от приёмника.
3. Разрядность фифо до 32 бит (сооветственно кадр spi).

С ДМА пока не разобрался, но ощущение что при штатном использовании (18 канал на передачу, 22 на приём)
нужного управления cs не получить.
На посмотреть cs такой эксперимент: 22-й канал настраиваю на отправку из массива, для начала отправки пушу в фифо 4 раза,
ожидаю увидеть cs в 1 каждые 32 бита - результат cs в 0 всю посылку, похоже dma запускается не тем сигналом что Энвик или дело во времени ?.
Перед тем как вникать в подробности dma хотелось бы узнать реализуема ли эта задача ?
Роман
Сообщения: 28
Зарегистрирован: 26 янв 2018, 12:01
Предприятие: ВНИИЭМ

Re: SPI

Сообщение Роман »

В предидущем сообщении под CS имелся ввиду SPI_FSS, когда писал про альтернативное управление CS пропустил что оно в принципе есть и задается полем SPH в SPI_CR0, но момент выборки данных и управление SPI_FSS не д.б. связаны.
В будущем хорошо было-бы иметь возможность событием PWM_SOC выставлять биты в NT_DMA->CHNL_ENABLE_SET для spi.
Это позволит получить аппаратную синхронизации spi ацп и шим, также хорошо было-бы если бы перед каждой dma транзакцией не надо было переинициализировать CHANNEL_CFG (у ti в piccolo dma не требует постоянного внимания).
bkolbov
Сообщения: 248
Зарегистрирован: 14 дек 2015, 11:37
Предприятие: АО НИИЭТ
Откуда: Воронеж

Re: SPI

Сообщение bkolbov »

Добрый день, Роман.

Благодарю за предложения!
С ДМА пока не разобрался, но ощущение что при штатном использовании (18 канал на передачу, 22 на приём)
нужного управления cs не получить.
На посмотреть cs такой эксперимент: 22-й канал настраиваю на отправку из массива, для начала отправки пушу в фифо 4 раза,
ожидаю увидеть cs в 1 каждые 32 бита - результат cs в 0 всю посылку, похоже dma запускается не тем сигналом что Энвик или дело во времени ?.
Перед тем как вникать в подробности dma хотелось бы узнать реализуема ли эта задача ?
Не совсем понятно почему вы ожидаете увидеть "cs в 1 каждые 32 бита"? Поясните подробнее, пожалуйста.
В будущем хорошо было-бы иметь возможность событием PWM_SOC выставлять биты в NT_DMA->CHNL_ENABLE_SET для spi.
Это позволит получить аппаратную синхронизации spi ацп и шим
Интересный вариант синхронизации. Расскажите пожалуйста поподробнее в каком случае или для чего такая синхронизация полезна и/или нужна?
Роман
Сообщения: 28
Зарегистрирован: 26 янв 2018, 12:01
Предприятие: ВНИИЭМ

Re: SPI

Сообщение Роман »

Было такое предположение (на случай если запуск дма работает по тому же сигналу что контроллер прерываний): записал в передающий фифо 4 элемента, они передались (соответсвенно CS в 1) и ответ оказался в приёмном фифо -> возникло событие (по времени совпадающее с irq), запускающее дма на передачу и т.д.
При управлении импульсным преобразователем, необходимо получить результат преобразования АЦП во вполне конкретный момент времени относительно момента коммутации (если я правильно понял именно для этого событие PWM_SOC и реализовано в случае внутреннего АЦП), соответственно хотелось бы иметь возможность получить результат преобразования spi АЦП как можно ближе по времени к внутреннему. Например ad7328, настроен в восьмиканальный конвеерный режим, посылаю 8 нулей (16 бит каждый), преобразование происходит в процессе приёма по клокам spi и результат преобразования в ответе, будут надеюсь и у нас, подобные микросхемы.
Я пока не добрался до АЦП, но, судя по форуму, его использование требует довольно трудоёмкого этапа настройки/калибровки, и сответственно разработки соответствующего вспомогательного оборудования, да и обвязка будет довольно обьёмной (по крайней мере при использовании только отечественной комплектухи, пока про АЦП - если уж нет входа источника опорного, то уж выход точно д.б., чтобы хоть всё плавало одинакаво!).
При низких частотах шим (думаю килогерц до 10-15) может хватить и того же ad7328 при наличии аппаратной синхронизации с нужным моментом времени, в этом случае конечно хотелось бы иметь дма не требующий переинициализации каждый цикл, т.е. настроил шим, spi, dma и оно там само опрашивается а мне только в шим прерывании следующую длительность считать.
Роман
Сообщения: 28
Зарегистрирован: 26 янв 2018, 12:01
Предприятие: ВНИИЭМ

Re: SPI

Сообщение Роман »

Ещё на тему spi ацп - гальваническая развязка по spi делается тривиально а вот на алаловый сигнал...
Ответить

Вернуться в «32-разрядные микроконтроллеры»