目录标题
- 一.基本定时器
-
- 1.基本定时器简介
- 2.时基单元
- 3.基本定时器定时实验
- 二.高级/通用定时器
-
- 1.计数器模式
- 2.时钟选择
- 3.产生输出比较PWM波
- 4.通用定时器PWM输出实验
- 5.高级定时器死区时间的互补输出PWM实验
- 6.高级定时器输入捕获-测量脉宽
- 7.TIM—高级定时器-PWM输入捕获实验
- 三.总结
数模转换器(DAC)提供时钟。实际上,它们在芯片内部直接连接到DAC通过触发输出直接驱动DAC。这两个定时器是独立的,不共享任何资源
**
计数模式 预加载自动重装载使能量位置(ARPE)
时钟源
计算定时时间 *定时器的定时时间等于计数器的中断周期乘以中断次数。计数器在 CK_CNT 在驱动下,计数的时间是 CK_CLK 倒数等于:1/(TIMxCLK/(PSC 1),中断时间等于:1/(CK_CLK * ARR)。如果在中断服务程序中设置 time,用来 记 录 中 断的 次 数,那 么 就 可 以计 算 出我们 需 要 的 定时 时 间等于 : 1/CK_CLK * (ARR 1)time。
定时器初始化结构的详细解释
滤波器分频比,基本定时器无此功能,无需设置。 (5) TIM_RepetitionCounter:属于高级控制寄存器专用寄存器位的重复计数器,它可以很容易地控制输出 PWM 的个数,以后会解释。
因此,我们只需要使用基本定时器的分频值PSC与重装载ARR
因为代码很简单,直接上代码
main.c
int main(void) {
//LED 端口初始化 LED_GPIO_Config(); ///基本定时器初始化 BASIC_TIM_Init(); while(1)
{
//500次更新中断(500ms),LED翻转一次
if( g_time==500 )
{
LED1_TOGGLE
g_time=0;
}
}
}
BasicTim.h
#ifndef __BASICTIM_H
#define __BASICTIM_H
#include "stm32f10x.h"
#define BASIC_TIM6
#ifdef BASIC_TIM6
#define BASIC_TIM TIM6
#define BASIC_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd
#define BASIC_TIM_CLK RCC_APB1Periph_TIM6
#define BASIC_TIM_Prescaler (72-1)
#define BASIC_TIM_Period (1000-1)
#define BASIC_TIM_IRQn TIM6_IRQn
#define BASIC_TIM_IRQHandler TIM6_IRQHandler
#else
#define BASIC_TIM TIM6
#define BASIC_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd
#define BASIC_TIM_CLK RCC_APB1Periph_TIM6
#define BASIC_TIM_Prescaler (72-1)
#define BASIC_TIM_Period (1000-1)
#define BASIC_TIM_IRQn TIM6_IRQn
#define BASIC_TIM_IRQHandler TIM6_IRQHandler
#endif /* BASIC_TIM6 */
void BASIC_TIM_Init(void);
#endif /*__BASICTIM_H*/
BasicTim.c
#include "BasicTim.h"
static void BASIC_TIM_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructrue;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructrue.NVIC_IRQChannel = BASIC_TIM_IRQn;
NVIC_InitStructrue.NVIC_IRQChannelPreemptionPriority =1;
NVIC_InitStructrue.NVIC_IRQChannelSubPriority =1;
NVIC_InitStructrue.NVIC_IRQChannelCmd =ENABLE;
NVIC_Init(&NVIC_InitStructrue);
}
static void BASIC_TIM_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructrue;
//开启定时器时钟
BASIC_TIM_APBxClock_FUN(BASIC_TIM_CLK,ENABLE);
//时钟预分频
TIM_TimeBaseInitStructrue.TIM_Prescaler =BASIC_TIM_Prescaler;
//重装载寄存器
TIM_TimeBaseInitStructrue.TIM_Period =BASIC_TIM_Period;
TIM_TimeBaseInit(BASIC_TIM,&TIM_TimeBaseInitStructrue);
TIM_ClearFlag(BASIC_TIM,TIM_FLAG_Update);
TIM_ITConfig(BASIC_TIM,TIM_IT_Update,ENABLE);
TIM_Cmd(BASIC_TIM, ENABLE);
}
void BASIC_TIM_Init(void)
{
BASIC_TIM_NVIC_Config();
BASIC_TIM_Config();
}
中断服务函数
高级定时器有所有定时器的功能,所以以高级定时器讲解为主,通用定时器就是在高级对定时器做减法 高级控制定时器比通用定时器增加了可编程死区互补输出、重复计数器、带刹车(断路)功能,这些功能都是针对工业电机控制方面,而且比通用定时器多了个重复。 高级定时器的功能: TIM1和TIM8定时器的功能包括: ● 16位向上、向下、向上/下自动装载计数器 ● 16位可编程(可以实时修改)预分频器,计数器时钟频率的分频系数为1~65535之间的任意 数值 ● 多达4个独立通道: ─ 输入捕获 ─ 输出比较 ─ PWM生成(边缘或中间对齐模式) ─ 单脉冲模式输出 ● 死区时间可编程的互补输出 ● 使用外部信号控制定时器和定时器互联的同步电路 ●允许在指定数目的计数器周期之后更新定时器寄存器的重复计数器 ● 刹车输入信号可以将定时器输出信号置于复位状态或者一个已知状态 ● 如下事件发生时产生中断/DMA: ─ 更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发) ─ 触发事件(计数器启动、停止、初始化或者由内部/外部触发计数) ─ 输入捕获 ─ 输出比较 ─ 刹车信号输入 ● 支持针对定位的增量(正交)编码器和霍尔传感器电路 ● 触发输入作为外部时钟或者按周期的电流管理 高级/通用定时器的时基单元与基本定时器一致,这里就不赘言啦。 不过高级定时器多了个重复计数器。
重复计数寄存器
在定时器发生上溢或下溢 事件是递减重复计数器的值,只有当重复计数器为 0 时才会生成更新事件。在发生 N+1个上溢或下溢事件(N 为 RCR 的值)时产生更新事件。
重复计数器在下述任一条件成立时递减(递减一次): ● 向上计数模式下每次计数器溢出时 ●向下计数模式下每次计数器下溢时 ●中央对齐模式下每次上溢和每次下溢时 虽然这样限制了PWM的最大循环周期为128(重复计数器是8位的),但它能够在每个PWM周期2次更新占空比。在中央对齐模式下,因为波形是对称的,如果每个PWM周期中仅刷新一次比较寄存器,则最大的分辨率为2xTck。
当更新事件由软件产生(通过设置TIMx_EGR 中的UG位)或者通过硬件的从模式控制器产生,则无论重复计数器的值是多少,立即发生更新事件,并且TIMx_RCR寄存器中的内容被重载入到重复计数器。
1.向上计数模式 在向上计数模式中,计数器从0计数到自动加载值(TIMx_ARR计数器的内容),然后重新从0开始计数并且产生一个计数器溢出事件。 如果使用了重复计数器功能,在向上计数达到设置的重复计数次数(TIMx_RCR)时,产生更新事件(UEV);否则每次计数器溢出时就会产生更新事件。
当发生一个更新事件时,所有的寄存器都被更新,硬件同时(依据URS位)设置更新标志位(TIMx_SR寄存器中的UIF位) ● 重复计数器被重新加载为TIMx_RCR寄存器的内容。 ● 自动装载影子寄存器被重新置入预装载寄存器的值(TIMx_ARR)。 ● 预分频器的缓冲区被置入预装载寄存器的值(TIMx_PSC寄存器的内容) 2.向下计数模式 在向下模式中,计数器从自动装入的值(TIMx_ARR计数器的值)开始向下计数到0,然后从自动装入的值重新开始并且产生一个计数器向下溢出事件,如果使用了重复计数器,当向下计数重复了重复计数寄存器(TIMx_RCR)中设定的次数后,将产生更新事件(UEV),否则每次计数器下溢时就产生更新事件
当发生更新事件时,所有的寄存器都被更新,并且(根据URS位的设置)更新标志位(TIMx_SR寄存器中的UIF位)也被设置。 ● 重复计数器被重置为TIMx_RCR寄存器中的内容 ● 预分频器的缓存器被加载为预装载的值(TIMx_PSC寄存器的值)。 ● 当前的自动加载寄存器被更新为预装载值(TIMx_ARR寄存器中的内容)。注:自动装载在计数器重载入之前被更新,因此下一个周期将是预期的值。 3.中央对齐模式(向上/向下计数) 在中央对齐模式,计数器从0开始计数到自动加载的值(TIMx_ARR寄存器)−1,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器下溢事件;然后再从0开始重新计数。 在此模式下,不能写入TIMx_CR1中的DIR方向位。它由硬件更新并指示当前的计数方向。
可以在每次计数上溢和每次计数下溢时产生更新事件;也可以通过(软件或者使用从模式控制器)设置TIMx_EGR寄存器中的UG位产生更新事件。然后,计数器重新从0开始计数,预分频器也重新从0开始计数。
其他两个模式依次类推
计数器时钟可由下列时钟源提供: ● 内部时钟(CK_INT) ● 外部时钟模式1:外部输入引脚 ● 外部时钟模式2:外部触发输入ETR ● 内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器。如可以配置一个定时器Timer1而作为另一个定时器Timer2的预分频器。
如果禁止了从模式控制器(SMS=000),则CEN、DIR(TIMx_CR1寄存器)和UG位(TIMx_EGR寄存器)是事实上的控制位,并且只能被软件修改(UG位仍被自动清除)。只要CEN位被写成’1’,预分频器的时钟就由内部时钟CK_INT提供
- 2.外部时钟源模式1 这是其中一个时钟信号输入引脚 当TIMx_SMCR寄存器的SMS=111时,此模式被选中。计数器可以在选定输入端的每个上升沿或下降沿计数。 1)时钟信号输入引脚 当使用外部时钟模式 1 的时候,时钟信号来自于定时器的输入通道,总共有 4 个,分别为 TI1/2/3/4,即 TIMx_CH1/2/3/4。具体使用哪一路信号,由 TIM_CCMRx 的位CCxS[1:0]配置,其中 CCMR1 控制 TI1/2,CCMR2 控制 TI3/4。
假设要配置要配置向上计数器在T12输入端的上升沿计数,使用下列步骤:
2)滤波器 如果来自外部的时钟信号的频率过高或者混杂有高频干扰信号的话,我们就需要使用滤波器对信号重新采样,来达到降频或者去除高频干扰的目的,具体的由 TIMx_CCMRx的位 ICxF[3:0]配置。 配置TIMx_CCMR1寄存器的IC2F[3:0],选择输入滤波器带宽(如果不需要滤波器,保持IC2F=0000) 3)边沿检测 边沿检测的信号来自于滤波器的输出,在成为触发信号之前,需要进行边沿检测,决定是上升沿有效还是下降沿有效,具体的由 TIMx_CCER 的位 CCxP 配置。 配置TIMx_CCER寄存器的CC2P=0,选定上升沿极性 4)触发选择 当使用外部时钟模式1时,触发源有两个,一个是滤波后的定时器输入 1(TI1FP1)和滤波后的定时器输入 2(TI2FP2),具体的由 TIMxSMCR 的位 TS[2:0]配置。 配置TIMx_SMCR寄存器中的TS=110,选定TI2作为触发输入源 5)从模式选择 选定了触发源信号后,最后我们需把信号连接到 TRGI 引脚,让触发信号成为外部时钟模式 1 的输入,最终等于 CK_PSC,然后驱动计数器 CNT 计数。具体的配置TIMx_SMCR 的位 SMS[2:0]为 111 即可选择外部时钟模式 1。 6)使能计数器 设置TIMx_CR1寄存器的CEN=1,启动计数器 当上升沿出现在TI2,计数器计数一次,且TIF标志被设置。 外部时钟1配置库函数
选定此模式的方法为:令TIMx_SMCR寄存器中的ECE=1 计数器能够在外部触发ETR的每一个上升沿或下降沿计数 例如,要配置在ETR下每2个上升沿计数一次的向上计数器,使用下列步骤
1)时钟信号输入引脚 当使用外部时钟模式 2 的时候,时钟信号来自于定时器的特定输入通道 TIMx_ETR,只有 1 个。 2)外部触发极性 来自 ETR 引脚输入的信号可以选择为上升沿或者下降沿有效,具体的由 TIMx_SMCR的位 ETP 配置。
选择ETR的上升沿检测,置TIMx_SMCR寄存器中的ETP=0 3)外部触发预分频器 由于 ETRP 的信号的频率不能超过 TIMx_CLK(72M)的 1/4,当触发信号的频率很高的情况下,就必须使用分频器来降频,具体的由 TIMx_SMCR 的位 ETPS[1:0]配置。
设置预分频器,置TIMx_SMCR寄存器中的ETPS[1:0]=01 3)滤波器 如果 ETRP 的信号的频率过高或者混杂有高频干扰信号的话,我们就需要使用滤波器对 ETRP 信号重新采样,来达到降频或者去除高频干扰的目的。具体的由 TIMx_SMCR 的位 ETF[3:0]配置,其中的 fDTS是由内部时钟 CK_INT 分频得到,具体的由 TIMx_CR1 的位CKD[1:0]配置。 整个定时器的滤波器都是一样的功能。
本例中不需要滤波器,置TIMx_SMCR寄存器中的ETF[3:0]=0000 4)从模式选择 经过滤波器滤波的信号连接到 ETRF 引脚后,触发信号成为外部时钟模式 2 的输入,最终等于 CK_PSC,然后驱动计数器 CNT 计数。具体的配置 TIMx_SMCR 的位 ECE 为 1即可选择外部时钟模式 2。
开启外部时钟模式2,写TIMx_SMCR寄存器中的ECE=1 6)使能计数器 启动计数器,写TIMx_CR1寄存器中的CEN=1 计数器在每2个ETR上升沿计数一次 外部时钟模式2配置库函数
- 4.内部触发输入(ITRx) 使用一个定时器作为另一个定时器的预分频器。如可以配置一个定时 器Timer1而作为另一个定时器Timer2的预分频器。 ● 配置定时器1为主模式,它可以在每一个更新事件UEV时输出一个周期性的触发信号。在TIM1_CR2寄存器的MMS=’010’时,每当产生一个更新事件时在TRGO1上输出一个
上升沿
信号。 ● 连接定时器1的TRGO1输出至定时器2,设置TIM2_SMCR寄存器的TS=’001’,配置定时器2为使用ITR1作为内部触发的从模式。 ● 然后把从模式控制器置于外部时钟模式1(TIM2_SMCR寄存器的SMS=111);这样定时器2即可由定时器1周期性的上升沿(即定时器1的计数器溢出)信号驱动。 ● 最后,必须设置相应(TIMx_CR1寄存器)的CEN位分别启动两个定时器。
什么是PWM 脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。
输出比较的输出控制中,参考信号 OCxREF 在经过死区发生器之后会产生两路带死区的互补信号(通道 1~3 才有互补信号,通道 4 没有,其余跟通道1 ~ 3 一样),这两路带死区的互补信号然后就进入输出控制电路,如果没有加入死区控制,那么进入输出控制电路的信号就直接是 OCxREF。
1.PWM模式 脉冲宽度调制模式可以产生一个由TIMx_ARR寄存器确定频率、由TIMx_CCRx寄存器确定占空比的信号。
在TIMx_CCMRx寄存器中的OCxM位写入’110’(PWM模式1或’111’(PWM模式2),能够独立地设置每个OCx输出通道产生一路PWM。
先以简单的通道4位例,不带互补输出和死区控制
这里我都以通道1的寄存器位讲解,通道4是一模一样 控制OC1_REF的输出 选择有效电平,假设选择高电平有效 当选择PWM模式1,高电有效时,向上计数时 当选择PWM模式2,高电有效时,向上计数时 最后就是打开通道输出的开关 必须通过设置TIMx_CCMRx寄存器的OCxPE位使能相应的预装载寄存器,最后还要设置TIMx_CR1寄存器的ARPE位,(在向上计数或中心对称模式中)使能自动重装载的预装载寄存器。 对应库函数 相关库函数
- PWM 边沿对齐模式 ● 向上计数配置 下面是一个PWM模式1的例子。当TIMx_CNT<TIMx_CCRx时,PWM参考信号OCxREF为=高,否则为低。特殊情况(如果TIMx_CCRx中的比较值大于自动重装载值(TIMx_ARR),则OCxREF保持为’1’。如果比较值为0,则OCxREF保持为’0’。) 下图为TIMx_ARR=8时边沿对齐的PWM波形实例
首先要知道一个比较中断标记位
● 向上计数配置 下面是一个PWM模式1的例子。当TIMx_CNT<TIMx_CCRx时,PWM参考信号OCxREF为=高,否则为低。特殊情况(如果TIMx_CCRx中的比较值大于自动重装载值(TIMx_ARR),则OCxREF保持为’1’。如果比较值为0,则OCxREF保持为’0’。) 下图为TIMx_ARR=8时边沿对齐的PWM波形实例
● 向下计数的配置 当TIMx_CR1寄存器的DIR位为高时执行向下计数。参看13.3.2节。 在PWM模式1,当TIMx_CNT>TIMx_CCRx时参考信号OCxREF为低,否则为高。如果 TIMx_CCRx中的比较值大于TIMx_ARR中的自动重装载值,则OCxREF保持为’1’。该模式下不能产生0%的PWM波形。
PWM 中央对齐模式 当TIMx_CR1寄存器中的CMS位不为’00’时为中央对齐模式(所有其他的配置对OCxREF/OCx信号都有相同的作用)。根据不同的CMS位设置(中央对齐模式1、2、3),比较标志可以在计数器向上计数时被置1、在计数器向下计数时被置1、或在计数器向上和向下计数时被置1,TIMx_CR1寄存器中的计数方向位(DIR)由硬件更新,不要用软件修改它。 下图给出了一些中央对齐的PWM波形的例子
● TIMx_ARR=8 ● PWM模式1 ● TIMx_CR1寄存器的CMS=01,在中央对齐模式1下,当计数器向下计数时设置比较标志。
三种模式中央对齐模式中断标志何时置位: 中央对齐模式1(CSM=01): 只在计数器向下计数时,且TIMx_CNT的值与TIMx_CCR1的值相等CCXIF位被置位
中央对齐模式2(CSM=10): 只在计数器向上计数时,且TIMx_CNT的值与TIMx_CCR1的值相等CCXIF位被置位
中央对齐模式3(CSM=11): 在计数器向上和向下计数时,且TIMx_CNT的值与TIMx_CCR1的值相等CCXIF位均被置位。** 稍微画的有点乱了,不过噢配合文字还是可以理解清楚的
在看野火的就很好理解了 在中心对齐模式下,计数器 CNT 是工作做递增/递减模式下。开始的时候,计数器CNT 从 0 开始计数到自动重载值减 1(ARR-1),生成计数器上溢事件;然后从自动重载值开始向下计数到 1 并生成计数器下溢事件。之后从 0 开始重新计数。 图 32-14 是 PWM1 模式的中心对齐波形,ARR=8,CCR=4。第一阶段计数器 CNT 工作在递增模式下,从 0 开始计数,当 CNT<CCR 的值时,OCxREF 为有效的高电平,当CCR=<CNT<<ARR 时,OCxREF 为无效的低电平。第二阶段计数器 CNT 工作在递减模式从 ARR 的值开始递减,当 CNT>CCR 时,OCxREF 为无效的低电平,当 CCR=>CNT>=1时,OCxREF 为有效的高电平。
- 实验目的 使用定时器3的PWM功能,输出占空比可变PWM波,用来驱动LED灯,从而达到LED亮度由暗变亮,又从亮变暗,如此循环。
- 实验原理
一般人眼睛对于80Hz 以上刷新频率则完全没有闪烁感。频率太小的话 看起来就会闪烁 那么我们平时见到的LED灯,当它的频率大于50Hz的时候,人眼就会产生视觉暂留效果,基本就看不到闪烁了,而是一个常亮的LED灯。
但是如果是10毫秒内,5毫秒打开,5毫秒关闭,(频率100Hz) 这时候灯光的亮灭速度赶不上开关速度(LED灯还没完全亮就又熄灭了),由于视觉暂留作用 人眼不感觉电灯在闪烁,而是感觉灯的亮度少了 因为高电平时间(占空比)为50% 亮度也就为之前的50% 频率很高时,看不到闪烁,占空比越大,LED越亮; 频率很低时,可看到闪烁,占空比越大,LED越亮。 所以,在频率一定下,可以用不同占空比改变LED灯的亮度。使其达到一个呼吸灯的效果
我们选这PWM模式1、向上计数、高电平有效,然后输出一个PWM波,通过调解CRR寄存器的值,来改变PWM的占空比 首先我们知道 所以占比空越大高电平的时间越长灯就会越暗,所以我们先将占空比调成100%灯全灭,然后将占空比慢慢变小灯就会慢慢变亮(到最亮),然后又将占空比调大又慢慢熄灭,然后反复如此就是呼吸灯了
直接上代码: main.c
#include "stm32f10x.h"
#include "bsp_led.h"
#include "GeneralTim.h"
#define SOFT_DELAY Delay(0x0FFF1);
void Delay(__IO u32 nCount);
int main(void)
{
uint16_t led0pwmval=600;
uint8_t dir=1;
/* LED 端口初始化 */
LED_GPIO_Config();
//通用定时器初始化
GENERAL_TIM_Init();
while(1)
{
SOFT_DELAY
if(dir==1)
{
led0pwmval--;
}
else
{
led0pwmval++;
}
if(led0pwmval<300)
{
dir=0;
}
if(led0pwmval==600)
{
dir=1;
}
TIM_SetCompare3(GENERAL_TIM,led0pwmval);
}
}
void Delay(__IO uint32_t nCount) //简单的延时函数
{
for(; nCount != 0; nCount--);
}
GeneralTim.c
#include "GeneralTim.h"
static void GENERAL_TIM_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(GENERAL_TIM_CH3_GPIO_CLK,ENABLE);
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin =GENERAL_TIM_CH3_PIN;
GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
GPIO_Init(GENERAL_TIM_CH3_PORT,&GPIO_InitStructure);
}
static void GENERAL_TIM_Mode_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructrue;
TIM_OCInitTypeDef TIM_OCInitStructrue;
//开启定时器时钟
GENERAL_TIM_APBxClock_FUN(GENERAL_TIM_CLK,ENABLE);
//时钟预分频
TIM_TimeBaseInitStructrue.TIM_Prescaler =GENERAL_TIM_Prescaler;
//重装载寄存器
TIM_TimeBaseInitStructrue.TIM_Period =GENERAL_TIM_Period;
//向上计数
TIM_TimeBaseInitStructrue.TIM_CounterMode =TIM_CounterMode_Up;
TIM_TimeBaseInitStructrue.TIM_ClockDivision =TIM_CKD_DIV1;
TIM_TimeBaseInit(GENERAL_TIM,&TIM_TimeBaseInitStructrue);
//选择PWM1模式
TIM_OCInitStructrue.TIM_OCMode =TIM_OCMode_PWM1;
//使能输出通道
TIM_OCInitStructrue.TIM_OutputState =TIM_OutputState_Enable;
//高电平有效
TIM_OCInitStructrue.TIM_OCPolarity =TIM_OCPolarity_High;
TIM_OCInitStructrue.TIM_Pulse =600;
TIM_OC3Init(GENERAL_TIM, &TIM_OCInitStructrue);
//CRR3预装载使能
TIM_OC3PreloadConfig(GENERAL_TIM,TIM_OCPreload_Enable);
TIM_Cmd(GENERAL_TIM, ENABLE);
}
void GENERAL_TIM_Init(void)
{
GENERAL_TIM_GPIO_Config();
GENERAL_TIM_Mode_Config();
}
GeneralTim.h
#ifndef __GENERALTIM_H
#define __GENERALTIM_H
#include "stm32f10x.h"
// TIM3 输出比较通道
#define GENERAL_TIM_CH3_GPIO_CLK RCC_APB2Periph_GPIOB
#define GENERAL_TIM_CH3_PORT GPIOB
#define GENERAL_TIM_CH3_PIN GPIO_Pin_0
#define GENERAL_TIM TIM3
#define GENERAL_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd
#define GENERAL_TIM_CLK RCC_APB1Periph_TIM3
#define GENERAL_TIM_Prescaler 0
#define GENERAL_TIM_Period (600-1)
void GENERAL_TIM_Init(void);
#endif /*__GENERALTIM_H */
进入输出控制电路的信号会被分成两路,一路是原始信号,一路是被反向的信号,具体的由寄存器 CCER 的位 CCxP 和 CCxNP 控制。经过极性选择的信号是否由 OCx 引脚输出到外部引脚 CHx/CHxN 则由寄存器 CCER 的位 CxE/CxNE 配置。
如果加入了断路(刹车)功能,则断路和死区寄存器 BDTR 的 MOE、OSSI 和 OSSR 这三个位会共同影响输出的信号。
为什么要有死区时间 高级控制定时器(TIM1和TIM8)能够输出两路互补信号,并且能够管理输出的瞬时关断和接通。这段时间通常被称为死区,用户应该根据连接的输出器件和它们的特性(电平转换的延时、电源开关的延时等)来调整死区时间。
死区发生器 在生成的参考波形 OCxREF 的基础上,可以插入死区时间,用于生成两路互补的输出信号 OCx 和 OCxN,死区时间的大小具体由 BDTR 寄存器的位 DTG[7:0]配置。死区时间的大小必须根据与输出信号相连接的器件及其特性来调整。下面我们简单举例说明下带死区的PWM 信号的应用,我们以一个板桥驱动电路为例
在这个半桥驱动电路中,Q1 导通,Q2 截止,此时我想让 Q1 截止 Q2 导通,肯定是要先让Q1 截止一段时间之后,再等一段时间才让 Q2 导通,那么这段等待的时间就称为死区时间,因为 Q1 关闭需要时间(由 MOS 管的工艺决定)。如果 Q1 关闭之后,马上打开 Q2,那么此时一段时间内相当于 Q1 和 Q2 都导通了,这样电路会短路。 死区时间应该调为多少用户应该根据连接的输出器件和它们的特性(电平转换的延时、电源开关的延时等)来调整死区时间
如何配置死区时间 断路功能 断路功能就是电机控制的刹车功能,使能断路功能时,根据相关控制位状态修改输出信号电平。在任何情况下,OCx 和 OCxN 输出都不能同时为有效电平,这关系到电机控制常用的 H 桥电路结构原因。 断路源可以是时钟故障事件,由内部复位时钟控制器中的时钟安全系统(CSS)生成,也可以是外部断路输入 IO,两者是或运算关系。 系统复位启动都默认关闭断路功能,将断路和死区寄存器(TIMx_BDTR)的 BKE 为置 1,使能断路功能。可通过 TIMx_BDTR 寄存器的 BKP 位设置设置断路输入引脚的有效电平,设置为 1 时输入 BRK 为高电平有效,否则低电平有效。
发送断路时,将产生以下效果: 1.TIMx_BDTR 寄存器中主输出模式使能(MOE)位被清零,输出处于无效、空闲或复位状态; 2. 根据相关控制位状态控制输出通道引脚电平;当使能通道互补输出时,会根据情况自动控制输出通道电平; 3. 将 TIMx_SR 寄存器中的 BIF 位置 1,并可产生中断和 DMA 传输请求。 4.如果 TIMx_BDTR 寄存器中的 自动输出使能(AOE)位置 1,则 MOE 位会在发生下一个 UEV 事件时自动再次置 1。 具体MOE、OSSI、OSSR、CCXE、CCXNE四个位如何影响OCX与OCXN输出状态看下图 定时器比较输出初始化结构体 (1) TIM_OCMode:比较输出模式选择,总共有八种,常用的为 PWM1/PWM2。它设定CCMRx 寄存器 OCxM[2:0]位的值。 (2) TIM_OutputState:比较输出使能,决定最终的输出比较信号 OCx 是否通过外部引脚输出。它设定 TIMx_CCER 寄存器 CCxE/CCxNE 位的值。 (3) TIM_OutputNState:比较互补输出使能,决定 OCx 的互补信号 OCxN 是否通过外部引脚输出。它设定 CCER 寄存器 CCxNE 位的值。 (4) TIM_Pulse:比较输出脉冲宽度,实际设定比较寄存器 CCR 的值,决定脉冲宽度。可设置范围16位为 0 至 65535。
(5) TIM_OCPolarity:比较输出极性,可选 OCx 为高电平有效或低电平有效。它决定着定时器通道有效电平。它设定 CCER 寄存器的 CCxP 位的值。 (6) TIM_OCNPolarity:比较互补输出极性,可选 OCxN 为高电平有效或低电平有效。它设定 TIMx_CCER 寄存器的 CCxNP 位的值。 (7) TIM_OCIdleState:空闲状态时通道输出电平设置,可选输出 1 或输出 0,即在空闲状态(BDTR_MOE 位为 0)时,经过死区时间后定时器通道输出高电平或低电平。它设定CR2 寄存器的 OISx 位的值。 (8) TIM_OCNIdleState:空闲状态时互补通道输出电平设置,可选输出 1 或输出 0,即在空闲状态(BDTR_MOE 位为 0)时,经过死区时间后定时器互补通道输出高电平或低电平,设定值必须与 TIM_OCIdleState 相反。它设定是 CR2 寄存器的 OISxN 位的值。
断路和死区初始化结构体 (1) TIM_OSSRState:运行模式下的关闭状态选择,它设定 BDTR 寄存器 OSSR 位的值。 (2) TIM_OSSIState:空闲模式下的关闭状态选择,它设定 BDTR 寄存器 OSSI 位的值。 (3) TIM_LOCKLevel:锁定级别配置, BDTR 寄存器 LOCK[1:0]位的值。 (4) TIM_DeadTime:配置死区发生器,定义死区持续时间,可选设置范围为 0x0 至 0xFF。它设定 BDTR 寄存器 DTG[7:0]位的值。 (5) TIM_Break:断路输入功能选择,可选使能或禁止。它设定 BDTR 寄存器 BKE 位的值。 (6) TIM_BreakPolarity:断路输入通道 BRK 极性选择,可选高电平有效或低电平有效。它设定 BDTR 寄存器 BKP 位的值。 (7) TIM_AutomaticOutput:自动输出使能,可选使能或禁止,它设定 BDTR 寄存器 AOE位的值。
TIM_高级定时器_PWM带死区时间带刹车控制的互补输出实验
Advance_Tim.h
#ifndef __ADVANCETIM_H
#define __ADVANCETIM_H
#include "stm32f10x.h"
/************高级定时器TIM参数定义,只限TIM1和TIM8************/
// 当使用不同的定时器的时候,对应的GPIO是不一样的,这点要注意
// 这里我们使用高级控制定时器TIM1
#define ADVANCE_TIM TIM1
#define ADVANCE_TIM_APBxClock_FUN RCC_APB2PeriphClockCmd
#define ADVANCE_TIM_CLK RCC_APB2Periph_TIM1
// PWM 信号的频率 F = TIM_CLK/{(ARR+1)*(PSC+1)}
#define ADVANCE_TIM_PERIOD (8-1)
#define ADVANCE_TIM_PSC (9-1)
#define ADVANCE_TIM_PULSE 4
// TIM1 输出比较通道
#define ADVANCE_TIM_CH1_GPIO_CLK RCC_APB2Periph_GPIOA
#define ADVANCE_TIM_CH1_PORT GPIOA
#define ADVANCE_TIM_CH1_PIN GPIO_Pin_8
// TIM1 输出比较通道的互补通道
#define ADVANCE_TIM_CH1N_GPIO_CLK RCC_APB2Periph_GPIOB
#define ADVANCE_TIM_CH1N_PORT GPIOB
#define ADVANCE_TIM_CH1N_PIN GPIO_Pin_13
// TI