标签: pwm互补输出stm32高级定时器stm32带死区pwm输出 |
高级控制定时器(TIM1 和 TIM8)和通用定时器在基本定时器的基础上引入了外部引脚,可以实现输入捕获和输出比较功能。高级控制定时器比通用定时器增加了可编程死区互补输出、重复计数器、带刹车(断路)功能,这些功能都是针对工业电机控制方面。这几个功能在本书不做详细的介绍,主要介绍常用的输入捕获和输出比较功能。高级控制定时器时基单元包含一个 16 位自动重装载寄存器 ARR,一个 16 位的计数器CNT,可向上/下计数,一个 16位可编程预分频器 PSC,预分频器时钟源有多种可选,有内部的时钟、外部时钟。还有一个 8 位的重复计数器 RCR,这样最高可实现 40位的可编程定时。
高级定时器功能框图如下:
高级控制定时器时基单元功能包括四个寄存器,分别是计数器寄存器(CNT)、预分频器寄存器(PSC)、自动重载寄存器(ARR)和重复计数器寄存器(RCR)。其中重复计数器 RCR是高级定时器独有,通用和基本定时器没有。前面三个寄存器都是 16 位有效, TIMx_RCR寄存器是 8 位有效。
输入捕获可以对输入的信号的上升沿,下降沿或者双边沿进行捕获,常用的有测量输入信号的脉宽和测量 PWM 输入信号的频率和占空比这两种。
输入捕获的大概的原理就是,当捕获到信号的跳变沿的时候,把计数器 CNT 的值锁存到捕获寄存器 CCR 中,把前后两次捕获到的 CCR 寄存器中的值相减,就可以算出脉宽或零死角玩转 者频率。如果捕获的脉宽的时间长度超过你的捕获定时器的周期,就会发生溢出,这个我们需要做额外的处理。
输出比较就是通过定时器的外部引脚对外输出控制信号,有冻结、将通道 X(x=1,2,3,4)设置为匹配时输出有效电平、将通道 X 设置为匹配时输出无效电平、翻转、强制变为无效电平、强制变为有效电平、 PWM1 和 PWM2 这八种模式,具体使用哪种模式由寄存器 CCMRx 的位 OCxM[2:0]配置。其中 PWM 模式是输出比较中的特例,使用的也最多。
PWM就是对外输出脉宽(即占空比)可调的方波信号,信号频率由自动重装载寄存器ARR的值决定,信号占空比由比较寄存器CCR的值决定。
时基结构体 TIM_TimeBaseInitTypeDef用于定时器基础参数设置,与 TIM_TimeBaseInit函数配合使用完成配置。
代码清单 33-1 定时器基本初始化结构体
1 typedef struct {
2 uint16_t TIM_Prescaler; |
|
// 预分频器 |
3 uint16_t TIM_CounterMode; |
|
// 计数模式 |
4 uint32_t TIM_Period; |
|
// 定时器周期 |
5 uint16_t TIM_ClockDivision; |
|
// 时钟分频 |
6 uint8_t TIM_RepetitionCounter; |
|
// 重复计算器 |
7 } TIM_TimeBaseInitTypeDef;
输出比较结构体 TIM_OCInitTypeDef 用于输出比较模式,与 TIM_OCxInit 函数配合使用完成指定定时器输出通道初始化配置。高级控制定时器有四个定时器通道,使用时都必须单独设置。
代码清单 33-2 定时器比较输出初始化结构体
1 typedef struct {
2 uint16_t TIM_OCMode; |
|
// 比较输出模式 |
3 uint16_t TIM_OutputState; |
|
// 比较输出使能 |
4 uint16_t TIM_OutputNState; |
|
// 比较互补输出使能 |
5 uint32_t TIM_Pulse; |
|
// 脉冲宽度 |
6 uint16_t TIM_OCPolarity; |
|
// 输出极性 |
7 uint16_t TIM_OCNPolarity; |
|
// 互补输出极性 |
8 uint16_t TIM_OCIdleState; |
|
// 空闲状态下比较输出状态 |
9 uint16_t TIM_OCNIdleState; |
|
// 空闲状态下比较互补输出状态 |
10 } TIM_OCInitTypeDef;
输入捕获结构体 TIM_ICInitTypeDef 用于输入捕获模式,与 TIM_ICInit 函数配合使用完成定时器输入通道初始化配置。如果使用 PWM 输入模式需要与 TIM_PWMIConfig 函数配合使用完成定时器输入通道初始化配置。
代码清单 33-3 定时器输入捕获初始化结构体
1 typedef struct {
2 uint16_t TIM_Channel; |
|
// 输入通道选择 |
3 uint16_t TIM_ICPolarity; |
|
// 输入捕获触发选择 |
4 uint16_t TIM_ICSelection; |
|
// 输入捕获选择 |
5 uint16_t TIM_ICPrescaler; |
|
// 输入捕获预分频器 |
6 uint16_t TIM_ICFilter; |
|
// 输入捕获滤波器 |
7 } TIM_ICInitTypeDef;
断路和死区结构体 TIM_BDTRInitTypeDef 用于断路和死区参数的设置,属于高级定时器专用,用于配置断路时通道输出状态,以及死区时间。它与 TIM_BDTRConfig 函数配置使用完成参数配置。 这个结构体的成员只对应 BDTR 这个寄存器,有关成员的具体使用配置请参考手册 BDTR 寄存器的详细描述。
代码清单 33-4 断路和死区初始化结构体
1 typedef struct {
2 uint16_t TIM_OSSRState; |
|
// 运行模式下的关闭状态选择 |
3 uint16_t TIM_OSSIState; |
|
// 空闲模式下的关闭状态选择 |
4 uint16_t TIM_LOCKLevel; |
|
// 锁定配置 |
5 uint16_t TIM_DeadTime; |
|
// 死区时间 |
6 uint16_t TIM_Break; |
|
// 断路输入使能控制 |
7 uint16_t TIM_BreakPolarity; |
|
// 断路输入极性 |
8 uint16_t TIM_AutomaticOutput; |
|
// 自动输出使能 |
9 } TIM_BDTRInitTypeDef;
(1) 定时器用到的 GP IO 初始化
(2) 定时器时基结构体 TIM_TimeBaseInitTypeDef 初始化
(3) 定时器输出比较结构体 TIM_OCInitTypeDef 初始化
(4) 定时器刹车和死区结构体 TIM_BDTRInitTypeDef 初始化
#include "Advance_timer.h"
static void ADVANCE_TIM_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//输出比较通道GPIO初始化
RCC_APB2PeriphClockCmd(ADVANCE_TIM_CH1_GPIO_CLK,ENABLE);
GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_CH1_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(ADVANCE_TIM_CH1_PORT, &GPIO_InitStructure);
//输出比较通道的互补通道GPIO初始化
RCC_APB2PeriphClockCmd(ADVANCE_TIM_CH1N_GPIO_CLK,ENABLE);
GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_CH1N_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(ADVANCE_TIM_CH1N_PORT, &GPIO_InitStructure);
//输出比较通道的刹车通道GPIO初始化
RCC_APB2PeriphClockCmd(ADVANCE_TIM_BKIN_GPIO_CLK,ENABLE);
GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_BKIN_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(ADVANCE_TIM_BKIN_PORT, &GPIO_InitStructure);
//BKIN引脚默认输出低电平
GPIO_ResetBits(ADVANCE_TIM_BKIN_PORT,ADVANCE_TIM_BKIN_PIN);
}
static void ADVANCE_TIM_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
//设置中断组为0
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
//设置中断来源
NVIC_InitStructure.NVIC_IRQChannel = ADVANCE_TIM_IRQ;
//设置抢占优先级
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
//设置子优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
// ARR :自动重装载寄存器的值
// CLK_cnt:计数器的时钟,等于 Fck_int / (psc+1) = 72M/(psc+1)
// PWM 信号的周期 T = ARR * (1/CLK_cnt) = ARR*(PSC+1) / 72M
// 占空比P=CCR/(ARR+1)
static void ADVANCE_TIM_MODE_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
//开启定时器时钟,即内部Fck_int = 72M
ADVANCE_TIM_APBxClock_FUN(ADVANCE_TIM_CLK,ENABLE);
//自动重装载寄存器的值,累计TIM_Period+1个计数后产生一个更新或中断
TIM_TimeBaseStructure.TIM_Period = ADVANCE_TIM_PERIOD;
//驱动CNT计数器的时钟 = Fck_int / (psc+1) = 72M/(psc+1)
TIM_TimeBaseStructure.TIM_Prescaler = ADVANCE_TIM_PSC;
//时钟分频因子,配置死区时间时用到
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
//计数器计数模式,配置为向上计数
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(ADVANCE_TIM, & TIM_TimeBaseStructure);
// 配置为PWM模式1
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
// 输出使能
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
// 互补输出使能
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
// 设置占空比大小
TIM_OCInitStructure.TIM_Pulse = ADVANCE_TIM_PULSE;
// 输出通道电平极性配置
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
// 互补输出通道电平极性配置
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
// 输出通道空闲电平极性配置
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
// 互补输出通道空闲电平极性配置
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
TIM_OC1Init(ADVANCE_TIM, &TIM_OCInitStructure);
//使能TIMx在CCR1上的预装载寄存器
TIM_OC1PreloadConfig(ADVANCE_TIM, TIM_OCPreload_Enable);
// 有关刹车和死区结构体的成员具体可参考BDTR寄存器的描述
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;
// 输出比较信号死区时间配置,具体如何计算可参考 BDTR:UTG[7:0]的描述
// 这里配置的死区时间为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);
// 使能计数器
TIM_Cmd(ADVANCE_TIM, ENABLE);
// 主输出使能,当使用的是通用定时器时,这句不需要
TIM_CtrlPWMOutputs(ADVANCE_TIM, ENABLE);
}
void ADVANCE_TIM_Init(void)
{
ADVANCE_TIM_GPIO_Config();
ADVANCE_TIM_NVIC_Config();
ADVANCE_TIM_MODE_Config();
}
分享:
1
喜欢
0
赠金笔
阅读(2812)┊ 评论 (1)┊ 收藏(0) ┊转载(0) ┊ 喜欢▼ ┊打印┊举报/Report
前一篇:STM32学习总结-定时器PWM输入捕获测量脉冲的最小和最大频率计算公式
后一篇:STM32F10xx开发板学习笔记-MPU6050传感器实验
评论 重要提示:警惕虚假中奖信息
[发评论]
东理电子科技协会
内容还不够深入和全面。
2017-4-27 16:15回复(0)