Forum: Mikrocontroller und Digitale Elektronik USART mit DMA


von Jonathan S. (broky)


Lesenswert?

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
}

: Verschoben durch User
von Jonathan S. (broky)


Lesenswert?

Hallo,
hab den Fehler immer noch nicht gefunden. Kann es sein, USART erst nach 
der DMA Konfiguration eingeschaltet werden darf?

Gruß Broky

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Jonathan Schubert schrieb:
> Kann es sein, USART erst nach
> der DMA Konfiguration eingeschaltet werden darf?

Probieren geht über studieren ... und Versuch macht kluch :-)

von Jonathan S. (broky)


Lesenswert?

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
}

von Jonathan S. (broky)


Lesenswert?

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
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.