Forum: Mikrocontroller und Digitale Elektronik STM32F0: DMA Interrupt Problem


von stm32IT (Gast)


Lesenswert?

Hallo, ich habe ein kleines Problem mit meinem STM32F0. Er soll 
permanent mit dem ADC 4 Kanäle auslesen und dann per DMA in ein Array 
schreiben. Das lesen und ins Array schreiben funktioniert. Leider läuft 
der Controller aber nur bis zur Zeile in der das DMA gestartet wird. Die 
4 Werte werden ab da zwar weiter ins Array geschrieben, (habs mit STM 
Studio geprüft), jedoch werden die darauf folgenden Zeilen der 
main-Routine nicht ausgeführt. Woran könnte es liegen?


main.c
1
/* Includes ------------------------------------------------------------------*/
2
#include "stm32f0xx_hal.h"
3
4
/* USER CODE BEGIN Includes */
5
#include "stdbool.h"
6
#include "states.h"
7
/* USER CODE END Includes */
8
9
/* Private variables ---------------------------------------------------------*/
10
ADC_HandleTypeDef hadc;
11
DMA_HandleTypeDef hdma_adc;
12
TIM_HandleTypeDef htim1;
13
TIM_HandleTypeDef htim3;
14
15
/* USER CODE BEGIN PV */
16
17
// ADC Buffer which the DMA writes into  
18
volatile uint16_t ADCBuffer[]={0x0000, 0x0000, 0x0000, 0x0000, 0xAAAA}; 
19
20
/* USER CODE END PV */
21
22
/* Private function prototypes -----------------------------------------------*/
23
void SystemClock_Config(void);
24
static void MX_GPIO_Init(void);
25
static void MX_DMA_Init(void);
26
static void MX_ADC_Init(void);
27
static void MX_TIM1_Init(void);
28
static void MX_TIM3_Init(void);
29
30
/* USER CODE BEGIN PFP */
31
32
/* USER CODE END PFP */
33
34
/* USER CODE BEGIN 0 */
35
36
/* USER CODE END 0 */
37
38
int main(void)
39
{
40
41
  /* USER CODE BEGIN 1 */
42
43
  /* USER CODE END 1 */
44
45
  /* MCU Configuration----------------------------------------------------------*/
46
47
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
48
  HAL_Init();
49
50
  /* Configure the system clock */
51
  SystemClock_Config();
52
53
  /* Initialize all configured peripherals */
54
  MX_GPIO_Init();
55
  MX_DMA_Init();
56
  MX_ADC_Init();
57
  MX_TIM1_Init();
58
  MX_TIM3_Init();
59
60
  /* USER CODE BEGIN 2 */
61
  
62
  // switch on clock (pwm) for charge pump
63
  HAL_TIM_PWM_MspInit(&htim3); 
64
  HAL_TIM_PWM_Init(&htim3);
65
  HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3); 
66
  
67
  // switch on pwm for MOSFET
68
  HAL_TIM_PWM_MspInit(&htim1); 
69
  HAL_TIM_PWM_Init(&htim1);
70
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); 
71
  
72
        // switch on LED
73
  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET);  
74
  
75
  // switch on DMA 
76
  HAL_DMA_Init(&hdma_adc);                           
77
  HAL_ADC_Start_DMA(&hadc,(uint32_t*)ADCBuffer, 4);  
78
  
79
  
80
  // switch on ADC
81
  HAL_ADC_MspInit(&hadc);  // Init ADC and DMA
82
  HAL_ADC_Start(&hadc);
83
  
84
85
86
  /* USER CODE END 2 */
87
88
  /* Infinite loop */
89
  /* USER CODE BEGIN WHILE */
90
  while (1)
91
  {
92
  /* USER CODE END WHILE */
93
94
  /* USER CODE BEGIN 3 */
95
    
96
  
97
    if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_3)==GPIO_PIN_SET)){
98
      HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET);      // channel LED green on
99
      HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_RESET);    // channel LED red off
100
      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET);  // activates driver stage 
101
      HAL_Delay(1000);
102
    }
103
    
104
    
105
    
106
    if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_3)==GPIO_PIN_SET)){
107
      HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_RESET);      // channel LED green off
108
      HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_SET);    // channel LED red on
109
      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);  // deactivates driver stage 
110
      HAL_Delay(1000);
111
    }
112
    
113
    if( ADCBuffer[3] > 100){
114
      HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET);
115
    } else {
116
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET);
117
    }
118
    
119
    if(ADCBuffer[3] > 300){
120
      HAL_GPIO_WritePin(GPIOA,GPIO_PIN_12,GPIO_PIN_SET);
121
    } else {
122
      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET);
123
    }
124
    
125
    
126
  }
127
  /* USER CODE END 3 */
128
129
}
130
131
/** System Clock Configuration
132
*/
133
134
135
/* ADC init function */
136
void MX_ADC_Init(void)
137
{
138
139
  ADC_ChannelConfTypeDef sConfig;
140
141
    /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) 
142
    */
143
  hadc.Instance = ADC1;
144
  hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC;
145
  hadc.Init.Resolution = ADC_RESOLUTION12b;
146
  hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
147
  hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
148
  hadc.Init.EOCSelection = EOC_SEQ_CONV;
149
  hadc.Init.LowPowerAutoWait = DISABLE;
150
  hadc.Init.LowPowerAutoPowerOff = DISABLE;
151
  hadc.Init.ContinuousConvMode = ENABLE;
152
  hadc.Init.DiscontinuousConvMode = DISABLE;
153
  hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
154
  hadc.Init.DMAContinuousRequests = ENABLE;
155
  hadc.Init.Overrun = OVR_DATA_OVERWRITTEN;
156
  HAL_ADC_Init(&hadc);
157
158
    /**Configure for the selected ADC regular channel to be converted. 
159
    */
160
  sConfig.Channel = ADC_CHANNEL_0;
161
  sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
162
  sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5;
163
  HAL_ADC_ConfigChannel(&hadc, &sConfig);
164
165
    /**Configure for the selected ADC regular channel to be converted. 
166
    */
167
  sConfig.Channel = ADC_CHANNEL_1;
168
  HAL_ADC_ConfigChannel(&hadc, &sConfig);
169
170
    /**Configure for the selected ADC regular channel to be converted. 
171
    */
172
  sConfig.Channel = ADC_CHANNEL_2;
173
  HAL_ADC_ConfigChannel(&hadc, &sConfig);
174
175
    /**Configure for the selected ADC regular channel to be converted. 
176
    */
177
  sConfig.Channel = ADC_CHANNEL_3;
178
  HAL_ADC_ConfigChannel(&hadc, &sConfig);
179
180
}
181
182
/** 
183
  * Enable DMA controller clock
184
  */
185
void MX_DMA_Init(void) 
186
{
187
  /* DMA controller clock enable */
188
  __DMA1_CLK_ENABLE();
189
190
  /* DMA interrupt init */
191
  HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 2, 0);
192
  HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
193
194
}

interrupt.c
1
/* Includes ------------------------------------------------------------------*/
2
#include "stm32f0xx_hal.h"
3
#include "stm32f0xx.h"
4
#include "stm32f0xx_it.h"
5
6
/* USER CODE BEGIN 0 */
7
#include "stdbool.h"
8
9
10
11
/* USER CODE END 0 */
12
13
/* External variables --------------------------------------------------------*/
14
extern DMA_HandleTypeDef hdma_adc;
15
extern ADC_HandleTypeDef hadc;
16
17
/******************************************************************************/
18
/*            Cortex-M0 Processor Interruption and Exception Handlers         */ 
19
/******************************************************************************/
20
21
/**
22
* @brief This function handles System tick timer.
23
*/
24
void SysTick_Handler(void)
25
{
26
  /* USER CODE BEGIN SysTick_IRQn 0 */
27
28
   //SysTick goes off every 1ms
29
  
30
  
31
  
32
  /* USER CODE END SysTick_IRQn 0 */
33
  HAL_IncTick();
34
  HAL_SYSTICK_IRQHandler();
35
  /* USER CODE BEGIN SysTick_IRQn 1 */
36
37
  /* USER CODE END SysTick_IRQn 1 */
38
}
39
40
/******************************************************************************/
41
/* STM32F0xx Peripheral Interrupt Handlers                                    */
42
/* Add here the Interrupt Handlers for the used peripherals.                  */
43
/* For the available peripheral interrupt handler names,                      */
44
/* please refer to the startup file (startup_stm32f0xx.s).                    */
45
/******************************************************************************/
46
47
/**
48
* @brief This function handles DMA1 channel 1 interrupt.
49
*/
50
void DMA1_Channel1_IRQHandler(void)
51
{
52
  /* USER CODE BEGIN DMA1_Channel1_IRQn 0 */
53
  
54
  /* USER CODE END DMA1_Channel1_IRQn 0 */
55
  HAL_DMA_IRQHandler(&hdma_adc);
56
  /* USER CODE BEGIN DMA1_Channel1_IRQn 1 */
57
58
  /* USER CODE END DMA1_Channel1_IRQn 1 */
59
}
60
61
/**
62
* @brief This function handles ADC interrupt.
63
*/
64
void ADC1_IRQHandler(void)
65
{
66
  /* USER CODE BEGIN ADC1_IRQn 0 */
67
68
  /* USER CODE END ADC1_IRQn 0 */
69
  HAL_ADC_IRQHandler(&hadc);
70
  /* USER CODE BEGIN ADC1_IRQn 1 */
71
72
  /* USER CODE END ADC1_IRQn 1 */
73
}

von stm32IT (Gast)


Lesenswert?

Ups, die eigentlich IRQ-Handler vergessen, diese wurden allerdings nicht 
geändert. Die wurden von der STMCube so erstellt
1
void HAL_ADC_IRQHandler(ADC_HandleTypeDef* hadc)
2
{
3
  /* Check the parameters */
4
  assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
5
  assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode));
6
  assert_param(IS_ADC_EOC_SELECTION(hadc->Init.EOCSelection));
7
  
8
  /* ========== Check End of Conversion flag for regular group ========== */
9
  if( (__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOC) && __HAL_ADC_GET_IT_SOURCE(hadc, ADC_IT_EOC)) || 
10
      (__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOS) && __HAL_ADC_GET_IT_SOURCE(hadc, ADC_IT_EOS))   )
11
  {
12
    /* Update state machine on conversion status if not in error state */
13
    if(hadc->State != HAL_ADC_STATE_ERROR)
14
    {
15
      /* Change ADC state */
16
      hadc->State = HAL_ADC_STATE_EOC_REG;
17
    }
18
    
19
    /* Disable interruption if no further conversion upcoming by regular      */
20
    /* external trigger or by continuous mode,                                */
21
    /* and if scan sequence if completed.                                     */
22
    if(__HAL_ADC_IS_SOFTWARE_START_REGULAR(hadc) && 
23
       (hadc->Init.ContinuousConvMode == DISABLE)  )
24
    {
25
      /* If End of Sequence is reached, disable interrupts */
26
      if( __HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOS) )
27
      {
28
        /* Allowed to modify bits ADC_IT_EOC/ADC_IT_EOS only if bit           */
29
        /* ADSTART==0 (no conversion on going)                                */
30
        if (__HAL_ADC_IS_CONVERSION_ONGOING_REGULAR(hadc) == RESET)
31
        {
32
          /* Disable ADC end of sequence conversion interrupt */
33
          /* @Note: Overrun interrupt was enabled with EOC interrupt in        */
34
          /* HAL_Start_IT(), but is not disabled here because can be used     */
35
          /* by overrun IRQ process below.                                    */
36
          __HAL_ADC_DISABLE_IT(hadc, ADC_IT_EOC | ADC_IT_EOS);
37
        }
38
        else
39
        {
40
          /* Change ADC state to error state */
41
          hadc->State = HAL_ADC_STATE_ERROR;
42
          
43
          /* Set ADC error code to ADC IP internal error */
44
          hadc->ErrorCode |= HAL_ADC_ERROR_INTERNAL;
45
        }
46
      }
47
    }
48
    
49
    /* Conversion complete callback */
50
    /* @Note: into callback, to determine if conversion has been triggered     */
51
    /*       from EOC or EOS, possibility to use:                             */
52
    /*        " if( __HAL_ADC_GET_FLAG(&hadc, ADC_FLAG_EOS)) "                */
53
      HAL_ADC_ConvCpltCallback(hadc);
54
55
    
56
    /* Clear regular group conversion flag */
57
    /* @Note: in case of overrun set to OVR_DATA_PRESERVED, end of conversion  */
58
    /*       flags clear induces the release of the preserved data.           */
59
    /*       Therefore, if the preserved data value is needed, it must be     */
60
    /*       read preliminarily into HAL_ADC_ConvCpltCallback().              */
61
    __HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_EOC | ADC_FLAG_EOS) );
62
  }
63
   
64
  /* ========== Check Analog watchdog flags ========== */
65
  if(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_AWD) && __HAL_ADC_GET_IT_SOURCE(hadc, ADC_IT_AWD))
66
  {
67
    /* Change ADC state */
68
    hadc->State = HAL_ADC_STATE_AWD;
69
70
    /* Level out of window callback */ 
71
    HAL_ADC_LevelOutOfWindowCallback(hadc);
72
    
73
    /* Clear ADC Analog watchdog flag */
74
    __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_AWD);
75
   
76
  }
77
  
78
  
79
  /* ========== Check Overrun flag ========== */
80
  if(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_OVR) && __HAL_ADC_GET_IT_SOURCE(hadc, ADC_IT_OVR))
81
  {
82
    /* If overrun is set to overwrite previous data (default setting),        */
83
    /* overrun event is not considered as an error.                           */
84
    /* (cf ref manual "Managing conversions without using the DMA and without */
85
    /* overrun ")                                                             */
86
    /* Exception for usage with DMA overrun event always considered as an     */
87
    /* error.                                                                 */
88
    if ((hadc->Init.Overrun == OVR_DATA_PRESERVED)            ||
89
        HAL_IS_BIT_SET(hadc->Instance->CFGR1, ADC_CFGR1_DMAEN)  )
90
    {
91
      /* Change ADC state to error state */
92
      hadc->State = HAL_ADC_STATE_ERROR;
93
      
94
      /* Set ADC error code to overrun */
95
      hadc->ErrorCode |= HAL_ADC_ERROR_OVR;
96
      
97
      /* Error callback */ 
98
      HAL_ADC_ErrorCallback(hadc);
99
    }
100
    
101
    /* Clear the Overrun flag */
102
    __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_OVR);
103
  }
104
105
}

und
1
void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
2
{        
3
  /* Transfer Error Interrupt management ***************************************/
4
  if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma)) != RESET)
5
  {
6
    if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TE) != RESET)
7
    {
8
      /* Disable the transfer error interrupt */
9
      __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE);
10
    
11
      /* Clear the transfer error flag */
12
      __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma));
13
    
14
      /* Update error code */
15
      SET_BIT(hdma->ErrorCode, HAL_DMA_ERROR_TE);
16
17
      /* Change the DMA state */
18
      hdma->State = HAL_DMA_STATE_ERROR;    
19
    
20
      /* Process Unlocked */
21
      __HAL_UNLOCK(hdma); 
22
    
23
      if (hdma->XferErrorCallback != (void (*)(DMA_HandleTypeDef *))NULL)
24
      {
25
        /* Transfer error callback */
26
        hdma->XferErrorCallback(hdma);
27
      }
28
    }
29
  }
30
31
  /* Half Transfer Complete Interrupt management ******************************/
32
  if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma)) != RESET)
33
  {
34
    if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_HT) != RESET)
35
    { 
36
      /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
37
      if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0)
38
      {
39
        /* Disable the half transfer interrupt */
40
        __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
41
      }
42
      /* Clear the half transfer complete flag */
43
      __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma));
44
45
      /* Change DMA peripheral state */
46
      hdma->State = HAL_DMA_STATE_READY_HALF;
47
48
      if(hdma->XferHalfCpltCallback != (void (*)(DMA_HandleTypeDef *))NULL)
49
      {
50
        /* Half transfer callback */
51
        hdma->XferHalfCpltCallback(hdma);
52
      }
53
    }
54
  }
55
  
56
  /* Transfer Complete Interrupt management ***********************************/
57
  if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma)) != RESET)
58
  {
59
    if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TC) != RESET)
60
    {
61
      if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0)
62
      {
63
        /* Disable the transfer complete interrupt */
64
        __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TC);
65
      }
66
      /* Clear the transfer complete flag */
67
      __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma));
68
    
69
      /* Update error code */
70
      SET_BIT(hdma->ErrorCode, HAL_DMA_ERROR_NONE);
71
72
      /* Change the DMA state */
73
      hdma->State = HAL_DMA_STATE_READY;    
74
    
75
      /* Process Unlocked */
76
      __HAL_UNLOCK(hdma);
77
    
78
      if(hdma->XferCpltCallback != (void (*)(DMA_HandleTypeDef *))NULL)
79
      {       
80
        /* Transfer complete callback */
81
        hdma->XferCpltCallback(hdma);
82
      }
83
    }
84
  }
85
}

von Steff (Gast)


Lesenswert?

Auch wenn das hier schon etwas älter ist:

Das Problem liegt an der kurzen Sample Zeit

 sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5;

Erhöhe die Anzahl der Zyklen, denn der Controller befindet sich sonst 
ständig im IRQ.

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.