Forum: Mikrocontroller und Digitale Elektronik STM32F407 USART1 über DMA


von Mach F. (machfax)


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.

von holger (Gast)


Lesenswert?

Das ist falsch

  DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;

von Mach F. (machfax)


Angehängte Dateien:

Lesenswert?

Vielen Dank!
Passt jetzt, ausser dass die Ausgabe zu lange ist (siehe Bild)

von holger (Gast)


Lesenswert?

>Passt jetzt, ausser dass die Ausgabe zu lange ist (siehe Bild)

  DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

Ein char ist kein Halfword.

von Mach F. (machfax)


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

von holger (Gast)


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.

von holger (Gast)


Lesenswert?

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

Man könnte darauf kommen das dies schon mit Ausgabe der Uhrzeit
und Datum gesendet wurde.

von Mach F. (machfax)


Lesenswert?

holger schrieb:
>>Trotzdem habe ich am Anfang 0x00 vor dem 0x48 (H), warum dies?
>
> 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

von holger (Gast)


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?

von Mach F. (machfax)


Lesenswert?

holger schrieb:
> Das widerspricht meiner Theorie nicht.
>
> Wo kommt diese Ausgabe von Datum und Uhrzeit her?

Vom Terminal Programm Docklight.

Ist jetzt aber gelöst, hatte zweimal die Anweisung:

DMA_Cmd(DMA2_Stream7, ENABLE);

drin, einmal im main, einmal im config...

Danke

von holger (Gast)


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);

von Mach F. (machfax)


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!

von Uwe B. (derexponent)


Lesenswert?

nicht nur stur kopieren/einfügen sondern auch mal nachlesen
1
DMA2_Stream7, DMA_IT_HTIF4

wenn Stream7 dann "DMA_IT_HTIF7"

das gilt für alle 4 stellen im Code

Gruss Uwe

von Mach F. (machfax)


Angehängte Dateien:

Lesenswert?

Uwe B. schrieb:
> nicht nur stur kopieren/einfügen sondern auch mal nachlesen
>
>
1
> DMA2_Stream7, DMA_IT_HTIF4
2
>
>
> wenn Stream7 dann "DMA_IT_HTIF7"
>
> das gilt für alle 4 stellen im Code
>
> Gruss Uwe

Ok Danke. Aber wie soll dann bei Stream7 zwischen USART1 und 6 
unterschieden werden?
(siehe Bild)

von Felix G. (felixg)


Lesenswert?

Das sagst du dem doch schon in dieser Zeile:
1
  DMA_InitStruct.DMA_Channel = DMA_Channel_4; //USART1 ausgewählt

von Mach F. (machfax)


Lesenswert?

ok danke

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.