一.PWM简介

  PWM是 Pulse Width Modulation 的缩写,中文意思就是脉冲宽度调 制,简称脉宽调制。它是利用微处理器的数字输出来对模拟电路进行控 制的一种非常有效的技术,其控制简单、灵活和动态响应好等优点而成 为电力电子技术最广泛应用的控制方式,其应用领域包括测量,通信, 功率控制与变换,电动机控制、伺服控制、调光、开关电源,甚至某些 音频放大器,因此学习PWM具有十分重要的现实意义。 其实我们也可以这样理解,PWM是一种对模拟信号电平进行数字编码 的方法。通过高分辨率计数器的使用,方波的占空比被调制用来对一个 具体模拟信号的电平进行编码。PWM 信号仍然是数字的,因为在给定的 任何时刻,满幅值的直流供电要么完全有(ON),要么完全无(OFF)。电压 或电流源是以一种通(ON)或断(OFF)的重复脉冲序列被加到模拟负载上去 的。通的时候即是直流供电被加到负载上的时候,断的时候即是供电被 断开的时候。只要带宽足够,任何模拟值都可以使用 PWM 进行编码。

二.STM32F1 PWM介绍

  STM32F1除了基本定时器TIM6和TIM7,其他定时器都可以产生PWM输出 。其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出 。而通用定时器也能同时产生多达 4路的 PWM 输出,这些在定时器中断 章节中已经介绍过。 PWM的输出其实就是对外输出脉宽可调(即占空比调节)的方波信号 ,信号频率是由自动重装寄存器 ARR 的值决定,占空比由比较寄存器 CCR 的值决定。

  PWM输出比较模式总共有8种,具体由寄存器 CCMRx 的位 OCxM[2:0] 配置。我们这里只讲解最常用的两种PWM输出模式:PWM1和PWM2,其他几 种模式可以参考《STM32F10x中文参考手册》13、14、15定时器章节。

  PWM1和PWM2这两种模式用法差不多,区别之处就是输出电平的极性不 同。

  PWM模式根据计数器CNT计数方式,可分为边沿对齐模式和中心对齐模 式。

(1)PWM边沿对齐模式

  当 TIMx_CR1 寄存器中的 DIR 位为低时执行递增计数,计数器CNT从 0 计数到自动重载值(TIMx_ARR 寄存器的内容),然后重新从 0 开始 计数并生成计数器上溢事件。 以 PWM 模式 1 为例。只要TIMx_CNT < TIMx_CCRx, PWM 参考信号 OCxREF 便为有效的高电平,否则为无效的低电平。如果 TIMx_CCRx 中 的比较值小于自动重载值(TIMx_ARR 中),则 OCxREF 保持为“ 1”。 如果比较值为 0, 则 OCxREF 保持为“ 0”。

  当 TIMx_CR1 寄存器中的 DIR 位为高时执行递减计数,计数器CNT从 自动重载值(TIMx_ARR 寄存器的内容)递减计数到0,然后重新从 TIMx_ARR值开始计数并生成计数器下溢事件。 以 PWM 模式 1 为例。只要TIMx_CNT >TIMx_CCRx, PWM 参考信号 OCxREF 便为无效的低电平,否则为有效的高电平。如果 TIMx_CCRx 中 的比较值大于自动重载值(TIMx_ARR 中),则 OCxREF 保持为“ 1”。 此模式下不能产生0%的PWM波形。

(2)PWM中心对齐模式

  在中心对齐模式下,计数器 CNT 是工作做递增/递减模式下。开始的 时候, 计数器CNT 从 0 开始计数到自动重载值减 1(ARR-1),生成计数 器上溢事件;然后从自动重载值开始向下计数到 1 并生成计数器下溢事 件。之后从 0 开始重新计数。

  我们以ARR=8,CCRx=4为例进行介绍。第一阶段计数器CNT工作在递增 计数方式,从0开始计数,当TIMx_CNT < TIMx_CCRx时,PWM 参考信号 OCxREF为高电平,当TIMx_CNT >= TIMx_CCRx时,PWM 参考信号 OCxREF 为低电平。第二阶段计数器CNT工作在递减计数方式,从ARR开始递减计 数,当TIMx_CNT > TIMx_CCRx时,PWM 参考信号 OCxREF为低电平,当 TIMx_CNT <= TIMx_CCRx时,PWM 参考信号 OCxREF为高电平。

三.PWM输出配置步骤

(1)使能定时器及端口时钟,并设置引脚复用器映射 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE); 可选的参数在 stm32f10x_gpio.h 都已经列出来非常详细

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

(2)初始化定时器参数,包含自动重装值,分频系数,计数方式等

void TIM_TimeBaseInit(TIM_TypeDef*TIMx,TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

(3)初始化PWM输出参数,包含PWM模式、输出极性,使能等

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

(4)开启定时器

void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState); TIM_Cmd(TIM3,ENABLE); //开启定时器

(5)修改TIMx_CCRx的值控制占空比

void TIM_SetCompare1(TIM_TypeDef* TIMx, uint32_t Compare1);

(6)使能TIMx在CCRx上的预装载寄存器 使能输出比较预装载库函数是:

void  TIM_OCxPreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);

第一个参数用于选择定时器,第二个参数用于选择使能还是失能输出比较预装载寄存器,可选择为TIM_OCPreload_Enable、TIM_OCPreload_Disable。

(7)使能 TIMx 在 ARR 上的预装载寄存器允许位 使能 TIMx 在 ARR 上的预装载寄存器允许位库函数是:

void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);  //第一个参数用于选择定时器,第二个参数用于选择使能还是失能。

  高级定时器要想输出PWM波形,必须要设置一个 MOE 位(TIMx_BDTR 的第 15 位),以使能主输出,否则不会输出 PWM。库函数设置的函数为:

   void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState);

pwm.h
1 #ifndef _pwm_H
2 #define _pwm_H
3
4 #include "system.h"
5
6 void TIM3_CH1_PWM_Init(u16 per,u16 psc);
7
8 #endif

问题一:19行问什么要AFIO使能   27行改变管脚映射怎么回事

  27行改变管脚映射是对应第三步而言的,就是将定时器输出的管脚TIM_CH1即PA6管脚映射到PC6管脚输出(这里以TIM_CH1为例)

  而管脚映射需要用到AFIO这个外设里面寄存器的配置才能实现

问题二:24行为什么GPIOC使用复用推挽输出,为什么使用复用功能

  复用功能是接受其他外设所传递的数据(这里是复用的定时器结构图右下角所输出的数据)然后通过管脚输出

  总结:所比较的数据从TIM3_CH1口出来,经过AFIO外设内寄存器的配置将TIM3_CH1管脚即PA6管脚所映射到的PC6管脚上,经过PC6管脚的复用功能输出的模式将TIM3_CH1的数据输出

四、PWM代码

pwm.c
1 #include "pwm.h"
2
3 /*******************************************************************************
4 * 函 数 名 : TIM3_CH1_PWM_Init
5 * 函数功能 : TIM3通道1 PWM初始化函数
6 * 输 入 : per:重装载值
7 psc:分频系数
8 * 输 出 : 无
9 *******************************************************************************/
10 void TIM3_CH1_PWM_Init(u16 per,u16 psc)
11 {
12 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
13 TIM_OCInitTypeDef TIM_OCInitStructure;
14 GPIO_InitTypeDef GPIO_InitStructure;
15
16 /* 开启时钟 */
17 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
18 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
19 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //AFIO使能
20
21 /* 配置GPIO的模式和IO口 */
22 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
23 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
24 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
25 GPIO_Init(GPIOC,&GPIO_InitStructure);
26
27 GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE);//改变指定管脚的映射
28
29 TIM_TimeBaseInitStructure.TIM_Period=per; //自动装载值
30 TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //分频系数
31 TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
32 TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //设置向上计数模式
33 TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
34
35 TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
36 TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;
37 TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
38 TIM_OC1Init(TIM3,&TIM_OCInitStructure); //输出比较通道1初始化
39
40 TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable); //使能TIMx在 CCR1 上的预装载寄存器
41 TIM_ARRPreloadConfig(TIM3,ENABLE);//使能预装载寄存器
42
43 TIM_Cmd(TIM3,ENABLE); //使能定时器
44
45 }
 main.c
1 #include "system.h"
2 #include "SysTick.h"
3 #include "led.h"
4 #include "pwm.h"
5
6 int main()
7 {
8 u16 i=0;
9 u8 fx=0;
10 SysTick_Init(72);
11 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组 分2组
12 LED_Init();
13 TIM3_CH1_PWM_Init(500,72-1); //频率是2Kh
14
15 while(1)
16 {
17
18 if(fx==0)
19 {
20 i++;
21 if(i==300)
22 {
23 fx=1;
24 }
25 }
26 else
27 {
28 i--;
29 if(i==0)
30 {
31 fx=0;
32 }
33 }
34 TIM_SetCompare1(TIM3,i); //i值最大可以取499,因为ARR最大值是499.
35 delay_ms(10);
36 }
37 }

(stm32f103学习总结)—stm32 PMW输出实验的更多相关文章

  1. (stm32f103学习总结)—待机唤醒实验

    一.STM32待机模式介绍 1.1 STM32低功耗模式介绍 很多单片机具有低功耗模式,比如MSP430.STM8L等,我们的STM32 也不例外.默认情况下,系统复位或上电复位后,微控制器进入运行模 ...

  2. (stm32f103学习总结)—ADC模数转换实验

    一.STM32F1 ADC介绍 TM32F103 系列一般都有 3 个 ADC,这些 ADC 可以独立使用,也可 以使用双重(提高采样率).STM32F1 的 ADC 是 12 位逐次 逼近型的模拟数 ...

  3. MM32 备份域学习(兼容STM32)

    MM32 备份域学习(兼容STM32) 内容提要 备份域工作原理 备份域特性 备份域的保护:侵入检测 备份域侵入检测 备份域电源与主要内容 备份域特性 20字节数据后备寄存器(中容量和小容量产品),或 ...

  4. 第六周学习总结&第四次实验报告

    第六周学习总结&第四次实验报告 学习总结 这周我们简单的学习了一点点关于接口的内容,接口是Java中最重要的概念之一,接口可以理解为一个特殊的类, 里面由全局常量和公共的抽象方法组成,接口摆脱 ...

  5. MM32看门狗学习(兼容STM32)

    MM32看门狗学习(兼容STM32) IWDG独立看门狗 思维导图 IWDG框图与理解 1.独立看门狗分为两个部分,配置寄存器在1.8V供电区,计数器的核心部分在VDD供电区(即使停机/待机模式计数器 ...

  6. STM32 精确输出PWM脉冲数控制电机(转)

    STM32 精确输出PWM脉冲数控制电机 发脉冲两种目的1)速度控制2)位置控制 速度控制目的和模拟量一样,没有什么需要关注的地方发送脉冲方式为PWM,速率稳定而且资源占用少 stm32位置控制需要获 ...

  7. Redis学习笔记六:持久化实验(AOF,RDB)

    作者:Grey 原文地址:Redis学习笔记六:持久化实验(AOF,RDB) Redis几种持久化方案介绍和对比 AOF方式:https://blog.csdn.net/ctwctw/article/ ...

  8. stm32 PWM输出学习

    STM32 的定时器除了 TIM6 和 7,其他的定时器都可以用来产生 PWM 输出.其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出.通用定时器也能同时产生多达 4路 ...

  9. (stm32f103学习总结)—stm32定时器中断

    一.定时器介绍 STM32F1的定时器非常多,由2个基本定时器(TIM6.TIM7).4个通 用定时器(TIM2-TIM5)和2个高级定时器(TIM1.TIM8)组成.基本定 时器的功能最为简单,类似 ...

随机推荐

  1. Oracle之SQL的简单查询

    查询结构 --SQL语句的执行原理以及语法结构: /* SELECT * | 列名1[,列名2...] | 表达式 FROM 表名 [表的别名] WHERE 分组前的筛选条件 GROUP BY 列名1 ...

  2. IndexError:list assignment index out of range

    L=[] L[0]=2 L[1]=3 报错:IndexError: list assignment index out of range,列表超过限制 一种情况是:list[index]的index超 ...

  3. JAVA 异常和异常处理

    目录 一.异常 1.基本概念 2.异常体系图 3.五大运行时异常 4.编译异常 二.异常处理 1.异常处理的方式 1.1try-catch异常处理 注意事项 课堂练习题 1.2throws异常处理 注 ...

  4. HDFS连接JAVA,HDFS常用API

    先在pom.xml中导入依赖包 <dependencies> <!-- https://mvnrepository.com/artifact/org.apache.hadoop/ha ...

  5. 矩池云上安装yolov5并测试教程

    官方仓库:https://github.com/ultralytics/yolov5 官方文档:https://docs.ultralytics.com/quick-start/ 此案例我是租用了k8 ...

  6. 清华大学ucore操作系统课笔记

    操作系统 清华大学ucore操作系统课笔记 全文思维导图 1. 操作系统概述 1.1 什么是操作系统? 操作系统的定义 没有公认的精确定义 一个控制程序 一个系统软件 控制程序执行过程,防止错误和计算 ...

  7. MySQL-DB-封装-简易版

    <?php class DB{ private $link; public function __construct($host,$user,$password,$dbname,$port) { ...

  8. 【1024打卡】C++字符串的输出((c语言风格)

    c++字符串输出(c语言风格) 文章目录 c++字符串输出(c语言风格) 杂记 代码 杂记 今天程序设计竞赛白给了,果然还是太弱了,y总带带我TAT ┭┮﹏┭┮1024快乐 代码 c语言学习 #inc ...

  9. 痞子衡嵌入式:MCUBootUtility v3.5发布,支持串行NOR的ECC及双程序启动

    -- 痞子衡维护的 NXP-MCUBootUtility 工具距离上一个大版本(v3.4.0)发布过去半年了,这一次痞子衡为大家带来了版本升级 v3.5.0,这个版本主要有几个非常重要的更新需要跟大家 ...

  10. Java 8 + 10 = Java 18

    明天Java 18将正式发布, 虽然它不是长期支持 (LTS) 版本,但它却实现了九个 JEP(在Java 18列出).有哪些特性值得关注呢?今天胖哥为你提前解读.再看.点赞.转发.关注来一波吧. J ...