Forum: Mikrocontroller und Digitale Elektronik STM32F4 ADC in dual reg sim mode mit DMA


von Aljo E. (alrue)


Lesenswert?

Hallo,
ich benutzte das Nucleo-F446RE Board und möchte gleichzeitig ADC1 Ch0 
und ADC2 Ch1 und dann in den DMA schreiben und auslesen. Die gelesenen 
Daten sende ich dann über UART an meinen PC und empfange sie am COM Port 
über gtkterm.
Das Problem ist, dass ich jetzt in der main() eigentlich erst meinen 
ADC-Wert sende und dann ein 0x0A (Zeilenumbruch). Allerdings empfange 
ich nur das 0x0A, der ADC-Wert ist immer 00. Außerdem hört die 
Übertragung Ich glaube den ADC dual mode habe ich richtig initialisiert. 
Das Problem ist, dass ich mir nicht sicher bin, wann ich wo wie meinen 
m_ADCValue auslesen. Der ADC ist eigentlich über den TIM3 getriggert. 
Ich habe noch nicht verstanden ob ich den HAL_ADC_ConvCpltCallback 
brauche und ob ich den DMA2_Stream0_IRQHandler() implementieren muss. 
Funktioniert das auslesen über HAL_ADCEx_MultiModeGetValue?
1
void ADC_init(void){
2
3
    // 1. Init Timer for Interrupt trigger ************************************************
4
5
    TIM_ClockConfigTypeDef sClockSourceConfig;
6
    TIM_MasterConfigTypeDef sMasterConfig;
7
8
    // TIM3 clock enable
9
    __TIM3_CLK_ENABLE();
10
11
    //Init TIM3 Base
12
    m_hTIM3.Instance                 = TIM3;                        // Timer TIM3: Only Up, No DMA, MaxClock 84 MHz
13
    m_hTIM3.Init.ClockDivision             = TIM_CLOCKDIVISION_DIV1;
14
    m_hTIM3.Init.Prescaler               = 18000;                      // Teilt den Systemtakt: 180 MHz / 18000 = 10 kHz => 100 �s resolution [Inputtype short (0-65535)]
15
    m_hTIM3.Init.CounterMode             = TIM_COUNTERMODE_UP;
16
    m_hTIM3.Init.Period               = MYADCSAMPLETIME;                  // Timer runs till 65536 and automatically reset itself to zero. Inputtype short. Time = 500 * 100�s = 50 ms
17
    m_hTIM3.Init.RepetitionCounter           = 0;
18
19
    if(HAL_TIM_Base_Init(&m_hTIM3) != HAL_OK){
20
      ErrorLED();
21
    }
22
23
    //Config Timer3 TRGO
24
    sClockSourceConfig.ClockSource           = TIM_CLOCKSOURCE_INTERNAL;
25
    if(HAL_TIM_ConfigClockSource(&m_hTIM3, &sClockSourceConfig) != HAL_OK){
26
      ErrorLED();
27
    }
28
29
    sMasterConfig.MasterOutputTrigger         = TIM_TRGO_UPDATE;
30
    sMasterConfig.MasterSlaveMode           = TIM_MASTERSLAVEMODE_DISABLE;
31
    if(HAL_TIMEx_MasterConfigSynchronization(&m_hTIM3, &sMasterConfig) != HAL_OK){
32
      ErrorLED();
33
    }
34
35
    //Start timer
36
    if(HAL_TIM_Base_Start(&m_hTIM3) != HAL_OK){
37
      ErrorLED();
38
    }
39
40
    // 2. Enable ADC1, ADC2, DMA2 Clock ************************************************
41
42
    // Enable ADC Clk before DMA2 Clk
43
    __ADC1_CLK_ENABLE();
44
    __ADC2_CLK_ENABLE();
45
    __DMA2_CLK_ENABLE();
46
47
    // 3. Init DMA ************************************************
48
49
    m_hDMA2s0c0.Instance               = DMA2_Stream0;
50
    m_hDMA2s0c0.Init.Channel             = DMA_CHANNEL_0;
51
    m_hDMA2s0c0.Init.Direction             = DMA_PERIPH_TO_MEMORY;
52
    m_hDMA2s0c0.Init.PeriphInc             = DMA_PINC_DISABLE;                  //Always the same source
53
    m_hDMA2s0c0.Init.MemInc             = DMA_MINC_ENABLE;                  //Inc. Memory address
54
    m_hDMA2s0c0.Init.PeriphDataAlignment       = DMA_PDATAALIGN_WORD;                //Half DataWord = 16 Bit...
55
    m_hDMA2s0c0.Init.MemDataAlignment         = DMA_MDATAALIGN_WORD;
56
    m_hDMA2s0c0.Init.Mode               = DMA_CIRCULAR;                    //Normal Mode: if the register reaches zero, the stream is disabled
57
    m_hDMA2s0c0.Init.Priority             = DMA_PRIORITY_HIGH;
58
    m_hDMA2s0c0.Init.FIFOMode             = DMA_FIFOMODE_DISABLE;
59
    m_hDMA2s0c0.Init.FIFOThreshold           = DMA_FIFO_THRESHOLD_HALFFULL;
60
    m_hDMA2s0c0.Init.MemBurst             = DMA_MBURST_SINGLE;
61
    m_hDMA2s0c0.Init.PeriphBurst           = DMA_PBURST_SINGLE;
62
63
    if(HAL_DMA_Init(&m_hDMA2s0c0) != HAL_OK){
64
      ErrorLED();
65
    }
66
67
    // DMA mit ADC verlinken
68
    //__HAL_LINKDMA(Peripheral Handle , Memory Handle of ADC1, Pointer to DMA Controller Handle) -> Figure 1 in AN4031
69
    __HAL_LINKDMA(&m_hADC1, DMA_Handle, m_hDMA2s0c0);
70
71
    HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
72
    HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
73
74
75
    // 4. Init ADC1 ************************************************
76
77
    m_hADC1.Instance                = ADC1;
78
    m_hADC1.Init.ClockPrescaler            = ADC_CLOCKPRESCALER_PCLK_DIV2;            // APB2/4 = 90 MHz / 4 = 22,5 MHz // Max 36 MHz STM32F446
79
    m_hADC1.Init.Resolution              = ADC_RESOLUTION_8B;
80
    m_hADC1.Init.DataAlign              = ADC_DATAALIGN_RIGHT;
81
    m_hADC1.Init.ScanConvMode            = DISABLE;                      // In scan mode,automatic conversion is performed on a selected group of analog inputs.
82
    m_hADC1.Init.EOCSelection            = DISABLE;                      // EndOfConversation Flag. ADC signals the interrupt to the interrupt controller. The corresponding bit in the NVIC->ISPR register is set.
83
    m_hADC1.Init.ContinuousConvMode          = ENABLE;
84
    m_hADC1.Init.DiscontinuousConvMode        = DISABLE;
85
    m_hADC1.Init.DMAContinuousRequests         = ENABLE;                      // Specifies whether the DMA requests is performed in Continuous or in Single mode
86
    m_hADC1.Init.NbrOfConversion          = 1;                        // Number of used ADC Channels to use
87
    m_hADC1.Init.NbrOfDiscConversion        = 0;            // Messung durch den TriggerOut des Timer 3 gestartet
88
    m_hADC1.Init.ExternalTrigConvEdge        = ADC_EXTERNALTRIGCONVEDGE_RISING; //ADC_EXTERNALTRIGCONVEDGE_NONE;
89
    m_hADC1.Init.ExternalTrigConv          = ADC_EXTERNALTRIGCONV_T3_TRGO; //ADC_EXTERNALTRIGCONV_T1_CC1;
90
    if(HAL_ADC_Init(&m_hADC1) != HAL_OK){
91
      ErrorLED();
92
    }
93
94
    // 5. Init ADC2 ************************************************
95
96
    m_hADC2.Instance                = ADC2;
97
    m_hADC2.Init.ClockPrescaler            = ADC_CLOCKPRESCALER_PCLK_DIV2;            // APB2/4 = 90 MHz / 4 = 22,5 MHz // Max 36 MHz STM32F446
98
    m_hADC2.Init.Resolution              = ADC_RESOLUTION_8B;
99
    m_hADC2.Init.DataAlign              = ADC_DATAALIGN_RIGHT;
100
    m_hADC2.Init.ScanConvMode            = DISABLE;                      // In scan mode,automatic conversion is performed on a selected group of analog inputs.
101
    m_hADC2.Init.EOCSelection            = DISABLE;                      // EndOfConversation Flag. ADC signals the interrupt to the interrupt controller. The corresponding bit in the NVIC->ISPR register is set.
102
    m_hADC2.Init.ContinuousConvMode          = ENABLE;
103
    m_hADC2.Init.DiscontinuousConvMode        = DISABLE;
104
    m_hADC2.Init.DMAContinuousRequests        = ENABLE;                      // Specifies whether the DMA requests is performed in Continuous or in Single mode
105
    m_hADC2.Init.NbrOfConversion          = 1;                                      // Number of used ADC Channels to use
106
    m_hADC2.Init.NbrOfDiscConversion        = 0;
107
    m_hADC2.Init.ExternalTrigConv          = ADC_EXTERNALTRIGCONV_T3_TRGO;            // Messung durch den TriggerOut des Timer 3 gestartet
108
    m_hADC2.Init.ExternalTrigConvEdge        = ADC_EXTERNALTRIGCONVEDGE_RISING;
109
110
    if(HAL_ADC_Init(&m_hADC2) != HAL_OK){
111
      ErrorLED();
112
    }
113
114
    HAL_NVIC_SetPriority(ADC_IRQn, 0, 0);
115
    HAL_NVIC_EnableIRQ(ADC_IRQn);
116
117
    // 6. Config ADC Channel ************************************************
118
119
    ADC_ChannelConfTypeDef  sConfig;
120
121
    sConfig.Channel       = ADC_CHANNEL_0;
122
    sConfig.Rank         = 1;              // Refered to NbrOfConversion: Channel of ADC
123
    sConfig.SamplingTime     = ADC_SAMPLETIME_56CYCLES;    // Wie lange der ADConverter einen Wert aufnimmt:1/21MHz*56=2,6�s. Bestimmt die Genauigkeit
124
    sConfig.Offset         = 0;
125
126
    HAL_ADC_ConfigChannel(&m_hADC1, &sConfig);
127
128
    sConfig.Channel       = ADC_CHANNEL_1;
129
    sConfig.Rank         = 1;              // Refered to NbrOfConversion: Channel of ADC
130
    sConfig.SamplingTime     = ADC_SAMPLETIME_56CYCLES;    // Wie lange der ADConverter einen Wert aufnimmt:1/21MHz*56=2,6�s. Bestimmt die Genauigkeit
131
    sConfig.Offset         = 0;
132
133
    HAL_ADC_ConfigChannel(&m_hADC2, &sConfig);
134
135
    // 7. ADC Mode ************************************************
136
137
    ADC_MultiModeTypeDef   multimode;
138
139
    multimode.Mode         = ADC_DUALMODE_REGSIMULT;
140
    multimode.DMAAccessMode   = ADC_DMAACCESSMODE_1;          // MODE 2 ????????????????????
141
    multimode.TwoSamplingDelay   = ADC_TWOSAMPLINGDELAY_6CYCLES;
142
143
    if(HAL_ADCEx_MultiModeConfigChannel(&m_hADC1, &multimode) != HAL_OK){
144
      ErrorLED();
145
    }
146
147
    if(HAL_ADCEx_MultiModeConfigChannel(&m_hADC2, &multimode) != HAL_OK){
148
      ErrorLED();
149
    }
150
151
}
1
int main(){
2
3
  HAL_Init();
4
  SystemCoreClockConfigure_180MHz_internal();
5
6
  GPIO_PowerLub_init();
7
  UART_Init(mBaudrate);
8
  //Init_SPIMaster();
9
  ADC_init();
10
11
  uint8_t msg[1] = {0x0A};
12
13
  HAL_ADC_Start(&m_hADC2);
14
  HAL_ADCEx_MultiModeStart_DMA(&m_hADC1, (uint32_t *)m_ADCBuffer, 2);
15
16
  while(1){
17
18
    HAL_UART_Transmit(&huart2, (uint32_t *)m_ADCValue, 2, 0xAAFF);
19
    HAL_UART_Transmit(&huart2, (uint32_t *)msg, 1, 0xAAFF);
20
  }
21
22
}

von Jim M. (turboj)


Lesenswert?

Im geposteten Code wird m_ADCValue gar nicht gesetzt. Das da dann immer 
0x00 drin steht wäre die logische Folge.

Der Handler fürs DMA fehlt. IMO braucht man den ADC Interrupt hier 
nicht.

von Aljo E. (alrue)


Lesenswert?

Was genau meinst du mit nicht gesetzt?

Den DMA-Handler hab ich jetzt drin:

void DMA2_Stream0_IRQHandler(){

  HAL_DMA_IRQHandler(&m_hADC1);
}
Mich stellt sich noch die Frage, wann ich wo die Daten aus dem DMA 
abhole.
Kann ich das im ADC_MultiModeDMAConvCplt machen?

von Vincent H. (vinci)


Lesenswert?

In den HAL Libraries ist das so vorgesehen, dass ein Funktionsaufruf am 
IRQ-Vektor des DMA (=DMA2_Stream0_IRQHandler) überprüft für welche 
Funktion der DMA zuständig war und je nach Verlinkung und Settings 
deiner "m_hADC1" und "m_hDMA2s0c0" Strukturen den passenden Callback 
ausführt.

Der Callback müsste in diesem Fall selbst geschrieben werden, da in den 
Libs nur Stubs drin sind... oder weaks... irgendwas was halt nix tut.


Mir persönlich ist das etwas zu umständlich, da ich im vorraus ja 
bereits weiß welchen Zweck der DMA erfüllt. Aus diesem Grund 
implementiere ich das was im Prinzip im "HAL_DMA_IRQHandler" steht 
direkt in der Interruptfunktion.

Sprich etwa so:
1
void DMA2_Stream0_IRQHandler()
2
{
3
  if (TCIF Flag)
4
  { 
5
    TCIF = 0;
6
    Buffer lesen...
7
  }
8
}

von Aljo E. (alrue)


Lesenswert?

Ok, also mit dem DMA2_Stram0_IRQHandler habe ich das jetzt soweit 
verstanden. Dort setze ich mir mein Flag DMA_TC_Detect wenn das TC_Flag 
gesetzt wurde. Wenn mein DMA_TC_Detect gesetzt ist, dass lese ich die 
Werte in der main aus. Allerdings steht bei mir immernoch nur 00 00 in 
meinen ADCBuffer drin. Kann es sein, dass der ADC garnicht anfängt zu 
samplen?

Was meinte Jim mit ADCval nicht gesetzt?

Habe den Code etwas umstrukturiert. Hier der neue:
1
#include "stm32f4xx.h"
2
#include "stm32f4xx_hal.h"
3
#include "stm32f4xx_hal_adc.h"
4
#include "stm32f4xx_it.h"
5
#include "stm32f4xx_hal_dma.h"
6
7
#include "UART_init.h"
8
#include "GPIO_init.h"
9
#include "timer.h"
10
11
ADC_HandleTypeDef hadc1;
12
ADC_HandleTypeDef hadc2;
13
DMA_HandleTypeDef hdma_adc1;
14
15
volatile __IO uint32_t m_ADCBuffer[2];
16
__IO uint32_t m_ADCval[2];
17
18
volatile uint8_t DMA_TC_Detect;
19
20
void ADC_DMA_Init(void);
21
void HAL_MspInit(void);
22
void DMA2_Stream0_IRQHandler(void);
23
24
int main(){
25
26
  HAL_Init();
27
28
  SystemCoreClockConfigure_180MHz_internal();
29
30
  HAL_MspInit();
31
  GPIO_PowerLub_init();
32
  UART_Init(mBaudrate);
33
  ADC_DMA_Init();
34
35
  uint16_t msg_start[1] = {0xAA};
36
  uint16_t msg_stop[1] = {0xBB};
37
  m_ADCval[0] = 0;
38
39
  HAL_ADC_Start(&hadc2);
40
  HAL_ADCEx_MultiModeStart_DMA(&hadc1, (uint32_t *)m_ADCBuffer, 2);
41
42
  while(1){
43
44
    if(DMA_TC_Detect == 1){
45
46
      HAL_UART_Transmit(&huart2, (uint32_t *)msg_start, 1, 0xAAFF);
47
48
      //copy Values
49
      for(int i=0; i<2; i++){
50
        m_ADCval[0] = (m_ADCBuffer[0] >> 8) & 0xFF;
51
        m_ADCval[1] = m_ADCBuffer[1];
52
      }
53
54
      DMA_TC_Detect = 0;
55
56
      HAL_ADC_Start(&hadc2);
57
      HAL_ADCEx_MultiModeStart_DMA(&hadc1, (uint32_t *)m_ADCBuffer, 2);
58
59
      HAL_UART_Transmit(&huart2, (uint32_t *)m_ADCval, 4, 0xAAFF);
60
      HAL_UART_Transmit(&huart2, (uint32_t *)msg_stop, 1, 0xAAFF);
61
    }
62
  }
63
64
65
}
66
67
void ADC_DMA_Init(void){
68
69
  __ADC1_CLK_ENABLE();
70
  __ADC2_CLK_ENABLE();
71
  __DMA2_CLK_ENABLE();
72
73
  hdma_adc1.Instance = DMA2_Stream0;
74
  hdma_adc1.Init.Channel = DMA_CHANNEL_0;
75
  hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
76
  hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
77
  hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
78
  hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
79
  hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
80
  hdma_adc1.Init.Mode = DMA_CIRCULAR;
81
  hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH;
82
  hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
83
  hdma_adc1.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
84
  hdma_adc1.Init.MemBurst = DMA_MBURST_SINGLE;
85
  hdma_adc1.Init.PeriphBurst = DMA_PBURST_SINGLE;
86
  HAL_DMA_Init(&hdma_adc1);
87
88
  __HAL_LINKDMA(&hadc1,DMA_Handle,hdma_adc1);
89
90
  /* DMA interrupt init */
91
  HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
92
  HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
93
94
  ADC_MultiModeTypeDef multimode;
95
  ADC_ChannelConfTypeDef sConfig;
96
97
  hadc1.Instance = ADC1;
98
  hadc1.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2;
99
  hadc1.Init.Resolution = ADC_RESOLUTION8b;
100
  hadc1.Init.ScanConvMode = DISABLE;
101
  hadc1.Init.ContinuousConvMode = DISABLE;
102
  hadc1.Init.DiscontinuousConvMode = DISABLE;
103
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
104
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
105
  hadc1.Init.NbrOfConversion = 1;
106
  hadc1.Init.DMAContinuousRequests = ENABLE;
107
  hadc1.Init.EOCSelection = EOC_SINGLE_CONV;
108
  HAL_ADC_Init(&hadc1);
109
110
  hadc2.Instance = ADC2;
111
  hadc2.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2;
112
  hadc2.Init.Resolution = ADC_RESOLUTION8b;
113
  hadc2.Init.ScanConvMode = DISABLE;
114
  hadc2.Init.ContinuousConvMode = DISABLE;
115
  hadc2.Init.DiscontinuousConvMode = DISABLE;
116
  hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
117
  hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;
118
  hadc2.Init.NbrOfConversion = 1;
119
  hadc2.Init.DMAContinuousRequests = ENABLE;
120
  hadc2.Init.EOCSelection = EOC_SINGLE_CONV;
121
  HAL_ADC_Init(&hadc2);
122
123
  sConfig.Channel = ADC_CHANNEL_0;
124
  sConfig.Rank = 1;
125
  sConfig.SamplingTime = ADC_SAMPLETIME_56CYCLES;
126
  HAL_ADC_ConfigChannel(&hadc1, &sConfig);
127
128
129
  sConfig.Channel = ADC_CHANNEL_1;
130
  sConfig.Rank = 1;
131
  sConfig.SamplingTime = ADC_SAMPLETIME_56CYCLES;
132
  HAL_ADC_ConfigChannel(&hadc2, &sConfig);
133
134
  multimode.Mode = ADC_DUALMODE_REGSIMULT;
135
  multimode.DMAAccessMode = ADC_DMAACCESSMODE_1;
136
  multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_6CYCLES;
137
  HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode);
138
139
}
140
141
void DMA2_Stream0_IRQHandler(void){
142
143
  if(__HAL_DMA_GET_FLAG(&hdma_adc1, __HAL_DMA_GET_TC_FLAG_INDEX(&hdma_adc1)) != RESET){
144
    __HAL_DMA_CLEAR_FLAG(&hdma_adc1, __HAL_DMA_GET_TC_FLAG_INDEX(&hdma_adc1));
145
146
    DMA_TC_Detect = 1;
147
148
    if(__HAL_DMA_GET_FLAG(&hdma_adc1, __HAL_DMA_GET_HT_FLAG_INDEX(&hdma_adc1)) != RESET){
149
      __HAL_DMA_CLEAR_FLAG(&hdma_adc1, __HAL_DMA_GET_HT_FLAG_INDEX(&hdma_adc1));
150
    }
151
    else{
152
      DMA_TC_Detect = 1;
153
    }
154
  }
155
156
  HAL_DMA_IRQHandler(hadc1.DMA_Handle);
157
}
158
159
void HAL_MspInit(void)
160
{
161
  HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
162
163
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
164
}

1
void GPIO_PowerLub_init(void){
2
3
    GPIO_InitTypeDef GPIO_InitStruct;
4
5
    __GPIOA_CLK_ENABLE();
6
    __GPIOB_CLK_ENABLE();
7
    __GPIOC_CLK_ENABLE();
8
    
9
    GPIO_InitStruct.Pin   = GPIO_PIN_0 | GPIO_PIN_1;
10
    GPIO_InitStruct.Mode   = GPIO_MODE_ANALOG;
11
    GPIO_InitStruct.Pull   = GPIO_NOPULL;
12
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
13
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
14
15
...
16
17
}

von Reginald L. (Firma: HEGRO GmbH) (reggie)


Lesenswert?

Ich möchte keine Grundsatzdiskussion lostreten, aber benötigst du 
unbedingt die HAL-Lib? Bin mal von SPL auf HAL umgestiegen und dann 
wieder zurückgewechselt, weil ich, bis auf ein paar schöne Makros, 
keinerlei Vorteile der HAL-Lib für mein (relativ großes) Projekt 
entdecken konnte. Die STM-Community arbeitet bisher auch größtenteils 
noch mit SPL, sodass man hier eher Hilfe bekommt. Für zeitkritische 
Anwendungen ist die HAL-Lib auch nicht zu gebrauchen.

von aSma>> (Gast)


Lesenswert?

Servus,
ich kenne die HAL lib nicht, aber ich vermute, dass du vieles falsch 
eingestellt hast:

 /* DMA2 Stream0 channel0 configuration 
**************************************/
  DMA_DeInit(DMA2_Stream0);
  DMA_InitStructure.DMA_Channel = DMA_Channel_0;
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_ADDRESS;
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC1ConvertedValue;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
  DMA_InitStructure.DMA_BufferSize = BUFFERLENGHT;
  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_Stream0, &DMA_InitStructure);
  DMA_Cmd(DMA2_Stream0, ENABLE);

Die hälfte fehlt bei dir.


Vorallem ist das gewollt:
 hadc1.Init.Resolution = ADC_RESOLUTION8b; ???

volatile __IO uint32_t m_ADCBuffer[2];

__IO ist das nicht volatile? Doppelt hält besser?

Initialisiere mal: __IO uint32_t m_ADCBuffer[2] = {0xAA, 0xAA};

Dann guckst du, ob es sich ändert. Generell nehm mal das Referenz Manual 
und gucke nach, ob alle Register gesetzt sind.

Dabei sollte man nicht vergessen, dass ADCfmax = 30Mhz ist...

von Aljo E. (alrue)


Lesenswert?

Also erstmal zu der Frage ob HAL oder nicht:
Ich bin blutiger ARM-Anfänger und habe von daher erstmal mit den 
HAL-Bibs angefangen. Mitlerweile habe ich aber auch bemerkt bzw. 
eingesehen, dass diese vieles garnicht mal einfacher machen. Ich habe 
halt relativ schnell einfache Sachen zum laufen bekommen, ohne groß in 
irgendwelchen References und Manuals nachzulesen. Ich denke, das ist 
Segen und Fluch zugleich. Denn sobald es wie jetzt beim dual mode etwas 
komplizierter wird, sind mir die HAL-Bibs gerade etwas zu 
undurchsichtig.

Zu aSma:
Über die DMA_InitStructure bin ich auch schon öfter gestolpert. Ich bin 
mir nicht sicher ob die Sachen die bei "fehlen" oder ob die schon 
irgendwo in den HALs implementiert sind.
Mit dem __IO und volatile hattest du wohl recht, ist doppelt gemoppelt. 
War mir so nicht bewusst.

Ich habe den Buffer jetzt mal mit __IO uint32_t m_ADCBuffer[2] = {0xCC, 
0xCC}; initialisiert. Allerdings spuckt der mit immernoch 00 aus. Das 
heißt wohl, dass die Wert wirklich auf 00 gesetzt werden. Und ich hab 
immernoch keine Ahnung warum.

von aSma>> (Gast)


Lesenswert?

>...
>Ich habe halt relativ schnell einfache Sachen zum laufen bekommen, ohne >groß in 
irgendwelchen References und Manuals nachzulesen. Ich denke, das >ist Segen und 
Fluch zugleich. Denn sobald es wie jetzt beim dual mode >etwas komplizierter wird, 
sind mir die HAL-Bibs gerade etwas zu
>undurchsichtig.

Glaub es mir. Wenn du nicht dich näher mit der Pherepherie 
auseinandersetzen willst, dann bleib bei Arduino. Da läuft alles. 
Langsam aber es läuft.

Viele Leute denken, das Software-Entwicklung leicht wäre. Dabei stößt 
man ganz schnell an die Grenzen, wenn man kein Oszi oder LA hat.

Deshalb mein Tipp: Referenz Manual, Debug modus und losgehts.

von Reginald L. (Firma: HEGRO GmbH) (reggie)


Lesenswert?

Alex R. schrieb:
> Ich bin blutiger ARM-Anfänger
Gerade da würde ich die SPL-Lib empfehlen! Und am besten gleich das 
ReferenceManual, ProgrammingManual und ErrataSheet in nen Ordner 
schieben und immer wieder reinschauen, wenn irgend etwas nicht läuft.

Alex R. schrieb:
> Ich habe
> halt relativ schnell einfache Sachen zum laufen bekommen, ohne groß in
> irgendwelchen References und Manuals nachzulesen.
Das kriegst mit der SPL genauso hin. Wenn du die Manuals allerdings 
nicht beachten möchtest, kannst den µC gleich in die Tonne werfen. Egal 
ob SPL oder HAL.

Alex R. schrieb:
> HAL-Bibs gerade etwas zu
> undurchsichtig.
Steig auf SPL um. Falls du zeitkritische Operationen machst, empfehle 
ich auch gleich die nötigen Register manuell zu setzen. Ich benutze 
bsplws. nur bei Initialisierungsroutinen beim "Hochfahren" des µCs die 
SPL. In den ISRs setze ich die Register direkt.

aSma>> schrieb:
> Langsam aber es läuft.
Weisst du ob es was in Richtung Arduino, also mit richtig Leistung, aber 
baremetal gibt?

von Vincent H. (vinci)


Lesenswert?

aSma>> schrieb:
> Die hälfte fehlt bei dir.

Nein tut sie nicht.

Reginald L. schrieb:
> Steig auf SPL um. Falls du zeitkritische Operationen machst, empfehle
> ich auch gleich die nötigen Register manuell zu setzen. Ich benutze
> bsplws. nur bei Initialisierungsroutinen beim "Hochfahren" des µCs die
> SPL. In den ISRs setze ich die Register direkt.

Genau! Und dann lern am besten noch COBOL. Das is die Zukunft, 
versprochen!


@Topic
1.) Debuggen debuggen debuggen. Ich hab das Gefühl du hast generell noch 
nicht so viel Erfahrung mit µC und ohne Debugger geht einfach _gar 
nichts_. Du kannst jetzt auf die schnelle ja nicht einmal überprüfen ob
a) Dein Interrupt auslöst?
b) Der ADC/DMA überhaupt richtig gestartet wird.
c) Die UART/ADC Routinen, die da im Nanosekunden-Bereich aufgerufen 
werden, sich eh nicht gegenseitig abdrehn... (Ich vermute mal ST hat da 
Busy-Abfragen drin, aber garantieren kann ich das jetzt auch nicht.)

2.)
1
      
2
HAL_ADC_Start(&hadc2);
3
HAL_ADCEx_MultiModeStart_DMA(&hadc1, (uint32_t *)m_ADCBuffer, 2);

Du brauchst ADC2 nicht extra starten, die MultiMode Routine übernimmt 
das für dich.

von Reginald L. (Firma: HEGRO GmbH) (reggie)


Lesenswert?

Vincent H. schrieb:
> Genau! Und dann lern am besten noch COBOL. Das is die Zukunft,
> versprochen!
Clown zum Frühstück gehabt oder generell Stock im...?

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.