cancel
Showing results for 
Search instead for 
Did you mean: 

The signal result becomes a straight line on the DAC

macam1
Associate II

 

"I am using your program and made some changes, but when I use it in the function

 

 

HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)value, 89, DAC_ALIGN_12B_R); 
HAL_TIM_Base_Start(&htim4);

 

the signal result on the oscilloscope is not continuous. What I mean is, when I use a very long array, the result does not match what I expected. To help you understand, I am attaching two photos comparing the result I want and the result from the program.

WhatsApp Image 2024-09-06 at 16.06.24 (1).jpegWhatsApp Image 2024-09-06 at 16.06.24.jpeg

 

I have a signal result like the one on the left, but I want it to be like the one on the right. After investigating, it turns out that the length value in HAL_DAC_Start_DMA was manually changed. If it can be done automatically, please give suggestions so I don't have to set it manually.

program to check

 

uint16_t hold_samples = 50;
uint16_t firstHalf[64] =
{
2100, 2149, 2250, 2350, 2450, 2549, 2646, 2742, 2837, 2929, 3020, 3108, 3193, 3275, 3355,
3431, 3504, 3574, 3639, 3701, 3759, 3812, 3861, 3906, 3946, 3982, 4013, 4039, 4060, 4076,
4087, 4094, 4095, 4091, 4082, 4069, 4050, 4026, 3998, 3965, 3927, 3884, 3837, 3786, 3730,
3671, 3607, 3539, 3468, 3394, 3316, 3235, 3151, 3064, 2975, 2883, 2790, 2695, 2598, 2500,
2400, 2300, 2199, 2098

}; // Nilai pada bagian pertama
uint16_t secondHalf[71] =
{
1997, 1896, 1795, 1695, 1595, 1497,1305, 1212, 1120, 1031, 944, 860, 779, 701, 627,
556, 488, 424, 365, 309, 258, 211, 168, 130, 97, 69, 45, 26, 13,4, 0, 1, 8, 19, 35, 56, 82,
113, 149, 200, 283, 336, 394, 456, 521, 591, 664, 740, 820, 902, 987, 1075, 1166, 1258,
1353, 1449, 1546, 1645, 1745, 1845, 1947, 1965, 1990, 2010, 2022, 2047
}; // Nilai pada bagian kedua
uint16_t totalSize = (sizeof(firstHalf) / sizeof(uint16_t)) + hold_samples + (sizeof(secondHalf) / sizeof(uint16_t));
    uint16_t index = 0;
    uint16_t n_firstHalf = (sizeof(firstHalf) / sizeof(uint16_t));

    for (int i = 0; i < n_firstHalf; i++) {
        value[index] = firstHalf[i];
        index++;
    }

    for (int i = 0; i < hold_samples; i++) {
        value[index] = 2048;
        index++;
    }

    int n_secondHalf = (sizeof(secondHalf) / sizeof(uint16_t));
    for (int i = 0; i < n_secondHalf; i++) {
        value[index] = secondHalf[i];
        index++;
    }

HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)value, 89, DAC_ALIGN_12B_R);
HAL_TIM_Base_Start(&htim4);

 

7 REPLIES 7
LCE
Principal

1) Is the DMA in CIRCULAR mode?

2) you probably need to add the hold value to the end of the array

 

And please post source code with the "</>" button to make it more readable. And you can still edit your original post.

 

PS / edit: and the DAC can't draw stuff, so it's not "a straight line", it's a DC voltage.  

TDK
Guru

> HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)value, 89, DAC_ALIGN_12B_R);

You're sending more than 89 values. Shouldn't this be

HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)value, index, DAC_ALIGN_12B_R);

 

Is the value array of sufficient size? Needs to be 64 + 50 + 71 samples long, of type uint16_t. Your code does not include its definition.

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

Yes, I have tried using

HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)value, index, DAC_ALIGN_12B_R);

but there is no result. That's why I tried using a fixed number. Is there something wrong with my code? Because when I add a watch for index, it shows 'not evaluated'. I'm a bit confused, please help.

@TDK 

Show the full code. Attach it as a 7zip file if needed. No reason why index should not work. Make sure you're using circular DMA.

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

@LCE 

 

1. yes, DMA in circular mode

2. Can you give an example of what you mean? I'm a beginner and can't quite picture it. I just want to learn. Thank you for your feedback, I have already changed the output display.

macam1
Associate II

and this is my result if i run this code

Screenshot 2024-09-07 092921.png

and this is my code

 

#include "main.h"
//ADC_FINAL
//MAPP //OUTPUT = DAC //INPUT = ADC
#define ARRAY_SIZE 4
uint32_t AD_RES[ARRAY_SIZE];
uint32_t input_start = 0;
uint32_t input_end = 4095;
uint32_t output_start = 75; //92
uint32_t output_end = 3900; //3750
uint32_t newArray= 2048; //nilai yang diatur
uint32_t input;
uint32_t hasil;
uint32_t i;
uint32_t y;
uint32_t x;

ADC_HandleTypeDef hadc1;

DAC_HandleTypeDef hdac;
DMA_HandleTypeDef hdma_dac1;

TIM_HandleTypeDef htim4;

//ADC
uint32_t i = 0;
ADC_ChannelConfTypeDef ADC_CH_Cfg = {0};
uint32_t ADC_Channels[4] = {ADC_CHANNEL_1, ADC_CHANNEL_7, ADC_CHANNEL_8, ADC_CHANNEL_9};

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_DAC_Init(void);
static void MX_ADC1_Init(void);
static void MX_TIM4_Init(void);

//64+71 =135
uint16_t value[180] = {};
uint16_t hold_samples = 50; 
uint16_t firstHalf[64] = 
	{
		2100, 2149, 2250, 2350, 2450, 2549, 2646, 2742, 2837, 2929, 3020, 3108, 3193, 3275, 3355,
		3431, 3504, 3574, 3639, 3701, 3759, 3812, 3861, 3906, 3946, 3982, 4013, 4039, 4060, 4076,
		4087, 4094, 4095, 4091, 4082, 4069, 4050, 4026, 3998, 3965, 3927, 3884, 3837, 3786, 3730,
		3671, 3607, 3539, 3468, 3394, 3316, 3235, 3151, 3064, 2975, 2883, 2790, 2695, 2598, 2500,
		2400, 2300, 2199, 2098
		
	}; //first value
uint16_t secondHalf[71] = 
	{
		1997, 1896, 1795, 1695, 1595, 1497,1305, 1212, 1120, 1031, 944, 860, 779, 701, 627,
		556, 488, 424, 365, 309, 258, 211, 168, 130, 97, 69, 45, 26, 13,4, 0, 1, 8, 19, 35, 56, 82, 
		113, 149, 200, 283, 336, 394, 456, 521, 591, 664, 740, 820, 902, 987, 1075, 1166, 1258, 
		1353, 1449, 1546, 1645, 1745, 1845, 1947, 1965, 1990, 2010, 2022, 2047
	}; // second value

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_GPIO_Init();
  MX_DMA_Init();
  MX_DAC_Init();
  MX_ADC1_Init();
  MX_TIM4_Init();
	
  /* USER CODE BEGIN 2 */
//	for (uint32_t i = 124; i < 200; i++)
//	{
//		Value[i] = newArray;
//	}	
//	HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)Value, 131, DAC_ALIGN_12B_R); //115
//  HAL_TIM_Base_Start(&htim4);
	
				//keterangan untuk hasil sinyal:
				//1.  i = 124; i < 124; = 95
				//2.  i = 124; i < 140; =101
				//3. i = 124; i < 200;  =131
				
		uint16_t totalSize = (sizeof(firstHalf) / sizeof(uint16_t)) + hold_samples + (sizeof(secondHalf) / sizeof(uint16_t));	
		uint16_t index = 0;
    uint16_t n_firstHalf = (sizeof(firstHalf) / sizeof(uint16_t));
		
    for (int i = 0; i < n_firstHalf; i++) {
        value[index] = firstHalf[i];
        index++;
    }

    for (int i = 0; i < hold_samples; i++) {
        value[index] = 2048;
        index++;
    }

    int n_secondHalf = (sizeof(secondHalf) / sizeof(uint16_t));
    for (int i = 0; i < n_secondHalf; i++) {
        value[index] = secondHalf[i];
        index++;
    }				
	
	//HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)value, index, DAC_ALIGN_12B_R);
	HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)value, index, DAC_ALIGN_12B_R);
	HAL_TIM_Base_Start(&htim4);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  { 			
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		for(i=0; i<4; i++)
    {
			//ADC
			ADC_CH_Cfg.Channel = ADC_Channels[i];       
      HAL_ADC_ConfigChannel(&hadc1, &ADC_CH_Cfg); 
      HAL_ADC_Start(&hadc1);
      if(HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY) == HAL_OK) 
				{
          AD_RES[i] = HAL_ADC_GetValue(&hadc1);  
        }
         HAL_ADC_Stop(&hadc1); 
    }
			input = AD_RES[0]; 
			hasil = output_start + ((output_end - output_start)*(input - input_start))/(input_end - input_start);			
			__HAL_TIM_SET_AUTORELOAD(&htim4, hasil);
			__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_1, hasil); 
			y = hasil;
			x = input;
 }
  /* 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
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 80;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  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_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief ADC1 Initialization Function
  *  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_DIV4;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.ScanConvMode = DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_1;
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */

  /* USER CODE END ADC1_Init 2 */

}

/**
  * @brief DAC Initialization Function
  *  None
  * @retval None
  */
static void MX_DAC_Init(void)
{

  /* USER CODE BEGIN DAC_Init 0 */

  /* USER CODE END DAC_Init 0 */

  DAC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN DAC_Init 1 */

  /* USER CODE END DAC_Init 1 */

  /** DAC Initialization
  */
  hdac.Instance = DAC;
  if (HAL_DAC_Init(&hdac) != HAL_OK)
  {
    Error_Handler();
  }

  /** DAC channel OUT1 config
  */
  sConfig.DAC_Trigger = DAC_TRIGGER_T4_TRGO;
  sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
  if (HAL_DAC_ConfigChannel(&hdac, &sConfig, DAC_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN DAC_Init 2 */

  /* USER CODE END DAC_Init 2 */

}

/**
  * @brief TIM4 Initialization Function
  *  None
  * @retval None
  */
static void MX_TIM4_Init(void)
{

  /* USER CODE BEGIN TIM4_Init 0 */

  /* USER CODE END TIM4_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM4_Init 1 */

  /* USER CODE END TIM4_Init 1 */
  htim4.Instance = TIM4;
  htim4.Init.Prescaler = 10;
  htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim4.Init.Period = 65535;
  htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM4_Init 2 */

  /* USER CODE END TIM4_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_Stream5_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn);

}

/**
  * @brief GPIO Initialization Function
  *  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_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_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 */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  *   file: pointer to the source file name
  *   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 */

 

 

yeah, there are my code @TDK 

 

LCE
Principal

The way you fill the array right now is:

firstHalf, hold_samples, secondHalf

From what you have shown what you want you might want to add hold_samples to the end.

But first you have to make the DMA run continously.