【STM32】HAL库 PWM驱动舵机

本文介绍了如何使用STM32的HAL库进行舵机控制,包括设置定时器中断以生成20ms时基脉冲,以及通过PWM驱动LED实现LED灯的呼吸效果。详细讲解了舵机控制原理和代码实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

系列文章目录

【STM32】HAL库 新建MDK工程
【STM32】HAL库 定时器中断
【STM32】HAL库 PWM驱动LED呼吸灯


前言

使用按键控制PWM,驱动舵机

一、SG90舵机

舵机的控制一般需要一个20ms左右的时基脉冲,脉冲的高电平部分一般为0.5ms~2.5ms范围内的角度控制脉冲部分。以180度角度伺服为例,那么对应的控制关系是这样的:

高电平时间旋转角度
0.5ms0度
1.0ms45度
1.5ms90度
2.0ms135度
2.5ms180度

计数器自动重装值为ARR,0.5ms的计数次数为h。
ARR/ 20 = h / 0.5,h = ARR /40。

1ms旋转45度,1ms的计数次数为0.5ms的两倍 ,求系数k
ARR/ 40 * 2 = 45 *k + ARR/40,k = ARR/ 1800。

1ms的占空比为1 / 20
CCR = 占空比 * ARR = ARR / 20 = ARR/ 40 * 2
CCR = 角度 * ARR / 1800 + ARR /40

二、STM32CubeMX设置

舵机的控制一般需要一个20ms左右的时基脉冲,所以一个周期的时间为20ms,50Hz。舵机的死区时间为5us,所以重装载值需要小于4000 = 20ms/5us。重装载值取2000,50Hz = 72MHz / 分频系数/2000 ,分频系数为720。

在这里插入图片描述

按键引脚

三、代码

  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
   if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) == GPIO_PIN_RESET)
	 {
			HAL_Delay(20);
			while (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == GPIO_PIN_RESET);
			HAL_Delay(20);
		 	Angle += 30;
			if (Angle > 180)
			{
				Angle = 0;
			}
	 }
	 __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2,Angle  * (htim2.Init.Period + 1) / 1800 + (htim2.Init.Period + 1) / 40);
  }
  /* USER CODE END 3 */
### 使用 STM32 HAL 驱动舵机 舵机是一种位置伺服的回转角执行机构,广泛应用于机器人技术和其他自动化控制系统中。STM32 单片机可以通过 PWM 波形来控制舵机的角度。PWM 的占空比决定了舵机转动到的具体角度。 #### 初始化定时器用于生成 PWM 信号 为了生成适合舵机工作的 PWM 信号,需要先配置一个定时器通道作为 PWM 输出。这里以 `TIM2` 和 `TIM_CHANNEL_1`为例: ```c // 定义全局变量 htim2 来保存定时器句柄 TIM_HandleTypeDef htim2; void MX_TIM2_Init(void) { __HAL_RCC_TIM2_CLK_ENABLE(); // 设置定时器基本参数 TIM_OC_InitTypeDef sConfigOC; htim2.Instance = TIM2; htim2.Init.Prescaler = 79; // 假设系统时钟为80MHz,则此预分频值使得计数频率为1MHz (即周期为1us) htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 20000 - 1; // 设定自动重装载寄存器ARR=20ms-1(因为是从0开始),对应于标准50Hz刷新率 htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_PWM_Init(&htim2) != HAL_OK){ Error_Handler(); } sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 1500; // 初始脉冲宽度设置为中心位置(通常代表90度) sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK){ Error_Handler(); } } ``` 这段代码完成了对 `TIM2` 的初始化工作,并设置了 PWM 模式下的初始输出状态[^3]。 #### 修改比较值调整舵机角度 要改变舵机的位置,只需更改相应定时器通道的捕获/比较寄存器中的数值即可。例如,如果想要让舵机转向某个特定角度,可以根据该角度对应的微秒级高电平时间计算出合适的比较值并更新之: ```c uint16_t angle_to_compare(uint8_t angle) { uint16_t compare_value; float pulse_width_us = ((float)(angle + 45)) / 90 * 1000 + 1000; // 将角度转换成相应的脉宽(us),范围大约在1ms~2ms之间变化 compare_value = (uint16_t)((pulse_width_us / 20000) * 20000); // 计算得到匹配的CCR值 return compare_value; } void set_servo_angle(uint8_t angle) { __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, angle_to_compare(angle)); } ``` 在这个例子中,函数 `set_servo_angle()` 接受一个表示目标角度的整型参数,并调用辅助函数 `angle_to_compare()` 进行必要的单位换算后设定新的 CCR 寄存器值,从而达到调节舵机的目的。 #### 主程序循环部分 最后,在主程序里可以简单地调用上面定义好的接口来进行操作: ```c int main(void) { /* Reset of all peripherals, Initializes the Flash interface and Systick. */ HAL_Init(); SystemClock_Config(); // 配置系统时钟 MX_GPIO_Init(); // GPIO初始化 MX_TIM2_Init(); // 初始化定时器2 while (1) { set_servo_angle(0); // 移动至最左边 HAL_Delay(1000); set_servo_angle(90); // 中间位置 HAL_Delay(1000); set_servo_angle(180); // 最右边 HAL_Delay(1000); } } ``` 这样就完成了一个简单的测试流程,使舵机能按照指定的时间间隔依次移动到三个不同的方向上。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

youuuuvvu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值