STM32F407 USART1 über DMA

OP #3716997
Lesenswert?

Hallo zusammen

Ich möchte die USART1 über den DMA starten, was aber nicht richtig 
gelingt, denn jetzt habe ich endlos Zeichen auf dem Port, das heisst das 
Senden funktioniert, aber stellt nicht mehr ab, wieso das?

unsigned char bufferRS485[129] = "Hello World, this is a DMA test. If 
you can read this the DMA is still working!\n";

void USART1_Init(void)
{
  GPIO_InitTypeDef GPIOA_InitStructure;
    USART_InitTypeDef USART1_InitStructure;
  //USART 1 Init
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

  USART1_InitStructure.USART_BaudRate = 115200;
  USART1_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART1_InitStructure.USART_StopBits = USART_StopBits_1;
  USART1_InitStructure.USART_Parity = USART_Parity_No;
  USART1_InitStructure.USART_HardwareFlowControl = 
USART_HardwareFlowControl_None;
  USART1_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

  USART_Init(USART1, &USART1_InitStructure);
  USART_Cmd(USART1, ENABLE);

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

  GPIOA_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIOA_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIOA_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
  GPIOA_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  GPIOA_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(GPIOA, &GPIOA_InitStructure);

  GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
}

void DMA_RS485_Init(void)
{
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);

  DMA_InitTypeDef DMA_InitStruct;
  DMA_StructInit(&DMA_InitStruct);
  DMA_InitStruct.DMA_Channel = DMA_Channel_4;
  DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(USART1->DR);
  DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)&bufferRS485;
  DMA_InitStruct.DMA_DIR = DMA_DIR_MemoryToPeripheral;
  DMA_InitStruct.DMA_BufferSize = 129;
  DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStruct.DMA_PeripheralDataSize = 
DMA_PeripheralDataSize_HalfWord;
  DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStruct.DMA_Priority = DMA_Priority_Medium;
  DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Disable;
  DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
  DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_Init(DMA2_Stream7, &DMA_InitStruct);
}

Im Main läuft dies (nur 1mal)

USART1_Init();
DMA_RS485_Init();
USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
DMA_Cmd(DMA2_Stream7, ENABLE);


NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream7_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x07;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

void DMA2_Channel4_IRQHandler(void)
  {
  DMA_ClearFlag(DMA2_Stream2, DMA_FLAG_TCIF2);
  DMA_ClearFlag(DMA2_Stream7, DMA_FLAG_TCIF2);
  DMA_ClearFlag(DMA2_Stream2, DMA_FLAG_HTIF2);
  DMA_ClearFlag(DMA2_Stream7, DMA_FLAG_HTIF2);
  }


Was mache ich da falsch?

Danke.
OP #3717029
Lesenswert?

holger schrieb:
>>Passt jetzt, ausser dass die Ausgabe zu lange ist (siehe Bild)
>
>   DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
>
> Ein char ist kein Halfword.

Ok, habe es jetzt so gemacht:

  DMA_InitTypeDef DMA_InitStruct;
  DMA_StructInit(&DMA_InitStruct);
  DMA_InitStruct.DMA_Channel = DMA_Channel_4;
  DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(USART1->DR);
  DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)&bufferRS485;
  DMA_InitStruct.DMA_DIR = DMA_DIR_MemoryToPeripheral;
  DMA_InitStruct.DMA_BufferSize = 81;
  DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
  DMA_InitStruct.DMA_Priority = DMA_Priority_Medium;
  DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Enable;
  DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
  DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_Init(DMA2_Stream7, &DMA_InitStruct);


Trotzdem habe ich am Anfang 0x00 vor dem 0x48 (H), warum dies?

Danke Holger
Gast #3717037
Lesenswert?

>> Ein char ist kein Halfword.
>
>Das heisst wie macht man das richtig?

Man sucht in der Headerdatei nach DMA_MemoryDataSize_HalfWord.
Bei Eclipse z.B. muss man nur mal das Wort markieren und F3 drücken.
Dann schaut man nach was es da noch so gibt und besser passt.
Gast #3717052
Lesenswert?

>> Man könnte darauf kommen das dies schon mit Ausgabe der Uhrzeit
>> und Datum gesendet wurde.
>
>Nein ist es leider nicht, kommt definitiv über die USART1 raus

Das widerspricht meiner Theorie nicht.

Wo kommt diese Ausgabe von Datum und Uhrzeit her?
Gast #3717061
Lesenswert?

>  DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)&bufferRS485;
>  DMA_InitStruct.DMA_BufferSize = 81;

Ist dein String wirklich 81 Zeichen lang?

Versuchs mal so:

DMA_InitStruct.DMA_BufferSize = strlen(bufferRS485);
OP #3717067
Lesenswert?

holger schrieb:
> Ist dein String wirklich 81 Zeichen lang?
>
> Versuchs mal so:
>
> DMA_InitStruct.DMA_BufferSize = strlen(bufferRS485);

Nein waren 80, aber habe dies schon gefunden gehabt, DANKE!

Etwas anderes -> wegen dem Interrupt Controller für diesen DMA:

void DMA2_Stream7_IRQHandler (void)
  {
  /* Test on DMA Stream Transfer Complete interrupt */
  if (DMA_GetITStatus(DMA2_Stream7, DMA_IT_TCIF4))
    {
    /* Clear DMA Stream Transfer Complete interrupt pending bit */
    DMA_ClearITPendingBit(DMA2_Stream7, DMA_IT_TCIF4);

    //    USART_SendData(UART1, 'C');
    }

  /* Test on DMA Stream Half Transfer interrupt */
  if (DMA_GetITStatus(DMA2_Stream7, DMA_IT_HTIF4))
    {
    /* Clear DMA Stream Half Transfer interrupt pending bit */
    DMA_ClearITPendingBit(DMA2_Stream7, DMA_IT_HTIF4);

    // USART_SendData(UART4, 'H');
    }
  }


Die Routine wird aufgerufen aber beide if sind false, da auch eine Idee 
was falsch ist?

Herzlichen Dank!

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren