STM32——PWM波形输出

一、IC和OC

可以看到:定时器除了基本的定时中断功能,输入捕获、输出比较均是STM32定时器的功能

输入捕获IC(Input Capture)

输入捕获是一种用于测量外部信号脉冲宽度或频率的技术。它通过定时器模块捕获外部信号的特定事件(如脉冲的上升沿或下降沿),以便测量脉冲宽度、频率或其他相关参数。在STM32中,除了基本定时器TIM6和TIM7外,其他定时器通常都具有输入捕获功能。输入捕获常用于测量传感器输出、编码器信号、PWM输入信号等。

输出比较OC(Output Compare)

输出比较是通过比较定时器的计数器值与捕获/比较寄存器(CCR)的值,来操作输出电平的一种技术。它可以用来生成一定频率和占空比的PWM波形,实现对外部电路的控制。每个高级定时器和通用定时器在STM32中都拥有多个输出比较通道,这些通道可以独立配置,以生成不同的PWM波形。

捕获/比较寄存器,这个寄存器是输出比较和输入捕获共用的,两种功能在同一时刻只能选择一种执行。先将其用作输出比较来看,输出比较最重要的一个功能就是产生PWM波。也可以看到,通用计时器有四个输出比较通道:OC1~4

其中OC1的内部输出部分如下:

输出比较模式(TIMx_CCMRx寄存器中的OCxM位)和输出极性(TIMx_CCER寄存器中的 CCxP位)

在判断计数器CNT和捕获/比较寄存器CCR(capture /compare  register)的值并确认输出模式后输出一个OC1REF(OC1 Reference),它指的是与输出比较通道1(OC1)相关联的参考信号或电平状态。
它有两条之路可走,一条是进入主模式控制器就能够作为触发输出TRGO输出给其他定时器或者DA/DC转换;另一条是进入极性选择器TIMx_CCER,极性选择器置0则信号走上一路不做变换直接输出到输出使能电路,如果置1则让它走下支路可以使信号oc1ref经过一个非门电路将其反转,高变低,低变高。所以,oc1ref的电平状态不仅取决与CNT和CCR的比较,还取决于我们选取怎么样的输出模式

其中输出模式总共有以下几种:

这里细心一点就会发现:PWM模式1和模式2是完全相反的,也就是说,在两种不同模式下,oc1ref在经过选择器时,一个模式ref照常输出,一个模式ref取反。模式1和模式2正好互补,互为相反,所以在运用起来差别也并不太大。这里用的最多的就是PWM模式1。

而从计数模式上来看,PWM也和TIMx在作定时器时一样,也有向上计数模式、向下计数模式和中心对齐模式,关于3种模式的具体资料,可以查看《STM32参考手册》的“14.3.9 PWM模式”一节。

二、PWM输出

脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽度的控制。一般用来控制步进电机的速度等等。

STM32的定时器除了基本定时器TIM6和TIM7之外,其他的定时器都可以用来产生PWM输出,其中高级定时器TIM1和TIM8可以同时产生7路的PWM输出,而通用定时器也能同时产生4路的PWM输出。

PWM输出管脚

PWM的输出管脚是确定好的,具体的引脚功能可以查看《STM32参考手册》的“8.3.7 定时器复用功能重映射”一节。比如说TIM3的第2个通道,在没有重映射的时候,指定的管脚是PA7,如果设置部分重映射之后,TIM3_CH2的输出就被映射到PB5上了,如果设置了完全重映射的话,TIM3_CH2的输出就被映射到PC7上了。

在此需要强调的是,不同的TIMx有分配不同的引脚,但是考虑到管脚复用功能,STM32提出了一个重映射的概念,就是说通过设置某一些相关的寄存器,来使得在其他非原始指定的管脚上也能输出PWM。但是这些重映像的管脚也是由参考手册给出的。

复用和重映射的区别:

(1)可以看到PA9引脚、PA10引脚都有三种功能。其中第一项PA9和PA10是其默认功能,默认功能为GPIO功能,也即是作为通用的输入输出端口使用。这样我们就知道,当PA9引脚和PA10引脚不在作为默认的GPIO功能使用,而是作为USART1_TX/USART1_RX或者作TIM1_CH2/TIM1_CH3功能使用时,就是对PA9引脚和PA10引脚的复用。简单来说就是:一个引脚有多种外设的特定功能就叫复用

(2)重映射就是把原本属于这个引脚的复用映射到另外一个引脚上去,但是能不能够映射就要看上图引脚定义的重定义功能有没有原本引脚的复用功能存在。简单来说:将某些外设的特定功能从默认的GPIO引脚移动到其他GPIO引脚上。

那么部分重映射和完全重映射也就比较好理解了,都是相对于没有重映射来说,部分引脚改变则位部分重映射,全部引脚均改变则为完全重映射。

 PWM输出信号

PWM输出的是一个方波信号,信号的频率是由TIMx的时钟频率和TIMx_ARR预分频器所决定的,而输出信号的占空比则是由TIMx_CRRx寄存器确定的。

因此,可以通过向CRR中填入适当的数来输出自己所需的频率和占空比的方波信号。

三、TIMER输出PWM实现步骤

代码编写依托于以下:

定时器部分:

PWM配置部分:

定时器配置上篇文章讲过了,以下是PWM部分:

1.开启时钟;

RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM2,ENABLE );

RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOA,ENABLE );

2.配置GPIO

    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Mode =GPIO_Mode_AF_PP;
    GPIO_InitStruct.GPIO_Pin =GPIO_Pin_15 ;
    GPIO_InitStruct.GPIO_Speed =GPIO_Speed_50MHz ;
    GPIO_Init (GPIOA,&GPIO_InitStruct);

3.设置TIMx定时器的相关寄存器

    TIM_InternalClockConfig(TIM2);//开启内部时钟
    
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    TIM_TimeBaseInitStruct.TIM_ClockDivision =TIM_CKD_DIV1;   
 //1分频
    TIM_TimeBaseInitStruct.TIM_CounterMode =TIM_CounterMode_Up; //向上计数
    TIM_TimeBaseInitStruct.TIM_Period =;  //给ARR赋值
    TIM_TimeBaseInitStruct.TIM_Prescaler =; //给PSC赋值
    TIM_TimeBaseInitStruct.TIM_RepetitionCounter =0;//重复计数器是高级定时器才会用到,这里给0即可
    TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);//初始化定义

4.设置TIMx定时器的PWM相关寄存器

    TIM_OCInitTypeDef TIM_OCInitStruct;
    //  TIM_OCStructInit(&TIM_OCInitStruct); 
——>>PWM结构体内部成员有些是高级定时器才会进行配置,所以我们只需要保持默认值即可,该函数的作用就是设置默认值,如果有子成员需要修改,再在下面进行修改即可;
    TIM_OCInitStruct.TIM_OCMode =TIM_OCMode_PWM1;
    TIM_OCInitStruct.TIM_OCPolarity =TIM_OCPolarity_High;
    TIM_OCInitStruct.TIM_OutputState =TIM_OutputState_Enable;
    TIM_OCInitStruct.TIM_Pulse =90;  
//给CCR赋值
    TIM_OC1Init(TIM2,&TIM_OCInitStruct);


第1步需要注意的是通用定时器TIMx是由APB1提供时钟,而GPIO则是由APB2提供时钟。如果需要对PWM的输出进行重映像的话,还需要开启引脚复用时钟AFIO:

RCC_APB2PeriphClockCmd (RCC_APB2Periph_AFIO,ENABLE );


第2步设置GPIO时钟时,GPIO模式应该设置为复用推挽输出GPIO_Mode_AF_PP,如果需要引脚重映射的话,则需要用GPIO_PinRemapConfig()函数进行设置。

为什么GPIO要配置为复用推挽模式?——可以看到当I/O端口被配置为复用功能时,在开漏或推挽式配置中,输出缓冲器被打开,输出控制与片上外设直接连接,只有这样我们才能将定时器通道TIMx_Ch打通:

其中还需要注意,你想要映射到的那个引脚是否是调试引脚:

如果是调试引脚还需要使用GPIO_PinRemapConfig()函数关闭其调试端口的复用,才能够让它作为普通的GPIO口或复用定时器通道。


第3步设置TIMx定时器的相关寄存器。


第4步设置PWM相关寄存器,首先要设置PWM模式(默认情况下PWM是冻结的),然后设置占空比(根据前面所述公式进行计算),再设置输出比较极性:当设置为High时,输出信号不反相,当设置为Low时,输出信号反相之后再输出。最重要是要使能TIMx的输出状态和使能TIMx的PWM输出使能。

相关设置完成之后,就可以通过TIM_Cmd()来打开TIMx定时器,从而得到PWM输出了。

PWM函数如下:

#include "stm32f10x.h"                  // Device headervoid PWM_Init(void)
{RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM2,ENABLE );RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOA,ENABLE );RCC_APB2PeriphClockCmd (RCC_APB2Periph_AFIO,ENABLE );GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode =GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Pin =GPIO_Pin_0 ;GPIO_InitStruct.GPIO_Speed =GPIO_Speed_50MHz ;GPIO_Init (GPIOA,&GPIO_InitStruct);TIM_InternalClockConfig(TIM2);TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;TIM_TimeBaseInitStruct.TIM_ClockDivision =TIM_CKD_DIV1;TIM_TimeBaseInitStruct.TIM_CounterMode =TIM_CounterMode_Up;TIM_TimeBaseInitStruct.TIM_Period =100-1; //ARRTIM_TimeBaseInitStruct.TIM_Prescaler =720-1;//PSCTIM_TimeBaseInitStruct.TIM_RepetitionCounter =0;TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);TIM_OCInitTypeDef TIM_OCInitStruct;TIM_OCStructInit(&TIM_OCInitStruct);TIM_OCInitStruct.TIM_OCMode =TIM_OCMode_PWM1;TIM_OCInitStruct.TIM_OCPolarity =TIM_OCPolarity_High;TIM_OCInitStruct.TIM_OutputState =TIM_OutputState_Enable;TIM_OCInitStruct.TIM_Pulse =50;//CCRTIM_OC1Init(TIM2,&TIM_OCInitStruct);TIM_Cmd (TIM2 ,ENABLE );}

如果我想要把PA0的TIM2_Ch1_ETR功能映射到PA15:

代码示例如下:

#include "stm32f10x.h"                  // Device headervoid PWM_Init(void)
{RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM2,ENABLE );RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOA,ENABLE );RCC_APB2PeriphClockCmd (RCC_APB2Periph_AFIO,ENABLE );GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2,ENABLE );GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE );GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode =GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Pin =GPIO_Pin_15 ;GPIO_InitStruct.GPIO_Speed =GPIO_Speed_50MHz ;GPIO_Init (GPIOA,&GPIO_InitStruct);TIM_InternalClockConfig(TIM2);TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;TIM_TimeBaseInitStruct.TIM_ClockDivision =TIM_CKD_DIV1;TIM_TimeBaseInitStruct.TIM_CounterMode =TIM_CounterMode_Up;TIM_TimeBaseInitStruct.TIM_Period =100-1; //ARRTIM_TimeBaseInitStruct.TIM_Prescaler =720-1;//PSCTIM_TimeBaseInitStruct.TIM_RepetitionCounter =0;TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);TIM_OCInitTypeDef TIM_OCInitStruct;TIM_OCStructInit(&TIM_OCInitStruct);TIM_OCInitStruct.TIM_OCMode =TIM_OCMode_PWM1;TIM_OCInitStruct.TIM_OCPolarity =TIM_OCPolarity_High;TIM_OCInitStruct.TIM_OutputState =TIM_OutputState_Enable;TIM_OCInitStruct.TIM_Pulse =90;//CCRTIM_OC1Init(TIM2,&TIM_OCInitStruct);TIM_Cmd (TIM2 ,ENABLE );}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/408085.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024年AI编程新手必备工具,快速提升技能!

在当今这个技术日新月异的时代,AI编程已成为一个越来越重要的领域,吸引着众多新手和希望提升自己的中级开发者进入。 对于这些渴望在AI领域快速成长的人来说,选择合适的编程工具是至关重要的。 接下来,我们将深入探讨几款市场上…

Aria2安装和使用-Mac版

起因是需要网盘下载,无奈限速很烦,查找很多方案后,最终决定使用Aria2 Tampermonkey。 其中Aria2是一款开源轻量的下载软件,简单来说就是可以通过URL直接下载。 Tampermonkey则是一款插件,我这里是.crx结尾的谷歌插件…

抢单源码修正版,带教程,自动抓取订单,十几种语言可自动切换

亚马逊抢单源码自动抓取订单任务邀请英文,西班牙语可自动切换语言亲测修正版。带完整开源的前后台。 西班牙,英文,巴西,中文,德国,拉法兰西,荷兰,缅甸,Sverige,日本,Trk…

专利权和版权有什么区别?

专利权和版权有什么区别?

SD差点挂掉,后备军们兴奋入场,AI生图应用正在爆发?

前后不到一个月,两个开源生图模型相继上线。 首先是由称得上 SD 原班人马的黑森林实验室推出的 FLUX.1。黑森林实验室由 Stable Diffusion 的核心开发者 Robin Rombach 领衔创立,团队成员基本上都是 Stable Diffusion 3 的作者,其中三名元老…

内存管理篇-04伙伴系统

本小节有几个重要的知识点: 伙伴系统的思想伙伴系统的实现伙伴系统分配器:内存块的申请、释放过程伙伴算法和阶数 1.伙伴系统的思想 针对某个某个zone分区,(1)把物理地址相连的空闲页连接起来合成一个物理块&#xf…

数据结构——冒泡、选择、插入和希尔排序

目录 引言 冒泡排序 1.算法思想 2.算法步骤 3.代码实现 4.复杂度分析 选择排序 1.算法思想 2.算法步骤 3.代码实现 (1)优化前 (2)优化后 4.复杂度分析 插入排序 1.算法思想 2.算法步骤 3.代码实现 4.复杂度分析 希尔排序 1.算法思想 2.算法步骤 3.代码实…

tcp 网络通信及抓包工具的使用

tcp网络通信 本地回环(Loopback)的概念 本地回环地址是一个特殊的IP地址,用于指向计算机本身的网络接口。在IPv4中,最常见的本地回环地址是127.0.0.1,而在IPv6中则是::1。这个地址用于测试网络软件,确保网…

量化交易backtrader实践(四)_评价统计篇(1)_内置评价

背景 通过对基础的学习和不断深入的实践,当我们已经能够制作出快速获取数据,以及制作出多个股票 乘上多种策略进行回测的部分的时候,我们就会明显发现数据有点多了,比如10支股票都用了3种策略就得到30段数据,一页显示…

亲测好用,ChatGPT 3.5/4.0新手使用手册,最全论文指令手册~ 【2024年 更新】

本以为遥遥领先的GPT早就普及了,但小伙伴寻找使用的热度一直高居不下,其实现在很简单了! 国产大模型快200家了,还有很多成熟的国内AI产品,跟官网一样使用,还更加好用~ ① 3.5 大多数场景是够用的&#xff…

Mix|使用VS2017CMake构建Qt工程 仿照MVS(仅用于学习)

MVS下载链接:https://www.hikrobotics.com/cn/machinevision/service/download/?module0 CMake工程构建参考:CMake|VS2017CMake3.8搭建Qt项目 文章目录 效果图整体结构实现代码最外层CMakeLists.txt代码实现及CMakeLists.txt搭建CMakeLists.txt搭建主函…

[创业之路-141] :产品经理 - NPDP概述

目录 一、产品经理以及主要职责 1.1 概述 1、市场调研与需求分析 2、产品规划与设计 3、项目管理与协调 4、产品推广与销售支持 5、产品运营与维护 6、其他职责 1.2 产品经理与项目经理的职责分工 1.2.1 职责区别 产品经理 项目经理 1.2.2 合作方式 二、什么是NP…

EXCEL——Vlookup17个高级用法

大纲 一、基本语法 1、参数详解 二、入门篇 1、单条件查找 2、屏蔽查找返回的错误值 三、进阶篇 1、反向查找 2、包含查找 3、区间查找 4、含通配符查找 5、多列查找 6、多区域查找 四、高级篇 1、多条件查找 2、合并单元格查找 3、带合并单元格的多条件查找 …

[数据集][目标检测]夜间老鼠检测数据集VOC+YOLO格式316张1类别+视频文件1个

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):316 标注数量(xml文件个数):316 标注数量(txt文件个数):316 标注类别…

MATLAB进阶:矩阵代数

今天我们学习矩阵在MATLAB中的运算。 运算符 与数组运算相同: A. ’转罝 A’(共轭)转罝 共轭转置(A’或A†): 对于一个复数矩阵A,其共轭转置记作A’或A†。共轭转置不仅将矩阵A的行和列互…

大话C语言:第46篇 C语言项目工程化之Makefile详解

1 Makefile概述 Makefile是一种用于自动化构建和管理程序的工具,以文本文件的形式存在。它主要记录了程序的编译规则、依赖关系和操作指令,使得在开发过程中能够轻松地进行代码的编译、链接和部署。 Makefile文件中的命令有一定规范,一旦该文…

Unity--XLua调用C#

Unity–XLua调用C# 由于Unity/C# 和lua是两种语言,两种语言的特性不一样,因此,如果要互相调用的话,需要第三方作桥梁. 因此,为了在Unity中/C#中使用lua的特性,需要在Unity中安装插件,Xlua/toLu…

【学习笔记】8、脉冲波形的变换与产生

本章简略记录。 8.1 单稳态触发器(脉冲触发) 单稳态触发器 应用于 :(1)脉冲整型(2)脉冲延时 (3)定时 单稳态触发器的工作特性: 没有触发脉冲作用时&#xf…

Flink入门(五)--Flink算子

Map DataStream → DataStream 一个接受一个元素并产生一个元素的函数。 示例 dataStream.map { x > x * 2 } FlatMap DataStream → DataStream 一个接受一个元素并产生零个、一个或多个元素的函数。 例如 dataStream.flatMap { str > str.split(" ") }…

besier打断和升阶,高阶性质

欢迎关注更多精彩 关注我,学习常用算法与数据结构,一题多解,降维打击。 问题描述 对besier曲线在u处打断,生成两条besier曲线对besier曲线升阶处理 bezier高阶性质 求导推导 P ( t ) ∑ i 0 n B i n ( t ) b i \boldsymbol …