STM32
直播中

大红枣

11年用户 630经验值
私信 关注
[问答]

如何使用STM32F103ZET6定时器4 CH2通道产生PWM波?

如何使用STM32F103ZET6定时器4 CH2通道产生PWM波?

回帖(1)

褚毕赋

2021-11-25 09:52:09
添加了对于PWM中arr,psc以及division的说明,还有PWM的频率和占空比的改变问题
使用STM32F103ZET6 定时器4 CH2通道产生PWM波,在GPIOD,GPIO_PIN13引脚LED1产生呼吸灯效果。
实验工具:MDK5,STM32F103ZET6开发板
使用固件库编程
实验效果:LED灯亮——逐渐变暗——全灭——逐渐变亮——亮
相关程序已在最下方给出;
工程






pwm.c文件

#include "pwm.h"


//简单进行定时器初始化,设置 预装载值 和 分频系数
void Tim_Init(u16 arr,u16 psc)  
{
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseInitStruct;  // 初始化结构体


        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);//分配时钟
       
        //相关配置
        TIM_TimeBaseInitStruct.TIM_Prescaler        = psc;         //a number between 0x0000 and 0xFFFF
        TIM_TimeBaseInitStruct.TIM_Period                = arr;          //a number between 0x0000 and 0xFFFF
        TIM_TimeBaseInitStruct.TIM_CounterMode        = TIM_CounterMode_Up; //向上计数
        TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; //分频因子
        TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStruct);       


//打开定时器
        TIM_Cmd(TIM4,ENABLE);       
}


//初始化GPIO口
void Tim_GPIO_Init(void)
{
        GPIO_InitTypeDef          GPIO_InitStruct;   //GPIO初始化结构体
       


        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启AFIO时钟,进行重映射
       
        GPIO_PinRemapConfig(GPIO_Remap_TIM4 ,ENABLE);  //重映射开启
        //初始化GPIOD组时钟
         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);
       
        //初始化引脚
        GPIO_InitStruct.GPIO_Pin         = GPIO_Pin_13;                  //引脚
        GPIO_InitStruct.GPIO_Mode         = GPIO_Mode_AF_PP;                //复用推挽
        GPIO_InitStruct.GPIO_Speed        = GPIO_Speed_50MHz; //速度
        GPIO_Init(GPIOD,&GPIO_InitStruct);       
}


//pwm初始化
void Pwm_Init(u16 arr,u16 psc)
{
        TIM_OCInitTypeDef         TIM_OCInitStruct;   // PWM模式,输出等设置


        //初始化定时器和IO口
        Tim_GPIO_Init();
        Tim_Init(arr,psc);
       
        //初始化PWM模式
        TIM_OCInitStruct.TIM_OCMode                =  TIM_OCMode_PWM1;           //PWM1模式
        TIM_OCInitStruct.TIM_OutputState=  TIM_OutputState_Enable;//输出使能
        TIM_OCInitStruct.TIM_OCPolarity =  TIM_OCPolarity_High;           //高电平有效
        TIM_OC2Init(TIM4,&TIM_OCInitStruct);  //设置利用通道2输出
       
//这里只初始化通道1,我们可以根据自己需求初始化其它通道
//        TIM_OC2Init(TIM3,&TIM_OCInitstrcuture);
//        TIM_OC3Init(TIM3,&TIM_OCInitstrcuture);
//        TIM_OC4Init(TIM3,&TIM_OCInitstrcuture);


       
        //使能预装载寄存器:
        TIM_OC2PreloadConfig(TIM4,TIM_OCPreload_Enable);
       
        //使能自动重装载的预装载寄存器允许位       
        //TIM_ARRPreloadConfig(TIM4,ENABLE);       
}
pwm.h文件

#ifndef __PWM_H_
#define __PWM_H_
#include "stm32f10x.h"


void Pwm_Init(u16 arr,u16 psc);
void Tim_Init(u16 arr,u16 psc);
void Tim_GPIO_Init(void);




#endif
/*重装载时间
Tout = (arr+1)*(psc+1)/Tclk
系统时钟Tclk=72MHz
比如我们设置arr=7199,psc=9999
定时器更新(7199+1)*(1/7200)=1s,也就是1s进入一次更新Update
*/




由数据手册可以看出上电后默认功能并非定时器,想要使用定时器4必须对其进行功能复用,如何进行复用请参考
林一捆 的博客
在进行重映射时应参考数据手册,根据手册进行相关配置。
其中关于定时器的使用及设置问题请参考
private_void_main 的博客
有关通道CH2,CH1等的选择问题已经在程序中做了说明。
对于PWM中arr,psc以及division的说明;





arr是自动重装值,比如arr=300且无中断时,CNT从0加到300,再从0加到300一直循环。从图一可以看出在PWM中arr控制的是其周期










psc是预分频器,它可以改变来自APB1的时钟。
division控制APB1的分频
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; //分频因子
#define TIM_CKD_DIV1 ((uint16_t)0x0000)
#define TIM_CKD_DIV2 ((uint16_t)0x0100)
#define TIM_CKD_DIV4 ((uint16_t)0x0200)










PWM的频率计算方法
溢出时间(相当于pwm的周期)
Tout = (arr+1)(psc+1)/Tclk
系统时钟Tclk=72MHz
比如我们设置arr=7199,psc=9999
定时器更新(7199+1)
(1/7200)=1s,也就是周期为1s
频率=1/tout
PWM的占空比调节
比如我初始化为Pwm_Init(199,0);即 arr = 199,psc = 0;此时根据公式能够算出来pwm的频率和周期。但是要改变pwm的占空比则是靠TIM_SetCompare2(TIM4,i);函数 (实际上是改变CCRX的值) 例如令 i = 100,则占空比为100/199,如果我们写一个循环让 i 在0–199之间循环,那么我们就可以随意调节pwm的占空比了。
程序链接:https://pan.baidu.com/s/1ekL2o2xJtL32Wod_Gih1EQ
提取码:1fql
举报

更多回帖

发帖
×
20
完善资料,
赚取积分