cancel
Showing results for 
Search instead for 
Did you mean: 

Issue with DMA and ADC on STM32 Nucleo C031C6T6

Reebin
Associate

Hi,

I am new to DMA interfacing on the STM32 Nucleo C031C6T6 board. I am trying to send ADC conversion data to UART using DMA. I have tested the code in debugging mode, and after calling the HAL_ADC_Start_DMA() function, the program control seems to go elsewhere, preventing further function calls from being executed.

However, if I perform an arithmetic operation or an assignment instead of calling a function after invoking HAL_ADC_Start_DMA(), the program execution continues as expected. This suggests that the program doesn't allow function calls immediately after HAL_ADC_Start_DMA() is invoked.

Below is the code I'm working with:

 

Development Board: STM32 Nucleo C031C6T6

CubeIDE Version: 1.15.1

 

Best Regards

Reebin

 

Code:

 

/* USER CODE BEGIN Header */

/**

******************************************************************************

* @file : main.c

* @brief : Main program body

******************************************************************************

* @attention

*

* Copyright (c) 2024 STMicroelectronics.

* All rights reserved.

*

* This software is licensed under terms that can be found in the LICENSE file

* in the root directory of this software component.

* If no LICENSE file comes with this software, it is provided AS-IS.

*

******************************************************************************

*/

/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/

#include "main.h"

#include <stdio.h>

#include <stdint.h>

/* Private includes ----------------------------------------------------------*/

/* USER CODE BEGIN Includes */

 

/* USER CODE END Includes */

 

/* Private typedef -----------------------------------------------------------*/

/* USER CODE BEGIN PTD */

 

/* USER CODE END PTD */

 

/* Private define ------------------------------------------------------------*/

/* USER CODE BEGIN PD */

 

/* USER CODE END PD */

 

/* Private macro -------------------------------------------------------------*/

/* USER CODE BEGIN PM */

 

/* USER CODE END PM */

 

/* Private variables ---------------------------------------------------------*/

ADC_HandleTypeDef hadc1;

DMA_HandleTypeDef hdma_adc1;

 

UART_HandleTypeDef huart2;

 

/* USER CODE BEGIN PV */

uint32_t value_adc; // Buffer for ADC data

/* USER CODE END PV */

 

/* Private function prototypes -----------------------------------------------*/

void SystemClock_Config(void);

static void MX_DMA_Init(void);

static void MX_USART2_UART_Init(void);

static void MX_ADC1_Init(void);

/* USER CODE BEGIN PFP */

#if defined (__ICCARM__) || defined (__ARMCC_VERSION)

#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)

#elif defined(__GNUC__)

/* With GCC, small printf (option LD Linker->Libraries->Small printf

set to 'Yes') calls __io_putchar() */

#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)

#endif /* __ICCARM__ || __ARMCC_VERSION */

/* USER CODE END PFP */

 

/* Private user code ---------------------------------------------------------*/

/* USER CODE BEGIN 0 */

 

/* USER CODE END 0 */

 

/**

* @brief The application entry point.

* @retval int

*/

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 clock */

SystemClock_Config();

 

/* USER CODE BEGIN SysInit */

 

/* USER CODE END SysInit */

 

/* Initialize all configured peripherals */

MX_DMA_Init();

MX_USART2_UART_Init();

MX_ADC1_Init();

/* USER CODE BEGIN 2 */

HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&value_adc, 1);

/* USER CODE END 2 */

printf("\n\r ADC - DMA Example \n\r");

/* Infinite loop */

/* USER CODE BEGIN WHILE */

while (1)

{

/* USER CODE END WHILE */

// Print ADC values

printf("ADC Value : %lu\r\n",value_adc);

HAL_Delay(1000); // 1 second delay between prints

/* 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};

 

/** Initializes the RCC Oscillators according to the specified parameters

* in the RCC_OscInitTypeDef structure.

*/

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;

RCC_OscInitStruct.HSEState = RCC_HSE_ON;

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_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;

RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;

RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV1;

RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV1;

 

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

{

Error_Handler();

}

}

 

/**

* @brief ADC1 Initialization Function

* @PAram None

* @retval None

*/

static void MX_ADC1_Init(void)

{

 

/* USER CODE BEGIN ADC1_Init 0 */

 

/* USER CODE END ADC1_Init 0 */

 

ADC_ChannelConfTypeDef sConfig = {0};

 

/* USER CODE BEGIN ADC1_Init 1 */

 

/* USER CODE END ADC1_Init 1 */

 

/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)

*/

hadc1.Instance = ADC1;

hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;

hadc1.Init.Resolution = ADC_RESOLUTION_12B;

hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;

hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;

hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;

hadc1.Init.LowPowerAutoWait = DISABLE;

hadc1.Init.LowPowerAutoPowerOff = DISABLE;

hadc1.Init.ContinuousConvMode = ENABLE;

hadc1.Init.NbrOfConversion = 1;

hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;

hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;

hadc1.Init.DMAContinuousRequests = ENABLE;

hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;

hadc1.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_1CYCLE_5;

hadc1.Init.SamplingTimeCommon2 = ADC_SAMPLETIME_1CYCLE_5;

hadc1.Init.OversamplingMode = DISABLE;

hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH;

if (HAL_ADC_Init(&hadc1) != HAL_OK)

{

Error_Handler();

}

 

/** Configure Regular Channel

*/

sConfig.Channel = ADC_CHANNEL_0;

sConfig.Rank = ADC_REGULAR_RANK_1;

sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_1;

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

{

Error_Handler();

}

/* USER CODE BEGIN ADC1_Init 2 */

 

/* USER CODE END ADC1_Init 2 */

 

}

 

/**

* @brief USART2 Initialization Function

* @PAram None

* @retval None

*/

static void MX_USART2_UART_Init(void)

{

 

/* USER CODE BEGIN USART2_Init 0 */

 

/* USER CODE END USART2_Init 0 */

 

/* USER CODE BEGIN USART2_Init 1 */

 

/* USER CODE END USART2_Init 1 */

huart2.Instance = USART2;

huart2.Init.BaudRate = 115200;

huart2.Init.WordLength = UART_WORDLENGTH_8B;

huart2.Init.StopBits = UART_STOPBITS_1;

huart2.Init.Parity = UART_PARITY_NONE;

huart2.Init.Mode = UART_MODE_TX_RX;

huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;

huart2.Init.OverSampling = UART_OVERSAMPLING_16;

huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;

huart2.Init.ClockPrescaler = UART_PRESCALER_DIV1;

huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;

if (HAL_UART_Init(&huart2) != HAL_OK)

{

Error_Handler();

}

/* USER CODE BEGIN USART2_Init 2 */

 

/* USER CODE END USART2_Init 2 */

 

}

 

/**

* Enable DMA controller clock

*/

static void MX_DMA_Init(void)

{

 

/* DMA controller clock enable */

__HAL_RCC_DMA1_CLK_ENABLE();

 

/* DMA interrupt init */

/* DMA1_Channel1_IRQn interrupt configuration */

HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);

HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);

 

}

 

/* USER CODE BEGIN 4 */

/**

* @brief Retargets the C library printf function to the USART.

* @PAram None

* @retval None

*/

PUTCHAR_PROTOTYPE

{

/* Place your implementation of fputc here */

/* e.g. write a character to the USART2 and Loop until the end of transmission */

HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 0xFFFF);

 

return ch;

}

/* 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 */

}

 

#ifdef USE_FULL_ASSERT

/**

* @brief Reports the name of the source file and the source line number

* where the assert_param error has occurred.

* @PAram file: pointer to the source file name

* @PAram line: assert_param error line source number

* @retval None

*/

void assert_failed(uint8_t *file, uint32_t line)

{

/* USER CODE BEGIN 6 */

/* User can add his own implementation to report the file name and line number,

ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

/* USER CODE END 6 */

}

#endif /* USE_FULL_ASSERT */

4 REPLIES 4
MM..1
Chief III

Place code as code or c file not booth pls. And primary issue seems be missing dma channel config for ADC.

 

uint32_t value_adc; // Buffer for ADC data

 

too ADC return 16bit values, for DMA must be in RAM then maybe volatile...

Reebin
Associate

Hi 

I am new to DMA interfacing on the STM32 Nucleo C031C6T6 board, i tried your suggestions in my code but it didn't work, can please give me any example that interface simple ADC - DMA

Thanks, and regards
Reebin

Ozone
Lead II

As posters above said, stop posting code as text.
Use the "Insert code snipped" functionality.


But to the problem - all the relevant DMA code is missing.
I have no code examples for C0 series, or ever tried it on one, but on several F0, F1, F3 and F4 cores.

Usually, only one or two specific DMA channels/streams can be attached to the ADC. You would need to check the reference manual here. And you would need to set up the DMA correctly, i.e. peripheral-to-memory transfer, single-shot, 16-bit size, and correct number of items (channels).

The best option is to use an existing (HAL) example.
If there is none for your specific MCU, try one for a similiar MCU (another C0x) to provide the framework, and replace actual ADC/DMA settings with proper ones' for your MCU - again, in the reference manual.
AFAIK the DMA target address can have item size alignment (i.e. 16-bit in this case), but must be global/static, and not on the stack.