当前位置: 首页 > news >正文

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 );}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • C#实现数据采集系统-数据反写(1)MQTT订阅接收消息
  • 【回文数判断】输入一个5位数,判断它是不是回文数
  • springboot后端开发-自定义参数校验器
  • Win 10高效录屏指南:四大神器助力屏幕录制!
  • python学习之redis
  • openpyxl库详细介绍十分全面
  • QT-五子棋游戏
  • JavaScript 中的深拷贝新宠:structuredClone() 函数详解
  • 网络安全之xss靶场练习
  • 用py获取显卡的占用率
  • 【解压即玩】PC电脑版【漫威蜘蛛侠2】豪华中文版+通关存档+画质超棒,神作
  • MySQL——单表查询(二)按条件查询(11)OR 和 AND 关键字一起使用的情况
  • Springcloud从零开始--Eureka(一)
  • 九、 系统安全(考点篇)试题
  • 无人机飞手培训:考证、组装、维修技术详解
  • “Material Design”设计规范在 ComponentOne For WinForm 的全新尝试!
  • 【译】理解JavaScript:new 关键字
  • 8年软件测试工程师感悟——写给还在迷茫中的朋友
  • CAP理论的例子讲解
  • Flex布局到底解决了什么问题
  • HTML中设置input等文本框为不可操作
  • java 多线程基础, 我觉得还是有必要看看的
  • JS+CSS实现数字滚动
  • nfs客户端进程变D,延伸linux的lock
  • Spark in action on Kubernetes - Playground搭建与架构浅析
  • vue 配置sass、scss全局变量
  • webpack4 一点通
  • 测试如何在敏捷团队中工作?
  • 好的网址,关于.net 4.0 ,vs 2010
  • 设计模式(12)迭代器模式(讲解+应用)
  • 世界上最简单的无等待算法(getAndIncrement)
  • 说说动画卡顿的解决方案
  • #define,static,const,三种常量的区别
  • $con= MySQL有关填空题_2015年计算机二级考试《MySQL》提高练习题(10)
  • (附源码)springboot课程在线考试系统 毕业设计 655127
  • (附源码)ssm户外用品商城 毕业设计 112346
  • (六) ES6 新特性 —— 迭代器(iterator)
  • (三)Honghu Cloud云架构一定时调度平台
  • (学习日记)2024.04.10:UCOSIII第三十八节:事件实验
  • (一)基于IDEA的JAVA基础1
  • .NET 分布式技术比较
  • .NET6实现破解Modbus poll点表配置文件
  • .NET轻量级ORM组件Dapper葵花宝典
  • @RequestBody与@RequestParam
  • [ vulhub漏洞复现篇 ] Celery <4.0 Redis未授权访问+Pickle反序列化利用
  • [ vulhub漏洞复现篇 ] Hadoop-yarn-RPC 未授权访问漏洞复现
  • [ 云计算 | AWS ] 对比分析:Amazon SNS 与 SQS 消息服务的异同与选择
  • [《百万宝贝》观后]To be or not to be?
  • [<事务专题>]
  • [20190416]完善shared latch测试脚本2.txt
  • [Android] Android ActivityManager
  • [Angularjs]asp.net mvc+angularjs+web api单页应用
  • [BZOJ4566][HAOI2016]找相同字符(SAM)
  • [Cloud Networking] Layer Protocol (continue)
  • [CLR via C#]11. 事件