2021-08-08 02:54 PM
Hi!
I'm doing SDADC and I think there is some issues with the DMA for SDADC in STM32CubeIDE 1.7.0.
First, I have enabled DMA for SDADC1, SDADC2, SDADC3 and I have selected InjectedConversion = ENABLE.
Then I run this function.
volatile static int16_t SDADC1_Single[9];
volatile static int16_t SDADC2_Single[3];
volatile static int16_t SDADC3_Differential[5];
static float SDADC_Single_Calibration_Gain[12] = {0};
static float SDADC_Single_Calibration_Bias[12] = {0};
static float SDADC_Differential_Calibration_Gain[5] = {0};
static float SDADC_Differential_Calibration_Bias[5] = {0};
TIM_HandleTypeDef *handler_tim12;
TIM_HandleTypeDef *handler_tim13;
SDADC_HandleTypeDef *handler_sdadc1;
SDADC_HandleTypeDef *handler_sdadc2;
SDADC_HandleTypeDef *handler_sdadc3;
void STM32_PLC_Start_Analog_Input(TIM_HandleTypeDef* htim12, TIM_HandleTypeDef* htim13, SDADC_HandleTypeDef* hsdadc1, SDADC_HandleTypeDef* hsdadc2, SDADC_HandleTypeDef* hsdadc3) {
/*
* For TIM12, TIM13 and TIM16
* Timer clock: 48 Mhz
* Prescaler: 0
* Counter: 48000 (0xbb80)
* Update frequency: 1000 Hz
*/
HAL_TIM_OC_Start(htim13, TIM_CHANNEL_1); /* TIM13 Channel 1 is trigger source for SDADC1 */
HAL_TIM_OC_Start(htim12, TIM_CHANNEL_1); /* TIM12 Channel 1 is trigger source for SDADC2 */
HAL_TIM_OC_Start(htim12, TIM_CHANNEL_2); /* TIM12 Channel 2 is trigger source for SDADC3 */
if (HAL_SDADC_CalibrationStart(hsdadc1, SDADC_CALIBRATION_SEQ_1) != HAL_OK)
Error_Handler();
if (HAL_SDADC_CalibrationStart(hsdadc2, SDADC_CALIBRATION_SEQ_1) != HAL_OK)
Error_Handler();
if (HAL_SDADC_CalibrationStart(hsdadc3, SDADC_CALIBRATION_SEQ_1) != HAL_OK)
Error_Handler();
if (HAL_SDADC_PollForCalibEvent(hsdadc1, HAL_MAX_DELAY) != HAL_OK)
Error_Handler();
if (HAL_SDADC_PollForCalibEvent(hsdadc2, HAL_MAX_DELAY) != HAL_OK)
Error_Handler();
if (HAL_SDADC_PollForCalibEvent(hsdadc3, HAL_MAX_DELAY) != HAL_OK)
Error_Handler();
if(HAL_SDADC_InjectedStart_DMA(hsdadc1, (uint32_t*)SDADC1_Single, 9) != HAL_OK)
Error_Handler();
if(HAL_SDADC_InjectedStart_DMA(hsdadc2, (uint32_t*)SDADC2_Single, 3) != HAL_OK)
Error_Handler();
if(HAL_SDADC_InjectedStart_DMA(hsdadc3, (uint32_t*)SDADC3_Differential, 5) != HAL_OK)
Error_Handler();
/* Save */
handler_tim13 = htim13;
handler_tim12 = htim12;
handler_sdadc1 = hsdadc1;
handler_sdadc2 = hsdadc2;
handler_sdadc3 = hsdadc3;
}
And then I run this function when I want to change the gain and offsett for the SDADC. I begin with SDADC1.
/* Inline is only for optimization */
static inline int16_t* array_to_pointer(int16_t array[]){
return array; /* This return the address */
}
void STM32_PLC_Analog_Input_Set_Gain_Offset(uint8_t sdadc, uint8_t configuration_index, uint8_t gain, uint16_t offset) {
/* Initial */
SDADC_ConfParamTypeDef ConfParamStruct = {0};
ConfParamStruct.CommonMode = SDADC_COMMON_MODE_VSSA;
SDADC_HandleTypeDef *handler;
uint8_t length_DMA;
uint32_t *array_DMA;
/* Stop DMA */
switch(sdadc){
case 1:
/* Stop DMA for SDADC1 */
if(HAL_SDADC_InjectedStop_DMA(handler_sdadc1) != HAL_OK)
Error_Handler();
handler = handler_sdadc1;
length_DMA = 9;
array_DMA = (uint32_t*)array_to_pointer((int16_t*)SDADC1_Single);
ConfParamStruct.InputMode = SDADC_INPUT_MODE_SE_ZERO_REFERENCE;
break;
case 2:
/* Stop DMA for SDADC2 */
if(HAL_TIM_OC_Stop(handler_tim12, TIM_CHANNEL_1))
Error_Handler();
if(HAL_SDADC_InjectedStop_DMA(handler_sdadc2) != HAL_OK)
Error_Handler();
handler = handler_sdadc2;
length_DMA = 3;
array_DMA = (uint32_t*)array_to_pointer((int16_t*)SDADC2_Single);
ConfParamStruct.InputMode = SDADC_INPUT_MODE_SE_ZERO_REFERENCE;
break;
case 3:
/* Stop DMA for SDADC3 */
if(HAL_SDADC_InjectedStop_DMA(handler_sdadc3) != HAL_OK)
Error_Handler();
handler = handler_sdadc3;
length_DMA = 5;
array_DMA = (uint32_t*)array_to_pointer((int16_t*)SDADC3_Differential);
ConfParamStruct.InputMode = SDADC_INPUT_MODE_DIFF;
break;
default:
/* Stop DMA for SDADC1 */
if(HAL_SDADC_InjectedStop_DMA(handler_sdadc1) != HAL_OK)
Error_Handler();
handler = handler_sdadc1;
length_DMA = 9;
array_DMA = (uint32_t*)array_to_pointer((int16_t*)SDADC1_Single);
ConfParamStruct.InputMode = SDADC_INPUT_MODE_SE_ZERO_REFERENCE;
break;
}
/* Set gain and offset */
switch(gain){
case 0:
ConfParamStruct.Gain = SDADC_GAIN_1_2;
break;
case 1:
ConfParamStruct.Gain = SDADC_GAIN_1;
break;
case 2:
ConfParamStruct.Gain = SDADC_GAIN_2;
break;
case 3:
ConfParamStruct.Gain = SDADC_GAIN_4;
break;
case 4:
ConfParamStruct.Gain = SDADC_GAIN_8;
break;
case 5:
ConfParamStruct.Gain = SDADC_GAIN_16;
break;
case 6:
ConfParamStruct.Gain = SDADC_GAIN_32;
break;
default:
ConfParamStruct.Gain = SDADC_GAIN_1;
offset = 0;
break;
}
ConfParamStruct.Offset = offset;
/* Set calibration */
if (HAL_SDADC_PrepareChannelConfig(handler, configuration_index, &ConfParamStruct) != HAL_OK)
Error_Handler();
/* Start ADC again */
if (HAL_SDADC_CalibrationStart(handler, SDADC_CALIBRATION_SEQ_1) != HAL_OK)
Error_Handler();
if (HAL_SDADC_PollForCalibEvent(handler, HAL_MAX_DELAY) != HAL_OK)
Error_Handler();
if(HAL_SDADC_InjectedStart_DMA(handler, array_DMA, length_DMA) != HAL_OK)
Error_Handler();
}
The first thing that happens is that STM32F373VBTx calling this function
if(HAL_SDADC_InjectedStop_DMA(handler_sdadc1) != HAL_OK)
Error_Handler();
Then next step is that it's calling this function
/* Stop current DMA transfer */
if(HAL_DMA_Abort(hsdadc->hdma) != HAL_OK)
Then this if-statement runs
if(hdma->State != HAL_DMA_STATE_BUSY)
{
/* no transfer ongoing */
hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
/* Process Unlocked */
__HAL_UNLOCK(hdma);
return HAL_ERROR;
}
Because
hdma->State == HAL_DMA_STATE_READY
That means that the DMA wasn't enabled at the first time? Right?
This must be a bug, right?
And no...the SDADC with DMA does not work for me. Only with interrupt.