最基本的定时中断功能
1) TIM3 时钟使能。
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
2) 初始化定时器参数
voidTIM_TimeBaseInit(TIM_TypeDef*TIMx,
TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
第一个参数是确定是哪个定时器,这个比较容易理解。 第二个参数是定时器初始化参数结构体指针,结构体类型为 TIM_TimeBaseInitTypeDef,下面我们看看这个结构体的定义:
typedef struct
{
uint16_t TIM_Prescaler;
uint16_t TIM_CounterMode;
uint16_t TIM_Period;
uint16_t TIM_ClockDivision;
} TIM_TimeBaseInitTypeDef;
①TIM_Period 设置了在下一个更新事件装入活动的自动重装载寄存器周期的值。它的取值必须在 0x0000 和0xFFFF 之间。
②TIM_Prescaler 设置了用来作为 TIMx 时钟频率除数的预分频值。它的取值必须在 0x0000 和 0xFFFF 之间。
③TIM_ClockDivision 设置了时钟分割。该参数取值见下表。
TIM_CKD_DIV1 TDTS = Tck_tim
TIM_CKD_DIV2 TDTS = 2Tck_tim
TIM_CKD_DIV4 TDTS = 4Tck_tim
④TIM_CounterMode 选择了计数器模式。该参数取值见下表。
TIM_CounterMode_Up TIM 向上计数模式
TIM_CounterMode_Down TIM 向下计数模式
TIM_CounterMode_CenterAligned1 TIM 中央对齐模式 1 计数模式
TIM_CounterMode_CenterAligned2 TIM 中央对齐模式 2 计数模式
TIM_CounterMode_CenterAligned3 TIM 中央对齐模式 3 计数模式
3) 设置 TIM3_DIER 允许更新中断。
因为我们要使用 TIM3 的更新中断, 寄存器的相应位便可使能更新中断。 在库函数里面定时器中断使能是通过 TIM_ITConfig 函数来实现的:
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
①选择定时器号 取值为TIM1-TIM7
②选择使能的定时器的中断类型
TIM_IT_Update TIM 中断源
TIM_IT_CC1 TIM 捕获/比较 1 中断源
TIM_IT_CC2 TIM 捕获/比较 2 中断源
TIM_IT_CC3 TIM 捕获/比较 3 中断源
TIM_IT_CC4 TIM 捕获/比较 4 中断源
TIM_IT_Trigger TIM 触发中断源
③使能指定的中断 ENABLE DISABLE
4) TIM3 中断优先级设置。
NVIC
5) 允许 TIM3 工作,也就是使能 TIM3。
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)
这个函数非常简单,比如我们要使能定时器 3,方法为:
TIM_Cmd(TIM3, ENABLE); //使能 TIMx 外设
6) 编写中断服务函数。
在最后,还是要编写定时器中断服务函数,通过该函数来处理定时器产生的相关中断。在中断产生后,通过状态寄存器的值来判断此次产生的中断属于什么类型。然后执行相关的操作,我们这里使用的是更新(溢出)中断,所以在状态寄存器 SR 的最低位。在处理完中断之后应该向 TIM3_SR 的最低位写 0,来清除该中断标志。
在固件库函数里面, 用来读取中断状态寄存器的值判断中断类型的函数是:
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t)
该函数的作用是,判断定时器 TIMx 的中断类型 TIM_IT 是否发生中断。 比如,我们要判断定
时器 3 是否发生更新(溢出)中断,方法为:
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
{}
固件库中清除中断标志位的函数是:
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT)
该函数的作用是,清除定时器 TIMx 的中断 TIM_IT 标志位。 使用起来非常简单,比如我们在TIM3 的溢出中断发生后,我们要清除中断标志位,方法是:
TIM_ClearITPendingBit(TIM3, TIM_IT_Update );
例子:
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;//①
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseStructure.TIM_Period = arr; //②
TIM_TimeBaseStructure.TIM_Prescaler =psc;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE );//③
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //④
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM3, ENABLE); //⑤
}
void TIM3_IRQHandler(void) //⑥
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update );
LED1=!LED1;
}
}
流程首先第一步就是使能相应的时钟,使其有能量的来源 第二步就是写定时器的参数函数其中有四点 第三部就是使能要用的中断 第四部设定中断的优先级 第五步使能定时器的中断 最后就是编写中断程序PWM的输出
1)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定时器 3 时钟
2) 初始化 TIM3,设置 TIM3 的 ARR 和 PSC。在开启了 TIM3 的时钟之后,我们要设置 ARR 和 PSC 两个寄存器的值来控制输出 PWM 的周期。当 PWM 周期太慢(低于 50Hz)的时候,我们就会明显感觉到闪烁了。因此, PWM 周期在这里不宜设置的太小。 这在库函数是通过 TIM_TimeBaseInit 函数实现的调用的格式为:
TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化 TIMx 的
3) 设置 TIM3_CH2 的 PWM 模式,使能 TIM3 的 CH2 输出。接下来,我们要设置 TIM3_CH2 为 PWM 模式(默认是冻结的) 在库函数中, PWM 通道设置是通过函数 TIM_OC1Init()~TIM_OC4Init()来设置的我们直接来看看结构体的定义:
typedef struct
{
uint16_t TIM_OCMode;
uint16_t TIM_OutputState;
uint16_t TIM_Pulse;
uint16_t TIM_OCPolarity;
} TIM_OCInitTypeDef;
这一部分也是重点
参数 TIM_OCMode 设置模式是 PWM 还是输出比较,这里我们是 PWM 模式。
TIM_OCMode_Timing TIM 输出比较时间模式 比较成功后不在对应输出管脚上产生输出
TIM_OCMode_Active TIM 输出比较主动模式
TIM_OCMode_Inactive TIM 输出比较非主动模式
TIM_OCMode_Toggle TIM 输出比较触发模式 比较成功后反转电平
TIM_OCMode_PWM1 TIM 脉冲宽度调制模式 1
TIM_OCMode_PWM2 TIM 脉冲宽度调制模式 2
参数 TIM_OutputState 用来设置比较输出使能,也就是使能 PWM 输出到端口。
TIM_OutputState_Enable;
TIM_OutputState_Disable;
参数 TIM_OCPolarity 用来设置极性是高还是低。
TIM_OCPolarity_High TIM 输出比较极性高
TIM_OCPolarity_Low TIM 输出比较极性低
例子:
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择 PWM 模式 2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性高 意味高电平为有效
TIM_OC2Init(TIM3, &TIM_OCInitStructure); //初始化 TIM3 OC2
关于为什么没有用TIM_Pulse 实际上在后面的TIM_SetCompare2(TIM3,led0pwmval);函数中后面一个参数的值就是TIM_Pulse的值 这么做的好处是这个值得修改可以在主函数中完成而不用修改源文件中的值 使操作更方便
4) 使能 TIM3。
TIM_Cmd(TIM3, ENABLE); //使能 TIM3
6) 修改 TIM3_CCR2 来控制占空比。
最后,在经过以上设置之后, PWM 其实已经开始输出了,只是其占空比和频率都是固定的,而我们通过修改 TIM3_CCR2 则可以控制 CH2 的输出占空比。在库函数中,修改 TIM3_CCR2 占空比的函数是:
void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2);
TIM_SetCompare2(TIM3,led0pwmval);
PWM1中若当前值小于CCR则为有效 有效可以根据输出极性来设定若为高则是高电平有效 此事duty=CCR/ARR 又CCR决定占空比 ARR决定周期
上一篇:STM32学习笔记(5):通用定时器PWM输出
下一篇:STM32 PWM波驱动模拟舵机(库函数版)
推荐阅读最新更新时间:2024-11-13 02:09
设计资源 培训 开发板 精华推荐
- 使用 Diodes Incorporated 的 PT8A3516 的参考设计
- LTC3803MPS6-5 同步反激式转换器的典型应用电路
- 使用 Analog Devices 的 LTC1595 的参考设计
- LTC1275、12 位、300 ksps 采样 A/D 转换器和基准电压源的典型应用
- 电子色子
- EVAL-AD7902SDZ,用于评估 AD7902 双路伪差分、16 位、1 MSPS PulSAR ADC 的评估板
- AP2281 单摆率控制 LED 负载开关的典型应用
- EVB_RT7236GQW,基于RT7236GQW 5A降压稳压器的评估板
- NCP4586 150 mA、低噪声、低压差稳压器的典型应用
- FRDM-BC3770-EVB、BC3770 Freedom电池充电器扩展板,不带KL25Z