Hallo habe folgenden Code geschrieben zum Einlesen von ADC Werten von 2 Kanälen. Leider wird im DMA Array immer nur der erste Wert beschrieben. Ich habe schon zig Beispiele durch und finde den Fehler bei mir nicht. Fällt jemanden was auf ? Danke. uint32_t ADC_BUFF[ADC_Buff_NoOfBytes]; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); RCC_AHB1PeriphClockCmd(RCC_PERIPH_GPIOB, ENABLE); ADC_DeInit(); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Pin = Pin_0; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = Pin_1; GPIO_Init(GPIOB, &GPIO_InitStructure); ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ScanConvMode = ENABLE; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConvEdge_None; ADC_InitStructure.ADC_ExternalTrigConv = 0; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfConversion = 2; ADC_Init(ADC1, &ADC_InitStructure); // ADC Common configuration ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; ADC_CommonInit(&ADC_CommonInitStructure); ADC_RegularChannelConfig(ADC1,ADC_Chanel_8,1,ADC_SampleTime_3Cycles); ADC_RegularChannelConfig(ADC1,ADC_Chanel_9,2,ADC_SampleTime_15Cycles); ADC_Cmd(ADC1, ENABLE); // Enable ADC1 ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE); ADC_DMACmd(ADC1, ENABLE); ADC_SoftwareStartConv(ADC1); DMA_DeInit(DMA2_Stream4); DMA_InitStructure.DMA_Channel = DMA_Channel_0; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR; DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) &ADC_BUFF; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; DMA_InitStructure.DMA_BufferSize = (uint16_t) ADC_Buff_NoOfBytes; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA2_Stream4, &DMA_InitStructure); DMA_Cmd(DMA2_Stream4, ENABLE);
Moin,
> Leider wird im DMA Array immer nur der erste Wert beschrieben.
Was meinst du damit genau?
Hast du den ADC mal per Hand ausgelesen ob die Werte wirklich ankommen?
Die Werte sollen ja ins ADC_BUFF[2] geschrieben werden. Ich initialisiere das Array mit {10,10}. Der erste Wert ändert sich dann und der zweite bleibt 10. Also zumindest der Kanal 8 wird richtig ausgelesen.
Dann wird nur ein Wert übertragen, aso. Dein Define von ADC_Buff_NoOfBytes wird wohl 2 sein und nicht 4. Das sind die Anzahl der Bytes und nicht Worte. Also pro Kanal 16Bit sind 4 Bytes. Und da du alles in Half-Words schreibst sollte dein Deklaration: uint32_t ADC_BUFF[ADC_Buff_NoOfBytes]; uint16_t sein. Hier ist ein laufendes Beispiel, weiter unten: https://my.st.com/public/STe2ecommunities/mcu/Lists/STM32F4DISCOVERY/Flat.aspx?RootFolder=%2Fpublic%2FSTe2ecommunities%2Fmcu%2FLists%2FSTM32F4DISCOVERY%2F16%20bit%20result%20from%20ADC&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580002E3D0FFCC5A9AA4A9C29C3EECB7CCDBF¤tviews=1724
Nachtrag: Die 4 Byte brauchst du bei der Initialisierung der DMA: DMA_InitStructure.DMA_BufferSize = (uint16_t) (ADC_Buff_NoOfBytes*2);
Danke für den Hinweis. Habe jetzt das Halfword in Word geändert und nu läufts korrekt ;-) Der Name ADC_Buff_NoOfBytes war ein wenig verwirrend, eigentlich ist es nur die Anzahl der Elemente im enum ;-)
Hallo, mich interessiert, wie schnell die Werte ausgelesen werden können? Kann man evt. eine Zahl in Samples pro Sekunde ermitteln? Gruss MK_Munich
Ma Kra schrieb: > Hallo, mich interessiert, wie schnell die Werte ausgelesen werden > können? Kann man evt. eine Zahl in Samples pro Sekunde ermitteln? > Gruss > MK_Munich Muß man nicht ermitteln, ist aus dem Datenblatt ersichtlich.
Im STM32F405xx, STM32F407xx Datenblatt stehen in der Tat einige Werte (siehe Tabelle 65)... Sie gehen von 2 Msps bis 6 Msps bei fADC = 30 MHz und tS = 3 ADC cycles. Die 6 Msps werden nur bei 12-bit resolution Interleave Triple ADC mode erreicht. (Wie auch immer dies geht... Ich muss noch viel lesen.) Gruss MK_Munich
Sternius schrieb: > Danke für den Hinweis. Habe jetzt das Halfword in Word geändert und nu > läufts korrekt ;-) > Der Name ADC_Buff_NoOfBytes war ein wenig verwirrend, eigentlich ist es > nur die Anzahl der Elemente im enum ;-) Da Du den DMA2 verwendest, noch ein kleiner Hinweis: http://www.st.com/st-web-ui/static/active/en/resource/technical/document/errata_sheet/DM00037591.pdf DMA2 data corruption when managing AHB and APB peripherals in a concurrent way Description When the DMA2 is managing AHB Peripherals (only peripherals embedding FIFOs) and also APB transfers in a concurrent way, this generates a data corruption (multiple DMA access).STM32F40x and STM32F41x silicon limitations STM32F40x and STM32F41x 14/38 Doc ID 022183 Rev 4 When this condition occurs: • The data transferred by the DMA to the AHB peripherals could be corrupted in case of a FIFO target. • For memories, it will result in multiple access (not visible by the Software) and the data is not corrupted. • For the DCMI, a multiple unacknowledged request could be generated, which implies an unknown behavior of the DMA. AHB peripherals embedding FIFO are DCMI, CRYPTO, and HASH. On sales types without CRYPTO, only the DCMI is impacted. External FIFO controlled by the FSMC is also impacted. Workaround Avoid concurrent AHB (DCMI, CRYPTO, HASH, FSMC with external FIFO) and APB transfer management using the DMA2.
Hallo alle zusammen, ich habe den Quelltext von fast eins zu eins übernommen und weiterhin viele weite Beispiele aus dem Internet ausprobiert aber ich bekomme den DMA nicht zum laufen. Die ADC Umwandlung funktioniert selbst funktioniert bereits. Es wird aber kein einziger wert vom DMA übertragen. Hat hier vielleicht noch jemand einen Hinweis? Hier der Quelltext: void init_adc_test(void) { /*********************************************************************** ******************************* *Create structures and initalize them [OK] ************************************************************************ ******************************/ GPIO_InitTypeDef GPIO_InitStructure; ADC_InitTypeDef ADC_InitStructure; ADC_CommonInitTypeDef ADC_CommonInitStructure; DMA_InitTypeDef DMA_InitStructure; GPIO_StructInit(&GPIO_InitStructure); ADC_StructInit(&ADC_InitStructure); ADC_CommonStructInit(&ADC_CommonInitStructure); DMA_StructInit(&DMA_InitStructure); /*********************************************************************** ******************************* * 2.0 Set up the clocks are needed for the ADC [??] ************************************************************************ ******************************/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE); /*********************************************************************** ******************************* * 3.0 Initialization of the GPIO Pins [OK] ************************************************************************ ******************************/ /* Analog channel 12 configuration : PC.01 PC.02 PC.04 PC.05 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOC, &GPIO_InitStructure); /*********************************************************************** ******************************* * 4.0 Config the ADC1 [OK: Conversation is running (checked the memory of the data register)] ************************************************************************ ******************************/ ADC_DeInit(); ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//data converted will be shifted to right ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//Input voltage is converted into a 12bit number giving a maximum value of 4096 ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //the conversion is continuous, the input data is converted more than once ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConvEdge_None; ADC_InitStructure.ADC_NbrOfConversion = 4;//I think this one is clear :p ADC_InitStructure.ADC_ScanConvMode = ENABLE;//The scan is configured in one channel ADC_Init(ADC1,&ADC_InitStructure);//Initialize ADC with the previous configuration ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; ADC_CommonInit(&ADC_CommonInitStructure); ADC_RegularChannelConfig(ADC1,ADC_Channel_11,1,ADC_SampleTime_3Cycles); ADC_RegularChannelConfig(ADC1,ADC_Channel_12,2,ADC_SampleTime_3Cycles); ADC_RegularChannelConfig(ADC1,ADC_Channel_14,3,ADC_SampleTime_3Cycles); ADC_RegularChannelConfig(ADC1,ADC_Channel_15,4,ADC_SampleTime_3Cycles); ADC_Cmd(ADC1, ENABLE); // Enable ADC1 ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE); ADC_Cmd(ADC1, ENABLE); // Enable ADC1 ADC_SoftwareStartConv(ADC1); /*********************************************************************** ******************************* * 5.0 Configure the DMA [ERROR: no transport of the values] ************************************************************************ ******************************/ //==Configure DMA2 - Stream 4 DMA_DeInit(DMA2_Stream4); //Set DMA registers to default values DMA_InitStructure.DMA_Channel = DMA_Channel_0; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR; //Address of peripheral the DMA must map to DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) & ADCConvertedValue; //Variable to which ADC values will be stored DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; DMA_InitStructure.DMA_BufferSize = 4; //Buffer size (4 because we using two channels) DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA2_Stream4, &DMA_InitStructure); //Initialise the DMA DMA_Cmd(DMA2_Stream4, ENABLE); //Enable the DMA2 - Stream 0 }
Habe noch einen kleinen Fehler gefunden. Ich hatte vergessen den foglenden Befehl einzutragen. ADC_Cmd(ADC1, ENABLE); // Enable ADC1 ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE); ADC_DMACmd(ADC1, ENABLE); //Enable ADC1 DMA <--Fehlte ADC_SoftwareStartConv(ADC1); Jetzt läuft der DMA. Aber es wird nur ein Wert übertragen. Danach hält der ADC an und es wird kein weiterer Wert konvertiert. Idee?
Hat schonmal jemand Video mit dem Teil gesampled? Bekommt man es dann auf ein gängiges 320x240 TFT? Wird wohl schwierig?
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.