基于STM32F103C6T6HAL库控制SG90舵机

本文介绍了舵机的工作原理,重点讲解了STM32F103C6T6如何通过配置RCC时钟和定时器PWM来驱动舵机。在程序中,使用HAL库启动定时器并设置不同的占空比,实现舵机0度到180度的角度控制。通过调整定时器的CCR1寄存器值,实现了舵机角度的切换。
摘要由CSDN通过智能技术生成

材料:

(1)stm32f103c6t6

(2)舵机

一、组装

4e67a2ef782c4b9e9b7b99a837ffa998.jpeg

8c3cf9a8d65b4e7ebf595215337ff72c.jpeg

舵机原理:

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

0.5ms------------0度;
1.0ms-----------45度;
1.5ms----------90度;
2.0ms-----------135度;
2.5ms-----------180度;

5c6952ce0bff49cd8fca6e524bbf551d.jpeg

 

二、主要程序

1、STM32CUBEMX配置如下: 

(1) 配置RCC时钟:

 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA54K554Gv5Luj5biI,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA54K554Gv5Luj5biI,size_20,color_FFFFFF,t_70,g_se,x_16

(2) 时钟的配置:

30e50d8d720b4a01abec655fcce938f3.png 

(3) 配置定时器PWM

 8aa08c5af9ff4e7bb53354101b851d89.png

三、程序 

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();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
  HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);//定时器初始化
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	
  while (1){
		
      TIM1->CCR1=250; //20ms有0.5ms高脉冲
      HAL_Delay(1000);//延时一秒

	  TIM1->CCR1=50; //20ms有2.5ms高脉冲
      HAL_Delay(1000);//延时一秒
		
 
    /* USER CODE END WHILE */

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

 

 

 

 

 

 

  • 3
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是使用HAL库的PID算法控制舵机角度的示例代码,仅供参考: ```c #include "stm32f4xx_hal.h" #define SERVO_PWM_TIM TIM3 #define SERVO_PWM_CHANNEL TIM_CHANNEL_1 #define SERVO_MAX_ANGLE 180.0f #define SERVO_MIN_ANGLE 0.0f #define SERVO_MAX_DUTY_CYCLE 2000.0f #define SERVO_MIN_DUTY_CYCLE 1000.0f #define PID_KP 1.0f #define PID_KI 0.01f #define PID_KD 0.001f float servo_angle = 0.0f; float servo_setpoint = 90.0f; float servo_error = 0.0f; float servo_last_error = 0.0f; float servo_integral = 0.0f; float servo_derivative = 0.0f; float servo_pid_output = 0.0f; float servo_duty_cycle = 0.0f; TIM_HandleTypeDef htim_servo_pwm; void MX_TIM3_Init(void) { TIM_MasterConfigTypeDef sMasterConfig; TIM_OC_InitTypeDef sConfigOC; htim_servo_pwm.Instance = SERVO_PWM_TIM; htim_servo_pwm.Init.Prescaler = 0; htim_servo_pwm.Init.CounterMode = TIM_COUNTERMODE_UP; htim_servo_pwm.Init.Period = 20000; htim_servo_pwm.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_PWM_Init(&htim_servo_pwm); sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; HAL_TIMEx_MasterConfigSynchronization(&htim_servo_pwm, &sMasterConfig); sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 1500; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(&htim_servo_pwm, &sConfigOC, SERVO_PWM_CHANNEL); HAL_TIM_PWM_Start(&htim_servo_pwm, SERVO_PWM_CHANNEL); } void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) { if(htim == &htim_servo_pwm) { __HAL_TIM_SET_COMPARE(&htim_servo_pwm, SERVO_PWM_CHANNEL, servo_duty_cycle); } } float pid_controller(float setpoint, float input_value) { servo_error = setpoint - input_value; servo_integral += servo_error; servo_derivative = servo_error - servo_last_error; servo_pid_output = PID_KP * servo_error + PID_KI * servo_integral + PID_KD * servo_derivative; if(servo_pid_output > SERVO_MAX_DUTY_CYCLE) { servo_pid_output = SERVO_MAX_DUTY_CYCLE; } else if(servo_pid_output < SERVO_MIN_DUTY_CYCLE) { servo_pid_output = SERVO_MIN_DUTY_CYCLE; } servo_last_error = servo_error; return servo_pid_output; } void set_servo_angle(float angle) { if(angle > SERVO_MAX_ANGLE) { angle = SERVO_MAX_ANGLE; } else if(angle < SERVO_MIN_ANGLE) { angle = SERVO_MIN_ANGLE; } servo_duty_cycle = ((angle - SERVO_MIN_ANGLE) / (SERVO_MAX_ANGLE - SERVO_MIN_ANGLE)) * (SERVO_MAX_DUTY_CYCLE - SERVO_MIN_DUTY_CYCLE) + SERVO_MIN_DUTY_CYCLE; } int main(void) { HAL_Init(); MX_TIM3_Init(); while (1) { servo_angle = /* 读取舵机当前角度 */; servo_setpoint = /* 读取目标角度 */; set_servo_angle(pid_controller(servo_setpoint, servo_angle)); } } ``` 需要注意的是,这是一个简单的示例代码,实际使用时需要根据具体的舵机型号和控制要求进行适当调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值