cancel
Showing results for 
Search instead for 
Did you mean: 

How to handle the uncontrollable CNT value, and how to connect it with CCR?

macam1
Associate III

I am a beginner using the Nucleo-F334R8 with Keil and STM32CubeMX.

I want to read ADC data with DAC. The ADC is from a potentiometer, and I will read the DAC using an oscilloscope. I am using the program below so that when I run it, it will generate the frequency I need. I am using mapping to create the frequency range I want, with the frequency limits being from 10 Hz to 350 Hz, and I have achieved this according to the potentiometer setting I adjust. The biggest problem in my program is that when I run it and observe the CNT value, it counts up to the ARR value, and the oscilloscope displays a sinusoidal signal. However, when I adjust the signal back and forth, the signal disappears and only shows a straight line, with the CNT value becoming "VERY LARGE, EVEN INTO MILLIONS." I have to press the reset button on the Nucleo to display it again, but SOMETIMES IT DOESN'T WORK, and this is not a time/div issue since I have changed it, but rather a problem with CNT and ARR that I cannot control directly from the program. I have tried many things.

Because of this, I tried using a 32-bit ARR, but the CNT value became even larger and did not display the sinusoidal signal on the oscilloscope at all. When using a 16-bit ARR, the CNT displays stable values (which I think should produce a signal), but no signal appears on the oscilloscope, no matter how small. Then, my colleague suggested using CCR and preload, but I don't know where to place them. Since my colleague has left, I cannot ask him. Has anyone in this community experienced something similar? Please help me.

#include "main.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 */


//DAC
#define BUFFER_SIZE 225;
uint32_t Wave_LUT[225] = {
		2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048,2048, 2048, 2048, 2048, 2048,
		2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048,2048, 2048, 2048, 2048, 2048, 
		2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048,2048, 2048, 2048, 2048, 2048,
	  2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048,2048, 2048, 2048, 2048, 2048,
		2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048,2048, 2048, 2048, 2048, 2048, 
		2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048,2048, 2048, 2048, 2048, 2048,
    2048, 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, 1997, 1896, 1795, 1695, 1595, 1497, 1400, 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, 189,
    234, 283, 336, 394, 456, 521, 591, 664, 740, 820, 902, 987, 1075, 1166, 1258,
    1353, 1449, 1546, 1645, 1745, 1845, 1946, 1950, 1965, 1975, 1990, 1999, 2010,2022, 2047
};
#define ARRAY_SIZE 4
uint32_t AD_RES[ARRAY_SIZE];

//MAPP
//OUTPUT = DAC
//INPUT = ADC
uint32_t input_start = 0;
uint32_t input_end = 4095;
uint32_t output_start = 9;
uint32_t output_end = 375;
uint32_t input;
uint32_t i;
uint32_t hasil;
uint32_t y;
uint32_t x;

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
ADC_HandleTypeDef hadc1;

DAC_HandleTypeDef hdac1;
DMA_HandleTypeDef hdma_dac1_ch1;

TIM_HandleTypeDef htim2;

UART_HandleTypeDef huart2;

/* USER CODE BEGIN PV */

//ADC
uint32_t i = 0;
ADC_ChannelConfTypeDef ADC_CH_Cfg = {0};
uint32_t ADC_Channels[4] = {ADC_CHANNEL_6, ADC_CHANNEL_7, ADC_CHANNEL_8, ADC_CHANNEL_9};
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_ADC1_Init(void);
static void MX_TIM2_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_DAC1_Init(void);
/* USER CODE BEGIN PFP */

/* 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_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();
  MX_TIM2_Init();
  MX_USART2_UART_Init();
  MX_DAC1_Init();
  /* USER CODE BEGIN 2 */

		
	//ADC
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3);
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_4);
	ADC_ChannelConfTypeDef ADC_CH_Cfg = {0};
	ADC_CH_Cfg.Rank =  ADC_REGULAR_RANK_1;
  ADC_CH_Cfg.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
	
	
	
	//DAC
	
	HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_1, Wave_LUT, 225, DAC_ALIGN_12B_R);
	HAL_TIM_Base_Start(&htim2);
	
	
  /* 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(&htim2, hasil);
			__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, hasil); 
			y = hasil;
			x = input;
	}
		
	HAL_Delay(500);
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {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;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  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_DIV16;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC12;
  PeriphClkInit.Adc12ClockSelection = RCC_ADC12PLLCLK_DIV1;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != 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_MultiModeTypeDef multimode = {0};
  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC1_Init 1 */

  /* USER CODE END ADC1_Init 1 */

  /** Common config
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.ScanConvMode = ADC_SCAN_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;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure the ADC multi-mode
  */
  multimode.Mode = ADC_MODE_INDEPENDENT;
  if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_6;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */

  /* USER CODE END ADC1_Init 2 */

}

/**
  * @brief DAC1 Initialization Function
  * @PAram None
  * @retval None
  */
static void MX_DAC1_Init(void)
{

  /* USER CODE BEGIN DAC1_Init 0 */

  /* USER CODE END DAC1_Init 0 */

  DAC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN DAC1_Init 1 */

  /* USER CODE END DAC1_Init 1 */

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

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

  /* USER CODE END DAC1_Init 2 */

}

/**
  * @brief TIM2 Initialization Function
  * @PAram None
  * @retval None
  */
static void MX_TIM2_Init(void)
{

  /* USER CODE BEGIN TIM2_Init 0 */

  /* USER CODE END TIM2_Init 0 */

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

  /* USER CODE BEGIN TIM2_Init 1 */

  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 10;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 0;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */
	
//    // Konfigurasi master
//    sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
//    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
//    HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig);
	
  /* USER CODE END TIM2_Init 2 */
  HAL_TIM_MspPostInit(&htim2);

}
1 ACCEPTED SOLUTION

Accepted Solutions

 


> htim2.Init.Period = 0;

Set this to nonzero.

 

> htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
Set this to ENABLE.

JW

 

View solution in original post

4 REPLIES 4

 


> htim2.Init.Period = 0;

Set this to nonzero.

 

> htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
Set this to ENABLE.

JW

 

Thank you for your help, I really didn't expect it to be that simple. Would you kindly explain why the CNT doesn't reach millions just by adjusting the period and auto preload reload? Please, I've been thinking about it for 2 days but couldn't figure out what causes it. Would you be willing to explain? Thank you.:folded_hands:

Without ARR preload, for example if ARR was 30 and you set ARR to 10 at the moment when CNT is 20, CNT does not reach the new ARR and reload, but counts up to the maximum for given timer, which in case of 32-bit timer is cca 4E9.

Preload means, that the new ARR is not active until an Update event, i.e. until CNT has reached the *previous* ARR.

JW

 

 

hank you so much for your help, I understand now. Wishing you continued success.