Hallo Hallo, ich benutze einen STM32F4 und einen externen ADC der mir über I2S 24 bit Werte liefert, die dann in ein 32bit register geschrieben werden. Diese Daten will ich dann über TCP an meinen PC senden. netTCP_Send benötigt dafür einen 8bit Buffer in dem die zu sendenden Daten gespeichert sind. Um das ganze zu testen nehme ich erstmal den on board ADC. Dieser schreibt die gewandelten Daten in ein 16bit register. Jetzt will ich die Daten mittels DMA in einen Buffer (size=1000) schreiben und sie dann über TCP versenden. Die DMA verlangt das es sich um einen 32 bit buffer handeln soll. Ich hätte aber gerne einen 8 bit buffer. !---------------------------------------------------! Ich stell mir das so vor das die DMA das höherwertige byte des ersten samples in die erste Adresse des buffers schreibt und das niederwertigere byte in die zweite. Dann das höherwertige byte des zweiten samples in die dritte, niederwertigees in die vierte und so weiter. !---------------------------------------------------! Wenn der buffer halb voll ist sende ich über TCP und beschreibe die zweite Hälfte. Versende sie und fange zyklisch wieder am Anfang an. DMA und ADC funktionieren gut, nur leider werden die Daten halt in ein 32 bit register geschrieben und ich kann sie damit nicht per TCP versenden, da sonst die höherwertigen 8 bit verloren gehen. Falls die DMA das nicht kann habe ich mir auch schon was mit Schiebeoperatoren überlegt. Allerdings weis ich nicht wie ich ds schnell mit einem ganzen array machen sollte. Kann mir bitte jemand helfen die DMA so einzustllen, dass die Werte wir oben beschrieben in einen 8bit Memorybuffer geschrieben werden. Vielen vielen Dank schon mal.
Ich verstehe deine Problematik nicht... Ob du einen Buffer nun Byteweise beschreibst, oder immer 4 Byte auf einmal, ist doch völlig Banane. Ob du in deinem C-Programm nun uint8_t Buffer[4] oder uint32_t Buffer[1] definierst, ist nur in deinem Programm relevant. Der DMA sieht in beiden Fällen nur 4 Byte Speicher, die er beschreiben kann. Das einzige, was sich ändert, ist die Anzahl der Transfers. AnzahlTransfers = sizeof(Buffer) / BytesPerTransfer;
So sieht die DMA initialisierung im Moment aus. uint32_t ADCBuffer[2000]; hdma_adc1.Instance = DMA2_Stream0; hdma_adc1.Init.Channel = DMA_CHANNEL_0; hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE; hdma_adc1.Init.MemInc = DMA_MINC_ENABLE; hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; //hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; //hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_adc1.Init.Mode = DMA_CIRCULAR; hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH; hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE; hdma_adc1.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; hdma_adc1.Init.MemBurst = DMA_MBURST_SINGLE; hdma_adc1.Init.PeriphBurst = DMA_PBURST_SINGLE; HAL_DMA_Init(&hdma_adc1); __HAL_LINKDMA(&hadc1,DMA_Handle,hdma_adc1); HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn); HAL_ADC_Start_DMA(&hadc1,ADCBuffer, 2000); ADCBuffer muss 32bit haben (ist in HAL_ADC_Start_DMA vorgegen) Ich hätte aber gerne einen 8bit buffer der wie folgt aufgebaut ist ADCbuffer[0]=höherwertiges byte von sample 1 ADCbuffer[1]=niederwertiges byte von sample 1 ADCbuffer[2]=höherwertiges byte von sample 2 ADCbuffer[3]=niederwertiges byte von sample 2 ADCbuffer[4]=höherwertiges byte von sample 3 . . . . Leider steh ich gerade auf dem Schlauch und weis nicht wie ich das hinbekommen soll. Leider kann ich mit deinem Tip noch nicht soviel anfangen. Bitte, bitte konkreter. vielen Dank schon mal
ADC_HandleTypeDef hadc1; DMA_HandleTypeDef hdma_adc1; void ADC_Initisalize (void) { ADC_ChannelConfTypeDef sConfig; GPIO_InitTypeDef GPIO_InitStruct; /* Peripheral clock enable */ __ADC1_CLK_ENABLE(); /* GPIO Ports Clock Enable */ __GPIOA_CLK_ENABLE(); /* DMA controller clock enable */ __DMA2_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */ hadc1.Instance = ADC1; hadc1.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV8; hadc1.Init.Resolution = ADC_RESOLUTION12b; hadc1.Init.ScanConvMode = DISABLE; hadc1.Init.ContinuousConvMode = ENABLE; hadc1.Init.DiscontinuousConvMode = DISABLE; hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc1.Init.NbrOfConversion = 1; hadc1.Init.DMAContinuousRequests = ENABLE; hadc1.Init.EOCSelection = EOC_SINGLE_CONV; HAL_ADC_Init(&hadc1); /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. */ sConfig.Channel = ADC_CHANNEL_0; sConfig.Rank = 1; sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES; HAL_ADC_ConfigChannel(&hadc1, &sConfig); Dann kommt die DMA config. Der ADC tut was er tun soll. Dass passt. Die DMA auch, ausser dass sie alle 16bit samples in einen 32 bit buffer schreibt. Ich bräuchte einen acht bit buffer der die samples in low und high trennt und immmer wechseln speichert. Danke
Anderle K. schrieb: > hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; > hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; > hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE; Das funktioniert nicht! Für unterschiedliche Datengrößen brauchst du den FIFO! Ansonsten wird die Größe der Peripherie auch für Memory übernommen.
Also ich habe das mit der FIFO ausprobiert. Die initialisierung der DMA sieht jetzt so aus. hdma_adc1.Instance = DMA2_Stream0; hdma_adc1.Init.Channel = DMA_CHANNEL_0; hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE; hdma_adc1.Init.MemInc = DMA_MINC_ENABLE; hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; //hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; //hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_adc1.Init.Mode = DMA_CIRCULAR; hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH; hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_ENABLE; hdma_adc1.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL; hdma_adc1.Init.MemBurst = DMA_MBURST_SINGLE; hdma_adc1.Init.PeriphBurst = DMA_PBURST_SINGLE; HAL_DMA_Init(&hdma_adc1); __HAL_LINKDMA(&hadc1,DMA_Handle,hdma_adc1); HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn); HAL_ADC_Start_DMA(&hadc1,ADCBuffer, 2000); Im Anhang habe ich einen Screenshot von meinem Buffer gelegt. Ich denke dass jetzt pro 32bit Bufferzeile zwei 16 bit samples sind, die wiederrum in jeweils 2byte aufgeteilt sind. Ich hätte aber gerne einen buffer der in jeder Zeile genau ein byte hat, da TCP_send einen 8bit buffer benötigt. Wenn ich der Funktion meinen 32bit ADCbuffer gebe, werden die höherwertigen 24bit ja einfach abgeschnitten. So sieht der TCP Sendevorgang aus wenn die DMA sagt dass sie die Hälfte der Daten übertragen hat. osSignalWait(2U, osWaitForever); // Wait for signal LED_On (1); if (netTCP_SendReady (tcp_sock)) { LED_On (3); // The socket is ready to send the data maxlen = netTCP_GetMaxSegmentSize (tcp_sock); //hier NDTR auslesen und checken obs auch die Hälfte ist dann mit maxlen/1000 ersetzen sendbuf = netTCP_GetBuffer (1000); memcpy (sendbuf, &ADCBuffer[0], 1000); netTCP_Send (tcp_sock, sendbuf, sizeof(sendbuf)); LED_On (0); Vllt kann man den 32bit buffer ja auch so übergeben das er behandelt wird als wäre es ein 8bit buffer. Das sozusagen die Zeilen durchgescant werden. Leider weis ich nicht wie sowas funktioniert. Ich bin mir sicher dass ich wieder irgendwas recht einfaches nicht checke. Ich würde mich sehr um Hilfe freuen.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.