当前位置:   article > 正文

STM32F407控制舵机_stm32f4控制舵机经典代码

stm32f4控制舵机经典代码

STM32F407控制舵机运行

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

黑红白,黑线接GND,红线接VCC,信号线接白色线(有的舵机线的颜色不同,例如褐色红色橘色,仅颜色不同接法还如上述)
[黑红白,黑线接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); //使能定时器
		
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

程序内将定时器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);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

下面看主程序。

#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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

注意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)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

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

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

请勿转载
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/281065
推荐阅读
相关标签
  

闽ICP备14008679号