如何产生两个频率可变、相位差恒定的信号?

问题描述 投票:0回答:1

我有一块 STM32F411 Black Pill 板,我正在尝试用它来模拟旋转编码器。

我想生成两个 PWM 信号,它们始终异相 90 度,但频率可变。我尝试了How can I have VariableFrequency PWM with STM32?使用两个定时器的方法,但由于某种原因失败了。第二个通道 (TIM2) 最终处于恒定低电平。

我能够以恒定频率获得输出,但尝试更改它对 TIM2 通道不起作用。

配置

  • 系统时钟(HCLK):100 MHz
  • 两个定时器都以此频率运行(APB1 和 APB2)

TIM1

  • 通道 1:PWM 生成 CH1
  • 通道 2:输出比较无输出
  • 预分频器:999,自动重载寄存器:999(产生 100 Hz PWM)
  • 输出比较模式:匹配时有效电平

TIM2

  • 从机模式:触发模式
  • 触发源:ITR0
  • 通道 1:PWM 生成 CH1
  • 预分频器:999,自动重载寄存器:999(产生 100 Hz PWM)

代码
main.c

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();
  MX_TIM2_Init();
  /* USER CODE BEGIN 2 */
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
  HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_2);
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    TIM1->ARR = 999;
    TIM2->ARR = 999;
    TIM1->CCR1 = 499;
    TIM1->CCR2 = 249;
    TIM2->CCR1 = 499;

    HAL_GPIO_WritePin(LED_BUILTIN_GPIO_Port, LED_BUILTIN_Pin, GPIO_PIN_SET);
    HAL_Delay(1000);

    TIM1->ARR = 499;
    TIM2->ARR = 499;
    TIM1->CCR1 = 249;
    TIM1->CCR2 = 124;
    TIM2->CCR1 = 249;

    HAL_GPIO_WritePin(LED_BUILTIN_GPIO_Port, LED_BUILTIN_Pin, GPIO_PIN_RESET);
    HAL_Delay(1000);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

预期截图

逻辑分析仪截图

蓝色为TIM1 CH1,橙色为TIM2 CH1

编辑1:缩小问题范围

作为调试步骤,我尝试通过改变

TIM1->CCR2
来改变相移。这是行不通的。该图处于恒定相位差,如下图所示。

编辑 1 代码
main.c

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();
  MX_TIM2_Init();
  /* USER CODE BEGIN 2 */
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
  HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_2);
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);

  HAL_GPIO_WritePin(LED_BUILTIN_GPIO_Port, LED_BUILTIN_Pin, GPIO_PIN_SET);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    for (size_t i = 249; i < 999; i++)
    {
      TIM1->CCR2 = i;
      HAL_Delay(10);
    }


    HAL_GPIO_WritePin(LED_BUILTIN_GPIO_Port, LED_BUILTIN_Pin, GPIO_PIN_RESET);
    HAL_Delay(100);
    HAL_GPIO_WritePin(LED_BUILTIN_GPIO_Port, LED_BUILTIN_Pin, GPIO_PIN_SET);
    
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

编辑 1 来自逻辑分析仪的图表

蓝色为TIM1 CH1,橙色为TIM2 CH1

编辑2:西蒙的方法

尝试仅更改 PWM 信号的频率。这不行。

编辑2代码
main.c

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();
  MX_TIM2_Init();
  /* USER CODE BEGIN 2 */
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
  HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_2);
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);

  HAL_GPIO_WritePin(LED_BUILTIN_GPIO_Port, LED_BUILTIN_Pin, GPIO_PIN_SET);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    TIM1->ARR = 999;
    TIM2->ARR = 999;

    HAL_GPIO_TogglePin(LED_BUILTIN_GPIO_Port, LED_BUILTIN_Pin);
    HAL_Delay(1000);

    TIM1->ARR = 499;
    TIM2->ARR = 499;

    HAL_GPIO_TogglePin(LED_BUILTIN_GPIO_Port, LED_BUILTIN_Pin);
    HAL_Delay(1000);
    
    
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

编辑2逻辑分析仪截图

c timer stm32 stm32f4 pwm
1个回答
0
投票

首先尝试不使用从机模式来触发第二个定时器。我喜欢这样做的方法:

  • 使用相同的 PSC ARR 和 CRR 值初始化两个计时器
  • 将其中一个定时器的 CNT 寄存器设置为 ARR/4。
  • 启动两个计时器。

根据生成的频率,异步启动导致的延迟可能很重要,也可能不那么重要。

如果发现触发定时器的延迟是一个问题,只需使用相同的触发源开始生成来触发两个定时器即可。

© www.soinside.com 2019 - 2024. All rights reserved.