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


相关文章
|
4月前
STM32Cubemx PWM驱动加湿器模拟火山喷发效果
STM32Cubemx PWM驱动加湿器模拟火山喷发效果
63 14
|
4月前
STM32Cubemx PWM驱动SG90舵机
STM32Cubemx PWM驱动SG90舵机
144 13
|
4月前
STM32CubeMX PWM
STM32CubeMX PWM
57 9
|
3月前
|
编解码 算法
掌握PWM:STM32F103实现PWM控制直流电机小风扇
PWM,即脉冲宽度调制(Pulse Width Modulation),是一种广泛应用于电子和电机控制领域的信号编码方法。PWM的核心思想是通过改变数字信号的脉冲宽度来模拟模拟信号的幅度变化,从而达到控制输出功率的目的。
420 0
|
5月前
|
存储 数据安全/隐私保护 芯片
【STM32】详解嵌入式中FLASH闪存的特性和代码示例
【STM32】详解嵌入式中FLASH闪存的特性和代码示例
【STM32】详解独立看门狗的本质和使用步骤&代码
【STM32】详解独立看门狗的本质和使用步骤&代码
|
5月前
使用STM32F103标准库实现定时器控制LED点亮和关闭
通过这篇博客,我们学习了如何使用STM32F103标准库,通过定时器来控制LED的点亮和关闭。我们配置了定时器中断,并在中断处理函数中实现了LED状态的切换。这是一个基础且实用的例子,适合初学者了解STM32定时器和中断的使用。 希望这篇博客对你有所帮助。如果有任何问题或建议,欢迎在评论区留言。
378 2
|
4月前
stm32f407探索者开发板(十七)——串口寄存器库函数配置方法
stm32f407探索者开发板(十七)——串口寄存器库函数配置方法
625 0
|
5月前
|
IDE 开发工具
使用STM32F103标准库实现自定义键盘
通过本文,我们学习了如何使用STM32F103标准库实现一个简单的自定义键盘。我们首先初始化了GPIO引脚,然后实现了一个扫描函数来检测按键状态。这个项目不仅能够帮助我们理解STM32的GPIO配置和按键扫描原理,还可以作为进一步学习中断处理和低功耗设计的基础。希望本文对你有所帮助,祝你在嵌入式开发的道路上不断进步!
480 4
|
5月前
|
传感器
【经典案例】STM32F407使用HAL库配置I2C详解
STM32F407是一个强大的微控制器,广泛应用于嵌入式系统中。在许多应用中,我们需要使用I2C总线来与传感器、EEPROM、显示屏等外设进行通信。本文将详细介绍如何使用STM32 HAL库来配置和使用I2C接口。
605 2