本文章适用于STM32F103RBT6,其他型号可能有所不同
开发模板见我的GitHub仓库skyone-wzw@STM32F103RBT6-template
如果你觉得这篇文章有帮助,请star仓库或评论回复吧~
如果文章有任何错误(包括错别字)可以在这里提交Issue或邮件联系我
使能定时器时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIMx, ENABLE);
使能定时器时钟,对于中容量STM32F103,TIMx可以是:
TIM1
:高级定时器
TIM2
~`TIM4`通用定时器
例如
1 2
| RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
|
初始化定时器
TIM_TimeBaseInit(TIMx, &TIM_TimeBaseInitTypeDef)
定义计时器的重装载值、预分频系数、计数方式等
对于TIM_TimeBaseInitTypeDef
结构体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| typedef struct { uint16_t TIM_Prescaler; uint16_t TIM_CounterMode;
uint16_t TIM_Period; uint16_t TIM_ClockDivision; uint8_t TIM_RepetitionCounter; } TIM_TimeBaseInitTypeDef;
|
例如:
1 2 3 4 5 6 7 8 9 10
| TIM_TimeBaseInitTypeDef tim3; tim3.TIM_Period = 4999;
tim3.TIM_Prescaler = 7199;
tim3.TIM_CounterMode = TIM_CounterMode_Up; tim3.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInit(TIM3, &tim3);
|
开启定时器中断
TIM_ITConfig(TIMx, TIM_IT, ENABLE);
设置什么情况下中断,可以为:
1 2 3 4 5 6 7 8 9
| #define TIM_IT_Update ((uint16_t)0x0001)
#define TIM_IT_CC1 ((uint16_t)0x0002) #define TIM_IT_CC2 ((uint16_t)0x0004) #define TIM_IT_CC3 ((uint16_t)0x0008) #define TIM_IT_CC4 ((uint16_t)0x0010) #define TIM_IT_COM ((uint16_t)0x0020) #define TIM_IT_Trigger ((uint16_t)0x0040) #define TIM_IT_Break ((uint16_t)0x0080)
|
当然,用到中断就要设置中断优先级,此外,不要忘记在main函数开始时设置中断优先级分组
使能定时器
TIM_Cmd(TIMx, ENABLE);
非常简单,无需解释
写中断服务函数
对于高级定时器,中断服务函数的名字为:
void TIMx_BRK_IRQHandler()
void TIMx_UP_IRQHandler()
void TIMx_TRG_COM_IRQHandler()
void TIMx_CC_IRQHandler()
对于通用定时器,中断服务函数的名字为:
TIMx
中的x
换成对应计时器ID
例程
下面给出一个完整的例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| #include <stm32f10x.h> #include <system_stm32f10x.h>
void TIM3_IRQHandler() { if (TIM_GetFlagStatus(TIM3, TIM_FLAG_Update) == SET) { if (GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_0) == 1) { GPIO_ResetBits(GPIOC, GPIO_Pin_0); } else { GPIO_SetBits(GPIOC, GPIO_Pin_0); } TIM_ClearITPendingBit(TIM3, TIM_FLAG_Update); } }
int main() { SetSysClock(); NVIC_SetPriorityGrouping(NVIC_PriorityGroup_2);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseInitTypeDef tim3; tim3.TIM_Period = 4999; tim3.TIM_Prescaler = 7199; tim3.TIM_CounterMode = TIM_CounterMode_Up; tim3.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInit(TIM3, &tim3);
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
NVIC_InitTypeDef nvic_tim3; nvic_tim3.NVIC_IRQChannel = TIM3_IRQn; nvic_tim3.NVIC_IRQChannelPreemptionPriority = 2; nvic_tim3.NVIC_IRQChannelSubPriority = 2; nvic_tim3.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&nvic_tim3);
TIM_Cmd(TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); GPIO_InitTypeDef led0; led0.GPIO_Pin = GPIO_Pin_0; led0.GPIO_Mode = GPIO_Mode_Out_PP; led0.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &led0); GPIO_ResetBits(GPIOC, GPIO_Pin_0);
for (;;) { } }
|
没有附加依赖,使用定时器中断使LED闪烁,LED用的是GPIOC_0
为了方便分享和复习,所有代码写在一个文件里,实际开发这样做非常不对!