source: ctrl/firmware/Main/CubeMX/Core/Src/adc.c

Last change on this file was 113, checked in by Zed, 8 weeks ago

Added CAN bus support.

File size: 13.0 KB
Line 
1/* USER CODE BEGIN Header */
2/**
3  ******************************************************************************
4  * @file    adc.c
5  * @brief   This file provides code for the configuration
6  *          of the ADC instances.
7  ******************************************************************************
8  * @attention
9  *
10  * Copyright (c) 2025 STMicroelectronics.
11  * All rights reserved.
12  *
13  * This software is licensed under terms that can be found in the LICENSE file
14  * in the root directory of this software component.
15  * If no LICENSE file comes with this software, it is provided AS-IS.
16  *
17  ******************************************************************************
18  */
19/* USER CODE END Header */
20/* Includes ------------------------------------------------------------------*/
21#include "adc.h"
22
23/* USER CODE BEGIN 0 */
24
25#include <string.h>
26
27volatile ADC2_data_t ADC2Data __attribute__((section(".AXI_RAM_4_DMA")));
28volatile ADC3_data_t ADC3Data __attribute__((section(".BKP_RAM_4_DMA")));
29
30/* USER CODE END 0 */
31
32ADC_HandleTypeDef hadc2;
33ADC_HandleTypeDef hadc3;
34DMA_HandleTypeDef hdma_adc2;
35DMA_HandleTypeDef hdma_adc3;
36
37/* ADC2 init function */
38void MX_ADC2_Init(void)
39{
40
41  /* USER CODE BEGIN ADC2_Init 0 */
42
43  // This ADC is used to sample current that flows on shunts during cell charge and during cell discharge via electronic load
44
45  /* USER CODE END ADC2_Init 0 */
46
47  ADC_ChannelConfTypeDef sConfig = {0};
48
49  /* USER CODE BEGIN ADC2_Init 1 */
50
51  /* USER CODE END ADC2_Init 1 */
52
53  /** Common config
54  */
55  hadc2.Instance = ADC2;
56  hadc2.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
57  hadc2.Init.Resolution = ADC_RESOLUTION_16B;
58  hadc2.Init.ScanConvMode = ADC_SCAN_ENABLE;
59  hadc2.Init.EOCSelection = ADC_EOC_SEQ_CONV;
60  hadc2.Init.LowPowerAutoWait = DISABLE;
61  hadc2.Init.ContinuousConvMode = ENABLE;
62  hadc2.Init.NbrOfConversion = 3;
63  hadc2.Init.DiscontinuousConvMode = DISABLE;
64  hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START;
65  hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
66  hadc2.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;
67  hadc2.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
68  hadc2.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
69  hadc2.Init.OversamplingMode = ENABLE;
70  hadc2.Init.Oversampling.Ratio = 256;
71  hadc2.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_8;
72  hadc2.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER;
73  hadc2.Init.Oversampling.OversamplingStopReset = ADC_REGOVERSAMPLING_CONTINUED_MODE;
74  if (HAL_ADC_Init(&hadc2) != HAL_OK)
75  {
76    Error_Handler();
77  }
78
79  /** Configure Regular Channel
80  */
81  sConfig.Channel = ADC_CHANNEL_3;
82  sConfig.Rank = ADC_REGULAR_RANK_1;
83  sConfig.SamplingTime = ADC_SAMPLETIME_32CYCLES_5;
84  sConfig.SingleDiff = ADC_DIFFERENTIAL_ENDED;
85  sConfig.OffsetNumber = ADC_OFFSET_NONE;
86  sConfig.Offset = 0;
87  sConfig.OffsetSignedSaturation = DISABLE;
88  if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
89  {
90    Error_Handler();
91  }
92
93  /** Configure Regular Channel
94  */
95  sConfig.Channel = ADC_CHANNEL_4;
96  sConfig.Rank = ADC_REGULAR_RANK_2;
97  if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
98  {
99    Error_Handler();
100  }
101
102  /** Configure Regular Channel
103  */
104  sConfig.Channel = ADC_CHANNEL_5;
105  sConfig.Rank = ADC_REGULAR_RANK_3;
106  if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
107  {
108    Error_Handler();
109  }
110  /* USER CODE BEGIN ADC2_Init 2 */
111
112  HAL_Delay(100U);
113  if (HAL_OK != HAL_ADCEx_Calibration_Start(&hadc2, ADC_CALIB_OFFSET_LINEARITY, ADC_DIFFERENTIAL_ENDED)) Error_Handler();
114  HAL_Delay(100U);
115
116  uint32_t offset[ADC2_CHANNELS_NUM] = { 0U };
117  const uint32_t max_samples = 8192U / ((hadc2.Init.OversamplingMode == ENABLE)? hadc2.Init.Oversampling.Ratio: 1);
118  // Starting DMA converstion
119  if (HAL_OK != HAL_ADC_Start_DMA(&hadc2, (uint32_t*)&ADC2Data, ADC2_CHANNELS_NUM)) Error_Handler();
120   // Disabling interrupts, because we don't need it during offset calculation
121  __HAL_DMA_DISABLE_IT(&hdma_adc2, DMA_IT_HT | DMA_IT_TC);
122  uint32_t TC_flag = __HAL_DMA_GET_TC_FLAG_INDEX(&hdma_adc2);
123  for (uint32_t i = 0U; i < max_samples; i++)
124  {       // Waiting for conversion to finish
125          while(!__HAL_DMA_GET_FLAG(&hdma_adc2, TC_flag));        // For correct flag see __HAL_DMA_GET_TC_FLAG_INDEX macro description
126          // Reading ADC2 values
127          for (unsigned j = 0; j < ADC2_CHANNELS_NUM; j++) offset[j] += ADC2Data.Raw[j];
128          __HAL_DMA_CLEAR_FLAG(&hdma_adc2, TC_flag);
129  }
130
131  printf("ADC2 ");
132  for (unsigned j = 0U; j < ADC2_CHANNELS_NUM; j++)
133          printf("offset[%u] = %u%s", j, offset[j] / max_samples, (j < ADC2_CHANNELS_NUM - 1)?", ":"\n");
134
135  if (HAL_OK == HAL_ADC_Stop_DMA(&hadc2))
136  {
137          LL_ADC_SetOffset(hadc2.Instance, LL_ADC_OFFSET_1, LL_ADC_CHANNEL_3, (offset[0]/max_samples) * ((hadc2.Init.OversamplingMode == ENABLE)? hadc2.Init.Oversampling.Ratio: 1));
138          LL_ADC_SetOffset(hadc2.Instance, LL_ADC_OFFSET_2, LL_ADC_CHANNEL_4, (offset[1]/max_samples) * ((hadc2.Init.OversamplingMode == ENABLE)? hadc2.Init.Oversampling.Ratio: 1));
139          LL_ADC_SetOffset(hadc2.Instance, LL_ADC_OFFSET_3, LL_ADC_CHANNEL_5, (32767U) * ((hadc2.Init.OversamplingMode == ENABLE)? hadc2.Init.Oversampling.Ratio: 1));
140  }
141
142  if (HAL_OK != HAL_ADC_Start_DMA(&hadc2, (uint32_t*)&ADC2Data, ADC2_CHANNELS_NUM)) Error_Handler();
143  __HAL_DMA_DISABLE_IT(&hdma_adc2, DMA_IT_HT /*| DMA_IT_TC*/); // Disabling interrupts, because we don't need it
144
145
146  /* USER CODE END ADC2_Init 2 */
147
148}
149/* ADC3 init function */
150void MX_ADC3_Init(void)
151{
152
153  /* USER CODE BEGIN ADC3_Init 0 */
154
155  // This ADC is used to sample raw voltage on the battery connector.
156  // It is not very precise dut to the voltagedrop on the wires.
157
158  /* USER CODE END ADC3_Init 0 */
159
160  ADC_ChannelConfTypeDef sConfig = {0};
161
162  /* USER CODE BEGIN ADC3_Init 1 */
163
164  /* USER CODE END ADC3_Init 1 */
165
166  /** Common config
167  */
168  hadc3.Instance = ADC3;
169  hadc3.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
170  hadc3.Init.Resolution = ADC_RESOLUTION_12B;
171  hadc3.Init.DataAlign = ADC3_DATAALIGN_RIGHT;
172  hadc3.Init.ScanConvMode = ADC_SCAN_ENABLE;
173  hadc3.Init.EOCSelection = ADC_EOC_SEQ_CONV;
174  hadc3.Init.LowPowerAutoWait = DISABLE;
175  hadc3.Init.ContinuousConvMode = ENABLE;
176  hadc3.Init.NbrOfConversion = 4;
177  hadc3.Init.DiscontinuousConvMode = DISABLE;
178  hadc3.Init.ExternalTrigConv = ADC_SOFTWARE_START;
179  hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
180  hadc3.Init.DMAContinuousRequests = ENABLE;
181  hadc3.Init.SamplingMode = ADC_SAMPLING_MODE_NORMAL;
182  hadc3.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;
183  hadc3.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
184  hadc3.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
185  hadc3.Init.OversamplingMode = ENABLE;
186  hadc3.Init.Oversampling.Ratio = ADC3_OVERSAMPLING_RATIO_256;
187  hadc3.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_8;
188  hadc3.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER;
189  hadc3.Init.Oversampling.OversamplingStopReset = ADC_REGOVERSAMPLING_CONTINUED_MODE;
190  if (HAL_ADC_Init(&hadc3) != HAL_OK)
191  {
192    Error_Handler();
193  }
194
195  /** Configure Regular Channel
196  */
197  sConfig.Channel = ADC_CHANNEL_10;
198  sConfig.Rank = ADC_REGULAR_RANK_1;
199  sConfig.SamplingTime = ADC3_SAMPLETIME_640CYCLES_5;
200  sConfig.SingleDiff = ADC_SINGLE_ENDED;
201  sConfig.OffsetNumber = ADC_OFFSET_NONE;
202  sConfig.Offset = 0;
203  sConfig.OffsetSign = ADC3_OFFSET_SIGN_NEGATIVE;
204  if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
205  {
206    Error_Handler();
207  }
208
209  /** Configure Regular Channel
210  */
211  sConfig.Channel = ADC_CHANNEL_VBAT;
212  sConfig.Rank = ADC_REGULAR_RANK_2;
213  if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
214  {
215    Error_Handler();
216  }
217
218  /** Configure Regular Channel
219  */
220  sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
221  sConfig.Rank = ADC_REGULAR_RANK_3;
222  if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
223  {
224    Error_Handler();
225  }
226
227  /** Configure Regular Channel
228  */
229  sConfig.Channel = ADC_CHANNEL_VREFINT;
230  sConfig.Rank = ADC_REGULAR_RANK_4;
231  if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
232  {
233    Error_Handler();
234  }
235  /* USER CODE BEGIN ADC3_Init 2 */
236
237  HAL_Delay(100U);
238  if (HAL_OK != HAL_ADCEx_Calibration_Start(&hadc3, ADC_CALIB_OFFSET_LINEARITY, ADC_SINGLE_ENDED)) Error_Handler();
239  HAL_Delay(100U);
240
241  if (HAL_OK != HAL_ADC_Start_DMA(&hadc3, (uint32_t*)&ADC3Data, ADC3_CHANNELS_NUM)) Error_Handler();
242  __HAL_DMA_DISABLE_IT(&hdma_adc3, DMA_IT_HT);
243
244
245  /* USER CODE END ADC3_Init 2 */
246
247}
248
249void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
250{
251
252  GPIO_InitTypeDef GPIO_InitStruct = {0};
253  if(adcHandle->Instance==ADC2)
254  {
255  /* USER CODE BEGIN ADC2_MspInit 0 */
256
257  /* USER CODE END ADC2_MspInit 0 */
258    /* ADC2 clock enable */
259    __HAL_RCC_ADC12_CLK_ENABLE();
260
261    __HAL_RCC_GPIOA_CLK_ENABLE();
262    __HAL_RCC_GPIOC_CLK_ENABLE();
263    __HAL_RCC_GPIOB_CLK_ENABLE();
264    /**ADC2 GPIO Configuration
265    PA6     ------> ADC2_INP3
266    PA7     ------> ADC2_INN3
267    PC4     ------> ADC2_INP4
268    PC5     ------> ADC2_INN4
269    PB0     ------> ADC2_INN5
270    PB1     ------> ADC2_INP5
271    */
272    GPIO_InitStruct.Pin = BAT_I_SENSE_PLUS_Pin|BAT_I_SENSE_MINUS_Pin;
273    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
274    GPIO_InitStruct.Pull = GPIO_NOPULL;
275    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
276
277    GPIO_InitStruct.Pin = LOAD_I_SENSE_PLUS_Pin|LOAD_I_SENSE_MINUS_Pin;
278    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
279    GPIO_InitStruct.Pull = GPIO_NOPULL;
280    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
281
282    GPIO_InitStruct.Pin = BAT_U_SENSE_MINUS_Pin|BAT_U_SENSE_PLUS_Pin;
283    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
284    GPIO_InitStruct.Pull = GPIO_NOPULL;
285    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
286
287    /* ADC2 DMA Init */
288    /* ADC2 Init */
289    hdma_adc2.Instance = DMA1_Stream5;
290    hdma_adc2.Init.Request = DMA_REQUEST_ADC2;
291    hdma_adc2.Init.Direction = DMA_PERIPH_TO_MEMORY;
292    hdma_adc2.Init.PeriphInc = DMA_PINC_DISABLE;
293    hdma_adc2.Init.MemInc = DMA_MINC_ENABLE;
294    hdma_adc2.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
295    hdma_adc2.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
296    hdma_adc2.Init.Mode = DMA_CIRCULAR;
297    hdma_adc2.Init.Priority = DMA_PRIORITY_VERY_HIGH;
298    hdma_adc2.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
299    if (HAL_DMA_Init(&hdma_adc2) != HAL_OK)
300    {
301      Error_Handler();
302    }
303
304    __HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc2);
305
306  /* USER CODE BEGIN ADC2_MspInit 1 */
307
308  /* USER CODE END ADC2_MspInit 1 */
309  }
310  else if(adcHandle->Instance==ADC3)
311  {
312  /* USER CODE BEGIN ADC3_MspInit 0 */
313
314  /* USER CODE END ADC3_MspInit 0 */
315    /* ADC3 clock enable */
316    __HAL_RCC_ADC3_CLK_ENABLE();
317
318    __HAL_RCC_GPIOC_CLK_ENABLE();
319    /**ADC3 GPIO Configuration
320    PC0     ------> ADC3_INP10
321    */
322    GPIO_InitStruct.Pin = BAT_U_RAW_Pin;
323    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
324    GPIO_InitStruct.Pull = GPIO_NOPULL;
325    HAL_GPIO_Init(BAT_U_RAW_GPIO_Port, &GPIO_InitStruct);
326
327    /* ADC3 DMA Init */
328    /* ADC3 Init */
329    hdma_adc3.Instance = BDMA_Channel0;
330    hdma_adc3.Init.Request = BDMA_REQUEST_ADC3;
331    hdma_adc3.Init.Direction = DMA_PERIPH_TO_MEMORY;
332    hdma_adc3.Init.PeriphInc = DMA_PINC_DISABLE;
333    hdma_adc3.Init.MemInc = DMA_MINC_ENABLE;
334    hdma_adc3.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
335    hdma_adc3.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
336    hdma_adc3.Init.Mode = DMA_CIRCULAR;
337    hdma_adc3.Init.Priority = DMA_PRIORITY_LOW;
338    if (HAL_DMA_Init(&hdma_adc3) != HAL_OK)
339    {
340      Error_Handler();
341    }
342
343    __HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc3);
344
345  /* USER CODE BEGIN ADC3_MspInit 1 */
346
347  /* USER CODE END ADC3_MspInit 1 */
348  }
349}
350
351void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
352{
353
354  if(adcHandle->Instance==ADC2)
355  {
356  /* USER CODE BEGIN ADC2_MspDeInit 0 */
357
358  /* USER CODE END ADC2_MspDeInit 0 */
359    /* Peripheral clock disable */
360    __HAL_RCC_ADC12_CLK_DISABLE();
361
362    /**ADC2 GPIO Configuration
363    PA6     ------> ADC2_INP3
364    PA7     ------> ADC2_INN3
365    PC4     ------> ADC2_INP4
366    PC5     ------> ADC2_INN4
367    PB0     ------> ADC2_INN5
368    PB1     ------> ADC2_INP5
369    */
370    HAL_GPIO_DeInit(GPIOA, BAT_I_SENSE_PLUS_Pin|BAT_I_SENSE_MINUS_Pin);
371
372    HAL_GPIO_DeInit(GPIOC, LOAD_I_SENSE_PLUS_Pin|LOAD_I_SENSE_MINUS_Pin);
373
374    HAL_GPIO_DeInit(GPIOB, BAT_U_SENSE_MINUS_Pin|BAT_U_SENSE_PLUS_Pin);
375
376    /* ADC2 DMA DeInit */
377    HAL_DMA_DeInit(adcHandle->DMA_Handle);
378  /* USER CODE BEGIN ADC2_MspDeInit 1 */
379
380  /* USER CODE END ADC2_MspDeInit 1 */
381  }
382  else if(adcHandle->Instance==ADC3)
383  {
384  /* USER CODE BEGIN ADC3_MspDeInit 0 */
385
386  /* USER CODE END ADC3_MspDeInit 0 */
387    /* Peripheral clock disable */
388    __HAL_RCC_ADC3_CLK_DISABLE();
389
390    /**ADC3 GPIO Configuration
391    PC0     ------> ADC3_INP10
392    */
393    HAL_GPIO_DeInit(BAT_U_RAW_GPIO_Port, BAT_U_RAW_Pin);
394
395    /* ADC3 DMA DeInit */
396    HAL_DMA_DeInit(adcHandle->DMA_Handle);
397  /* USER CODE BEGIN ADC3_MspDeInit 1 */
398
399  /* USER CODE END ADC3_MspDeInit 1 */
400  }
401}
402
403/* USER CODE BEGIN 1 */
404
405/* USER CODE END 1 */
Note: See TracBrowser for help on using the repository browser.