cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 U545 - ADC DMA

Marc3
Associate

Hello everyone, 

I am currently starting my master thesis and i have to design a control loop for an inverter with the STM32 U545 RE-Q. I have started programming in STM32 a week ago so everything is complicated and overwhelming ...

 

I am aware that there are multiple examples that i can download from every family of NUCLEOS but non of them have worked for me. I have tried the U575 example called ADC, where data from the ADC is written on the DMA, i have configured the IDE as in the example, created the Node, the Queue, etc... And i have literally copied the lines of code provided in the main.c file but it is not working.

 

In fact, i can not compile as there are the following errors:

../Core/Src/main.c:112:3: warning: implicit declaration of function 'MX_ADCQueue_Config' [-Wimplicit-function-declaration]

112 | MX_ADCQueue_Config();

 

../Core/Src/main.c:114:56: error: 'ADCQueue' undeclared (first use in this function)

114 | if (HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel10, &ADCQueue) != HAL_OK)

 

I would like to configure 5 channels with the ADC4 and 5 channels with the ADC1 to monitor diverse voltage signals. Then I would like to trigger the ADC reading with

a timer with discontinuous reading as i want to have full control of the ADCs.

 

What advice would you give me? Has anyone ever ecountered this? How did you solve it?

If you have some examples please provide me those ...

Any help is welcomed

 

Marc

 

I attach you the main.c code:

 

 

int main(void)

{

 

/* USER CODE BEGIN 1 */

 

/* USER CODE END 1 */

 

/* MCU Configuration--------------------------------------------------------*/

 

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */

HAL_Init();

 

/* USER CODE BEGIN Init */

 

/* USER CODE END Init */

 

/* Configure the System Power */

SystemPower_Config();

 

/* Configure the system clock */

SystemClock_Config();

 

/* USER CODE BEGIN SysInit */

 

/* USER CODE END SysInit */

 

/* Initialize all configured peripherals */

MX_GPIO_Init();

MX_GPDMA1_Init();

MX_ADC4_Init();

MX_ICACHE_Init();

/* USER CODE BEGIN 2 */

 

MX_ADCQueue_Config();

__HAL_LINKDMA(&hadc4, DMA_Handle, handle_GPDMA1_Channel10);

if (HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel10, &ADCQueue) != HAL_OK)

{

Error_Handler();

}

if (HAL_ADC_Start_DMA(&hadc4,

(uint32_t *)aADCxConvertedData,

(ADC_CONVERTED_DATA_BUFFER_SIZE)

) != HAL_OK)

{

Error_Handler();

}

 

 

/* USER CODE END 2 */

 

/* Initialize led */

BSP_LED_Init(LED_GREEN);

 

/* Initialize USER push-button, will be used to trigger an interrupt each time it's pressed.*/

BSP_PB_Init(BUTTON_USER, BUTTON_MODE_EXTI);

 

/* Initialize COM1 port (115200, 8 bits (7-bit data + 1 stop bit), no parity */

BspCOMInit.BaudRate = 115200;

BspCOMInit.WordLength = COM_WORDLENGTH_8B;

BspCOMInit.StopBits = COM_STOPBITS_1;

BspCOMInit.Parity = COM_PARITY_NONE;

BspCOMInit.HwFlowCtl = COM_HWCONTROL_NONE;

if (BSP_COM_Init(COM1, &BspCOMInit) != BSP_ERROR_NONE)

{

Error_Handler();

}

 

/* Infinite loop */

/* USER CODE BEGIN WHILE */

while (1)

{

 

/* USER CODE END WHILE */

 

/* USER CODE BEGIN 3 */

}

/* USER CODE END 3 */

}

 

/**

* @brief System Clock Configuration

* @retval None

*/

void SystemClock_Config(void)

{

RCC_OscInitTypeDef RCC_OscInitStruct = {0};

RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

 

/** Configure the main internal regulator output voltage

*/

if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)

{

Error_Handler();

}

 

/** Initializes the CPU, AHB and APB buses clocks

*/

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_MSI;

RCC_OscInitStruct.HSIState = RCC_HSI_ON;

RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;

RCC_OscInitStruct.MSIState = RCC_MSI_ON;

RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;

RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_0;

RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;

RCC_OscInitStruct.PLL.PLLMBOOST = RCC_PLLMBOOST_DIV4;

RCC_OscInitStruct.PLL.PLLM = 3;

RCC_OscInitStruct.PLL.PLLN = 10;

RCC_OscInitStruct.PLL.PLLP = 2;

RCC_OscInitStruct.PLL.PLLQ = 2;

RCC_OscInitStruct.PLL.PLLR = 1;

RCC_OscInitStruct.PLL.PLLRGE = RCC_PLLVCIRANGE_1;

RCC_OscInitStruct.PLL.PLLFRACN = 0;

if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)

{

Error_Handler();

}

 

/** Initializes the CPU, AHB and APB buses clocks

*/

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK

|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2

|RCC_CLOCKTYPE_PCLK3;

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;

RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;

RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1;

 

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)

{

Error_Handler();

}

}

 

/**

* @brief Power Configuration

* @retval None

*/

static void SystemPower_Config(void)

{

 

/*

* Switch to SMPS regulator instead of LDO

*/

if (HAL_PWREx_ConfigSupply(PWR_SMPS_SUPPLY) != HAL_OK)

{

Error_Handler();

}

/* USER CODE BEGIN PWR */

/* USER CODE END PWR */

}

 

/**

* @brief ADC4 Initialization Function

* @param None

* @retval None

*/

static void MX_ADC4_Init(void)

{

 

/* USER CODE BEGIN ADC4_Init 0 */

 

/* USER CODE END ADC4_Init 0 */

 

ADC_ChannelConfTypeDef sConfig = {0};

 

/* USER CODE BEGIN ADC4_Init 1 */

 

/* USER CODE END ADC4_Init 1 */

 

/** Common config

*/

hadc4.Instance = ADC4;

hadc4.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV4;

hadc4.Init.Resolution = ADC_RESOLUTION_12B;

hadc4.Init.DataAlign = ADC_DATAALIGN_RIGHT;

hadc4.Init.ScanConvMode = ADC4_SCAN_DISABLE;

hadc4.Init.EOCSelection = ADC_EOC_SINGLE_CONV;

hadc4.Init.LowPowerAutoPowerOff = ADC_LOW_POWER_NONE;

hadc4.Init.LowPowerAutoWait = DISABLE;

hadc4.Init.ContinuousConvMode = ENABLE;

hadc4.Init.NbrOfConversion = 1;

hadc4.Init.ExternalTrigConv = ADC_SOFTWARE_START;

hadc4.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;

hadc4.Init.DMAContinuousRequests = DISABLE;

hadc4.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_LOW;

hadc4.Init.Overrun = ADC_OVR_DATA_PRESERVED;

hadc4.Init.SamplingTimeCommon1 = ADC4_SAMPLETIME_19CYCLES_5;

hadc4.Init.SamplingTimeCommon2 = ADC4_SAMPLETIME_19CYCLES_5;

hadc4.Init.OversamplingMode = DISABLE;

if (HAL_ADC_Init(&hadc4) != HAL_OK)

{

Error_Handler();

}

 

/** Configure Regular Channel

*/

sConfig.Channel = ADC_CHANNEL_4;

sConfig.Rank = ADC4_REGULAR_RANK_1;

sConfig.SamplingTime = ADC4_SAMPLINGTIME_COMMON_1;

sConfig.OffsetNumber = ADC_OFFSET_NONE;

sConfig.Offset = 0;

if (HAL_ADC_ConfigChannel(&hadc4, &sConfig) != HAL_OK)

{

Error_Handler();

}

/* USER CODE BEGIN ADC4_Init 2 */

 

/* USER CODE END ADC4_Init 2 */

 

}

 

/**

* @brief GPDMA1 Initialization Function

* @param None

* @retval None

*/

static void MX_GPDMA1_Init(void)

{

 

/* USER CODE BEGIN GPDMA1_Init 0 */

 

/* USER CODE END GPDMA1_Init 0 */

 

/* Peripheral clock enable */

__HAL_RCC_GPDMA1_CLK_ENABLE();

 

/* USER CODE BEGIN GPDMA1_Init 1 */

 

/* USER CODE END GPDMA1_Init 1 */

handle_GPDMA1_Channel10.Instance = GPDMA1_Channel10;

handle_GPDMA1_Channel10.InitLinkedList.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;

handle_GPDMA1_Channel10.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;

handle_GPDMA1_Channel10.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT1;

handle_GPDMA1_Channel10.InitLinkedList.TransferEventMode = DMA_TCEM_LAST_LL_ITEM_TRANSFER;

handle_GPDMA1_Channel10.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;

if (HAL_DMAEx_List_Init(&handle_GPDMA1_Channel10) != HAL_OK)

{

Error_Handler();

}

if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel10, DMA_CHANNEL_NPRIV) != HAL_OK)

{

Error_Handler();

}

/* USER CODE BEGIN GPDMA1_Init 2 */

 

/* USER CODE END GPDMA1_Init 2 */

 

}

 

/**

* @brief ICACHE Initialization Function

* @param None

* @retval None

*/

static void MX_ICACHE_Init(void)

{

 

/* USER CODE BEGIN ICACHE_Init 0 */

 

/* USER CODE END ICACHE_Init 0 */

 

/* USER CODE BEGIN ICACHE_Init 1 */

 

/* USER CODE END ICACHE_Init 1 */

 

/** Enable instruction cache in 1-way (direct mapped cache)

*/

if (HAL_ICACHE_ConfigAssociativityMode(ICACHE_1WAY) != HAL_OK)

{

Error_Handler();

}

if (HAL_ICACHE_Enable() != HAL_OK)

{

Error_Handler();

}

/* USER CODE BEGIN ICACHE_Init 2 */

 

/* USER CODE END ICACHE_Init 2 */

 

}

 

/**

* @brief GPIO Initialization Function

* @param None

* @retval None

*/

static void MX_GPIO_Init(void)

{

/* USER CODE BEGIN MX_GPIO_Init_1 */

/* USER CODE END MX_GPIO_Init_1 */

 

/* GPIO Ports Clock Enable */

__HAL_RCC_GPIOC_CLK_ENABLE();

 

/* USER CODE BEGIN MX_GPIO_Init_2 */

/* USER CODE END MX_GPIO_Init_2 */

}

 

/* USER CODE BEGIN 4 */

 

/* USER CODE END 4 */

 

/**

* @brief This function is executed in case of error occurrence.

* @retval None

*/

void Error_Handler(void)

{

/* USER CODE BEGIN Error_Handler_Debug */

/* User can add his own implementation to report the HAL error return state */

__disable_irq();

while (1)

{

}

/* USER CODE END Error_Handler_Debug */

}

 

 

 

 

 

 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

 

Starting with the example in full, before moving to something else. You need all the files to be correct/consistent, not just main.c.

STM32CubeU5/Projects/NUCLEO-U575ZI-Q/Examples/ADC/ADC_DMA_Transfer/Src/main.c at 6d33b36005af51e94604291501692cf73d7d1440 · STMicroelectronics/STM32CubeU5

 

The Example Selector in STM32CubeIDE can be used to load this example.

TDK_0-1739739847405.png

 

In this case you haven't modified your main.h file to include those definitions.

/* USER CODE BEGIN Includes */
#include "linked_list.h"
/* USER CODE END Includes */

/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */

/* USER CODE END ET */

/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
extern DMA_QListTypeDef ADCQueue;
/* USER CODE END EC */

 

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

4 REPLIES 4
TDK
Guru

 

Starting with the example in full, before moving to something else. You need all the files to be correct/consistent, not just main.c.

STM32CubeU5/Projects/NUCLEO-U575ZI-Q/Examples/ADC/ADC_DMA_Transfer/Src/main.c at 6d33b36005af51e94604291501692cf73d7d1440 · STMicroelectronics/STM32CubeU5

 

The Example Selector in STM32CubeIDE can be used to load this example.

TDK_0-1739739847405.png

 

In this case you haven't modified your main.h file to include those definitions.

/* USER CODE BEGIN Includes */
#include "linked_list.h"
/* USER CODE END Includes */

/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */

/* USER CODE END ET */

/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
extern DMA_QListTypeDef ADCQueue;
/* USER CODE END EC */

 

If you feel a post has answered your question, please click "Accept as Solution".

Just "follow" the compiler warnings:

1. "warning: implicit declaration of function 'MX_ADCQueue_Config'":
    You call a function which is not declared. Potentially, forgotten to include a H-file or to declare this function (as available somewhere else later, e.g. via "Linker"), but a need an external declaration for the function. Here it means: you call a function which is not declared (as a "prototype"), so that compiler could check if you provide enough and correct parameters.

2. "'ADCQueue' undeclared":

    Similar: you use a data object which is not declared: the compiler has no clue what it is, what the type of the data is...

You can "use" unknown functions, but you can not use unknown data objects (therefore this error).

As TDK has mentioned:

maybe, both are there, e.g. the function coming from another C-code file (e.g. HAL driver), and the data variable defined (instantiated) in another file. But your code file does not declare both. Something missing, like an #include or an "extern" declaration.

What you could do to find the root cause:

  • Use in IDE the function "Declaration" (let's look where it is declared)
  • or in IDE "References", where it is used as well
  • Something like "go to declaration" or "go to implementation"
  • to make sure, your compiler can see as you, that it should be resolved somewhere

If you do not find it - something is missing (often a H-file to include, to declare in your file that something is "external").

On data objects: the compiler will not continue if it does not know what "it is". On a function called - the compiler warns you, that it cannot "check" if you call the function properly.

Even you can fix it via declarations of the function (as external) and the data object (as external) - the linker will complain at the end, when it cannot find one of those in any file.
Here, the compiler cannot check it what it is.
In this case, you need to add some other files to your project.

Just do what the compiler would do:

  • is it declared or defined in all the files your project will use?
  • if it is declared - do you use the file where it is declared?
  • use a "grep" tool to find where are these functions, data objects, defined AND declared
  • check, if you use all these files, e.g. adding more #include <file> files or adding more (external) C-code files to your project

Good morning, 

 

Thank you for the fast reply.

 

I uninstalled and reinstalled the STM32CubeIDE and followed your steps and now at least the project can be built.

 

Can I do something else apart from building it? Of course it is not going to work as i have different nucleo but if i try to "copy/follow" the same procedures in a new project with my nucleo should work right? 

 

Thank you

Good morning, 

 

Thank you for the fast reply. 

 

Since I am new i have some questions ... 

 

If i take some project which is alredy done can i apply the same strategy on my nucleo? Which documents do i have to look at if i want to have the same functionality? 

 

Thank you