定时器分类
定时器分类STM32F1系列中,除了互联型的产品,共有8个定时器,分为基本定时器,通用定时器和高级定时器。
- 基本定时器 TIM6/7 是一个16位的只能向上计数的定时器,只能定时,没有外部IO。
- 通用定时器 TIM2/3/4/5 是一个16位的可以向上/下计数的定时器,可以定时,可以输出比较,可以输入捕捉,每个定时器有四个外部IO。
- 高级定时器 TIM1/8 是一个16位可以向上/下计数的定时器,可以定时,可以输出比较,可以输入捕捉,还可以有三相电机互补输出信号,每个定时器有8个外部IO。
原理图:
所用开发板:ZET6
LED初始化;PB5,PE5,开发板上的两个LED灯!
#define LED0 GPIO_Pin_5
#define LED0_PORT GPIOB //PB5
#define LED1 GPIO_Pin_5
#define LED1_PORT GPIOE //PE5
void LED_Init(void)
{
//这里的时钟一定要开对呀!!!!!!
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure; //初始化结构体
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = LED0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(LED0_PORT, &GPIO_InitStructure);
GPIO_SetBits(LED0_PORT, LED0); //置高电平,默认熄灭
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = LED1;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(LED1_PORT, &GPIO_InitStructure);
GPIO_SetBits(LED1_PORT, LED1);
}
定时器6初始化函数
基本定时器 TIM6/7 是一个16位的只能向上计数的定时器,只能定时,没有外部IO。
具体配置如下:
void TIM6_Config(uint16_t Period, uint16_t Prescaler)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); //挂载在APB1总线上
TIM_TimeBaseInitTypeDef TIM_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
TIM_InitStructure.TIM_Period = Period;
TIM_InitStructure.TIM_Prescaler = Prescaler;
TIM_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up; //基本定时器只支持向上计数
TIM_InitStructure.TIM_RepetitionCounter = DISABLE; //重复计数次数,基本定时器也不支持
TIM_TimeBaseInit(TIM6, &TIM_InitStructure);
TIM_ClearITPendingBit (TIM6, TIM_IT_Update);//先清除中断标志位
TIM_ITConfig(TIM6, TIM_IT_Update | TIM_IT_Trigger, ENABLE); //使能
TIM_Cmd(TIM6, ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
定时器6中断函数
void TIM6_IRQHandler(void)//500ms基准定时
{
static uint8_t LED_Count;
if (TIM_GetITStatus (TIM6, TIM_IT_Update) == SET )
{
//如果读到0,给1,否则给0,实现500ms翻转电平
( GPIO_ReadOutputDataBit(LED0_PORT, LED0) == RESET ) \
? GPIO_SetBits(LED0_PORT, LED0) \
: GPIO_ResetBits(LED0_PORT, LED0); //三目运算符,更简洁
LED_Count++;
if (LED_Count >= 2) //两次计数为1s
{
( GPIO_ReadOutputDataBit(LED1_PORT, LED1) == RESET ) \
? GPIO_SetBits(LED1_PORT, LED1) \
: GPIO_ResetBits(LED1_PORT, LED1);
LED_Count = 0;
}
TIM_ClearITPendingBit (TIM6, TIM_IT_Update); //清除中断标志位
}
}
用三目运算符写这个IO口电平反转的功能代码太长了,我用连接符给分开咯,更整齐一点……
三目运算符( *** ? ### : @@@ )
简化版的if else语句,如果***成立,就执行 ### 程序,否则就执行 @@@ 程序
在开发STM32时使用三目运算符会很方便!
这个定时器自定义时长,还以为是啥高端的东西呢!
没想到和51单片机里的定时器一样用~
在中断里定义几个静态局部变量 static uint8_t LED_Count;
定时器 有一个基准定时,这里设置500ms
每次进中断,这几个静态局部变量都++ LED_Count++;
然后if语句判断,根据想要定时的时间长短来计算LED_Count变量的值!
if语句里执行对应的操作,然后手动清零这个计数变量!
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "LED.h"
#include "Timer6.h"
int main(void)
{
Delay_Init (72);
LED_Init();
TIM6_Config (10000-1 , 3600-1); //500ms定时
/*
3600分频,72000000/3600 = 20000, 1s计数两万
500ms = 0.5s 0.5s*20000 = 10000
*/
while(1)
{ }
}
/***********************************END OF FILE***********************************/
最后抓个波形玩玩~
用逻辑分析仪抓取波形一定要和开发板共地哟!而且还有将开发板上电!
最重要的是连接对引脚,别问为啥了~_~