STM32 CubeMx LL PWM波控制舵机

5 篇文章 2 订阅
4 篇文章 0 订阅

主控芯片:STM32F103C8T6
舵机:MG996R
关于舵机的工作原理请看其他博主
1. RCC时钟配置
在这里插入图片描述

2. CubeMx定时器配置(注意这里只提供关键设置,关于RCC,SYS配置过程都一样):
主控频率72M,定时器预分频设置为72-1,自动重装值为20000-1(这里可以根据自己需要自行修改),只要保证输出的PWM波是50Hz即可,为什么是50Hz请看舵机工作原理。
直接上手写了,下面就是舵机角度占空比的转换关系(二元一次方程组求出角度和系数的关系)
在这里插入图片描述

在这里插入图片描述3. 定义一个PA10口用于模拟PWM波
在这里插入图片描述4. 生成LL库
在这里插入图片描述5. 接下来就是生成的代码了,这里只放关键代码
(1)tim.c 生成的代码不能直接用,需要添加相关使能来是定时器通过工作;

void MX_TIM1_Init(void)
{

  /* USER CODE BEGIN TIM1_Init 0 */

  /* USER CODE END TIM1_Init 0 */

  LL_TIM_InitTypeDef TIM_InitStruct = {0};
  LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0};
  LL_TIM_BDTR_InitTypeDef TIM_BDTRInitStruct = {0};

  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
  /* Peripheral clock enable */
  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM1);

  /* USER CODE BEGIN TIM1_Init 1 */

  /* USER CODE END TIM1_Init 1 */
  TIM_InitStruct.Prescaler = 71;
  TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
  TIM_InitStruct.Autoreload = 19999;
  TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
  TIM_InitStruct.RepetitionCounter = 0;
  LL_TIM_Init(TIM1, &TIM_InitStruct);
  LL_TIM_EnableARRPreload(TIM1);
  LL_TIM_SetClockSource(TIM1, LL_TIM_CLOCKSOURCE_INTERNAL);
  LL_TIM_OC_EnablePreload(TIM1, LL_TIM_CHANNEL_CH4);
  TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
  TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_DISABLE;
  TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_DISABLE;
  TIM_OC_InitStruct.CompareValue = 0;
  TIM_OC_InitStruct.OCPolarity = LL_TIM_OCPOLARITY_HIGH;
  TIM_OC_InitStruct.OCIdleState = LL_TIM_OCIDLESTATE_LOW;
  TIM_OC_InitStruct.OCNIdleState = LL_TIM_OCIDLESTATE_LOW;
  LL_TIM_OC_Init(TIM1, LL_TIM_CHANNEL_CH4, &TIM_OC_InitStruct);
  LL_TIM_OC_DisableFast(TIM1, LL_TIM_CHANNEL_CH4);
  LL_TIM_SetTriggerOutput(TIM1, LL_TIM_TRGO_RESET);
  LL_TIM_DisableMasterSlaveMode(TIM1);
  TIM_BDTRInitStruct.OSSRState = LL_TIM_OSSR_DISABLE;
  TIM_BDTRInitStruct.OSSIState = LL_TIM_OSSI_DISABLE;
  TIM_BDTRInitStruct.LockLevel = LL_TIM_LOCKLEVEL_OFF;
  TIM_BDTRInitStruct.DeadTime = 0;
  TIM_BDTRInitStruct.BreakState = LL_TIM_BREAK_DISABLE;
  TIM_BDTRInitStruct.BreakPolarity = LL_TIM_BREAK_POLARITY_HIGH;
  TIM_BDTRInitStruct.AutomaticOutput = LL_TIM_AUTOMATICOUTPUT_DISABLE;
  LL_TIM_BDTR_Init(TIM1, &TIM_BDTRInitStruct);
  /* USER CODE BEGIN TIM1_Init 2 */

  /* USER CODE END TIM1_Init 2 */
  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA);
    /**TIM1 GPIO Configuration
    PA11     ------> TIM1_CH4
    */
  GPIO_InitStruct.Pin = LL_GPIO_PIN_11;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

}

/* USER CODE BEGIN 1 */
void PWM_Iint(void)  //该函数是初始化使能,需要再生成的代码后面加上
{
	LL_TIM_CC_EnableChannel(TIM1,LL_TIM_CHANNEL_CH4);
	LL_TIM_EnableCounter(TIM1);
	LL_TIM_EnableAllOutputs(TIM1);
}

void Servo_Control(uint16_t angle) //该函数是用来控制舵机的角度的,其实也就是占空比之间的转换,我这里自动重装值是20000-1
{
	float temp;
	temp = 100*((1.0 / 9.0) * angle + 5.0);//寄存器值 = 1/9 * 角度 + 5
	LL_TIM_OC_SetCompareCH4(TIM1, (uint16_t)temp);//将角度值写入比较寄存器
}

(2)main主函数里面,首先调用PWM_Iint(void) ,使能相关寄存器;下面用了三种方法来控制PWM输出,角度控制,占空比控制,模拟PWM控制(暂时无法自己控制旋转速度,希望指正)
a. 下面的代码是实现舵机正反向旋转90度的代码,

	/*角度控制*/
			for(i=10;i<90;i++)
			{
				Servo_Control(i);
				LL_mDelay(10); //用来控制旋转速度
			}
			for(i=90;i>10;i--)
			{
				Servo_Control(i);
				LL_mDelay(10);	//用来控制旋转速度
			}

b. 以下方法可以稳定控制舵机旋转,也就是旋转精度,同样实现正反正反90度旋转

	/*占空比控制*/
				for(i=500;i<1500;i++)
				{
					LL_TIM_OC_SetCompareCH4(TIM1, (uint16_t)i);//将角度值写入比较寄存器
					LL_mDelay(1);
				}
				for(i=1500;i>500;i--)
				{
					LL_TIM_OC_SetCompareCH4(TIM1, (uint16_t)i);//将角度值写入比较寄存器
					LL_mDelay(1);	
				}

c. 以下方法是通过任意IO模拟PWM占空比变换的波形,但是该方法暂时无法实现舵机转速的控制,只用于学习PWM原理

/*模拟PWM PA10*/
				for(i=500;i<1500;i++)
				{
					LL_GPIO_SetOutputPin(PWM_Servo_GPIO_Port,PWM_Servo_Pin);
					delay_us(i);
					LL_GPIO_ResetOutputPin(PWM_Servo_GPIO_Port,PWM_Servo_Pin);	
					delay_us((20000-i));					
				}
				for(i=1500;i>500;i--)
				{			
					LL_GPIO_SetOutputPin(PWM_Servo_GPIO_Port,PWM_Servo_Pin);
					delay_us(i);
					LL_GPIO_ResetOutputPin(PWM_Servo_GPIO_Port,PWM_Servo_Pin);	
					delay_us(20000-i);					
				}
				void delay_us(uint16_t time) //这里的延时函数一并给出
				{    
				   uint16_t i=0;  
				   while(time--)
				   {
				      i=10;  
				      while(i--) ;    
				   }
				}						

在这里插入图片描述
测试舵机之前可以用示波器观察波形运行时间,占空比变化,便于理解。关于舵机的工作原理有时间再补存。
代码链接:STM32 CubeMx LL PWM波控制舵机

  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Flash*强

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

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

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

打赏作者

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

抵扣说明:

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

余额充值