Forum: Mikrocontroller und Digitale Elektronik STM32F407 USART1 mit DMA IRQ bei weniger Bytes


von Mach F. (machfax)


Lesenswert?

Hallo zusammen

Ich arbeite auf einem STM32F407
Ich benutze den DMA um bei der USART1 die Daten einzulesen. Die Länge 
ist auf 16Bytes eingestellt.

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

  //USART1 TX IRQ Configuration over the DMA Controller
  DMA_DeInit(DMA2_Stream7);
  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)&RS485_TX_Buffer;
  DMA_InitStruct.DMA_DIR = DMA_DIR_MemoryToPeripheral;
  DMA_InitStruct.DMA_BufferSize = RS485_data_size;
  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);

  //USART1 RX IRQ Configuration over the DMA Controller
  DMA_DeInit(DMA2_Stream5);
  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)&RS485_RX_Buffer;
  DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralToMemory;
  DMA_InitStruct.DMA_BufferSize = RS485_data_size;
  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_Stream5, &DMA_InitStruct);

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

  /* Enable DMA Stream Transfer Complete interrupt */
  DMA_ClearITPendingBit(DMA2_Stream7, DMA_IT_TCIF7);
  DMA_ITConfig(DMA2_Stream7, DMA_IT_TC, ENABLE);

  /* Enable DMA Stream Receive Complete interrupt */
  DMA_ClearITPendingBit(DMA2_Stream7, DMA_IT_TCIF5);
  DMA_ITConfig(DMA2_Stream5, DMA_IT_TC, ENABLE);

  DMA_ClearITPendingBit(DMA2_Stream7, DMA_IT_FEIF5);
  DMA_ITConfig(DMA2_Stream5, DMA_IT_FE, ENABLE);

  DMA_Cmd(DMA2_Stream5, ENABLE);  //RX enable  -> receive
}

/* Defines */
#define RS485_Port  GPIOA
#define  RS485_RX  GPIO_Pin_10
#define  RS485_TX  GPIO_Pin_9
#define  RS485_RTS  GPIO_Pin_12
#define  RS485_CTS  GPIO_Pin_11

#define RS485_data_size  16

Wenn jetzt warum auch immer nicht 16Bytes ankommen, sondern 1 Byte 
(Störung z.Bsp) und danach korrekt die 16 Bytzes dann löst der Interrupt 
aus und die Daten sind im Buffer, nur dass das 1. Byte dann den Wert der 
Störung hat und bei den 16Bytes die korrekt reinkommen somit 1 Byte 
fehlt. Wie kann man dies umgehen? Ich müsste ja einen Interrupt bei 
jedem Byte haben und wenn innerhalb von einer Zeit die restlichen Bytes 
nicht kommen den Buffer wieder löschen. Wenn ich den DMA auf 1 Byte 
einstelle ist die schöne DMA Funktion aber dahin und ich muss von Hand 
die Bytes zusammensetzen.

Jemand ne Idee?

Vielen Dank

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.