(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)组成.基本定 时器的功能最为简单,类似 ...
随机推荐
- 从零开始,开发一个 Web Office 套件(6):光标 & Click 事件
<从零开始, 开发一个 Web Office 套件>系列博客目录 这是一个系列博客,最终目的是要做一个基于 HTML Canvas 的.类似于微软 Office 的 Web Office ...
- 用WebDev.WebServer40.EXE调试VS代码
1.找到WebDev.WebServer40的录井,一般位于C:/Program Files (x86)/Common Files/Microsoft Shared/DevServer/10.0/We ...
- python刷剑指offer(21-40)(一刷)
21.输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序 ...
- JZ-040-数组中只出现一次的数字
数组中只出现一次的数字 题目描述 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 题目链接: 数组中只出现一次的数字 代码 /** * 标题:数组中只出现 ...
- JZ-003-从尾到头打印链表
从尾到头打印链表 题目描述 输入一个链表,按链表从尾到头的顺序返回一个ArrayList. 题目链接: 从尾到头打印链表 代码 import java.util.ArrayList; /** * 标题 ...
- laravel7 jqAjax下拉框搜索
html: 设置页面改变事件 <div id="show"> <div class="page-container" style=" ...
- NOIP集训题目解析
11.01 子段和 题目大意 给定一个长度为 \(n\) 的序列 \(a\) ,\(a_i=\{ -1,0,1 \}\) ,需要将 \(a\) 中的 \(0\) 变为 \(1\) 或 \(-1\) , ...
- Python列表生成
# For More :http://www.codebelief.com/article/2017/02/python-advanced-programming-list-comprehension ...
- linux下hadoop2.6.1源码64位的编译
linux下hadoop2.6.1源码64位的编译 一. 前言 Apache官网上提供的hadoop本地库是32位的,如果我们的Linux服务器是64位的话,就会现问题.我们在64位服务器执行Hado ...
- SSM集成Thymeleaf
创建项目 Spring+SpringMVC+MyBatis的配置文件 数据库内容 dao层+service层+controller层 映射文件 前端简单页面 配置tomcat,运行显示 总体项目架构 ...