欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

STM32F407控制舵机

程序员文章站 2024-02-22 18:27:52
...

STM32F407控制舵机运行

	使用STM32F407控制舵机,首先来看下舵机图片

STM32F407控制舵机
[黑红白,黑线接GND,红线接VCC,信号线接白色线(有的舵机线的颜色不同,例如褐色红色橘色,仅颜色不同接法还如上述)]
舵机需要信号的周期为20ms,即频率为50Hz。
接下来正式操作:
步骤一:STM32F4程序(本次程序的PWM信号产生的周期频率由定时器TIM14通道1产生(TIM14_CH1),想要使用其它定时器也没关系下面会讲到)

#include "pwm.h"

void TIM14_CH1_PWM_Init(u16 per,u16 psc)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_OCInitTypeDef TIM_OCInitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14,ENABLE);//使能TIM14时钟
	
	GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14);//管脚复用
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF; //复用输出模式
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//管脚设置
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;//速度为100M
	GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出
	GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉
	GPIO_Init(GPIOF,&GPIO_InitStructure); //初始化结构体
	
	
	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(TIM14,&TIM_TimeBaseInitStructure);	
	
	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;
	TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
	TIM_OC1Init(TIM14,&TIM_OCInitStructure); //输出比较通道1初始化
	
	TIM_OC1PreloadConfig(TIM14,TIM_OCPreload_Enable); //使能TIMx在 CCR1 上的预装载寄存器
	TIM_ARRPreloadConfig(TIM14,ENABLE);//使能预装载寄存器
	
	TIM_Cmd(TIM14,ENABLE); //使能定时器
		
}

程序内将定时器14的初始化放在函数内方便在主程序内调用。
注意1:舵机需要PWM信号为500微妙到2500微秒,500对应舵机-90度,2500对应舵机+90度,那么1500微秒就是舵机的0度了(按我的理解不同型号舵机也是这样的数据控制,并且试验验证过)。

注意2:程序内的这条语句会影响到实验结果:
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;
你可以选择等号后面写TIM_OCPolarity_Low,或者TIM_OCPolarity_High。
按照我程序里为TIM_OCPolarity_Low,那么主程序内赋给PWM函数的值如下
TIM_SetCompare1(TIM14,500); //舵机-90度 delay_ms(2000);//延时2秒,好观察现象 TIM_SetCompare1(TIM14,1500); //舵机0度 delay_ms(2000); TIM_SetCompare1(TIM14,2500); //舵机+90度 delay_ms(2000);
如果等号后面写TIM_OCPolarity_High,
即TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;
那么主程序内赋给PWM函数的值如下

		TIM_SetCompare1(TIM14,19500); 
		delay_ms(2000);
		TIM_SetCompare1(TIM14,18500); 
		delay_ms(2000);
		TIM_SetCompare1(TIM14,17500); 
		delay_ms(2000);

下面看主程序。

#include "system.h"
#include "SysTick.h"
#include "pwm.h"


int main()
{
	SysTick_Init(168);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //中断优先级分组 分2组
	TIM14_CH1_PWM_Init(20000-1,84-1); //50Hz
	while(1)
	{
		TIM_SetCompare1(TIM14,500);
		delay_ms(2000);
		TIM_SetCompare1(TIM14,1500); 
		delay_ms(2000);
		TIM_SetCompare1(TIM14,2500); 
		delay_ms(2000);			
	}
}

注意1:定时器14产生的PWM信号的周期即频率由:
TIM14_CH1_PWM_Init(20000-1,84-1); //50Hz来产生
先讲第二个参数,84-1,为84分频,(假如你是72-1,那就是72分频的意思),我的TIM14在APB1总线上,而我设置APB1总线上即为82MHz,(你要移植到你的程序里,参考你自己的PWM程序的分频数即可),82MHz分频82,即为1MHz,即为1微秒,那么第一个参数20000-1即为1微秒乘以20000的意思,那么就是20ms即50Hz了,那么PWM的周期频率就可以了(注意:大家必须调到20ms,50Hz)。
你需要通过之前的学习,和F4的rcc头文件来确定不同定时器挂接在哪个总线上,例如TIM14在我F4的stm32f4xx_rcc.h文件里如下:

#define RCC_APB1Periph_TIM2              ((uint32_t)0x00000001)
#define RCC_APB1Periph_TIM3              ((uint32_t)0x00000002)
#define RCC_APB1Periph_TIM4              ((uint32_t)0x00000004)
#define RCC_APB1Periph_TIM5              ((uint32_t)0x00000008)
#define RCC_APB1Periph_TIM6              ((uint32_t)0x00000010)
#define RCC_APB1Periph_TIM7              ((uint32_t)0x00000020)
#define RCC_APB1Periph_TIM12             ((uint32_t)0x00000040)
#define RCC_APB1Periph_TIM13             ((uint32_t)0x00000080)
#define RCC_APB1Periph_TIM14             ((uint32_t)0x00000100)
#define RCC_APB1Periph_WWDG              ((uint32_t)0x00000800)
#define RCC_APB1Periph_SPI2              ((uint32_t)0x00004000)
#define RCC_APB1Periph_SPI3              ((uint32_t)0x00008000)
#define RCC_APB1Periph_USART2            ((uint32_t)0x00020000)
#define RCC_APB1Periph_USART3            ((uint32_t)0x00040000)
#define RCC_APB1Periph_UART4             ((uint32_t)0x00080000)
#define RCC_APB1Periph_UART5             ((uint32_t)0x00100000)
#define RCC_APB1Periph_I2C1              ((uint32_t)0x00200000)
#define RCC_APB1Periph_I2C2              ((uint32_t)0x00400000)
#define RCC_APB1Periph_I2C3              ((uint32_t)0x00800000)
#define RCC_APB1Periph_CAN1              ((uint32_t)0x02000000)
#define RCC_APB1Periph_CAN2              ((uint32_t)0x04000000)
#define RCC_APB1Periph_PWR               ((uint32_t)0x10000000)
#define RCC_APB1Periph_DAC               ((uint32_t)0x20000000)
#define RCC_APB1Periph_UART7             ((uint32_t)0x40000000)
#define RCC_APB1Periph_UART8             ((uint32_t)0x80000000)
#define IS_RCC_APB1_PERIPH(PERIPH) ((((PERIPH) & 0x09013600) == 0x00) && ((PERIPH) != 0x00))
/**
  * @}
  */ 
  
/** @defgroup RCC_APB2_Peripherals 
  * @{
  */ 
#define RCC_APB2Periph_TIM1              ((uint32_t)0x00000001)
#define RCC_APB2Periph_TIM8              ((uint32_t)0x00000002)
#define RCC_APB2Periph_USART1            ((uint32_t)0x00000010)
#define RCC_APB2Periph_USART6            ((uint32_t)0x00000020)
#define RCC_APB2Periph_ADC               ((uint32_t)0x00000100)
#define RCC_APB2Periph_ADC1              ((uint32_t)0x00000100)
#define RCC_APB2Periph_ADC2              ((uint32_t)0x00000200)
#define RCC_APB2Periph_ADC3              ((uint32_t)0x00000400)
#define RCC_APB2Periph_SDIO              ((uint32_t)0x00000800)
#define RCC_APB2Periph_SPI1              ((uint32_t)0x00001000)
#define RCC_APB2Periph_SPI4              ((uint32_t)0x00002000)
#define RCC_APB2Periph_SYSCFG            ((uint32_t)0x00004000)
#define RCC_APB2Periph_TIM9              ((uint32_t)0x00010000)
#define RCC_APB2Periph_TIM10             ((uint32_t)0x00020000)
#define RCC_APB2Periph_TIM11             ((uint32_t)0x00040000)
#define RCC_APB2Periph_SPI5              ((uint32_t)0x00100000)
#define RCC_APB2Periph_SPI6              ((uint32_t)0x00200000)
#define RCC_APB2Periph_SAI1              ((uint32_t)0x00400000)
#define RCC_APB2Periph_LTDC              ((uint32_t)0x04000000)

可以看到TIM14在APB1总线上,如果你想用其它定时器如TIM2到TIM13,你就可以不用注意时钟频率问题,因为它们都是和TIM14一样在AHB1上的,你只需要在代码内将有TIM14的地方改成TIMx你想要的那个定时器。当然多个定时器一起用也行,只要配置起来就OK。STM32F407控制舵机

TIM14映射在PF9上,我们将PF9连接在舵机的数据线上(白色线),给STM32F4开发板烧录程序,就可以按照自己想法操作舵机了。按照主程序里的参数设置500,即-90度,1500,即0度,2500,即+90度。那么舵机就会90度的间断转动。头文件该添加函数名的不要忘记。

请勿转载