1
+ #include " stm32h7_hal.h"
2
+
3
+ #if defined(STM32H7xx)
4
+
5
+ // #define SIMPLEFOC_STM32_DEBUG
6
+
7
+ #include " ../../../../communication/SimpleFOCDebug.h"
8
+ #define _TRGO_NOT_AVAILABLE 12345
9
+
10
+ ADC_HandleTypeDef hadc;
11
+
12
+ /* *
13
+ * Function initializing the ADC and the injected channels for the low-side current sensing
14
+ *
15
+ * @param cs_params - current sense parameters
16
+ * @param driver_params - driver parameters
17
+ *
18
+ * @return int - 0 if success
19
+ */
20
+ int _adc_init (Stm32CurrentSenseParams* cs_params, const STM32DriverParams* driver_params)
21
+ {
22
+ ADC_InjectionConfTypeDef sConfigInjected ;
23
+
24
+ // check if all pins belong to the same ADC
25
+ ADC_TypeDef* adc_pin1 = _isset (cs_params->pins [0 ]) ? (ADC_TypeDef*)pinmap_peripheral (analogInputToPinName (cs_params->pins [0 ]), PinMap_ADC) : nullptr ;
26
+ ADC_TypeDef* adc_pin2 = _isset (cs_params->pins [1 ]) ? (ADC_TypeDef*)pinmap_peripheral (analogInputToPinName (cs_params->pins [1 ]), PinMap_ADC) : nullptr ;
27
+ ADC_TypeDef* adc_pin3 = _isset (cs_params->pins [2 ]) ? (ADC_TypeDef*)pinmap_peripheral (analogInputToPinName (cs_params->pins [2 ]), PinMap_ADC) : nullptr ;
28
+ if ( ((adc_pin1 != adc_pin2) && (adc_pin1 && adc_pin2)) ||
29
+ ((adc_pin2 != adc_pin3) && (adc_pin2 && adc_pin3)) ||
30
+ ((adc_pin1 != adc_pin3) && (adc_pin1 && adc_pin3))
31
+ ){
32
+ #ifdef SIMPLEFOC_STM32_DEBUG
33
+ SIMPLEFOC_DEBUG (" STM32-CS: ERR: Analog pins dont belong to the same ADC!" );
34
+ #endif
35
+ return -1 ;
36
+ }
37
+
38
+ /* *Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
39
+ */
40
+ hadc.Instance = (ADC_TypeDef *)pinmap_peripheral (analogInputToPinName (cs_params->pins [0 ]), PinMap_ADC);
41
+
42
+ if (hadc.Instance == ADC1) __HAL_RCC_ADC12_CLK_ENABLE ();
43
+ #ifdef ADC2 // if defined ADC2
44
+ else if (hadc.Instance == ADC2) __HAL_RCC_ADC12_CLK_ENABLE ();
45
+ #endif
46
+ #ifdef ADC3 // if defined ADC3
47
+ else if (hadc.Instance == ADC3) __HAL_RCC_ADC3_CLK_ENABLE ();
48
+ #endif
49
+ else {
50
+ #ifdef SIMPLEFOC_STM32_DEBUG
51
+ SIMPLEFOC_DEBUG (" STM32-CS: ERR: Pin does not belong to any ADC!" );
52
+ #endif
53
+ return -1 ; // error not a valid ADC instance
54
+ }
55
+
56
+ #ifdef SIMPLEFOC_STM32_DEBUG
57
+ SIMPLEFOC_DEBUG (" STM32-CS: Using ADC: " , _adcToIndex (&hadc)+1 );
58
+ #endif
59
+
60
+ hadc.Init .ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
61
+ hadc.Init .Resolution = ADC_RESOLUTION_12B;
62
+ hadc.Init .ScanConvMode = ENABLE;
63
+ hadc.Init .ContinuousConvMode = DISABLE;
64
+ hadc.Init .DiscontinuousConvMode = DISABLE;
65
+ hadc.Init .ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
66
+ hadc.Init .ExternalTrigConv = ADC_SOFTWARE_START; // for now
67
+ #if defined(ADC_VER_V5_V90)
68
+ // only for ADC3
69
+ if (hadc.Instance == ADC3){
70
+ hadc.Init .DataAlign = ADC3_DATAALIGN_RIGHT;
71
+ }
72
+ // more info here
73
+ // https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32H7xx_HAL_Driver/Inc/stm32h7xx_hal_adc.h#L170C13-L170C27
74
+ hadc.Init .DMAContinuousRequests = DISABLE;
75
+ // not sure about this one!!! maybe use: ADC_SAMPLING_MODE_NORMAL
76
+ hadc.Init .SamplingMode = ADC_SAMPLING_MODE_BULB;
77
+ #endif
78
+ hadc.Init .NbrOfConversion = 1 ;
79
+ hadc.Init .NbrOfDiscConversion = 0 ;
80
+ hadc.Init .EOCSelection = ADC_EOC_SINGLE_CONV;
81
+
82
+ hadc.Init .LowPowerAutoWait = DISABLE;
83
+
84
+
85
+ if ( HAL_ADC_Init (&hadc) != HAL_OK){
86
+ #ifdef SIMPLEFOC_STM32_DEBUG
87
+ SIMPLEFOC_DEBUG (" STM32-CS: ERR: cannot init ADC!" );
88
+ #endif
89
+ return -1 ;
90
+ }
91
+
92
+ /* *Configures for the selected ADC injected channel its corresponding rank in the sequencer and its sample time
93
+ */
94
+ sConfigInjected .InjectedNbrOfConversion = _isset (cs_params->pins [2 ]) ? 3 : 2 ;
95
+ // if ADC1 or ADC2
96
+ if (hadc.Instance == ADC1 || hadc.Instance == ADC2){
97
+ // more info here: https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32H7xx_HAL_Driver/Inc/stm32h7xx_hal_adc.h#L658
98
+ sConfigInjected .InjectedSamplingTime = ADC_SAMPLETIME_2CYCLE_5;
99
+ }else {
100
+ // adc3
101
+ // https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32H7xx_HAL_Driver/Inc/stm32h7xx_hal_adc.h#L673
102
+ sConfigInjected .InjectedSamplingTime = ADC3_SAMPLETIME_2CYCLES_5;
103
+ }
104
+ sConfigInjected .ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONV_EDGE_RISINGFALLING;
105
+ sConfigInjected .AutoInjectedConv = DISABLE;
106
+ sConfigInjected .InjectedDiscontinuousConvMode = DISABLE;
107
+ sConfigInjected .InjectedOffset = 0 ;
108
+ sConfigInjected .InjectedSingleDiff = ADC_SINGLE_ENDED;
109
+ sConfigInjected .InjectedOffsetNumber = ADC_OFFSET_NONE;
110
+ sConfigInjected .QueueInjectedContext = DISABLE;
111
+ sConfigInjected .InjecOversamplingMode = DISABLE;
112
+
113
+ // automating TRGO flag finding - hardware specific
114
+ uint8_t tim_num = 0 ;
115
+ for (size_t i=0 ; i<6 ; i++) {
116
+ TIM_HandleTypeDef *timer_to_check = driver_params->timers_handle [tim_num++];
117
+ TIM_TypeDef *instance_to_check = timer_to_check->Instance ;
118
+
119
+ uint32_t trigger_flag = _timerToInjectedTRGO (timer_to_check);
120
+ if (trigger_flag == _TRGO_NOT_AVAILABLE) continue ; // timer does not have valid trgo for injected channels
121
+
122
+ // check if TRGO used already - if yes use the next timer
123
+ if ((timer_to_check->Instance ->CR2 & LL_TIM_TRGO_ENABLE) || // if used for timer sync
124
+ (timer_to_check->Instance ->CR2 & LL_TIM_TRGO_UPDATE)) // if used for ADC sync
125
+ {
126
+ continue ;
127
+ }
128
+
129
+ // if the code comes here, it has found the timer available
130
+ // timer does have trgo flag for injected channels
131
+ sConfigInjected .ExternalTrigInjecConv = trigger_flag;
132
+
133
+ // this will be the timer with which the ADC will sync
134
+ cs_params->timer_handle = timer_to_check;
135
+ // done
136
+ break ;
137
+ }
138
+ if ( cs_params->timer_handle == NP ){
139
+ // not possible to use these timers for low-side current sense
140
+ #ifdef SIMPLEFOC_STM32_DEBUG
141
+ SIMPLEFOC_DEBUG (" STM32-CS: ERR: cannot sync any timer to injected channels!" );
142
+ #endif
143
+ return -1 ;
144
+ }else {
145
+ #ifdef SIMPLEFOC_STM32_DEBUG
146
+ SIMPLEFOC_DEBUG (" STM32-CS: Using timer: " , stm32_getTimerNumber (cs_params->timer_handle ->Instance ));
147
+ #endif
148
+ }
149
+
150
+ uint32_t ranks[4 ] = {ADC_INJECTED_RANK_1, ADC_INJECTED_RANK_2, ADC_INJECTED_RANK_3, ADC_INJECTED_RANK_4};
151
+ for (int i=0 ; i<3 ; i++){
152
+ // skip if not set
153
+ if (!_isset (cs_params->pins [i])) continue ;
154
+ sConfigInjected .InjectedRank = ranks[i];
155
+ sConfigInjected .InjectedChannel = _getADCChannel (analogInputToPinName (cs_params->pins [i]));
156
+ if (HAL_ADCEx_InjectedConfigChannel (&hadc, &sConfigInjected ) != HAL_OK){
157
+ #ifdef SIMPLEFOC_STM32_DEBUG
158
+ SIMPLEFOC_DEBUG (" STM32-CS: ERR: cannot init injected channel: " , (int )_getADCChannel (analogInputToPinName (cs_params->pins [i])) );
159
+ #endif
160
+ return -1 ;
161
+ }
162
+ }
163
+
164
+
165
+ delay (1000 );
166
+ #ifdef SIMPLEFOC_STM32_ADC_INTERRUPT
167
+ // enable interrupt
168
+ HAL_NVIC_SetPriority (ADC_IRQn, 0 , 0 );
169
+ HAL_NVIC_EnableIRQ (ADC_IRQn);
170
+ #endif
171
+
172
+ cs_params->adc_handle = &hadc;
173
+ return 0 ;
174
+ }
175
+
176
+
177
+ /* *
178
+ * Function to initialize the ADC GPIO pins
179
+ *
180
+ * @param cs_params current sense parameters
181
+ * @param pinA pin number for phase A
182
+ * @param pinB pin number for phase B
183
+ * @param pinC pin number for phase C
184
+ * @return int 0 if success, -1 if error
185
+ */
186
+ int _adc_gpio_init (Stm32CurrentSenseParams* cs_params, const int pinA, const int pinB, const int pinC)
187
+ {
188
+ int pins[3 ] = {pinA, pinB, pinC};
189
+ const char * port_names[3 ] = {" A" , " B" , " C" };
190
+ for (int i=0 ; i<3 ; i++){
191
+ if (_isset (pins[i])){
192
+ // check if pin is an analog pin
193
+ if (pinmap_peripheral (analogInputToPinName (pins[i]), PinMap_ADC) == NP){
194
+ #ifdef SIMPLEFOC_STM32_DEBUG
195
+ SimpleFOCDebug::print (" STM32-CS: ERR: Pin " );
196
+ SimpleFOCDebug::print (port_names[i]);
197
+ SimpleFOCDebug::println (" does not belong to any ADC!" );
198
+ #endif
199
+ return -1 ;
200
+ }
201
+ pinmap_pinout (analogInputToPinName (pins[i]), PinMap_ADC);
202
+ cs_params->pins [i] = pins[i];
203
+ }
204
+ }
205
+ return 0 ;
206
+ }
207
+
208
+ #ifdef SIMPLEFOC_STM32_ADC_INTERRUPT
209
+ extern " C" {
210
+ void ADC_IRQHandler (void )
211
+ {
212
+ HAL_ADC_IRQHandler (&hadc);
213
+ }
214
+ }
215
+ #endif
216
+
217
+ #endif
0 commit comments