|
|
  |
stm32f411 spi1+DMA, непрерывная выдача данных |
|
|
|
Sep 5 2017, 08:48
|
Частый гость
 
Группа: Участник
Сообщений: 121
Регистрация: 27-04-09
Из: Украина
Пользователь №: 48 342

|
Цитата(adnega @ Sep 5 2017, 11:41)  Вам нужно DMA_Mode_Circular. DMA_Mode_Circular у меня работает, но это чисто для отладки Вч части, так как постоянно выдаётся таблица из флеши, а мне нужно готовить данные т.е. модулировать исходные данные процессором для подачи в ВЧ модулятор, где уже будет этот поток модулироваться несущей для излучения в антенну.
|
|
|
|
|
Sep 5 2017, 09:44
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(Volldemar @ Sep 5 2017, 11:48)  DMA_Mode_Circular у меня работает, но это чисто для отладки Вч части, так как постоянно выдаётся таблица из флеши, а мне нужно готовить данные т.е. модулировать исходные данные процессором для подачи в ВЧ модулятор, где уже будет этот поток модулироваться несущей для излучения в антенну. Дык, сделайте обработчик прерываний HT и TC для этого DMA. Я делаю примерно так Код void DMA2_Stream7_IRQHandler(void) { if(DMA2->HISR & (1 << DMA_HISR_HTIF7)) { DMA2->HIFCR = (1 << DMA_HISR_HTIF7); dma_event = 1; }
if(DMA2->HISR & (1 << DMA_HISR_TCIF7)) { DMA2->HIFCR = (1 << DMA_HISR_TCIF7); dma_event = 2; } }
в idle
if(dma_event == 1) { dma_event = 0; // заполняем первую половину кольца } if(dma_event == 2) { dma_event = 0; // заполняем вторую половину кольца }
|
|
|
|
|
Sep 5 2017, 11:22
|
Частый гость
 
Группа: Участник
Сообщений: 121
Регистрация: 27-04-09
Из: Украина
Пользователь №: 48 342

|
Инит ДМА вот такой: Код void DMA_Config ( uint8_t * Memory0BaseAddr, uint16_t size ) { DMA_InitTypeDef DMA_InitStructure; NVIC_InitTypeDef NVIC_InitStructure;
// Сброс настроек DMA каналов DMA_DeInit ( SPI_DMA_MASTER_Tx_DMA_Stream );
RCC_AHB1PeriphClockCmd ( SPI_DMA_MASTER_DMA_CLK, ENABLE );
DMA_DeInit(SPIx_TX_DMA_STREAM); /* Configure DMA Initialization Structure */ DMA_InitStructure.DMA_BufferSize = size; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t) (&(SPIx->DR)); DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_Priority = DMA_Priority_High; /* Configure TX DMA */ DMA_InitStructure.DMA_Channel = SPIx_TX_DMA_CHANNEL; DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)Memory0BaseAddr; DMA_Init(SPIx_TX_DMA_STREAM, &DMA_InitStructure);
// Configure the DMA interrupt priority NVIC_InitStructure.NVIC_IRQChannel = DMAx_Streamx_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = (uint8_t)(configKERNEL_INTERRUPT_PRIORITY >> 4); NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init ( &NVIC_InitStructure );
SPI_I2S_ITConfig ( SPIx, SPI_I2S_IT_TXE, ENABLE );
DMA_DoubleBufferModeConfig(DMA2_Stream5, Buffer1TX_SPI1[0], DMA_Memory_0); //первый массив для выдачи DMA_DoubleBufferModeConfig(DMA2_Stream5, Buffer2TX_SPI1[0], DMA_Memory_1); //второй массив для выдачи
DMA_DoubleBufferModeCmd ( DMA2_Stream5, ENABLE );
SPI_I2S_DMACmd ( SPI_DMA_MASTER, SPI_I2S_DMAReq_Tx, ENABLE ); DMA_ITConfig ( SPI_DMA_MASTER_Tx_DMA_Stream, DMA_IT_TC, ENABLE ); } обработчик прерывания: Код void DMA2_Stream5_IRQHandler ( void ) { portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
// Stream3 transfer complete interrupt? if(DMA_GetITStatus (SPIx_TX_DMA_STREAM,SPI_DMA_MASTER_Tx_DMA_IT)) { // clear pending interrupt DMA_ClearITPendingBit (SPIx_TX_DMA_STREAM,SPI_DMA_MASTER_Tx_DMA_IT);
if(DMA_GetCurrentMemoryTarget (SPIx_TX_DMA_STREAM)) { // Memory 1 is current target DMA_MemoryTargetConfig (SPIx_TX_DMA_STREAM,Buffer2TX_SPI1[0],DMA_Memory_0); } else { // Memory 0 is current target DMA_MemoryTargetConfig(SPIx_TX_DMA_STREAM,Buffer1TX_SPI1[0],DMA_Memory_1); } } xSemaphoreGiveFromISR ( xSemaphore_spi1, &xHigherPriorityTaskWoken ); xTaskResumeFromISR (&xHandleSPI1); portEND_SWITCHING_ISR ( xHigherPriorityTaskWoken );
} ну а запускается всё вот так: Код ukladkabufTXSPI1 ( Buffer1TX_SPI1 );//заполнение первого массива инфой ukladkabufTXSPI1 ( Buffer2TX_SPI1 );//заполнение второго массива инфой DMA_Cmd ( SPI_DMA_MASTER_Tx_DMA_Stream, ENABLE ); и всё это Не работает, ЧЯДНТ?
|
|
|
|
|
Sep 5 2017, 12:18
|
Участник

Группа: Участник
Сообщений: 40
Регистрация: 27-01-17
Пользователь №: 95 184

|
Как минимум, в функцию DMA_DoubleBufferModeConfig(DMA2_Stream5, Buffer1TX_SPI1[0], DMA_Memory_0); необходимо давать адрес буфера, а него его первое значение. Функция то всё съест, на входе просто uint32_t. Улетает небось в hardFault, т.е. лезете в непонятную область данных.
|
|
|
|
|
Sep 5 2017, 12:20
|
Частый гость
 
Группа: Участник
Сообщений: 121
Регистрация: 27-04-09
Из: Украина
Пользователь №: 48 342

|
Цитата(Hold @ Sep 5 2017, 15:18)  Как минимум, в функцию DMA_DoubleBufferModeConfig(DMA2_Stream5, Buffer1TX_SPI1[0], DMA_Memory_0); необходимо давать адрес буфера, а него его первое значение. Функция то всё съест, на входе просто uint32_t. Улетает небось в hardFault, т.е. лезете в непонятную область данных. если прописать: Код DMA_DoubleBufferModeConfig(DMA2_Stream5, &Buffer1TX_SPI1, DMA_Memory_0); вываливает варнинг: Код warning: passing argument 2 of 'DMA_DoubleBufferModeConfig' makes integer from pointer without a cast [-Wint-conversion]
|
|
|
|
|
Sep 5 2017, 12:26
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (Volldemar @ Sep 5 2017, 15:20)  вываливает варнинг: Посылайте луч поноса авторам этой "библиотеки", которые передают указатель в виде целого (и даже не специально предназначенного для этого типа uintptr_t) и добавляйте явное приведение типа. Кстати, взятие адреса тут не требуется - имя массива автоматически преобразовывается к указателю на его нулевой элемент: CODE DMA_DoubleBufferModeConfig(DMA2_Stream5, (uintptr_t)Buffer1TX_SPI1, DMA_Memory_0);
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 5 2017, 12:35
|
Частый гость
 
Группа: Участник
Сообщений: 121
Регистрация: 27-04-09
Из: Украина
Пользователь №: 48 342

|
даже если прописать: Код DMA_DoubleBufferModeConfig(DMA2_Stream5, Buffer1TX_SPI1, DMA_Memory_0); что собственно не является ошибкой, получается такой же варнинг: Код warning: passing argument 2 of 'DMA_DoubleBufferModeConfig' makes integer from pointer without a cast [-Wint-conversion] так что только так передавать: Код Buffer1TX_SPI1[0]
Сообщение отредактировал Volldemar - Sep 5 2017, 12:36
|
|
|
|
|
Sep 5 2017, 13:04
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (Volldemar @ Sep 5 2017, 15:35)  даже если прописать: CODE DMA_DoubleBufferModeConfig(DMA2_Stream5, Buffer1TX_SPI1, DMA_Memory_0); что собственно не является ошибкой, получается такой же варнинг: CODE warning: passing argument 2 of 'DMA_DoubleBufferModeConfig' makes integer from pointer without a cast [-Wint-conversion] Во-первых - да, формально это не является ошибкой, поэтому вы получаете не error, а только лишь warning. А теперь найдите 10 отличий: CODE DMA_DoubleBufferModeConfig(DMA2_Stream5, (uintptr_t)Buffer1TX_SPI1, DMA_Memory_0); QUOTE (Volldemar @ Sep 5 2017, 15:35)  так что только так передавать: CODE Buffer1TX_SPI1[0] Если вам все равно, что передавать - то да, можно и так.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 5 2017, 16:39
|
Частый гость
 
Группа: Участник
Сообщений: 169
Регистрация: 31-08-05
Из: New York
Пользователь №: 8 118

|
Цитата(Volldemar @ Sep 5 2017, 08:35)  так что только так передавать: Buffer1TX_SPI1[0] Buffer1TX_SPI1[0] - это не указатель. Его нельзя передавать. Можно так, например: &Buffer1TX_SPI1[0] или так Buffer1TX_SPI1
--------------------
ASB
|
|
|
|
|
Sep 6 2017, 08:02
|
Частый гость
 
Группа: Участник
Сообщений: 121
Регистрация: 27-04-09
Из: Украина
Пользователь №: 48 342

|
Цитата(Aleksandr Baranov @ Sep 5 2017, 19:39)  Buffer1TX_SPI1[0] - это не указатель. Его нельзя передавать. Можно так, например: &Buffer1TX_SPI1[0] или так Buffer1TX_SPI1 Вопрос о правильной передаче параметра - решен!
Сообщение отредактировал Volldemar - Sep 6 2017, 11:36
|
|
|
|
|
Sep 6 2017, 12:14
|
Частый гость
 
Группа: Участник
Сообщений: 169
Регистрация: 31-08-05
Из: New York
Пользователь №: 8 118

|
Цитата(Volldemar @ Sep 6 2017, 07:43)  Появилась выдача в SPI, но тут подкралось НО! как теперь определять, что мнфа из одного из массивов уже ушла полностью и пора готовить второй массив с данными? "Half transfer interrupt" никак не поможет?
--------------------
ASB
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|