USART mit DMA

OP #2672371
Hallo,
ich bin mal wieder mit meinem STM32f4 am tüfteln. Ich versuche per USART 
mit DMA Daten zu empfangen. Leider löst kein Interrupt aus. USART senden 
und Empfangen mit Interrupt funktioniert aber. Daher schließe ich 
darauf, dass die DMA Konfiguration nicht stimmt. Hat hier jemand schon 
Erfahrung oder ein kleines Beispiel. Wäre sehr dankbar!
1
void initPC_Com()
2
{
3
  USART_Config conf;
4
  //USART_DMA_Config dmaConf;
5
  configureUSART2(&conf);
6
  //configureUSART2_DMA(&dmaConf);
7
  USART_Ini(&conf);
8

9
  currentUsedUSART = &conf;
10

11

12
  USARTDMA_Ini(&TestBuf,9);
13
}
14

15
static inline void configureUSART2(USART_Config* conf)
16
{
17
  conf->Rx_Source = GPIO_PinSource3;
18
  conf->Tx_Source = GPIO_PinSource2;
19
  conf->LowSpeed_APB_PeripheralClock = RCC_APB1Periph_USART2;
20
  conf->AHB1_PeripheralClock_Rx = RCC_AHB1Periph_GPIOA;
21
  conf->AHB1_PeripheralClock_Tx = RCC_AHB1Periph_GPIOA;
22
  conf->GPIO_Rx_Pin = GPIO_Pin_3;
23
  conf->GPIO_Tx_Pin = GPIO_Pin_2;
24
  conf->Rx_PORT = GPIOA;
25
  conf->Tx_PORT = GPIOA;
26
  conf->GPIO_AlternativeFunction = GPIO_AF_USART2;
27
  conf->USARTx = USART2;
28

29
  conf->InterfaceConfig.USART_BaudRate = 115200;
30
  conf->InterfaceConfig.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
31
  conf->InterfaceConfig.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
32
  conf->InterfaceConfig.USART_Parity = USART_Parity_No;
33
  conf->InterfaceConfig.USART_StopBits = USART_CR2_STOP_1;
34
  conf->InterfaceConfig.USART_WordLength = USART_WordLength_8b;
35

36
  conf->USART_GPIO_Config.GPIO_Mode = GPIO_Mode_AF;
37
  conf->USART_GPIO_Config.GPIO_Speed = GPIO_Speed_25MHz;
38
  conf->USART_GPIO_Config.GPIO_OType = GPIO_OType_PP;
39
  conf->USART_GPIO_Config.GPIO_PuPd = GPIO_PuPd_NOPULL;
40
};
41

42
void USART_Ini(USART_Config* conf)
43
{
44
    RCC_APB1PeriphClockCmd(conf->LowSpeed_APB_PeripheralClock, ENABLE);
45
    RCC_AHB1PeriphClockCmd(conf->AHB1_PeripheralClock_Rx, ENABLE);
46
    RCC_AHB1PeriphClockCmd(conf->AHB1_PeripheralClock_Tx, ENABLE);
47

48
    //Changes the mapping for the pins to use for USART for Port A
49
    GPIO_PinAFConfig(conf->Tx_PORT, conf->Tx_Source, conf->GPIO_AlternativeFunction);
50
    GPIO_PinAFConfig(conf->Rx_PORT, conf->Rx_Source, conf->GPIO_AlternativeFunction);
51

52
    conf->USART_GPIO_Config.GPIO_Pin = conf->GPIO_Rx_Pin;
53
    GPIO_Init(conf->Rx_PORT,&(conf->USART_GPIO_Config));
54
    conf->USART_GPIO_Config.GPIO_Pin = conf->GPIO_Tx_Pin;
55
    GPIO_Init(conf->Tx_PORT,&(conf->USART_GPIO_Config));
56

57
    //Set upt the USART configuration
58
    USART_Init(conf->USARTx,&(conf->InterfaceConfig));
59

60
    //Enable USART 2 now
61
    USART_Cmd(conf->USARTx, ENABLE);
62
}
63

64
void USARTDMA_Ini(uint8_t* buffer,uint32_t size)
65
{
66
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
67

68
  DMA_DeInit(DMA1_Stream2);
69
  DMA_Cmd(DMA1_Stream2, DISABLE);
70
  DMA_InitTypeDef DMA_InitStruct;
71
  DMA_StructInit(&DMA_InitStruct);
72
  DMA_InitStruct.DMA_Channel = DMA_Channel_0;
73
  DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(USART2->DR);
74
  DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)buffer;
75
  DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralToMemory;
76
  DMA_InitStruct.DMA_BufferSize = size;
77
  DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
78
  DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
79
  DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
80
  DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
81
  DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;
82
  DMA_InitStruct.DMA_Priority = DMA_Priority_Medium;
83
  DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Disable;
84
  DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
85
  DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single;
86
  DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
87
  DMA_Init(DMA1_Stream2, &DMA_InitStruct);
88
  DMA_Cmd(DMA1_Stream2, ENABLE);
89
  USART_DMACmd(USART2, USART_DMAReq_Rx, ENABLE);
90

91
  NVIC_InitTypeDef NVIC_InitStructure;
92
  /* Enable the USARTx Interrupt */
93
  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream2_IRQn;
94
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0f;
95
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0f;
96
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
97
  NVIC_Init(&NVIC_InitStructure);
98

99
  /* Enable USART */
100
  DMA_ITConfig(DMA1_Stream2, DMA_IT_TC, ENABLE);
101
}
OP
Leider haben alle meine Änderungen bisher kein Ergebnis gezeigt. Es 
landen weder Daten im Puffer noch bekomme ich einen Interrupt wenn der 
Puffer voll ist. Ich habe den Ablauf an das "How to use this driver" der 
stm32f4xx_dma.c angepasst. Leider ohne Erfolg. Hat noch jemand einen 
Tipp? Wäre euch total dankbar.

Die DMA-Clock habe ich mit den USART-Clocks eingeschaltet.

Hier mein neuer Code.
1
//global buffer
2
uint8_t TestBuf []= {0,0,0,0,0,0,0,0,0};
3

4
//function call
5
USARTDMA_Ini((uint32_t)TestBuf,9);
6

7

8
void USARTDMA_Ini(uint32_t buffer,uint32_t size)
9
{
10
  DMA_DeInit(DMA1_Stream2);
11
  DMA_Cmd(DMA1_Stream2, DISABLE);
12

13
  DMA_InitTypeDef DMA_InitStruct;
14
  DMA_StructInit(&DMA_InitStruct);
15
  DMA_InitStruct.DMA_Channel = DMA_Channel_0;
16
  DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(USART2->DR);
17
  DMA_InitStruct.DMA_Memory0BaseAddr = buffer;
18
  DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralToMemory;
19
  DMA_InitStruct.DMA_BufferSize = size;
20
  DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
21
  DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
22
  DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
23
  DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
24
  DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;
25
  DMA_InitStruct.DMA_Priority = DMA_Priority_Medium;
26
  DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Disable;
27
  DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
28
  DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single;
29
  DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
30
  DMA_Init(DMA1_Stream2, &DMA_InitStruct);
31

32
  NVIC_InitTypeDef NVIC_InitStructure;
33
  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream2_IRQn;
34
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0f;
35
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0f;
36
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
37
  NVIC_Init(&NVIC_InitStructure);
38

39
  DMA_ITConfig(DMA1_Stream2, DMA_IT_TC, ENABLE);
40

41
  DMA_Cmd(DMA1_Stream2, ENABLE);
42

43
  USART_DMACmd(USART2, USART_DMAReq_Rx, ENABLE);
44
}
OP
So nach einem weiteren langen Tag habe ich die Lösung gefunden. Das 
Problem war zum einen das bei dem Cycle Mode die Länge vom Puffer nicht 
beliebig sein kann. Zum anderen muss man für für Richtung Peripherie zum 
Speicher den stream 5 mit dem channel 4 wählen. Hier mein 
funktionierender Code:
1
uint8_t TestBuf []= {0,0,0,0,0,0,0,0,0};
2

3
USART_DMA_Config dmaConf;
4
configureUSART2_DMA(&dmaConf);
5
USART_DMA_Ini(&dmaConf,(uint32_t)TestBuf,8);
6

7

8
static inline void configureUSART2_DMA(USART_DMA_Config* conf)
9
{
10
  conf->DMAy_Streamx  = DMA1_Stream5;
11

12
  conf->dmaConfigure.NVIC_IRQChannel = DMA1_Stream5_IRQn;
13
  conf->dmaConfigure.NVIC_IRQChannelCmd = ENABLE;
14
  conf->dmaConfigure.NVIC_IRQChannelPreemptionPriority = 0x0f;
15
  conf->dmaConfigure.NVIC_IRQChannelSubPriority = 0x0f;
16

17

18
  conf->USART_DMAReq = USART_DMAReq_Rx;
19
  conf->USARTx = USART2;
20

21
  DMA_StructInit(&(conf->dmaConf));
22
  conf->dmaConf.DMA_Channel = DMA_Channel_4;
23
  conf->dmaConf.DMA_PeripheralBaseAddr = (uint32_t)&(USART2->DR);
24
  conf->dmaConf.DMA_Memory0BaseAddr = 0;//Set in my dma init function
25
  conf->dmaConf.DMA_DIR = DMA_DIR_PeripheralToMemory;
26
  conf->dmaConf.DMA_BufferSize = 0;//Set in my dma init function
27
  conf->dmaConf.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
28
  conf->dmaConf.DMA_MemoryInc = DMA_MemoryInc_Enable;
29
  conf->dmaConf.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
30
  conf->dmaConf.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
31
  conf->dmaConf.DMA_Mode = DMA_Mode_Circular;
32
  conf->dmaConf.DMA_Priority = DMA_Priority_Medium;
33
  conf->dmaConf.DMA_FIFOMode = DMA_FIFOMode_Disable;
34
  conf->dmaConf.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
35
  conf->dmaConf.DMA_MemoryBurst = DMA_PeripheralBurst_INC8;
36
  conf->dmaConf.DMA_PeripheralBurst = DMA_PeripheralBurst_INC8;
37

38
  conf->fullInterrupt = DMA_IT_TC;
39
  conf->halfInterrupt = DMA_IT_HT;
40
}
41

42
void USART_DMA_Ini(USART_DMA_Config* conf, uint32_t* bufferAddress,uint32_t size)
43
{
44
  DMA_DeInit(conf->DMAy_Streamx);
45
  while (DMA_GetCmdStatus(conf->DMAy_Streamx) != DISABLE){}
46
  DMA_Cmd(conf->DMAy_Streamx, DISABLE);
47

48
  conf->dmaConf.DMA_Memory0BaseAddr = (uint32_t)bufferAddress;
49
  conf->dmaConf.DMA_BufferSize = size;
50

51
  DMA_Init(conf->DMAy_Streamx, &(conf->dmaConf));
52

53
  if(conf->fullInterrupt > 0)
54
    DMA_ITConfig(conf->DMAy_Streamx, conf->fullInterrupt, ENABLE);
55
  if(conf->halfInterrupt > 0)
56
    DMA_ITConfig(conf->DMAy_Streamx, conf->halfInterrupt, ENABLE);
57

58
  NVIC_Init(&(conf->dmaConfigure));
59

60
  DMA_Cmd(conf->DMAy_Streamx, ENABLE);
61

62
  USART_DMACmd(conf->USARTx, conf->USART_DMAReq, ENABLE);
63
}
64

65
void DMA1_Stream5_IRQHandler()
66
{
67
  if(DMA_GetFlagStatus(DMA1_Stream5,DMA_FLAG_HTIF5) != RESET)
68
  {
69
    LED_Toggle(LED1);
70
    DMA_ClearFlag(DMA1_Stream5,DMA_FLAG_HTIF5);
71
  }
72
  else if(DMA_GetFlagStatus(DMA1_Stream5,DMA_FLAG_TCIF5) != RESET)
73
  {
74
    LED_Toggle(LED2);
75
    DMA_ClearFlag(DMA1_Stream5,DMA_FLAG_TCIF5);
76
  }
77
  else
78
    LED_Toggle(LED0);
79
  char b = TestBuf[0];
80

81
}

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 14 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.