如何修复我的代码,使 STM32 Nucleo 板上的 LED 与 1 秒、50% 占空比 PWM 同步闪烁?
How do I fix my code to make an LED blink on an STM32 Nucleo Board in sync with 1sec, 50% duty cycle PWM?
我的板子是NUCLEO-H743ZI2
我将 TIM4、CH2 配置为 PWM,这样 TIM4 输出应为半秒高电平和半秒低电平。这是 block.ioc 时钟和引脚配置
我自动生成代码并尝试添加我自己的代码以使用 PWM 的 H/L 切换 LED。我想做的是:
if(timer_4 == HIGH) LED_state = !LED_state
这是实际代码:
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_ETH_Init();
MX_USART3_UART_Init();
MX_USB_OTG_FS_PCD_Init();
MX_DAC1_Init();
MX_TIM3_Init();
MX_TIM4_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_2);
uint16_t timer_init_val = __HAL_TIM_GET_COUNTER(&htim4);
uint16_t timer_poll;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
timer_poll = __HAL_TIM_GET_COUNTER(&htim4);
if(timer_poll - timer_init_val >= 500) {
HAL_GPIO_TogglePin(GPIOB,LD1_Pin);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
我知道这很可能行不通。实际上。我很困惑,因为将 >=500 替换为 <=100 实际上让它看起来像是在工作......但 LED 只是以看似随机的间隔闪烁。
我试图测试 !timer{..}(计时器达到 0)是否可以切换 LED,但我的方法 none 似乎有效。
我是不是对定时器有什么误解?我错过了什么非常明显的东西吗?使用 1 秒 PWM
使 LED 闪烁似乎并不困难
您所写的内容执行以下操作:
- 对于 500 次计时器计数,什么都不做
- 之后反复打开和关闭 LED(快于肉眼可见的速度),直到计时器结束
- 当计时器结束时(65.536 秒?)转到 (1)。
你不能用 GPIO_TogglePin 真正做到这一点,因为你会在计数器的相同值期间多次调用它。
试试这样的东西:
if (((timer_poll - timer_init_val) % 1000) < 500)
{
HAL_GPIO_WritePin(GPIOB, LD1_Pin, 0);
}
else
{
HAL_GPIO_WritePin(GPIOB, LD1_Pin, 1);
}
但是当计时器结束时,这仍然不是完全干净的。要解决这个问题,您可以将计时器的周期调整为序列周期的倍数。
我的板子是NUCLEO-H743ZI2
我将 TIM4、CH2 配置为 PWM,这样 TIM4 输出应为半秒高电平和半秒低电平。这是 block.ioc 时钟和引脚配置
我自动生成代码并尝试添加我自己的代码以使用 PWM 的 H/L 切换 LED。我想做的是:
if(timer_4 == HIGH) LED_state = !LED_state
这是实际代码:
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_ETH_Init();
MX_USART3_UART_Init();
MX_USB_OTG_FS_PCD_Init();
MX_DAC1_Init();
MX_TIM3_Init();
MX_TIM4_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_2);
uint16_t timer_init_val = __HAL_TIM_GET_COUNTER(&htim4);
uint16_t timer_poll;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
timer_poll = __HAL_TIM_GET_COUNTER(&htim4);
if(timer_poll - timer_init_val >= 500) {
HAL_GPIO_TogglePin(GPIOB,LD1_Pin);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
我知道这很可能行不通。实际上。我很困惑,因为将 >=500 替换为 <=100 实际上让它看起来像是在工作......但 LED 只是以看似随机的间隔闪烁。 我试图测试 !timer{..}(计时器达到 0)是否可以切换 LED,但我的方法 none 似乎有效。
我是不是对定时器有什么误解?我错过了什么非常明显的东西吗?使用 1 秒 PWM
使 LED 闪烁似乎并不困难您所写的内容执行以下操作:
- 对于 500 次计时器计数,什么都不做
- 之后反复打开和关闭 LED(快于肉眼可见的速度),直到计时器结束
- 当计时器结束时(65.536 秒?)转到 (1)。
你不能用 GPIO_TogglePin 真正做到这一点,因为你会在计数器的相同值期间多次调用它。
试试这样的东西:
if (((timer_poll - timer_init_val) % 1000) < 500)
{
HAL_GPIO_WritePin(GPIOB, LD1_Pin, 0);
}
else
{
HAL_GPIO_WritePin(GPIOB, LD1_Pin, 1);
}
但是当计时器结束时,这仍然不是完全干净的。要解决这个问题,您可以将计时器的周期调整为序列周期的倍数。