基于STM32F103ZET6库函数PWM输出实验

  • PWM 简介
  • 硬件设计
  • 软件设计

使 用 TIM3 的通道 2,把通道 2 重映射到 PB5,产生 PWM 来控制 DS0 的亮度。

PWM 简介

简单一点,就是对脉冲宽度的控制。

STM32 的定时器除了 TIM6 和 7。其他的定时器都可以用来产生 PWM 输出。其中高级定 时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出。而通用定时器也能同时产生多达 4 路的 PWM 输出,这样,STM32 最多可以同时产生 30 路 PWM 输出!这里我们仅利用 TIM3 的 CH2 产生一路 PWM 输出。如果要产生多路输出,大家可以根据我们的代码稍作修改即可。

通过库函数来配置该 功能的步骤。 PWM 相关的函数设置在库函数文件 stm32f10x_tim.h 和 stm32f10x_tim.c 文件中。
1.开启 TIM3 时钟以及复用功能时钟,配置 PB5 为复用输出。
要使用 TIM3,我们必须先开启 TIM3 的时钟。 这里我们还要配置 PB5 为复用输出,这是因为 TIM3_CH2 通道将重映射到 PB5 上,此时,PB5 属于复用功能输出。库函数使能 TIM3 时钟的方法是:

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定时器 3 时钟

库函数设置 AFIO 时钟的方法是:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);  //复用时钟使能

这里简单列出 GPIO 初始化的一行代码即可:

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出

2.设置 TIM3_CH2 重映射到 PB5 上。
因为 TIM3_CH2默认是接在 PA7上的,所以我们需要设置 TIM3_REMAP为部分重映射(通 过 AFIO_MAPR 配置),让 TIM3_CH2 重映射到 PB5 上面。在库函数函数里面设置重映射的函 数是:

void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);

STM32 重映射只能重映射到特定的端口。第一个 入口参数可以理解为设置重映射的类型,比如 TIM3 部分重映射入口参数为 GPIO_PartialRemap_TIM3,这 点可以顾名思义了。所以 TIM3 部分重映射的库函数实现方法是:

GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);

3.初始化 TIM3,设置 TIM3 的 ARR 和 PSC。
在开启了 TIM3 的时钟之后,我们要设置 ARR 和 PSC 两个寄存器的值来控制输出 PWM 的 周期。当 PWM 周期太慢(低于 50Hz)的时候,我们就会明显感觉到闪烁了。因此,PWM 周 期在这里不宜设置的太小。这在库函数是通过 TIM_TimeBaseInit 函数实现的

TIM_TimeBaseStructure.TIM_Period = arr;                                         //设置自动重装载值
TIM_TimeBaseStructure.TIM_Prescaler =psc;                                      //设置预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = 0;                                   //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;                    //向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);                                 //根据指定的参数初始化 TIMx 的

4.设置 TIM3_CH2 的 PWM 模式,使能 TIM3 的 CH2 输出。
我们要设置 TIM3_CH2 为 PWM 模式(默认是冻结的),因为我们的 DS0 是低电 平亮,而我们希望当 CCR2 的值小的时候,DS0 就暗,CCR2 值大的时候,DS0 就亮,所以我 们要通过配置 TIM3_CCMR1 的相关位来控制 TIM3_CH2 的模式。在库函数中,PWM 通道设 置是通过函数 TIM_OC1Init()~TIM_OC4Init()来设置的,不同的通道的设置函数不一样,这里我 们使用的是通道 2,所以使用的函数是 TIM_OC2Init()。

void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);

看看结构体 TIM_OCInitTypeDef 的定义:

typedef struct
{   uint16_t TIM_OCMode; uint16_t TIM_OutputState;     uint16_t TIM_OutputNState;    uint16_t TIM_Pulse;            uint16_t TIM_OCPolarity;       uint16_t TIM_OCNPolarity;      uint16_t TIM_OCIdleState;     uint16_t TIM_OCNIdleState;
}TIM_OCInitTypeDef;

这里我们讲解一下与我们要求相关的几个成员变量:
参数 TIM_OCMode 设置模式是 PWM 还是输出比较,这里我们是 PWM 模式。
参数 TIM_OutputState 用来设置比较输出使能,也就是使能 PWM 输出到端口。
参数 TIM_OCPolarity 用来设置极性是高还是低。
其他的参数 TIM_OutputNState,TIM_OCNPolarity,TIM_OCIdleState 和 TIM_OCNIdleState 是 高级定时器 TIM1 和 TIM8 才用到的。

要实现我们上面提到的场景,方法是:

TIM_OCInitTypeDef  TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;                      //选择 PWM 模式 2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;          //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;              //输出极性高
TIM_OC2Init(TIM3, &TIM_OCInitStructure);                                //初始化 TIM3 OC2

5.使能 TIM3。
在完成以上设置了之后,我们需要使能 TIM3。

TIM_Cmd(TIM3, ENABLE);  //使能 TIM3

6.修改 TIM3_CCR2 来控制占空比。
在经过以上设置之后,PWM 其实已经开始输出了,只是其占空比和频率都是固定 的,而我们通过修改 TIM3_CCR2 则可以控制 CH2 的输出占空比。继而控制 DS0 的亮度。
在库函数中,修改 TIM3_CCR2 占空比的函数是:

void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2);

对于其他通道,分别有一个函数名字,函数格式为 TIM_SetComparex(x=1,2,3,4)。
通过以上 6 个步骤,我们就可以控制 TIM3 的 CH2 输出 PWM 波了。

硬件设计

本实验用到的硬件资源有:
1) 指示灯 DS0
2) 定时器 TIM3

软件设计

在 timer.c 里面加入了 如下代码:

//TIM3 PWM部分初始化
//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void TIM3_PWM_Init(u16 arr,u16 psc)
{  GPIO_InitTypeDef GPIO_InitStructure;TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;TIM_OCInitTypeDef  TIM_OCInitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);                           //使能定时器3时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB  | RCC_APB2Periph_AFIO, ENABLE);    //使能GPIO外设和AFIO复用功能模块时钟GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);                           //Timer3部分重映射  TIM3_CH2->PB5    //设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形    GPIOB.5GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;                                       //TIM_CH2GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                               //复用推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);                                            //初始化GPIO//初始化TIM3TIM_TimeBaseStructure.TIM_Period = arr;                                      //设置在下一个更新事件装入活动的自动重装载寄存器周期的值TIM_TimeBaseStructure.TIM_Prescaler =psc;                                         //设置用来作为TIMx时钟频率除数的预分频值 TIM_TimeBaseStructure.TIM_ClockDivision = 0;                                   //设置时钟分割:TDTS = Tck_timTIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;                    //TIM向上计数模式TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);                              //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位//初始化TIM3 Channel2 PWM模式   TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;                                 //选择定时器模式:TIM脉冲宽度调制模式2TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;                    //比较输出使能TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;                      //输出极性:TIM输出比较极性高TIM_OC2Init(TIM3, &TIM_OCInitStructure);                                       //根据T指定的参数初始化外设TIM3 OC2TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);                                //使能TIM3在CCR2上的预装载寄存器TIM_Cmd(TIM3, ENABLE);                                                         //使能TIM3}

头文件 timer.h 与上一个的不同是加入了 TIM3_PWM_Init 的声明

#ifndef __TIMER_H
#define __TIMER_H
#include "sys.h"void TIM3_Int_Init(u16 arr,u16 psc);
void TIM3_PWM_Init(u16 arr,u16 psc);
#endif

main.c

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "timer.h"int main(void)
{       u16 led0pwmval=0;u8 dir=1;    delay_init();                                           //延时函数初始化     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);       //设置NVIC中断分组2:2位抢占优先级,2位响应优先级uart_init(115200);                                      //串口初始化为115200LED_Init();                                               //LED端口初始化TIM3_PWM_Init(899,0);                                 //不分频。PWM频率=72000000/900=80Khzwhile(1){delay_ms(10);   if(dir){led0pwmval++;}else{ led0pwmval--;}if(led0pwmval>300){dir=0;}if(led0pwmval==0){dir=1;}                                      TIM_SetCompare2(TIM3,led0pwmval);         }
}

这里,我们从死循环函数可以看出,我们将 led0pwmval 这个值设置为 PWM 比较值,也就 是通过 led0pwmval 来控制 PWM 的占空比,然后控制 led0pwmval 的值从 0 变到 300,然后又 从 300 变到 0,如此循环,因此 DS0 的亮度也会跟着从暗变到亮,然后又从亮变到暗。至于这 里的值,我们为什么取 300,是因为 PWM 的输出占空比达到这个值的时候,我们的 LED 亮度 变化就不大了(虽然最大值可以设置到 899),因此设计过大的值在这里是没必要的。

基于STM32F103ZET6库函数PWM输出实验相关推荐

  1. 基于STM32F103ZET6库函数定时器中断实验

    基于STM32F103ZET6库函数定时器中断实验 STM32F1 通用定时器简介 定时器相关的库函数主要集中在固件库文件 stm32f10x_tim.h 和 stm32f10x_tim.c 文件中 ...

  2. 基于STM32F103ZET6库函数按键输入实验

    基于STM32F103ZET6库函数按键输入实验 GPIO_ReadInputDataBit函数 硬件设计 软件设计 我们将通过 ALIENTEK 精英 STM32F103 上载有的 3 个按钮(KE ...

  3. 基于STM32F103ZET6库函数外部中断实验

    基于STM32F103ZET6库函数外部中断实验 外部中断简介 IO 口外部中断的一般步骤 软件设计 外部中断简介 通过板载的 3 个按键,控制板载的两个 LED 的亮灭以及蜂鸣器的发声. 代码主要分 ...

  4. 基于STM32F103ZET6库函数串口实验

    基于STM32F103ZET6库函数串口实验 本次实验实现如下功能 串口设置的一般步骤可以总结为如下几个步骤 与串口基本配置直接相关的几个固件库函数 1.串口时钟使能. 2.串口复位. 3.串口参数初 ...

  5. STM32 PWM输出实验总结

    本实验是基于STM32 407的板子,使用的是通用定时器TIM14,相关的博文其实有很多,本文主要是基于他们结合个人学习理解总结整理,并非完全原创,只希望能帮助更好理解PWM输出的过程尤其是TIM_A ...

  6. 【学习记录】 STM32 PWM输出实验

    STM32 PWM工作过程 以通道1为例: CCR1:捕获比较(值)寄存器(x=1,2,3,4):设置比较值. CCMR1: OC1M[2:0]位: 对于PWM方式下,用于设置PWM模式1[110]或 ...

  7. STM32L475裸机例程学习 定时器中断和PWM输出实验

    定时器中断和PWM输出实验 所以阿-笔记的重要性哇!之前看过的内容在做后面的内容涉及到了发现没有笔记,看的时间太久远,竟然全部忘记了,真是个悲伤的故事:( 那就重来吧.由于这两个实验都跟TIM定时器关 ...

  8. 【手拉手 带你准备电赛】PWM究竟是什么(附:PWM输出实验完整代码)

    目录 PWM简介 PWM原理 PWM实验内容 PWM实验步骤 PWM实验代码 PWM解惑时刻 1.向上计数 2.刹车.死区 附录 初始化函数的完整代码 主函数的完整代码 都知道BMW,那么你们知道PW ...

  9. STM32学习笔记(五 定时器及应用 3 PWM输出实验 )

    一.PWM 简介 脉冲宽度调制(PWM) Pulse Width Modulation (调制) 简单来说就是对脉冲宽度的控制. 高级定时器 TIM1 和 TIM8: 可以同时产生多达 7 路的 PW ...

最新文章

  1. 怎么使用CAD编辑器来打开图纸中的所有图层
  2. stm32l0的停止模式怎么唤醒_汇聚力量,守护安全:2020 “AnQ唤醒云课堂”圆满收官!...
  3. how is bookmark function implemented in Opportunity
  4. express项目创建
  5. mybatis TypeHandler 类型处理器
  6. Vue 安装 live-server
  7. linux内核发包工具,Linux内核发包工具pktgen测试方案说明
  8. 一加8 Pro相机能“透视”,一加工程师:大家不要“有一个大胆的想法”
  9. 卷积神经网络训练准确率突然下降_基于联邦学习和卷积神经网络的入侵检测方法...
  10. 中国双面柔性印刷电路板(FPC)市场趋势报告、技术动态创新及市场预测
  11. jquery插入节点
  12. 实用软件工程第二版(吕云翔)课后选择答案
  13. 光环PMP 疑难点辨析
  14. 梁宁:增长思维30讲脑图笔记
  15. JavaScript 刮刮乐
  16. 程序猿生存指南-7 相亲之路(下)
  17. 开源图像数据集管理工具fiftyone使用
  18. CC3200+TB6612FNG 驱动电机实现开环控制
  19. 2019年5大企业网盘对比
  20. PASCAL VOC2012数据集

热门文章

  1. 用c语言编写两个有序数组合并,C++实现两个有序数组的合并
  2. 数据结构--柯朵莉树
  3. Android 对控件设置边框样式(边框颜色,圆角)和图片样式(圆角)
  4. adb wifi 实现多设备无线连接Android手机
  5. 深入浅出kubernetes之client-go的DeltaFIFO
  6. tensorflow学习笔记(三十七):如何自定义LSTM的initial state
  7. JAVA 获取微信用户信息,看完这篇你必须得学会
  8. 如何使用FMEA软件制作FMEA | SunFMEA
  9. hnust 2022汇编语言期中考试笔记
  10. 人大金仓数据库KingBase+SpringBoot+MyBatis的使用