历史上的今天
返回首页

历史上的今天

今天是:2025年06月27日(星期五)

正在发生

2019年06月27日 | STM32复习笔记(八)PWM输出和 输入捕获

2019-06-27 来源:eefocus

一、STM32 PWM工作过程:

STM32 PWM工作过程(通道1为例)


CCR1:捕获比较(值)寄存器(x=1,2,3,4):设置比较值。


CCMR1: OC1M[2:0]位:对于PWM方式下,用于设置PWM模式1【110】或者PWM模式2【111】


CCER:CC1P位:输入/捕获1输出极性。0:高电平有效,1:低电平有效。


CCER:CC1E位:输入/捕获1输出使能。0:关闭,1:打开。


二、PWM模式1 & PWM模式2:

寄存器TIMx_CCMR1的OC1M[2:0]位来分析:


void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);


void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);


(1)自动重载的预装载寄存器:


void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);


简单的说,ARPE=1,ARR立即生效。。。APRE=0,ARR下个比较周期生效。

(2)STM32 定时器3输出通道引脚:


Datasheet中表格会有详细说明


三、PWM输出库函数概述:

(1)PWM输出库函数:

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


typedef struct

{

  uint16_t TIM_OCMode;  //PWM模式1或者模式2

  uint16_t TIM_OutputState; //输出使能 OR失能

  uint16_t TIM_OutputNState;

  uint16_t TIM_Pulse; //比较值,写CCRx

  uint16_t TIM_OCPolarity; //比较输出极性

  uint16_t TIM_OCNPolarity; 

  uint16_t TIM_OCIdleState;  

  uint16_t TIM_OCNIdleState; 

} TIM_OCInitTypeDef;

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //PWM模式2

TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能

TIM_OCInitStructure. TIM_Pulse=100;

TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高

TIM_OC2Init(TIM3, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 OC2

(2)设置比较值函数:

void TIM_SetCompareX(TIM_TypeDef* TIMx, uint16_t Compare2);


(3)使能输出比较预装载:

void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);


(4)使能自动重装载的预装载寄存器允许位:

void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);


四、PWM输出配置步骤:

① 使能定时器3和相关IO口时钟。


         使能定时器3时钟:RCC_APB1PeriphClockCmd();


         使能GPIOB时钟:RCC_APB2PeriphClockCmd();


② 初始化IO口为复用功能输出。函数:GPIO_Init();


        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;      


③ 这里我们是要把PB5用作定时器的PWM输出引脚,所以要重映射配置,


     所以需要开启AFIO时钟。同时设置重映射。


        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);


        GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);


④  初始化定时器:ARR,PSC等:TIM_TimeBaseInit();


⑤  初始化输出比较参数:TIM_OC2Init();


⑥  使能预装载寄存器: TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);


⑦  使能定时器:TIM_Cmd();


⑧  不断改变比较值CCRx,达到不同的占空比效果:TIM_SetCompare2();


五、STM32 PWM工作过程---输入捕获:


附可直接使用的配置:(方便做各种智能车、擂台等4PWM)

1、底层配置:

void speed_Init(void)    //TIM3_CH1->PC6 CH2->PC7 CH3->PC8 CH4->PC9

//**********电机驱动设置************//

TIM_OCInitTypeDef  TIM_OCInitStructure;

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure ;

GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟  

TIM_DeInit(TIM3);//初始化TIM3寄存器

 

GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE); //Timer3完全重映射  TIM3_CH1->PC6 CH2->PC7 CH3->PC8 CH4->PC9

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9; //TIM1_CH1  //设置该引脚为复用输出功能,输出TIM3 CH1的PWM脉冲波形 GPIOC.6

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

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIO                

//**************************************************************************

//  定时器1设置: 72分频,频率10KHz,向上计数,105是为了速度为100时,PWM占空比不会到100,方便电机驱动自举生压。一般PWM频率大于1K,4-10K比较好。

//************************************************************************** 

    TIM_TimeBaseStructure.TIM_Period = 105-1;

    TIM_TimeBaseStructure.TIM_Prescaler = 71;

    TIM_TimeBaseStructure.TIM_ClockDivision = 0;

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

 

// 主定时器T3为 PWM3 模式 

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;

    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

    TIM_OCInitStructure.TIM_Pulse = 0;  

    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

    TIM_OC1Init(TIM3, &TIM_OCInitStructure);

    TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);//使能的预装载寄存器

    

    TIM_OCInitStructure.TIM_Pulse = 0; 

    TIM_OC2Init(TIM3, &TIM_OCInitStructure); 

    TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);//使能的预装载寄存器

 

    TIM_OCInitStructure.TIM_Pulse = 0; 

    TIM_OC3Init(TIM3, &TIM_OCInitStructure); 

    TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);//使能的预装载寄存器

 

    TIM_OCInitStructure.TIM_Pulse = 0; 

    TIM_OC4Init(TIM3, &TIM_OCInitStructure); 

    TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);//使能的预装载寄存器

    

    TIM_ARRPreloadConfig(TIM3, ENABLE); //使能定时器3

    TIM_Cmd(TIM3, ENABLE);

}

2、函数调用:

#include "delay.h"

#include "sys.h"

#include "sumjess_pwm.h"

 int main(void)

 {   

int b = 0;

delay_init();

   speed_Configuration();


while(1) 

{

for(b=0;b<100;b+=10){

TIM_SetCompare1(TIM3,b);   delay_ms(100);}

for(b=100;b>1;b-=10){

TIM_SetCompare1(TIM3,b);   delay_ms(100);}

    TIM_SetCompare1(TIM3,0);  delay_ms(2000);

for(b=0;b<100;b+=10){

TIM_SetCompare2(TIM3,b);   delay_ms(100);}

for(b=100;b>1;b-=10){

TIM_SetCompare2(TIM3,b);   delay_ms(100);}

TIM_SetCompare2(TIM3,0);  delay_ms(2000);

for(b=0;b<100;b+=10){

TIM_SetCompare3(TIM3,b);   delay_ms(100);}

for(b=100;b>1;b-=10){

TIM_SetCompare3(TIM3,b);   delay_ms(100);}

    TIM_SetCompare3(TIM3,0);  delay_ms(2000);

for(b=0;b<100;b+=10){

TIM_SetCompare4(TIM3,b);   delay_ms(100);}

for(b=100;b>1;b-=10){

TIM_SetCompare4(TIM3,b);   delay_ms(100);}

    TIM_SetCompare4(TIM3,0);  delay_ms(2000);

}

}

☆注:该函数满载为105,即:TIM_SetCompare1(TIM3,105);由于驱动半桥需要自举升压,占空比必须小于98%。最好在95%以下。所以写者留出5%,使用时只需写:0%~100%之间即可。

六、STM32 输入捕获工作过程(通道1为例):


一句话总结工作过程:通过检测TIMx_CHx上的边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将当前定时器的值(TIMx_CNT)存放到对应的捕获/比较寄存器(TIMx_CCRx)里面,完成一次捕获。


(1)步骤1:设置输入捕获滤波器(通道1为例)



(2)步骤2:设置输入捕获极性(通道1为例)



(3)步骤三:设置输入捕获映射通道(通道1为例):


(4)步骤四:设置输入捕获分频器(通道1为例):



(5)步骤五:捕获到有效信号可以开启中断:



(6)最后:看看定时器通道对应引脚TIM5为例:


七、输入捕获通道初始化函数:

void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);


typedef struct

{

  uint16_t TIM_Channel; //捕获通道1-4   

  uint16_t TIM_ICPolarity; //捕获极性

  uint16_t TIM_ICSelection; //映射关系

  uint16_t TIM_ICPrescaler; //分频系数

  uint16_t TIM_ICFilter;  //滤波器

} TIM_ICInitTypeDef;

TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1; TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;

TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; 

TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;

TIM5_ICInitStructure.TIM_ICFilter = 0x00;

TIM_ICInit(TIM5, &TIM5_ICInitStructure);


 


八、通道极性设置独立函数:

void TIM_OCxPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);

九、获取通道捕获值

uint32_t TIM_GetCapture1(TIM_TypeDef* TIMx);

十、输入捕获的一般配置步骤:

① 初始化定时器和通道对应IO的时钟。


② 初始化IO口,模式为输入:GPIO_Init();


    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 输入


③初始化定时器ARR,PSC


   TIM_TimeBaseInit();


④初始化输入捕获通道


   TIM_ICInit();


⑤如果要开启捕获中断,


    TIM_ITConfig();


    NVIC_Init();


⑥使能定时器:TIM_Cmd();


⑦编写中断服务函数:TIMx_IRQHandler();


推荐阅读

史海拾趣

Hitachi Metals公司的发展小趣事

随着汽车工业向智能化、电动化方向发展,Hitachi Metals敏锐地捕捉到了这一趋势带来的商机。公司加大了对汽车电子部件的研发和生产投入,特别是在汽车活塞环材料领域取得了显著成就。其生产的钢制活塞环材料在日本市场占据领先地位,不仅为众多汽车制造商提供了高质量的产品,还通过技术创新不断提升产品的附加值。此外,公司还积极拓展汽车电子控制单元(ECU)等关键部件的市场,进一步巩固了其在汽车电子领域的地位。

Einfochips公司的发展小趣事

Einfochips公司一直致力于嵌入式系统的创新与发展。在某一时期,该公司推出了Eragon600,一款基于Qualcomm Snapdragon 600处理器的全新嵌入式开发平台。这一平台的推出,标志着Einfochips在嵌入式系统开发领域取得了重要突破。Eragon600不仅具备强大的处理能力,还适用于多种行业,包括工业、安全与监控、信息、娱乐等。在多个领域的广泛应用,进一步巩固了Einfochips在嵌入式系统开发领域的领先地位。

珠海艾派克(APEXMIC)公司的发展小趣事

近年来,艾派克通过一系列战略性并购,实现了公司的国际化发展。其中最为引人注目的是艾派克科技股份有限公司与太盟投资集团共同牵头收购利盟公司的案例。这次收购不仅使艾派克获得了先进的技术、国际化的品牌和团队,还进一步拓宽了公司的业务范围和市场渠道。通过并购,艾派克成功跻身真正意义上的国际化打印公司,为全球打印行业的未来发展打开了新的想象空间。

Fujitsu America公司的发展小趣事

在计算机技术发展的早期阶段,Fujitsu就展现出了强大的研发实力。1954年,Fujitsu成功研制出日本第一台电脑FACOM 100,这一里程碑式的成就不仅标志着Fujitsu在计算机领域的正式起步,也为其后续在ICT领域的发展奠定了坚实基础。Fujitsu America作为Fujitsu在全球的重要分支机构,积极将这一创新成果引入北美市场,推动了当地计算机技术的普及和应用。

FLIR公司的发展小趣事

随着业务规模的不断扩大,FLIR逐渐将目光投向全球市场。公司在全球范围内建立了多个生产基地和销售服务网络,包括在美国本土的波特兰、波士顿、圣巴巴拉和波兹曼等城市设立的工厂,以及在瑞典斯德哥尔摩和爱沙尼亚塔林等海外地区设立的分支机构。这些生产基地和销售服务网络为FLIR在全球市场的拓展提供了有力支持,使得公司能够更好地服务于全球客户,满足他们多样化的需求。

Fedco_Batteries公司的发展小趣事

为了拓展国际市场,Fedco_Batteries积极寻求与国内外企业的合作。他们与多家知名企业建立了战略合作关系,共同研发新型电池技术,开拓新市场。同时,公司还积极参加国际展会和论坛,与国际同行交流学习,不断提升自身的竞争力。这种合作共赢的发展模式,让Fedco_Batteries在国际市场上取得了显著的成绩。

问答坊 | AI 解惑

PDF——电源管理技术的飞跃

PDF——电源管理技术的飞跃!这个帖子如何??请留下您的意见。…

查看全部问答>

如何模拟按下enter键

现在遇到的情况是这样的:基于vxworks 操作系统 过程描述:应用层(相对驱动来说)发送命令(write 到一个输出文件描述符)--》在哪里被接受不清楚--》终端打印一些信息--》这些信息在用户按下 回车键后 被应用程序 接收(read文件描述符),然后解析 ...…

查看全部问答>

一个统计Sysenter指令的驱动,却会导致系统崩溃

我写了一个驱动用来统计 sysenter 指令发生的次数在 Windows XP操作系统上. 但是如果我在我的所有CPU上运行时(双核系统),系统会在几分钟后崩溃,崩溃点不同。如果我只在其中一个核上运行,不会有什么问题。 我不知道这是为什么。 x86 Platform ...…

查看全部问答>

png双缓冲,出现边框变粗,变模糊,希望得到帮助

我的代码如下 CoCreateInstance(CLSID_ImagingFactory,NULL,CLSCTX_INPROC_SERVER,IID_IImagingFactory, (void **)&pImgFactory); //创建COM组件 pImgFactory->CreateImageFromFile(L\"\\\\Storage Card\\\\imgBrowsedown1.png\",&pImage);//读取 ...…

查看全部问答>

物理基地址如何映射到应用程序可访问的空间?

物理基地址如何映射到应用程序可访问的空间? 我要访问研华PCM3724的PC104 I/O卡输入输出,其基地址为0x300. BYTE* PCMMem=(BYTE*)LocalAlloc(LPTR,10*sizeof(BYTE)); DWORD dwRegBase=0x0300; PHYSICAL_ADDRESS PhyAddr={dwRegBase,0}; DWORD ...…

查看全部问答>

》》》调查:如果STM32具有外部存储器接口,您打算怎么用?

请分几个问题回答:一、存放程序代码  1) 存储器介质是什么? RAM、NOR Flash或其它  2) 存储器容量?最大及最小要求  3) 存储器速度? 100ns、40ns等二、存放数据 &nbs ...…

查看全部问答>

PC13为什么不能输出秒脉冲?

ST32F101的PC13口能输出校准时钟却不能输出秒脉冲是怎么回事?    /* Enable PWR and BKP clocks */     RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);     /* Allow access to ...…

查看全部问答>

怪现象?串口发送丢数

使用STM32F103VC控制器,使用串口2,9600波特率,使用2.03库,程序很简单,用串口把一个数组顺序发出去, //和上位机通信 void uart2_send_byte(u8 ch) {   USART_SendData(USART2, ch);   /* Loop until the end of ...…

查看全部问答>

歡迎大家來討論:MCU 的 IO 口封裝為什麼不按順序排列?

以前 89C51 的 IO 口在封裝上都是都是從 0 到 7 的順序來排列,但是現在很多 MCU 的 IO 口都不是這樣排列的了,感覺一個字\"亂\".. 這其中有什麼奧秘嗎? 希望大家來討論討論.…

查看全部问答>

TI Sitara 的AM18系列入门-编译

Sitara  有强大的HMI,HMI设备包括硬件与软件。这里的软件也就是组态软件,硬件我更关心的是他的串口和以太网接口。  在有些的情况下可能要使用的串口会非常的多,可能会达到七八个之多,这是就很少有CPU可以达到这个程度,这时 ...…

查看全部问答>