STM32 的通用定时器可以被用于:测量输入信号的脉冲长度
(
输入捕获
)
或者产 生输出波形(
输出比较和
PWM)
等。 使用定时器预分频器和
RCC
时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。
一、
STM32F1
的通用
TIMx (TIM2
、
TIM3
、
TIM4)
定时器功能包括:
1)16
位向上、向下、向上
/
向下自动装载计数器(
TIMx_CNT
)。
2)16
位可编程
(
可以实时修改
)
预分频器
(TIMx_PSC)
,计数器时钟频率的分频系数为
1
~
65535
之间的任意数值。
3
)
4
个独立通道(
TIMx_CH1~4
),这些通道可以用来作为:
A
.输入捕获
B
.输出比较
C
.
PWM
生成
(
边缘或中间对齐模式
)
D
.单脉冲模式输出
4
)可使用外部信号(
TIMx_ETR
)控制定时器和定时器互连(可以用
1
个定时器控制另外
一个定时器)的同步电路。
5
)如下事件发生时产生中断
/DMA
:
A
.更新:计数器向上溢出
/
向下溢出,计数器初始化
(
通过软件或者内部
/
外部触发
)
B
.触发事件
(
计数器启动、停止、初始化或者由内部
/
外部触发计数
)
C
.输入捕获
D
.输出比较
E
.支持针对定位的增量
(
正交
)
编码器和霍尔传感器电路
F
.触发输入作为外部时钟或者按周期的电流管理
二、
要了解三个寄存器,
1、
控制寄存器(可以得到计数器使能位、计数器的方式:向上计数、向下计数、还有计数对齐方式,还有定时器的时钟分频因子)
2、
DMA/中断使能寄存器(用定时器的更新中断,来允许由于更新事件所产生的中断。
)
3、预分频寄存器(寄存器 用设置对时钟进行分频,然后提供给计数器,作为计数器的时钟
)
三、
定时器的时钟来源有
4
个:
1
)内部时钟(
CK_INT
)
2
)外部时钟模式
1
:外部输入脚(
TIx
)
3
)外部时钟模式
2
:外部触发输入(
ETR
)
4
)内部触发输入(
ITRx
):使用
A
定时器作为
B
定时器的预分频器(
A
为
B
提供时钟)。
四、下面是定时器中断的软件设计
TIM_HandleTypeDefTIM3_Handler;//定时器句柄
//通用定时器3中断初始化
//arr:自动重装值
//psc:时钟预分频数
//定时器溢出时间计算方法:Tout((arr+1)*(psc+1))/Ft us
Ft=定时器工作频率,单位:Mhz
//这里使用的是tim3!
void TIM3_Init(u16 arr,u16 psc)
{
TIM3_handler.Instance = TIM3;//通用定时器3
TIM3_Handler.Init.Prescaler = psc;//分频系数
TIM3_Handler.CounterMode = TIM_COUNTERMODE_UP;//向上计数器
TIM3_Handler.Init.Period = arr;//自动装载值
TIM3_Handler.Init.ClockDivision = TIM_AUTORELOAD_PRELOAD_ENABLE;//使能自动重载
HAL_TIM_Base_Init(&TIM3_Handler);//初始化定时器3
HAL_TIM_Base_Start_IT(&TIM3_Handler);/使能定时器3更新中断:TIM_IT_UPDATE
}
//定时器底层驱动,开启时钟,设置中断优先级
//此函数会被HAL_TIM_Base_Init()函数调用
void HAL_TIM_Base_MspInit(TIM_HandlerTypeDef*htim)
{
if(htim->Instance == TIM3)
{
_HAL_RCC_TIM3_CLK_ENABLE();//使能TIM3时钟
HAL_NVIC_SetPriority(TIM3_IRQn,1,3);
//设置中断优先级,抢占优先级1,子优先级3
HAL_NVIC_EnableIRQ(TIM3_IRQn);//开启TIM3中断
}
}
//定时器3中断服务函数
void TIM3_IRQHandler(void)
{
HAL_TIM_IRQHandler(&TIM3_Handler);
}
//回调函数,定时器中断服务函数调用
void HAL_TIM_PeriodElapsedCallbake(TIM_HandleTypeDef*htim)
{
if(htim == (&TIM3_Handler))
{
LED1=!LED1;//LED1反转
}
}
int main(void)
{
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(RCC_PLL_MUL9); //设置时钟,72M
delay_init(72); //初始化延时函数
uart_init(9600); // 初始化串口
LED_Init(); //初始化LED
TIM3_Init(5000-1,7200-1); //初始化定时器3,定时器时钟为72M,分频系数为7199,
//所以定时器3的频率为72M/7200 = 10k,自动重装载4999,那么定时器周期就是500ms
while(1)
{
LED0 = !LED0;//LED0反转
delay_ms(200); //延时200ms
}
}
此段代码对 TIM3 进行初始化之后,进入死循环等待 TIM3溢出中断,当 TIM3_CNT 的值等于 TIM3_ARR 的值的时候,就会产生 TIM3 的更新中断,然后在中断里面取反 LED1,TIM3_CNT 再从 0 开始计数。根据上面的公式,我们可以算出中断溢出时间为 500ms,即 Tout= ((4999+1)*( 7199+1))/72=500000us=500ms。
实验现象:
如果没有错误,我们将看 DS0 不停闪烁(每 400ms 闪烁一次),
而 DS1 也是不停的闪烁,但是闪烁时间较 DS0 慢(1s 一次)。