STM32:PWM驱动舵机(内含:1.接线原理图/实物图+2.代码部分+3.补充知识部分)

简介: STM32:PWM驱动舵机(内含:1.接线原理图/实物图+2.代码部分+3.补充知识部分)

1.接线原理图:


39348fd4bd3643af8cf740280533b92d.png


注:红线接5V,不是3.3V(电压小,带不动)

实物图:


6e6b4819343344b4a85f1abfb0154cbc.png


PWM驱动舵机:按下按键,舵机输出轴角度变化,OLED显示该角度。

2.代码部分如下:

主函数代码部分:


cb41ea72ec3d45548e637b6c06f5e03d.png

#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Servo.h"
#include "Key.h"
uint8_t KeyNum;
float Angle;
int main(void)
{
OLED_Init();
Servo_Init();
Key_Init();
OLED_ShowString(1,1,"Angle:");
Servo_SetAngle(90);//通过自定义函数设置角度
//注:以下分别设置也可完成任务,但是比较麻烦不方便。
// PWM_SetCompare2(500);//舵机为0° 示波器观察结果:f=50Hz,高电平时间=0.5ms
// PWM_SetCompare2(2500);//舵机自动转为180° 示波器观察结果:f=50Hz,高电平时间=2.5ms
// PWM_SetCompare2(1500);//舵机自动转为90° 示波器观察结果:f=50Hz,高电平时间=1.5ms
while(1)
{
KeyNum=Key_GetNum();
if(KeyNum==1)
{
Angle+=30;
if(Angle>180)
{
Angle=0;
}
}Servo_SetAngle(Angle);
OLED_ShowNum(1,7,Angle,3);
}
}

PWM.c部分:


af4ae0e09de740b4a23b29a3e867e4b4.png

6472af5188b34a1ebbdd19bd71199963.png

9a6aa22a953e4b0facc03ed497ad7025.png


86e377d9215c4ebeaddea900fb59eb01.png


#include "stm32f10x.h" // Device header


//操作思路可参考:(图PWM基本结构)


//1.RCC开启时钟,把TIM外设和GPIO外设的时钟打开。


//2.初始化时基单元,选择内部时钟-----使用的还是TIM2,所以直接复制粘贴内部时钟部分代码


//3.初始化输出比较单元,(重要函数TIM_OC1Init)包括CCR的值,输出比较模式,极性选择,输出使能。(结构体)


//4.初始化GPIO,(第三步的输出比较模式的值需要GPIO输出展示)TIM_OC1Init,GPIO口初始化为复用推挽输出


//5.运行控制,启动计数器。


void PWM_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//第一步:开启APB1时钟,因为TIM2是APB1总线的外设
TIM_InternalClockConfig(TIM2);//第二步:选择时基单元的内部时钟
//第二步:配置时基单元----TIM_TimeBaseInit的第二个参数是结构体,配置结构体
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
//TIM_CKD_DIV1,1分频,不分配;TIM_CKD_DIV2,2分频;TIM_CKD_DIV4,4分频----要求不高时,随意选择
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
//TIM_CounterMode_Up向上计数;TIM_CounterMode_Down向下计数;TIM_CounterMode_CenterAligned1等为中央对齐
TIM_TimeBaseInitStructure.TIM_Period=20000-1;//ARR的值
TIM_TimeBaseInitStructure.TIM_Prescaler=72-1;//PSC的值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//高级定时器用到,通用定时器选0
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);//结构体
//第三步:初始化输出比较单元,总共有四个,需要哪个通道(GPIO口),初始化哪个函数
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);//给结构体赋初始值
//TIM_OCInitStructure.TIM_OCIdleState=;//高级定时器才会用到
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//设置输出比较模式
//TIM_OCInitStructure.TIM_OCNIdleState=;//高级定时器
//TIM_OCInitStructure.TIM_OCNPolarity=;//高级定时器才会用到
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//设置输出比较极性,TIM_OCPolarity_High有效电平为高电平
//TIM_OCInitStructure.TIM_OutputNState=;//高级定时器才会用到
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//设置输出使能,TIM_OutputState_Enable使能
TIM_OCInitStructure.TIM_Pulse=0;//设置CCR寄存器的值。
TIM_OC2Init(TIM2, &TIM_OCInitStructure);//此处使用PWM输出第二通道。
//第四步:初始化输出PWM的GPIO(舵机使用通道2,GPIO_PIN_1)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//选择复用推挽输出,使外设控制引脚(参照复用开漏/推挽输出图)
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;//使用通道2,改为GPIO_Pin_1
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//第五步:启动定时器
TIM_Cmd(TIM2,ENABLE);
//ARR,PSC,CCR是用来计算频率,占空比和分辨率的(参考参数计算)
//计算时,频率,占空比,分辨率是自己设置的,是已知的,因此,变为解方程组,
//(频率为1/20ms=50Hz,占空比50%,分辨率1%)
//PSC+1=72,ARR+1=20K;CCR=500~2500--->CCR=0.5ms~2.5ms
}
//舵机使用2通道设置CCR
//更改占空比需要用的PWM_SetCompare2
void PWM_SetCompare2(uint16_t Compare)
{
TIM_SetCompare1(TIM2,Compare);
}
//补充:
//PWM频率: Freq = CK_PSC / (PSC + 1) / (ARR + 1)
//PWM占空比: Duty = CCR / (ARR + 1)
//PWM分辨率: Reso = 1 / (ARR + 1)
//PSC+1=72; ARR+1=20KHz CCR=500--->0.5ms CCR=2500--->2.5ms

PWM.h部分:

ae971180e9cc49af996083252c9414fa.png

#ifndef __PWM_H
#define __PWM_H
void PWM_Init(void);
void PWM_SetCompare2(uint16_t Compare);
#endif

舵机控制角度 Servo.c部分:

5a31ae2695b9490280938a589ef9c03d.png

#include "stm32f10x.h" // Device header
#include "PWM.h"
void Servo_Init(void)
{
PWM_Init();
}
void Servo_SetAngle(float Angle)//舵机设置角度
{
PWM_SetCompare2(Angle/180*2000+500);//输入值/180是占用总角度的比例,然后*2000是总比例+500是起始偏转角
}

舵机控制角度Servo.h部分:

a919191291b741fcb6741dc7f91f6a7e.png

#ifndef __SERVO_H
#define __SERVO_H
void Servo_SetAngle(float Angle);
void Servo_Init(void);
#endif


3.补充部分:


//补充:

//PWM频率:    Freq = CK_PSC / (PSC + 1) / (ARR + 1)

//PWM占空比:    Duty = CCR / (ARR + 1)

//PWM分辨率:    Reso = 1 / (ARR + 1)

//PSC+1=72;      ARR+1=20KHz       CCR=500--->0.5ms     CCR=2500--->2.5ms


相关文章
|
15天前
【STM32】基于HAL库的360度编码器、摇杆代码编写
【STM32】基于HAL库的360度编码器、摇杆代码编写
|
13天前
|
缓存 网络协议 算法
[蓝桥杯嵌入式]hal库 stm32 PWM的使用(随时修改占空比,随时修改频率)
[蓝桥杯嵌入式]hal库 stm32 PWM的使用(随时修改占空比,随时修改频率)
|
15天前
|
传感器
STM32循迹小车原理介绍和代码示例
STM32循迹小车原理介绍和代码示例
|
15天前
【STM32】通过RTThread驱动W25QXXX
【STM32】通过RTThread驱动W25QXXX
|
15天前
stm32f4外设学习篇(代码集合)(三)
stm32f4外设学习篇(代码集合)
|
15天前
stm32f4外设学习篇(代码集合)(二)
stm32f4外设学习篇(代码集合)
|
15天前
|
芯片
stm32f4外设学习篇(代码集合)(一)
stm32f4外设学习篇(代码集合)