(stm32f103学习总结)—stm32 PMW输出实验
一.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输出实验的更多相关文章
- (stm32f103学习总结)—待机唤醒实验
一.STM32待机模式介绍 1.1 STM32低功耗模式介绍 很多单片机具有低功耗模式,比如MSP430.STM8L等,我们的STM32 也不例外.默认情况下,系统复位或上电复位后,微控制器进入运行模 ...
- (stm32f103学习总结)—ADC模数转换实验
一.STM32F1 ADC介绍 TM32F103 系列一般都有 3 个 ADC,这些 ADC 可以独立使用,也可 以使用双重(提高采样率).STM32F1 的 ADC 是 12 位逐次 逼近型的模拟数 ...
- MM32 备份域学习(兼容STM32)
MM32 备份域学习(兼容STM32) 内容提要 备份域工作原理 备份域特性 备份域的保护:侵入检测 备份域侵入检测 备份域电源与主要内容 备份域特性 20字节数据后备寄存器(中容量和小容量产品),或 ...
- 第六周学习总结&第四次实验报告
第六周学习总结&第四次实验报告 学习总结 这周我们简单的学习了一点点关于接口的内容,接口是Java中最重要的概念之一,接口可以理解为一个特殊的类, 里面由全局常量和公共的抽象方法组成,接口摆脱 ...
- MM32看门狗学习(兼容STM32)
MM32看门狗学习(兼容STM32) IWDG独立看门狗 思维导图 IWDG框图与理解 1.独立看门狗分为两个部分,配置寄存器在1.8V供电区,计数器的核心部分在VDD供电区(即使停机/待机模式计数器 ...
- STM32 精确输出PWM脉冲数控制电机(转)
STM32 精确输出PWM脉冲数控制电机 发脉冲两种目的1)速度控制2)位置控制 速度控制目的和模拟量一样,没有什么需要关注的地方发送脉冲方式为PWM,速率稳定而且资源占用少 stm32位置控制需要获 ...
- Redis学习笔记六:持久化实验(AOF,RDB)
作者:Grey 原文地址:Redis学习笔记六:持久化实验(AOF,RDB) Redis几种持久化方案介绍和对比 AOF方式:https://blog.csdn.net/ctwctw/article/ ...
- stm32 PWM输出学习
STM32 的定时器除了 TIM6 和 7,其他的定时器都可以用来产生 PWM 输出.其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出.通用定时器也能同时产生多达 4路 ...
- (stm32f103学习总结)—stm32定时器中断
一.定时器介绍 STM32F1的定时器非常多,由2个基本定时器(TIM6.TIM7).4个通 用定时器(TIM2-TIM5)和2个高级定时器(TIM1.TIM8)组成.基本定 时器的功能最为简单,类似 ...
随机推荐
- 网络类型PAN、LAN、WLAN、CAN、MAN、WAN简单介绍
转至:https://www.cnblogs.com/itmacy/p/12290036.html PAN:personal area network 个人区域网络 无线连接:蓝牙,红外,NFC 有线 ...
- urllib-访问网页的两种方式:GET与POST
学习自:https://www.jianshu.com/p/4c3e228940c8 使用参数.关键字访问服务器 访问网络的两种方法: 1.GET 利用参数给服务器传递信息 参数data为dict类型 ...
- MySQL:一些操作
参考:MySQL使用教程 写在开头:语句后都要注意加分号; 1.MySQL服务,在普通的cmd而不是MySQL cmd下进行 --停止MySQL服务 net stop mysql80 --启动MySQ ...
- C语言刷二叉树(一)基础部分
二叉树基础部分 144. 二叉树的前序遍历 方法一:递归 /** * Definition for a binary tree node. * struct TreeNode { * int val; ...
- vue项目npm run dev 报错error in ./src/main.js Module build failed: ReferenceError: Unknown plugin "transform-vue-jsx" specified in......
问题: vue项目npm run dev运行时报错,如下图: 原因: 缺少组件 解决办法: 安装相应的组件: npm install babel-plugin-transform-vue-jsx ...
- 微服务入门二:SpringCloud(版本Hoxton SR6)
一.什么是SpringCloud 1.官方定义 1)官方定义:springcloud为开发人员提供了在分布式系统中快速构建一些通用模式的工具(例如配置管理.服务发现.断路器.智能路由.微代理.控制总线 ...
- PHP动态修改配置文件
文件结构: index.php 主页 config 配置文件 doUpdate.php 修改功能页 index.php <html> <head> <title>修 ...
- PhpStorm 编辑器上更改文件后自动上传服务器
在编辑器内设置自动上传后很方便,,,就不用编辑完了之后还要去服务器里面上传,很麻烦!!!设置了自动上传Ctrl +S 就可以上传了 方便至极~~~~~~~希望可以帮到大家 1.菜单栏找到[工具/To ...
- jmeter关于入参转码encode问题
我们的工作中,通过抓包经常会发现有很多入参都是被encode过一层,形成了如上图所示的样子: 这些参数我们是可以通过fiddler去转码的:但是如果我们要做jmeter的脚本,不可能每一次都手动去转码 ...
- CentOS7.5环境下Docker基本操作
1. 查找Docker中Centos镜像文件 docker search centos 2. 下载Docker中Centos镜像文件(默认下载最新版本) docker pull centos 3. ...