目标:
1- 把PWM信号的频率改成100KHZ
2- 使用高级定时器1输出4路占空比相同的PWM信号
编程要点:
1.定时器用到的GPIO初始化
2.定时器时基结构体f初始化
3.定时器输出比较结构体初始化
宏定义:
#ifndef _LL_TIM_H
#define _LL_TIM_H
#include "stm32f10x.h"
// 这里我们使用高级控制定时器TIM1
#define TIM_arr (10-1)
#define TIM_psc (72-1)
#define TIM_ccr1 5
void TIM1_Init(void);
#endif
GPIO初始化:
static void TIM1_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
//设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形 GPIOA.8
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM1_CH1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//设置该引脚为复用输出功能,输出TIM1 CH2的PWM脉冲波形 GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //TIM1_CH2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//设置该引脚为复用输出功能,输出TIM1 CH3的PWM脉冲波形 GPIOA.10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //TIM1_CH3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//设置该引脚为复用输出功能,输出TIM1 CH4的PWM脉冲波形 GPIOA.11
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //TIM1_CH4
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
定时器模式配置:
// PWM 信号的频率F = TIM_CLK/{(ARR+1) *(PSC+1)}
// TIM_CLK等于72MHz
// ARR :自动重装载寄存器的值,对应TIM_arr这个宏
// PSC :计数器时钟的分频因子,对应TIM_psc这个宏
// 占空比Duty=CCR/(ARR+1),CCR对应TIM_ccr1这个宏,该测试程序中占空比{ 5/(10-1)}为50%
static void TIM1_Model_Config(void)
{
// 开启定时器时钟,即内部时钟CK_INT=72M
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
/*--------------------时基结构体初始化-------------------------*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
TIM_TimeBaseStructure.TIM_Period=TIM_arr;
TIM_TimeBaseStructure.TIM_Prescaler= TIM_psc; // 驱动CNT计数器的时钟 = Fck_int/(psc+1)
// 时钟分频因子 ,配置死区时间时需要用到
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; //不分频
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;// 计数器计数模式,设置为向上计数
// 重复计数器的值,没用到不用管
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);// 初始化定时器
/*-------------------------输出比较结构体初始化---------------------------------*/
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;// 配置为PWM模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;// 输出通道电平极性配置
TIM_OCInitStructure.TIM_Pulse = TIM_ccr1;// 设置占空比大小
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);//使能TIM1在CCR1上的预装载寄存器
//ch2 PWM模式
TIM_OCInitStructure.TIM_Pulse = TIM_ccr1;// 设置占空比大小
TIM_OC2Init(TIM1, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);//使能TIM1在CCR1上的预装载寄存器
//ch3 PWM模式
TIM_OCInitStructure.TIM_Pulse = TIM_ccr1;// 设置占空比大小
TIM_OC3Init(TIM1, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);//使能TIM1在CCR1上的预装载寄存器
//ch4 PWM模式
TIM_OCInitStructure.TIM_Pulse = TIM_ccr1;// 设置占空比大小
TIM_OC4Init(TIM1, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);//使能TIM1在CCR1上的预装载寄存器
TIM_Cmd(TIM1, ENABLE); // 使能计数器
TIM_CtrlPWMOutputs(TIM1, ENABLE);// 主输出使能,当使用的是通用定时器时,这句不需要
}
void TIM1_Init(void)
{
TIM1_GPIO_Config();
TIM1_Model_Config();
}
主函数:
int main(void)
{
/* 高级定时器初始化 */
TIM1_Init();
while(1)
{
}
}
下载验证
需要注意的地方
// * 【注意】:TIM_TimeBaseInitTypeDef结构体里面有5个成员,TIM6和TIM7的寄存器里面只有
// * TIM_Prescaler和TIM_Period,所以使用TIM6和TIM7的时候只需初始化这两个成员即可,
// * 另外三个成员是通用定时器和高级定时器才有.
// *-----------------------------------------------------------------------------
// *typedef struct
// *{ TIM_Prescaler --------------------------都有
// * TIM_CounterMode ----------------------TIMx,x[6,7]没有,其他都有
// * TIM_Period---------------------------------都有
// * TIM_ClockDivision -----------------------TIMx,x[6,7]没有,其他都有
// * TIM_RepetitionCounter------------------TIMx,x[1,8,15,16,17]才有
// *}TIM_TimeBaseInitTypeDef;
// -----------------------------------------------------------------------------
// /
/**-----------------------------------------------------------------------------------------------/
/【注意】TIM_CtrlPWMOutputs(TIM1, ENABLE); // 主输出使能,当使用的是通用定时器时,这句不需要
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;//重复计数器,高级控制定时器特有
*/
// * 【注意】:高级控制定时器比通用定时器增加了可编程死区互补输出、重复计数器、带刹车(断路)功能,主要针对工业电机控制方面,通过设置死区时间(由MOS管工艺确定)防止电路短路;
/*-------------------刹车和死区结构体初始化-------------------*/
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;
// 这里配置的死区时间为152ns
TIM_BDTRInitStructure.TIM_DeadTime = 11;
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;
// 当BKIN引脚检测到高电平的时候,输出比较信号被禁止,就好像是刹车一样
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
TIM_BDTRConfig(ADVANCE_TIM, &TIM_BDTRInitStructure);
【注意】定时器输出频率和占空比问题
1.系统频率(TIM_CLK)设置为72MHz时,F = TIM_CLK/{(ARR+1) *(PSC+1)}
//(为什么要加1,是因为是从0开始计数)
//ARR:0~65535
//PSC:1~65536
2.占空比由CCR和ARR决定 Duty=CCR/(ARR+1)