ST意法半导体
直播中

王鹏

8年用户 1417经验值
私信 关注
[问答]

如何验证PWM波形的某些时钟频率是否正确呢

大家好,我只是想测试和验证 PWM 波形的某些时钟频率是否正确。我使用 CubeMX 生成了一些代码,将 MCU 的时钟频率设置为 72 mHz,我正在尝试实现 20 kHz 的 PWM 频率。我启用了定时器 1,通道 1 作为输出通道(多路复用到我板上的引脚 E9)。我还确保调用 HAL_tiM_PWM_Start,这样我的计时器就会真正开始计数,从而生成波形。目前我将脉冲设置为一个应该产生 100% 占空比的值,但无论我设置什么占空比,我都不会得到任何波形。
将引脚连接到逻辑分析仪表明没有任何东西被捕获并且引脚一直保持低电平。我通过将引脚连接到带有 LED 的面包板来确认这一点,当我单步执行我的代码时,没有任何东西会驱动 LED 打开。我在 Keil 中的步骤中注意到端口 E 的 IDR 寄存器将切换位 9,因此 PWM 必须以某种方式影响引脚状态,但 ODR 和 BSRR 寄存器始终保持为 0。附上我的代码:
  • 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_TIM1_Init();
  •   /* USER CODE BEGIN 2 */
  •   /* USER CODE END 2 */
  •   /* Infinite loop */
  •   /* USER CODE BEGIN WHILE */
  •   HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);
  •   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
  •   */
  •   __HAL_RCC_PWR_CLK_ENABLE();
  •   __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
  •   /** 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.PLL.PLLState = RCC_PLL_ON;
  •   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  •   RCC_OscInitStruct.PLL.PLLM = 8;
  •   RCC_OscInitStruct.PLL.PLLN = 144;
  •   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 TIM1 Initialization Function
  •   * @param None
  •   * @retval None
  •   */
  • static void MX_TIM1_Init(void)
  • {
  •   /* USER CODE BEGIN TIM1_Init 0 */
  •   /* USER CODE END TIM1_Init 0 */
  •   TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  •   TIM_MasterConfigTypeDef sMasterConfig = {0};
  •   TIM_OC_InitTypeDef sConfigOC = {0};
  •   TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
  •   /* USER CODE BEGIN TIM1_Init 1 */
  •   /* USER CODE END TIM1_Init 1 */
  •   htim1.Instance = TIM1;
  •   htim1.Init.Prescaler = 35;
  •   htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  •   htim1.Init.Period = 99;
  •   htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  •   htim1.Init.RepetitionCounter = 0;
  •   htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  •   if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
  •   {
  •     Error_Handler();
  •   }
  •   sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  •   if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
  •   {
  •     Error_Handler();
  •   }
  •   if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
  •   {
  •     Error_Handler();
  •   }
  •   sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  •   sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  •   if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  •   {
  •     Error_Handler();
  •   }
  •   sConfigOC.OCMode = TIM_OCMODE_PWM1;
  •   sConfigOC.Pulse = 99;
  •   sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  •   sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
  •   sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  •   sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
  •   sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
  •   if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  •   {
  •     Error_Handler();
  •   }
  •   sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
  •   sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
  •   sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
  •   sBreakDeadTimeConfig.DeadTime = 0;
  •   sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
  •   sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
  •   sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
  •   if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
  •   {
  •     Error_Handler();
  •   }
  •   /* USER CODE BEGIN TIM1_Init 2 */
  •   /* USER CODE END TIM1_Init 2 */
  •   HAL_TIM_MspPostInit(&htim1);
  • }
  • /**
  •   * @brief GPIO Initialization Function
  •   * @param None
  •   * @retval None
  •   */
  • static void MX_GPIO_Init(void)
  • {
  •   /* GPIO Ports Clock Enable */
  •   __HAL_RCC_GPIOH_CLK_ENABLE();
  •   __HAL_RCC_GPIOE_CLK_ENABLE();
  • }

回帖(1)

王莹

2022-12-15 10:26:40
确保该引脚确实如您所想的那样连接。如果是 Nucleo 或 Disco 板,请检查跳线/焊桥。作为测试,将给定的引脚设置为输出并在 GPIO_ODR 中切换它,也许在调试器中,以查看对 LED 的影响。
对于定时器操作,读取并检查(或发布)TIM 和相关 GPIO 寄存器内容。确保 GPIOx_MODER 设置为 AF,并且在 GPIOx_AFR 中为给定的引脚选择了正确的 AF;由于 Timer1 是一个高级定时器,请确保设置了 TIMx_BDTR.MOE。
定时器不会以任何方式影响 GPIO_ODR/GPIO_BSRR。OTOH,GPIO_IDR 反映了引脚的实际状态,不管它是如何驱动的(除非在 GPIOx_MODER 中设置为模拟)。
我不使用多维数据集。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分