stm32基础学习——PWM的基本使用
stm32基础学习——PWM的使用
所有可用资源可在我的gitee仓库查找,点击即可前往。
一、前言
本篇文章继续介绍stm32的一些基本使用,文章主要是介绍PWM的相关使用,PWM的相关使用过程步骤简单来说主要分为以下:配置输出引脚->配置定时器->配置PWM->运行定时器,而本篇文章主要分为两部分:1. 用PWM来设置LED的不同亮度;2. 用PWM来控制舵机。使用废话不多说,咱们开始。
二、准备工作
硬件:
- stm32F103C8T6开发板
- ST-LINK V2下载器一个
- 3~5V的LED灯(发光二极管)一个
- SG90舵机一个
- 杜邦线若干+面包板
软件:
- Keil 5(没安装可以点击进入我的另一篇博客有详细下载及配置教程)
其他(需要自行下载,点击前往,下载template文件即可):
- stm32工程模板(由于新建模板比较麻烦,初学还是找个工程模板吧,方便点)
电路图1:
电路图2:
电路图2这里注意一个问题,正常来说舵机最好是由外部电源独立供电的(同时共地),用stm32供电可能电流不够无法工作,但是我身边也没有独立电源,所以最终我是把舵机正负极接的ST-Link调试器上的正负极,也就是下图这里。
三、编写代码
在配置的过程需要注意的是,不同的引脚对应着不同的TIM通道,配置需要一一对应,不然程序没达到预期的效果还不知道错在哪里,部分引脚的TIM通道如下图所示,这里我使用的是TIM2的通道2(TIM2_CH2),对应的PA2引脚,所以引脚部分我就配置PA2就行。

3.1 PWM控制LED
这里的示例是使用50%的占空比也就是50%的亮度点亮LED灯,其中占空比表示高电平持续时间在整个周期中的比例。
/*
目的:使用PWM控制LED的亮度
占空比= (CRR + 1) / (ARR + 1)
平均电压 = 占空比 × 电源电压
平均功率 = (占空比)² × 最大功率
所以一半的占空比 就是最高亮度的一半
过程:配置引脚->配置定时器->配置PWM模式->运行定时器
*/
#include "stm32f10x.h"
int main(void)
{
// 配置LED的GPIO输出
//这里使用的是TIM2_CH(通道2),对应引脚PA2
//具体服用对应表可自行查看使用
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置定时器 1kHz 占空比50%
//打开定时器时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// 配置定时器参数
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频 不分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //技术模式 向上计数
TIM_TimeBaseStructure.TIM_Period = 1000 - 1; // ARR
TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1; // PSC
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
// 配置PWM模式
TIM_OCInitTypeDef TIM_OCStruct;
TIM_OCStruct.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCStruct.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCStruct.TIM_Pulse = 500 - 1; // CRR
TIM_OC3Init(TIM2, &TIM_OCStruct);
// 开始运行定时器
TIM_Cmd(TIM2, ENABLE);
while(1){
};
}
烧录并下载,可以看到LED以一半的亮度亮起来了,然后为了方便对比,可以把50%的占空比改成10%,也就是把CRR改成100-1,即TIM_OCStruct.TIM_Pulse = 100 - 1,重新编译下载后能看到亮度较之前要微弱很多。而至于为什么50%、的占空比时,我们人眼看到LED是一直亮着的?这是因为人5眼的视觉暂留效应,当频率足够快时,我们人眼看到的就是一直亮着的。
3.2 PWM控制舵机
本篇文章继续介绍stm32的一些基本使用,文章主要是介绍舵机的相关使用,舵机的使用步骤大概分为以下几个:时钟初始化->输出引脚初始化->定时器初始化->输出通道初始化,而我们要怎么控制舵机的旋转角度呢?这里主要跟PSC、ARR和CCR这三个参数有关。下面主要简单介绍这三个参数,然后介绍如何设置舵机的角度,最后是舵机使用小案列。
(1)相关参数的介绍
首先是PSC(预分频器),作用是对系统时钟进行分频,得到定时器实际的工作频率,通俗来说就是决定计数器数多快。其中我们要了解的公式是定时器时钟 = 系统时钟 ÷ (PSC + 1)。
然后是ARR(自动重装载值寄存器),其值代表着计数的周期,例如本次的示例项目使用的是20ms为周期的舵机,那么我就要设置好ARR的值与之对应。
最后是CCR(捕获/比较寄存器),其值能控制每一周期的高电平持续时间,我们最终也是设置该值来控制舵机的旋转角度的。
有了以上了解后这里我们举几个例子,尝试去设置舵机的旋转角度为0°、90°和180°时,上面的三个参数该设置为多少合适,同样我使用的是周期为20ms,最大旋转角度为180°的SG90舵机,然后使用的板子型号是STM32F103C8T6,时钟频率为72MHz。


然后接下来是计算CRR的值

(2)示例代码
#include "stm32f10x.h"
#include "delay.h"
// 舵机角度定义
#define ANGLE_0 0
#define ANGLE_90 90
#define ANGLE_180 180
// 初始化函数(与之前相同)
void TIM2_PWM_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Period = 1999; // ARR = 2000-1 (20ms)
TIM_TimeBaseStructure.TIM_Prescaler = 719; // PSC = 720-1 (100kHz)
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_Pulse = 150; // 初始90°(CRR=150)
TIM_OC3Init(TIM2, &TIM_OCInitStructure);
TIM_Cmd(TIM2, ENABLE);
}
// 设置舵机角度(简化版)
void Set_Servo_Angle(uint8_t angle)
{
uint16_t ccr_value;
// 角度转CCR值:0°=50, 90°=150, 180°=250
if(angle == ANGLE_0)
ccr_value = 50;
else if(angle == ANGLE_90)
ccr_value = 150;
else if(angle == ANGLE_180)
ccr_value = 250;
else
ccr_value = 150; // 默认90°
TIM2->CCR3 = ccr_value; // 设置CCR寄存器
}
// 主函数:0°→90°→180°→90°→0°循环
int main(void)
{
SystemInit();
Delay_Init();
TIM2_PWM_Init();
// 初始位置:90°
Set_Servo_Angle(ANGLE_90);
Delay(1000);
while(1)
{
// 0度,停留1秒
Set_Servo_Angle(ANGLE_0);
Delay(1000);
// 90度,停留1秒
Set_Servo_Angle(ANGLE_90);
Delay(1000);
// 180度,停留1秒
Set_Servo_Angle(ANGLE_180);
Delay(1000);
// 回到90度,停留1秒
Set_Servo_Angle(ANGLE_90);
Delay(1000);
}
}
烧录下载并运行,可看到舵机在0°,90°,180°循环旋转。
四、结束语
好了,stm32的基本使用——定时器的使用先介绍到这,后续有时间我继续更新这方面的文章,敬请期待,我是“风行男孩”,咱有缘再见!(码字不易,转载请标明出处!若是文章有帮助,点个赞留个痕迹即可。)
更多推荐



所有评论(0)