开发环境:Window 7
开发工具:Keil uVision4
硬件:STM32F103VCT6
定时器最基本的功能就是定时处理事情。比如定时发送USART数据、定时采集AD数据、定时检测IO口电位、还可以通过IO口输出波形等。可以实现非常丰富的功能。
STM32系列的定时器分为基本定时器、通用定时器、高级控制定时器。后者包括前者的全部功能。所以先掌握基本定时器可以更好理解后面功能繁多的定时器。
通常地,STM32高级定时器TIM1、TIM8,通用定时器TIM2、TIM3、TIM4、TIM5,基本定时器TIM6、TIM7。
有用过STM32的话都知道,STM32所有的外设初始化都是使用标准库里的初始化结构体和初始化函数,下面先说一下IM_TimeBaseInitTypeDef structure 结构体成员的含义。
TIM_TimeBaseInitTypeDef 定义于文件“stm32f10x_tim.h”:
typedef struct
{
u16 TIM_Period;
u16 TIM_Prescaler;
u8 TIM_ClockDivision;
u16 TIM_CounterMode;
u8 TIM_RepetitionCounter;
} TIM_TimeBaseInitTypeDef;
TIM_Period:定时器周期,当计数寄存器的值递增到等于该值时,将相关事件标志位置位。范围0~65535。
TIM_Prescaler:定时器预分频设置。时钟源经该预分频器才是定时器时钟。范围0~65535。
TIM_ClockDivision:时钟分频。基本定时器没有这个功能,无需设置。
TIM_CounterMode:定时器计数方式设置。基本定时器只能向上计数,无需设置。
TIM_RepetitionCounter :重复计数器,基本定时器没有这个功能,无需设置。
虽然定时器初始化结构体有5个成员,但是对于基本定时器只需设置其中两个就可以了。下面是一个定时0.5s翻转IO口电平的例子。
循环定时时间的计算:基本定时器只有内部时钟72MHz,定时器的实际时钟=内部时钟/(定时器预分频+1),那么TIM_Prescaler设置为7200-1,内部时钟源经过定时器预分频后即可得到10kHz(72MHz/((7200-1)+1))的频率。然后TIM_Period设置为5000-1,(这里因为计数是从0开始的,所以要减1),即可以得到定时为0.5s(5000*(1/10kHz))的定时器。代码如下:
创建一个TIME_base.h
#ifndef __TIMER_BASE_H
#define __TIMER_BASE_H
#include "stm32f10x.h"
void TIME_NVIC_Configuration(void);
void TIME_Configuration(void);
void GPIO_Config(void);
#endif
创建一个TIME_base.c
#include "TIME_base.h"
void TIME_NVIC_Configuration(void)//如果系统会产生多种中断,那么就存在中断响应的优先级
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置优先级分组
NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn; //指定IRQ通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //指定先占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //定义的IRQ是被使能还是失能
NVIC_Init(&NVIC_InitStructure);
}
void TIME_Configuration(void)//配置TIM6
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
TIM_TimeBaseStructure.TIM_Period = 5000; //设置了在下一个更新事件装入活动的自动重装载寄存器周期的值 范围是0x0000-0xFFFF
TIM_TimeBaseStructure.TIM_Prescaler =(7200-1); //设置了用来作为 TIMx 时钟频率除数的预分频值
TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
TIM_ITConfig(TIM6,TIM_IT_Update|TIM_IT_Trigger,ENABLE);//使能或者失能 TIM 的中断,详见附录图1
TIM_Cmd(TIM6, ENABLE);
}
void GPIO_Config(void)//配置一个IO口:
{
/*定义一个GPIO_InitTypeDef类型的结构体*/
GPIO_InitTypeDef GPIO_InitStructure;
/*开启GPIOB的外设时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
/*选择要控制的GPIOB引脚*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
/*设置引脚模式为通用推挽输出*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/*设置引脚速率为50MHz */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/*调用库函数,初始化GPIOB*/
GPIO_Init(GPIOB, &GPIO_InitStructure);
/*PB.0 输出高*/
GPIO_SetBits(GPIOB,GPIO_Pin_0);
}
附录图1:
在stm32f10x_it.c添加定时器触发的中断处理函数:
void TIM6_IRQHandler(void)
{
if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET) //获取中断状态
{
TIM_ClearITPendingBit(TIM6, TIM_IT_Update ); //清除中断标志
//在这里做中断需要处理的事情,尽可能精简,避免过长时间停留在中断里面
GPIO_WriteBit(GPIOB, GPIO_Pin_0, (BitAction)(1-(GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_0))));
}
}
创建一个main.c
#include "TIME_base.h"
int main(void)
{
/* IO端口配置 */
GPIO_Config();
/* TIM6 定时配置 */
TIME_NVIC_Configuration();
TIME_Configuration();
while(1){
}
}
将上面的TIM6全部换成TIM7也是可以的。
然后就可以把编译好的程序下载到开发板了,可以在PB.0引脚处接一个led,那么led就会每0.5s闪烁一次。
水平有限,仅供参考,错误以及不足之处还望多多指教。
上一篇:stm32之TIM-高级定时器应用实例一(详细)
下一篇:stm32之ADC应用实例(单通道、多通道、基于DMA)
推荐阅读最新更新时间:2024-11-04 13:12
设计资源 培训 开发板 精华推荐
- 具有 5V 输出的 LT1076IR 正负转换器的典型应用
- Fan4860同步微型升压稳压器典型应用电路
- MAXREFDES1238:适用于Version ACAP平台的可扩展,单输入,6输出,电源解决方案
- TYGV_a_01
- SIP79L12AC 三端小电流负电压稳压器典型应用
- LT6654AHS6-1.25、16 位 ADC 电压基准的典型应用
- 使用 Analog Devices 的 AD9834BRU 的参考设计
- 使用 Analog Devices 的 LTC1406CGN 的参考设计
- NCP731ADNADJR2GEVB:LDO 稳压器(38V、150mA、低噪声 8uVRMS、可调、MSOP-8 封装)评估板
- 用于视频/成像的差分放大器