Forum: Mikrocontroller und Digitale Elektronik Usart Rx mit DMA


von peter m. (bastler788)


Lesenswert?

Hallo,

früher habe ich bei meinem Mikrocontroller einen FIFO Baustein 
eingesetzt, der die Bytes empfangen hat. im Timer interrupt des 
Mikrocontroller habe ich dann immer geschaut ob in dem FIFO was drin 
steht und wenn ja ausgelesen.
Dadurch waren höhere Übertragungsraten möglich ohne das der Controller 
immer im UART Interrupt fest hängt.

Nun setzt ich einen STM32 ein, dieser besitz ja ein DMA Modul. Dieses 
wollte ich für des damalige FIFO einsetzen. aber mittlwerweile hab ich 
gelesen das DMA pollen schwachsinnig ist oder es nicht geht. Aber wie 
sollte ich es dann machen, wenn die empfangene Telegrammlänge sich immer 
ändern kann?

Am liebsten wäre es mir wenn ich das DMA so einsetzen könnte wie damals 
das FIFO. kennt sich jemand damit aus und kann mir helfen?

DANKE

von Blackbird (Gast)


Lesenswert?

Wenn die STM32 auch Cortex-M3 Kerne haben, könnte man von den EFM32 
Controllern (Energy Micro) die Beispiele im Prinzip übernehmen. Dort 
wird die Low Energy UART per DMA verwendet.

Blackbird

von peter m. (bastler788)


Lesenswert?

meine Konfiguration sieht wie folgt aus von dem DMA

void DMA_Configuration(void)
{
  DMA_InitTypeDef  DMA_InitStructure;

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

  DMA_DeInit(DMA1_Channel1);
  DMA_InitStructure.DMA_BufferSize = (uint16_t)3;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)RxBuffer1;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART3->DR;
  DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte; 
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;

  DMA_Init(DMA1_Channel1, &DMA_InitStructure);

    /* Enable the USART Rx DMA request */
  USART_DMACmd(USART3, USART_DMAReq_Rx, ENABLE);

   /* Enable DMA Stream Half Transfer and Transfer Complete interrupt */
  DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
  DMA_ITConfig(DMA1_Channel1, DMA_IT_HT, ENABLE);

   DMA_Cmd(DMA1_Channel1, ENABLE);


  /* Enable the UART4 RX DMA Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

Da die Schnittstelle über Interrupt funktioniert, geh ich davon aus das 
die Konfiguration stimmt, allerdings hab ich jetzt den Interrupt 
ausgeschalten, damit es über DMA funktioniert

von peter m. (bastler788)


Lesenswert?

kann mir niemand helfen?

von Tobias K. (kurzschluss81)


Lesenswert?

Beim MSP habe ich immer so gemacht das ich dem DMA die Gesamtmenge der 
Bytes gegeben habe welche in meinen Puffer reinpassen.
Dann habe ich 10msec Takt geschaut aob sich Menge "der noch nicht 
Empfangenen*" Bytes geändert hat. Wenn diese runtergegangen ist und an 
einem Punkt für eine Bestimmte Zeit stehen geblieben ist habe ich den 
EMpfang als beendet angesehen und das Telegram ausgewertet.
Das hat hervorragend funktioniert. Du brauchst aber irgendeine 
Bytemenge.





* Beim MSP steht im Entsprechenden Register nur die menge der Bytes 
welche noch nicht verarbeitet wurden.

von peter m. (bastler788)


Lesenswert?

danke, interesanter hinweis.

aber bin noch dabei meinen DMA generell zum laufen zu bekommen, aber es 
klappt einfach nicht.

hab mir schon einige beispiele angeschaut aber irgendwie geht es 
trotzdem nicht

von Tobias K. (kurzschluss81)


Lesenswert?

Ja der DMA ist allg. nicht ganz einfach da man ihm nicht beim Arbeiten 
zuschauen kann um zu sehen wo was schiefläuft. Hab auch ne ganze  Weile 
gebraucht bis ich Ihn beim MSP430 zum laufen gebracht hatte.

von peter m. (bastler788)


Lesenswert?

Problem gelöst!!!!

Das hauptproblem lag darin das ich den falschen Kanal gewählt hatte, 
dachte des wäre egal welcher. aber ein Blick ins Ref. Manual hilft

von peter m. (bastler788)


Lesenswert?

allerdings hab ich das problem, dass das erste Byte als 0x00 eingelesen 
wird

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.