首先我们要解决
硬件问题:
舵机工作电压是多少? 一般供电范围是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,&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,&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,&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->DR); //读取接收到的数据
if(r!=0x0D&&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: