Hi Leute, ich versuche aktuell auf einem STM32F205VG mit ADC1 im continuous scan modus zwei pins und den Temperatursensor einzulesen. Die Daten sollen via DMA in ein struct kopiert werden. Folgenden Quelltext hab ich mir aus den Herstellerbeispielen zusammen gestellt und inzwischen auch einiges an Zeit mit Fehlersuche verbraten, da das struct sich einfach nicht füllen will. Wenn jemand von euch den Fehler sieht wärs super. Da das einlesen von mehreren Pins erfolglos war habe ich die (mMn) zuständigen Stellen auskommentiert um mit den eingefügten Pendants es erstmal mit einem Pin zum Laufen zu kriegen, wieder erfolglos... #define HMI_GIER_PORT GPIOA #define HMI_GIER_PIN GPIO_Pin_5 #define HMI_GIER_CLK RCC_AHB1Periph_GPIOA #define HMI_GIER_ADC_CHANNEL ADC_Channel_5 #define HMI_THROTTLE_PORT GPIOC #define HMI_THROTTLE_PIN GPIO_Pin_1 #define HMI_THROTTLE_CLK RCC_AHB1Periph_GPIOC #define HMI_THROTTLE_ADC_CHANNEL ADC_Channel_11 #define HMI_ADC ADC1 #define HMI_ADC_CLK RCC_APB2Periph_ADC1 #define HMI_DMA DMA2 #define HMI_DMA_CHANNEL DMA_Channel_0 #define HMI_DMA_STREAM DMA2_Stream0 #define HMI_DMA_CLK RCC_AHB1Periph_DMA2 #define HMI_ADC_DR_Address ((uint32_t)HMI_ADC+0x10) ... typedef struct { uint8_t start; uint16_t gier; uint16_t throttle; uint16_t cpu_temp; uint8_t stop; } SENSORS_t; __IO SENSORS_t SENSOR_States; ... /*!< Enable ADC1, DMA2 and GPIO clocks */ RCC_AHB1PeriphClockCmd(HMI_DMA_CLK | HMI_GIER_CLK | HMI_THROTTLE_CLK, ENABLE); RCC_APB2PeriphClockCmd(HMI_ADC_CLK, ENABLE); /*!< DMA2 Stream0 configuration */ DMA_DeInit(HMI_DMA_STREAM); DMA_InitStructure.DMA_Channel = HMI_DMA_CHANNEL; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)HMI_ADC_DR_Address; DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&(SENSOR_States.gier); DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; //DMA_InitStructure.DMA_BufferSize = 3; DMA_InitStructure.DMA_BufferSize = 1; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; 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(HMI_DMA_STREAM, &DMA_InitStructure); DMA_Cmd(HMI_DMA_STREAM, ENABLE); /*!< Configure pins as analog input */ GPIO_InitStructure.GPIO_Pin = HMI_GIER_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(HMI_GIER_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = HMI_THROTTLE_PIN; GPIO_Init(HMI_THROTTLE_PORT, &GPIO_InitStructure); /*!< TempSensor and VrefInt Init */ ADC_TempSensorVrefintCmd(ENABLE); /*!< ADC Common Init */ ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles; ADC_CommonInit(&ADC_CommonInitStructure); /*!< ADC1 Init */ ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; //ADC_InitStructure.ADC_ScanConvMode = ENABLE; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC_InitStructure.ADC_NbrOfConversion = 3; ADC_InitStructure.ADC_NbrOfConversion = 1; ADC_Init(ADC1, &ADC_InitStructure); /*!< ADC1 regular channel configuration */ ADC_RegularChannelConfig(ADC1, HMI_GIER_ADC_CHANNEL, 1, ADC_SampleTime_3Cycles); //ADC_RegularChannelConfig(ADC1, HMI_THROTTLE_ADC_CHANNEL, 2, ADC_SampleTime_3Cycles); //ADC_RegularChannelConfig(ADC1, ADC_Channel_TempSensor, 3, ADC_SampleTime_3Cycles); /*!< Enable DMA request after last transfer (Single-ADC mode) */ ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE); /*!< Enable ADC1 DMA */ ADC_DMACmd(ADC1, ENABLE); /*!< Enable ADC1 */ ADC_Cmd(ADC1, ENABLE); /*!< Start ADC1 Software Conversion */ ADC_SoftwareStartConv(ADC1); Danke für eure Hilfe im Voraus, Alex
Ohne DMA würde es wahrscheinlich gehen, da auf dem Controller allerdings ein ziemlich großer Kalman-Filter laufen muss und noch einiges anderes muss ich DMA verwenden wo nur irgend möglich. Sieht jemand den Fehler? Danke im Voraus, Alex
>Sieht jemand den Fehler?
#define HMI_ADC_DR_Address ((uint32_t)HMI_ADC+0x10)
Noch mal im Datenblatt nachsehen!
Super, danke für den Hinweis. Da war schonmal ein Fehler drin. 0x4C sollte stimmen, funktioniert aber immer noch nicht. Sieht noch jemand etwas?
>funktioniert aber immer noch nicht.
Was funktioniert nicht?
Ich wäre da ganz vorsichtig per DMA Daten in eine
so ungünstig aufgebaute Struktur zu übertragen.
Stichworte Alignment und Padding.
Und lass dir mal sizeof(SENSORS_t); ausgeben.
Das wird nicht 8 sein;)
So, Start- und Stopmarkierung auf uint16_t aufgeblasen und jetzt funktioniert's (auch im scanmode). Das Seltsame: sollte die DMA nicht trotz misalignment Daten kopieren, nur um 1 Byte verschoben?
>So, Start- und Stopmarkierung auf uint16_t aufgeblasen und jetzt >funktioniert's (auch im scanmode). >Das Seltsame: sollte die DMA nicht trotz misalignment Daten kopieren, >nur um 1 Byte verschoben? Dann hast du wohl ein pack-struct in den Compileroptionen? In dem Fall wolltest du Halfwords auf ungerade Adressen schreiben. Und das geht laut Datenblatt nicht mit dem DMA.
Nicht das ich wüsste. Für's makefile benutze ich das Eclipse GNU ARM plugin und darin sind alle pack-structures deaktiviert. Hast du sonst noch eine Idee? Danke im Übrigen für den Tipp, jetzt funktionierts wenigstens ;)
>Nicht das ich wüsste. Für's makefile benutze ich das Eclipse GNU ARM >plugin und darin sind alle pack-structures deaktiviert. Hmm. Dann hätte das gehen müssen. Oder du warst nicht darauf vorbereitet das: typedef struct { uint8_t start; hier ein Padding Byte eingefügt wird. uint16_t gier; uint16_t throttle; >Hast du sonst noch eine Idee? Das alte Programm das nicht funktioniert noch mal hernehmen und dann mal im Map File nachsehen was da los ist. An welcher Adresse liegt die Struktur und wie groß ist sie.
Es sind zwei paddingbytes vorhanden, die Addresse sieht gut aus. Wie gesagt, das die Daten misaligned sind war zu erwarten, aber das die DMA erst gar keine Daten schreibt kann ich nicht nachvollziehen. Bzw.: da ich nie mit SENSOR_States+x sondern mit SENSOR_states.stelle arbeite, sollte der Compiler nicht automatisch das paddingbyte bei der Addressberechnung berücksichtigen?
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.