定时器主从模式实现PWM脉冲个数、占空比以及频率可调(250kHz以下)

本文介绍了一种使用STM32F103ZET6微控制器通过GPIO和定时器配置实现PWM脉冲输出的方法。通过TIM3和TIM4配置,实现了频率可调、占空比可控的PWM信号,并通过中断程序处理脉冲数量。测试表明在250kHz以下频率,系统能准确控制PWM脉冲个数,超过该频率则可能出现异常。
摘要由CSDN通过智能技术生成

GPIO配置:

void GPIO_config(void)
{
    GPIO_InitTypeDef	GPIO_InitStructure;
    
    RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3 | RCC_APB1Periph_TIM4, ENABLE);     //使能TIM3 | TIM4时钟
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);    //使能GPIOA时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;                                       //TIM3-CH1: PA6
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;			                        //复用推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                               //指定输出速率最大为50MHz
    GPIO_Init(GPIOA, &GPIO_InitStructure);	                                        //初始化GPIO口
}

主定时器配置----配置PWM脉冲频率和占空比:

/*--------主定时器配置--------*/
void TIM3_Config(u32 Freq, u8 DutyCycle)
{
    u16 ARR;                                                       //声明变量ARR -- 自动重装值
    u16 PSC = 1;                                                   //声明变量PSC并赋初值PSC=1, 预分频系数
    u16 CCR;                                                       //声明变量CCR -- 输出捕获寄存器脉冲值
    TIM_TimeBaseInitTypeDef		TIM_TimeBaseStructure;             //定义定时器初始化结构体
    TIM_OCInitTypeDef		    TIM_OCInitStructure;               //定义定时器输出配置结构体
    
    /*--------根据PWM脉冲频率设定定时器时钟的预分频系数--------*/
    while(SystemCoreClock/PSC/Freq>65535)                         //当自动重装值大于65535时,预分频系数加1
    {
        PSC++;
    }
    ARR = SystemCoreClock/PSC/Freq;                               //根据频率Freq以及TIME时钟的预分频值PSC计算自动重装载值
    /*---------定时器初始化配置---------*/
    TIM_TimeBaseStructure.TIM_Period = (ARR - 1);                 //指定在下一次更新事件时要加载到活动自动重载寄存器中的周期值
    TIM_TimeBaseStructure.TIM_Prescaler = (PSC - 1);              //指定用于分频 TIME 时钟的预分频器值
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;       //指定时钟分频,不分频
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   //指定计数模式,向上计数
    TIM_TimeBaseInit( TIM3, &TIM_TimeBaseStructure);              //初始化TIM3
	
	/*--------定时器输出配置--------*/ 
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;             // 设置工作模式是PWM,且为PWM1工作模式,TIMx_CNT<TIMx_CCR1时为高电平
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 也就是使能PWM输出到端口					
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;      // 输出极性,低电平有效
	CCR = ARR * (100 - DutyCycle) /100;
	TIM_OCInitStructure.TIM_Pulse = CCR ;                         //设置待装入捕获寄存器的脉冲值
	TIM_OC1Init( TIM3, &TIM_OCInitStructure);                     //初始化 TIM3-OC1
	TIM_SelectMasterSlaveMode( TIM3, TIM_MasterSlaveMode_Enable); //定时器主从模式使能
	TIM_SelectOutputTrigger( TIM3, TIM_TRGOSource_Update);        //选择触发方式:使用更新事件作为触发输出
	TIM_OC1PreloadConfig( TIM3, TIM_OCPreload_Enable);            //TIM3-CH1预装载使能				
	TIM_ARRPreloadConfig( TIM3, ENABLE);                          //使能ARR预装载寄存器
}

从定时器配置----配置PWM脉冲数量:

/*-------- 从定时器配置 --------*/
void TIM4_Config(u16 PulseNum)
{
    TIM_TimeBaseInitTypeDef	TIM_TimeBaseStructure;
    NVIC_InitTypeDef	NVIC_InitStructure;
    
    TIM_TimeBaseStructure.TIM_Period = PulseNum;                  //设定脉冲个数
    TIM_TimeBaseStructure.TIM_Prescaler = 0;                      //不分频
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;       //指定时钟分频,不分频
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   //向上计数
    TIM_TimeBaseInit( TIM4, &TIM_TimeBaseStructure);

    TIM_SelectInputTrigger( TIM4, TIM_TS_ITR2);                   // TIM3-主,TIM4-从 ITR2
    TIM_SelectSlaveMode( TIM4,TIM_SlaveMode_External1 );          // TIM4从模式,选择触发器(TRGI)的上升沿为计数器提供时钟
    TIM_ITConfig( TIM4, TIM_IT_Update, DISABLE);                  // 禁用TIM4更新中断

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);               //中断组别:3
    NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;      
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

PWM脉冲函数配置:

void PWM_Output(u32 Freq, u8 DutyCycle, u16 PulseNum)             
{
	TIM4_Config(PulseNum);
	TIM_Cmd( TIM4, ENABLE);
	TIM_ClearITPendingBit( TIM4, TIM_IT_Update);
	TIM_ITConfig( TIM4, TIM_IT_Update, ENABLE);
	TIM3_Config(Freq, DutyCycle);
	TIM_Cmd( TIM3, ENABLE);
}

中断程序配置:

void TIM4_IRQHandler(void)
{
	if (TIM_GetITStatus( TIM4, TIM_IT_Update) != RESET)
	{
		TIM_ClearITPendingBit( TIM4, TIM_IT_Update);			// 清除中断标志位
		TIM_Cmd( TIM3, DISABLE);			// 关闭定时器3
		TIM_Cmd( TIM4, DISABLE);			// 关闭定时器4
		TIM_ITConfig( TIM4, TIM_IT_Update, DISABLE);
	}
}

主函数部分:

#include "delay.h"
#include "timer.h"


int main(void)
{		
	delay_init();	    	//延时函数初始化
    GPIO_config();
   
    while(1)
	{
        PWM_Output(250000,50,2); //频率:250kHz;占空比:50%; 脉冲数量 2;
        delay_us(2000);
	}
}

头文件内容:

#ifndef __TIMER_H
#define __TIMER_H
#include "sys.h"



/** 接口函数**/
void GPIO_config(void);
void TIM3_ConfigTIM3_Config(u32 Freq, u8 DutyCycle);
void TIM4_Config(u16 PulseNum);
void PWM_Output(u32 Freq, u8 DutyCycle, u16 PulseNum);
#endif


运行结果:

经测试:250kHz以下,上述配置可实现精确控制PWM脉冲个数,超过250kHz,脉冲个数异常

测试芯片:STM32F103ZET6 

  • 8
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值