STM32串口控制舵机

首先我们要解决

硬件问题:

舵机工作电压是多少? 一般供电范围是4.8V-6.0V电压,我这种舵机3V、5V不影响使用,个人觉得不要太大就行了。 舵机的三根线代表什么意思? 红色的是电源正极,黑色的是电源负极,白色的是信号线。有些舵机线是红棕橘三色,分别对应红黑白。 STM32开发板可以直接连接舵机吗? 有人可以直接连接,没有出现什么问题,但是有人可能会出现单片机复位的情况,可能是舵机瞬间驱动电流太大,使供电电压下降,引起单片机复位,我试验一下确实是电压太低了,舵机一开,电压就开始下降,从4点多降到3点多,最好还是分成两个电源,舵机一个,STM32一个,然后再把他们共地,单片机电压就会非常稳定,不会再复位。 我通过一个稳压模块给舵机供电 舵机发烫可能是什么问题? 接线接反了,或者是舵机受到阻碍了。

舵机代码

我的代码总体框架是:

***PWM(主要)***

***LCD显示(次要)***

***串口改变占空比***

1、 PWM 简单的配置就不说了。

/*******************************************************************************
* 函 数 名         : TIM3_CH1_PWM_Init
* 函数功能		   : TIM3通道1 PWM初始化函数
* 输    入         : per:重装载值
					 psc:分频系数
* 输    出         : 无
*******************************************************************************/
void TIM3_CH1_PWM_Init(u16 per,u16 psc)
{<!-- -->
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_OCInitTypeDef TIM_OCInitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	
	/* 开启时钟 */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
//	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	
	/*  配置GPIO的模式和IO口 */
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
	GPIO_Init(GPIOA,&amp;GPIO_InitStructure);
	
//	GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE);//改变指定管脚的映射	
	
	TIM_TimeBaseInitStructure.TIM_Period=per;   //自动装载值
	TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //分频系数
	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //设置向上计数模式
	TIM_TimeBaseInit(TIM3,&amp;TIM_TimeBaseInitStructure);	
	
	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse = 10;							//确定占空比,这个值决定了有效电平的时间
	TIM_OC1Init(TIM3,&amp;TIM_OCInitStructure); //输出比较通道1初始化
	
	TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable); //使能TIMx在 CCR1 上的预装载寄存器
	TIM_ARRPreloadConfig(TIM3,ENABLE);//使能预装载寄存器
	
	TIM_Cmd(TIM3,ENABLE); //使能定时器
		
}

接下来是设置自动装载值和分频系数,因为舵机的控制一般需要一个20ms左右的时基脉冲,我们需要一个20ms的PWM周期。

TIM3_CH1_PWM_Init(200-1,7200-1);	

分频系数7200-1是什么意思? 我们用的是TIM3,TIM3挂载在APB1时钟上。 在这里插入图片描述 默认情况下,系统和APB2都是72MHz,APB1是36MHz。 在这里插入图片描述 如果预分频系数不为1,那么定时器的时钟频率被设为与其相连的APB总线频率的2倍,所以TIM3的时钟频率应该算72MHz。那为什么要减1呢,因为它默认加1。1MHz的频率,脉冲周期就是1us,分频7200-1就是100us。 自动装载值200-1是什么意思? 就是数到199就清零了,重新开始了,0~199就可以看做一个周期啦。这样一个周期就是200*100us=20ms。

TIM_SetCompare1(TIM3, num);

这个函数用来设置占空比,只要计数比num小,就会产生有效的高电平。(由我们的配置决定的。) 在这里插入图片描述 在这里插入图片描述

2、 LCD显示(次要)

完成初始化后

LCD_ShowNum(50,50,num,3,16);

显示占空比达到的值

3、 串口改变占空比

/*******************************************************************************
* 函 数 名         : USART1_IRQHandler
* 函数功能		   : USART1中断函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/ 
void USART1_IRQHandler(void)                	//串口1中断服务程序
{<!-- -->
	u8 r;
	static char pwm[4];
	static int i=0;
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断
	{<!-- -->
		r =USART_ReceiveData(USART1);//(USART1-&gt;DR);	//读取接收到的数据
		if(r!=0x0D&amp;&amp;r!=0x0A)
		{<!-- -->
			pwm[i]=r;
			i++;
		}
		else
		{<!-- -->
			i=0;
			num=(atoi(pwm));
			TIM_SetCompare1(TIM3, num);
		}
		USART_SendData(USART1,r);
		while(USART_GetFlagStatus(USART1,USART_FLAG_TC) != SET);
	} 
	USART_ClearFlag(USART1,USART_FLAG_TC);
}

总的来说就是把ASCII码一个个接住储存在数组中,直到检测到回车键和换行键,把数组中的ASCII码变成一个数字,赋给num,从而改变占空比。

实验

舵机最大最小可以转多少度? 真的通过占空比改角度吗? 在这里插入图片描述 这是理论上高电平的周期可以实现舵机的角度,我们来试验一下。 一个脉冲周期是100us,那么5个就是500us=0.5ms。 在这里插入图片描述 我们在串口助手发送05,要记得加上回车,转换成16进制是这样的 在这里插入图片描述 舵机转成这样 在这里插入图片描述 在逻辑分析仪上观察到的PWM是这样的 在这里插入图片描述 周期是20ms,频率是50Hz,脉冲宽度500us,这就是我们所输出的PWM。 现在我们串口发送25, 舵机转成这样 在这里插入图片描述 在逻辑分析仪上观察到的PWM是这样的 在这里插入图片描述 尴尬了,我这个是270度的 在这里插入图片描述 市面有90-180-270-360度,觉得道理应该差不多的。 下面是main.c: 在这里插入图片描述