22
22
23
23
enum { ADC_IRQ_PRIORITY = 1 }; // ADC interrupt priority
24
24
25
+ typedef struct {
26
+ ADC_HandleTypeDef * adc_handle ; // Pointer to the ADC handle
27
+ ADC_ChannelConfTypeDef adc_config ; // ADC channel configuration
28
+ DMA_HandleTypeDef * dma_handle ; // Pointer to the DMA handle
29
+ uint16_t * adc_buffer_data ; // Pointer to the ADC data buffer
30
+ uint32_t adc_buffer_size ; // Size of the ADC data buffer
31
+ ADC_LL_CompleteCallback
32
+ adc_complete_callback ; // Callback for ADC completion
33
+ bool initialized ; // Flag to indicate if the ADC is initialized
34
+ } ADCInstance ;
35
+
25
36
static ADC_HandleTypeDef g_hadc = { nullptr };
26
37
27
38
static ADC_ChannelConfTypeDef g_config = { 0 };
28
39
29
- static ADC_LL_CompleteCallback volatile g_adc_complete_callback ;
40
+ static DMA_HandleTypeDef g_hdma_adc = { nullptr };
41
+
42
+ static ADCInstance g_adc_instance = {
43
+ .adc_handle = & g_hadc ,
44
+ .dma_handle = & g_hdma_adc ,
45
+ };
30
46
31
47
/**
32
48
* @brief Initializes the ADC MSP (MCU Support Package).
@@ -45,16 +61,42 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
45
61
__HAL_RCC_ADC_CLK_ENABLE ();
46
62
// Enable GPIOA clock
47
63
__HAL_RCC_GPIOA_CLK_ENABLE ();
64
+ // Enable DMA1 clock
65
+ __HAL_RCC_GPDMA1_CLK_ENABLE ();
48
66
49
67
// Configure GPIO pin for ADC1_IN0 (PA0)
50
68
gpio_init .Pin = GPIO_PIN_0 ; // PA0
51
69
gpio_init .Mode = GPIO_MODE_ANALOG ;
52
70
gpio_init .Pull = GPIO_NOPULL ;
53
71
HAL_GPIO_Init (GPIOA , & gpio_init );
54
72
73
+ /*DMA for the ADC*/
74
+ g_hdma_adc .Instance = GPDMA1_Channel6 ; // DMA channel for ADC1
75
+ g_hdma_adc .Init .Request = GPDMA1_REQUEST_ADC1 ;
76
+ g_hdma_adc .Init .BlkHWRequest = DMA_BREQ_SINGLE_BURST ;
77
+ g_hdma_adc .Init .Direction = DMA_PERIPH_TO_MEMORY ;
78
+ g_hdma_adc .Init .SrcInc = DMA_SINC_FIXED ;
79
+ g_hdma_adc .Init .DestInc = DMA_DINC_INCREMENTED ;
80
+ g_hdma_adc .Init .SrcDataWidth = DMA_SRC_DATAWIDTH_HALFWORD ;
81
+ g_hdma_adc .Init .DestDataWidth = DMA_DEST_DATAWIDTH_HALFWORD ;
82
+ g_hdma_adc .Init .Priority = DMA_LOW_PRIORITY_LOW_WEIGHT ;
83
+ g_hdma_adc .Init .SrcBurstLength = 1 ;
84
+ g_hdma_adc .Init .DestBurstLength = 1 ;
85
+ g_hdma_adc .Init .TransferAllocatedPort =
86
+ (DMA_SRC_ALLOCATED_PORT0 | DMA_DEST_ALLOCATED_PORT0 );
87
+ g_hdma_adc .Init .TransferEventMode = DMA_TCEM_BLOCK_TRANSFER ;
88
+ g_hdma_adc .Init .Mode = DMA_NORMAL ;
89
+ if (HAL_DMA_Init (& g_hdma_adc ) != HAL_OK ) {
90
+ THROW (ERROR_HARDWARE_FAULT );
91
+ }
92
+ __HAL_LINKDMA (& g_hadc , DMA_Handle , g_hdma_adc );
93
+
55
94
// Enable ADC1 interrupt
56
95
HAL_NVIC_SetPriority (ADC1_IRQn , ADC_IRQ_PRIORITY , 0 );
57
96
HAL_NVIC_EnableIRQ (ADC1_IRQn );
97
+
98
+ HAL_NVIC_SetPriority (GPDMA1_Channel6_IRQn , ADC_IRQ_PRIORITY , 1 );
99
+ HAL_NVIC_EnableIRQ (GPDMA1_Channel6_IRQn );
58
100
}
59
101
60
102
/**
@@ -65,52 +107,75 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
65
107
* parameters.
66
108
*
67
109
*/
68
- void ADC_LL_init (ADC_LL_TriggerSource adc_trigger_timer )
110
+ void ADC_LL_init (
111
+ uint16_t * adc_buf ,
112
+ uint32_t sz ,
113
+ ADC_LL_TriggerSource adc_trigger_timer
114
+ )
69
115
{
116
+ if (adc_buf == nullptr || sz == 0 ) {
117
+ THROW (ERROR_INVALID_ARGUMENT );
118
+ return ;
119
+ }
120
+
121
+ if (g_adc_instance .initialized ) {
122
+ THROW (ERROR_RESOURCE_BUSY );
123
+ return ;
124
+ }
125
+
126
+ // Initialize the ADC handle
127
+ ADCInstance * instance = & g_adc_instance ;
70
128
71
129
// Initialize the ADC peripheral
72
- g_hadc . Instance = ADC1 ;
73
- g_hadc . Init .ClockPrescaler =
130
+ instance -> adc_handle -> Instance = ADC1 ;
131
+ instance -> adc_handle -> Init .ClockPrescaler =
74
132
ADC_CLOCK_SYNC_PCLK_DIV1 ; // ADC clock and prescaler
75
- g_hadc . Init .Resolution = ADC_RESOLUTION_12B ;
76
- g_hadc . Init .DataAlign = ADC_DATAALIGN_RIGHT ;
77
- g_hadc . Init .ScanConvMode = DISABLE ;
78
- g_hadc . Init .EOCSelection = ADC_EOC_SINGLE_CONV ;
79
- g_hadc . Init .LowPowerAutoWait = DISABLE ;
80
- g_hadc . Init .ContinuousConvMode = DISABLE ;
81
- g_hadc . Init .NbrOfConversion = 1 ;
82
- g_hadc . Init .DiscontinuousConvMode = DISABLE ;
133
+ instance -> adc_handle -> Init .Resolution = ADC_RESOLUTION_12B ;
134
+ instance -> adc_handle -> Init .DataAlign = ADC_DATAALIGN_RIGHT ;
135
+ instance -> adc_handle -> Init .ScanConvMode = DISABLE ;
136
+ instance -> adc_handle -> Init .EOCSelection = ADC_EOC_SINGLE_CONV ;
137
+ instance -> adc_handle -> Init .LowPowerAutoWait = DISABLE ;
138
+ instance -> adc_handle -> Init .ContinuousConvMode = DISABLE ;
139
+ instance -> adc_handle -> Init .NbrOfConversion = 1 ;
140
+ instance -> adc_handle -> Init .DiscontinuousConvMode = DISABLE ;
83
141
if (adc_trigger_timer == ADC_TRIGGER_TIMER6 ) {
84
- g_hadc . Init .ExternalTrigConv = ADC_EXTERNALTRIG_T6_TRGO ;
142
+ instance -> adc_handle -> Init .ExternalTrigConv = ADC_EXTERNALTRIG_T6_TRGO ;
85
143
} else {
86
144
THROW (ERROR_INVALID_ARGUMENT );
87
145
return ;
88
146
}
89
- g_hadc .Init .ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING ;
90
- g_hadc .Init .SamplingMode = ADC_SAMPLING_MODE_NORMAL ;
91
- g_hadc .Init .DMAContinuousRequests = DISABLE ;
92
- g_hadc .Init .Overrun = ADC_OVR_DATA_OVERWRITTEN ;
93
- g_hadc .Init .OversamplingMode = DISABLE ;
147
+ instance -> adc_handle -> Init .ExternalTrigConvEdge =
148
+ ADC_EXTERNALTRIGCONVEDGE_RISING ;
149
+ instance -> adc_handle -> Init .SamplingMode = ADC_SAMPLING_MODE_NORMAL ;
150
+ instance -> adc_handle -> Init .DMAContinuousRequests = DISABLE ;
151
+ instance -> adc_handle -> Init .Overrun = ADC_OVR_DATA_OVERWRITTEN ;
152
+ instance -> adc_handle -> Init .OversamplingMode = DISABLE ;
94
153
95
154
if (HAL_ADC_Init (& g_hadc ) != HAL_OK ) {
96
155
THROW (ERROR_HARDWARE_FAULT );
97
156
}
98
157
99
- // Configure ADC channel
158
+ // Configure the ADC channel
159
+ instance -> adc_config = g_config ;
100
160
g_config .Channel = ADC_CHANNEL_0 ; // ADC1_IN0
101
161
g_config .Rank = ADC_REGULAR_RANK_1 ;
102
162
g_config .SamplingTime = ADC_SAMPLETIME_12CYCLES_5 ;
103
163
g_config .SingleDiff = ADC_SINGLE_ENDED ; // Single-ended input
104
164
g_config .OffsetNumber = ADC_OFFSET_NONE ;
105
165
g_config .Offset = 0 ;
106
- if (HAL_ADC_ConfigChannel (& g_hadc , & g_config ) != HAL_OK ) {
166
+ if (HAL_ADC_ConfigChannel (instance -> adc_handle , & g_config ) != HAL_OK ) {
107
167
THROW (ERROR_HARDWARE_FAULT );
108
168
}
109
169
110
170
// Calibration with error handling
111
171
if (HAL_ADCEx_Calibration_Start (& g_hadc , ADC_SINGLE_ENDED ) != HAL_OK ) {
112
172
THROW (ERROR_HARDWARE_FAULT );
113
173
} // Calibration
174
+
175
+ // Set the ADC buffer and size
176
+ instance -> adc_buffer_data = adc_buf ;
177
+ instance -> adc_buffer_size = sz ;
178
+ instance -> initialized = true;
114
179
}
115
180
116
181
/**
@@ -119,10 +184,24 @@ void ADC_LL_init(ADC_LL_TriggerSource adc_trigger_timer)
119
184
*/
120
185
void ADC_LL_deinit (void )
121
186
{
187
+ if (!g_adc_instance .initialized ) {
188
+ THROW (ERROR_RESOURCE_UNAVAILABLE );
189
+ return ;
190
+ }
191
+
192
+ ADCInstance * instance = & g_adc_instance ;
193
+ // Stop the ADC conversion;
194
+ HAL_NVIC_DisableIRQ (ADC1_IRQn ); // Disable ADC1 interrupt
195
+
122
196
// Deinitialize the ADC peripheral
123
- if (HAL_ADC_DeInit (& g_hadc ) != HAL_OK ) {
197
+ if (HAL_ADC_DeInit (instance -> adc_handle ) != HAL_OK ) {
124
198
THROW (ERROR_HARDWARE_FAULT );
125
199
}
200
+
201
+ instance -> adc_buffer_data = nullptr ;
202
+ instance -> adc_buffer_size = 0 ;
203
+ instance -> adc_complete_callback = nullptr ; // Clear the callback
204
+ instance -> initialized = false;
126
205
}
127
206
128
207
/**
@@ -134,10 +213,15 @@ void ADC_LL_deinit(void)
134
213
*/
135
214
void ADC_LL_start (void )
136
215
{
137
- // Start the ADC conversion
138
- if (HAL_ADC_Start_IT (& g_hadc ) != HAL_OK ) {
216
+ __HAL_ADC_CLEAR_FLAG (& g_hadc , ADC_FLAG_OVR ); // Clear any previous flags
217
+
218
+ if (HAL_ADC_Start_DMA (
219
+ & g_hadc ,
220
+ (uint32_t * )g_adc_instance .adc_buffer_data ,
221
+ g_adc_instance .adc_buffer_size
222
+ ) != HAL_OK ) {
139
223
THROW (ERROR_HARDWARE_FAULT );
140
- }
224
+ } // Start ADC in DMA mode
141
225
}
142
226
143
227
/**
@@ -150,24 +234,38 @@ void ADC_LL_start(void)
150
234
void ADC_LL_stop (void )
151
235
{
152
236
// Stop the ADC conversion
153
- if (HAL_ADC_Stop_IT (& g_hadc ) != HAL_OK ) {
237
+ if (HAL_ADC_Stop_DMA (& g_hadc ) != HAL_OK ) {
154
238
THROW (ERROR_HARDWARE_FAULT );
155
239
}
156
240
}
157
241
242
+ /**
243
+ * @brief Sets the ADC complete callback.
244
+ *
245
+ * This function sets the user-defined callback that will be called when the
246
+ * ADC conversion is complete.
247
+ *
248
+ * @param callback Pointer to the callback function.
249
+ */
158
250
void ADC_LL_set_complete_callback (ADC_LL_CompleteCallback callback )
159
251
{
160
- g_adc_complete_callback = callback ; // Set the user-defined callback
252
+ g_adc_instance .adc_complete_callback =
253
+ callback ; // Set the user-defined callback
161
254
}
162
255
163
256
void HAL_ADC_ConvCpltCallback (ADC_HandleTypeDef * hadc )
164
257
{
165
258
(void )hadc ; // Suppress unused parameter warning
166
- uint32_t value = HAL_ADC_GetValue ( & g_hadc );
167
- if (g_adc_complete_callback != nullptr ) {
168
- g_adc_complete_callback ( value
259
+
260
+ if (g_adc_instance . adc_complete_callback != nullptr ) {
261
+ g_adc_instance . adc_complete_callback (
169
262
); // Call the user-defined callback with the ADC value
170
263
}
171
264
}
172
265
173
266
void ADC1_IRQHandler (void ) { HAL_ADC_IRQHandler (& g_hadc ); }
267
+
268
+ void GPDMA1_Channel6_IRQHandler (void )
269
+ {
270
+ HAL_DMA_IRQHandler (& g_hdma_adc ); // Handle DMA interrupts
271
+ }
0 commit comments