Skocz do zawartości

STM32F103RBT6 komunikacja SPI z wykorzystaniem DMA


Vroobee

Pomocna odpowiedź

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ś ?

Link do komentarza
Share on other sites

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?

Link do komentarza
Share on other sites

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.

Link do komentarza
Share on other sites

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.

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.