Skocz do zawartości

STM32F103RBT6 komunikacja SPI z wykorzystaniem DMA


Pomocna odpowiedź

Napisano

Witam,
mam pewien problem z wykonaniem wysyłania danych przez SPI z wykorzystaniem DMA. Mianowicie przy konfiguracji DMA (wycinek z biblioteki z konfiguracją DMA):

#include "stm32f10x.h"
#include "../src/DMA_Init/dma_init.h"

uint32_t SPI_RxValue[rx_size];
uint32_t SPI_TxValue[tx_size] = {0x00};

void dma_init (void){
DMA_InitTypeDef dma;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

DMA_DeInit(DMA1_Channel2);
DMA_StructInit(&dma);
dma.DMA_PeripheralBaseAddr = (uint32_t)&SPI1->DR; //Address of peripheral the DMA must map to
dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
dma.DMA_MemoryBaseAddr = (uint32_t)&SPI_RxValue[0]; //Variable to which received data will be stored
dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
dma.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
dma.DMA_DIR = DMA_DIR_PeripheralSRC;
dma.DMA_BufferSize = rx_size; //Buffer size
dma.DMA_Mode = DMA_Mode_Circular;
dma.DMA_Priority = DMA_Priority_VeryHigh;
dma.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel2, &dma); //Initialise the DMA
DMA_Cmd(DMA1_Channel2, ENABLE); //Enable the DMA1 - Channel1

DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE);

//==Configure DMA1 - Channel5== (memory -> SPI)
DMA_DeInit(DMA1_Channel3); //Set DMA registers to default values
DMA_StructInit(&dma);
dma.DMA_PeripheralBaseAddr = (uint32_t)&SPI1->DR; //Address of peripheral the DMA must map to
dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
dma.DMA_MemoryBaseAddr = (uint32_t)&SPI_TxValue[0]; //Variable from which data will be transmitted
dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
dma.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
dma.DMA_DIR = DMA_DIR_PeripheralDST;
dma.DMA_BufferSize = tx_size; //Buffer size
dma.DMA_Mode = DMA_Mode_Circular;
dma.DMA_Priority = DMA_Priority_VeryHigh;
dma.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel3, &dma); //Initialise the DMA
DMA_Cmd(DMA1_Channel3, ENABLE); //Enable the DMA1 - Channel5

SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx | SPI_I2S_DMAReq_Tx, ENABLE);
}

i instrukcji wysyłania przez SPI:

uint8_t spi_sendrec(uint8_t byte){
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, byte);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
return SPI_I2S_ReceiveData(SPI1);
}

podczas debugowania pierwsze wysłanie wartości przez SPI przebiega ok, a przy następnej instrukcji wysyłania program się zawiesza. Wydaje mi się, że brakuje jakiejś flagi czyszczącej bit dotyczący wysyłania ale pewny nie jestem. Dodam jeszcze instrukcję obsługi przerwania odbioru przez SPI:

void DMA1_Channel2_IRQHandler(void){
uint8_t i=0;
if(DMA_GetITStatus(DMA1_IT_HT4)) {
	SPI_TxValue[0]=SPI_RxValue[0];
	DMA_ClearITPendingBit(DMA1_IT_HT4);
}
if(DMA_GetITStatus(DMA1_IT_TC4)) {
	for (i=0;i<=7;i++){
		SPI_TxValue[i]=SPI_RxValue[i];
	}
	DMA_ClearITPendingBit(DMA1_IT_TC4);
}
}

Gdyby ktoś był łaskaw sprawdzić i móc powiedzieć co mogło pójść nie tak to byłbym wdzięczny 🙂

[ Dodano: 27-09-2016, 20:35 ]

Ktoś coś ?

Hej, średnio znam się na STMach, ale spróbuję pomóc.

Widzę pewne niezgodności w typach danych (według mnie tu tkwi problem):

- Bufory SPI_RxValue i SPI_TxValue mają typ: uint32_t

- W DMA1_Channel2 ustawiasz DataSize na: Byte

- W DMA1_Channel3 ustawiasz DataSize na: HalfWord

- Funkcja spi_sendrec przyjmuje i zwraca: uint8_t

Poza tym możesz powiedzieć co oznaczają flagi: DMA1_IT_HT4 i DMA1_IT_TC4? Oraz ile wynosi rx_size i tx_size?

1. Chcesz używać DMA, ale twój kod do wysyłania po SPI jest bez DMA

2. DMA masz ustawione w trybie circular. Jak dobrze pamiętam spowoduje to ciągłe wysyłanie, bo bufor się nigdy nie skończy... sprawdziłeś co pojawia się na wyjściu SPI? Umieść w buforze jakąś wartość typu 0x55 i powinieneś mieć na przemian 0/1/0/1/0/1/ na wyjściu SPI... no i oczywiście clock.

Tryb powinien być Normal i jak chcesz zacząć wysyłać następną "ramkę" to ponownie ustawiasz wskaźnik na pamięć gdzie jest początek buforu, buforsize i odpalasz znowu DMA.

Dzięki za odpowiedzi !

Do tej pory ogarniałem tylko przykłady z kursu STM32F1 na bibliotekach STL, teraz chciałem wykorzystać DMA w transmisji. MirekCz, czy mógłbyś jakoś mnie naprowadzić jak by to napisać, żeby transmisja odbywała się przy pomocy DMA ? Jak by wyglądała instrukcja wysyłania/odbierania z DMA ? Może jakiś przykład macie. Szukać szukałem ale znalazłem tylko inicjalizację, żadnych konkretnych instrukcji.

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...