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