添加库函数
- 打开
Manage Run-Time Environment
- 选择
Device->StdPeriph Drivers->TIM
定时器分类
分类 |
定时器 |
计数器分辨率 |
计数器类型 |
捕获/比较通道 |
互补输出 |
基本定时器 |
TIM6 |
16位 |
向上 |
0 |
无 |
基本定时器 |
TIM7 |
16位 |
向上 |
0 |
无 |
通用定时器 |
TIM2 |
16位 |
向上/向下 |
4 |
无 |
通用定时器 |
TIM3 |
16位 |
向上/向下 |
4 |
无 |
通用定时器 |
TIM4 |
16位 |
向上/向下 |
4 |
无 |
通用定时器 |
TIM5 |
16位 |
向上/向下 |
4 |
无 |
高级定时器 |
TIM1 |
16位 |
向上/向下 |
4 |
有 |
高级定时器 |
TIM8 |
16位 |
向上/向下 |
4 |
有 |
TIM初始化
TIM宏定义
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
79
80
81
82
83
84
85
| #ifndef __MY_TIME_H
#define __MY_TIME_H
#include "stm32f10x.h"
//使用那个定时器就把那个写1
#define BASIC_TIM6 0
#define BASIC_TIM7 0
#define ADVANCE_TIM1 0
#define ADVANCE_TIM8 0
#define GENERAL_TIM2 1
#define GENERAL_TIM3 0
#define GENERAL_TIM4 0
#define GENERAL_TIM5 0
#if BASIC_TIM6
#define MY_TIM TIM6
#define MY_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd
#define MY_TIM_CLK RCC_APB1Periph_TIM6
#define MY_TIM_Period 1000-1
#define MY_TIM_Prescaler 72-1
#define MY_TIM_IRQ TIM6_IRQn
#define MY_TIM_IRQHandler TIM6_IRQHandler
#elif BASIC_TIM7
#define MY_TIM TIM7
#define MY_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd
#define MY_TIM_CLK RCC_APB1Periph_TIM7
#define MY_TIM_Period 1000-1
#define MY_TIM_Prescaler 72-1
#define MY_TIM_IRQ TIM7_IRQn
#define MY_TIM_IRQHandler TIM7_IRQHandler
#elif ADVANCE_TIM1
#define MY_TIM TIM1
#define MY_TIM_APBxClock_FUN RCC_APB2PeriphClockCmd
#define MY_TIM_CLK RCC_APB2Periph_TIM1
#define MY_TIM_Period (1000-1)
#define MY_TIM_Prescaler 72-1
#define MY_TIM_IRQ TIM1_UP_IRQn
#define MY_TIM_IRQHandler TIM1_UP_IRQHandler
#elif ADVANCE_TIM8
#define MY_TIM TIM8
#define MY_TIM_APBxClock_FUN RCC_APB2PeriphClockCmd
#define MY_TIM_CLK RCC_APB2Periph_TIM8
#define MY_TIM_Period (1000-1)
#define MY_TIM_Prescaler 72-1
#define MY_TIM_IRQ TIM8_UP_IRQn
#define MY_TIM_IRQHandler TIM8_UP_IRQHandler
#elif GENERAL_TIM2
#define MY_TIM TIM2
#define MY_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd
#define MY_TIM_CLK RCC_APB1Periph_TIM2
#define MY_TIM_Period (1000-1)
#define MY_TIM_Prescaler 72-1
#define MY_TIM_IRQ TIM2_IRQn
#define MY_TIM_IRQHandler TIM2_IRQHandler
#elif GENERAL_TIM3
#define MY_TIM TIM3
#define MY_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd
#define MY_TIM_CLK RCC_APB1Periph_TIM3
#define MY_TIM_Period (1000-1)
#define MY_TIM_Prescaler 72-1
#define MY_TIM_IRQ TIM3_IRQn
#define MY_TIM_IRQHandler TIM3_IRQHandler
#elif GENERAL_TIM4
#define MY_TIM TIM4
#define MY_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd
#define MY_TIM_CLK RCC_APB1Periph_TIM4
#define MY_TIM_Period (1000-1)
#define MY_TIM_Prescaler 72-1
#define MY_TIM_IRQ TIM4_IRQn
#define MY_TIM_IRQHandler TIM4_IRQHandler
#elif GENERAL_TIM5
#define MY_TIM TIM5
#define MY_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd
#define MY_TIM_CLK RCC_APB1Periph_TIM5
#define MY_TIM_Period (1000-1)
#define MY_TIM_Prescaler 72-1
#define MY_TIM_IRQ TIM5_IRQn
#define MY_TIM_IRQHandler TIM5_IRQHandler
#endif
void MY_TIM_Init(void);
#endif
|
TIM中断配置和初始化设置
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
| #include "my_tim.h"
/**
* @brief 配置嵌套向量中断控制器NVIC
* @param 无
* @retval 无
*/
static void MY_TIM_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
// 设置中断组为0
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
// 设置中断来源
NVIC_InitStructure.NVIC_IRQChannel = MY_TIM_IRQ ;
// 设置主优先级为 0
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
// 设置抢占优先级为3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
// 使能中断
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/**
* @brief TIM配置
* 定时时间TIME=(TIM_Period+1)*(TIM_Prescaler+1)/CLK
* @param 无
* @retval 无
*/
static void MY_TIM_Mode_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
// 开启定时器时钟,即内部时钟CK_INT=72M
MY_TIM_APBxClock_FUN(MY_TIM_CLK, ENABLE);
// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
TIM_TimeBaseStructure.TIM_Period=MY_TIM_Period;
// 时钟预分频数
TIM_TimeBaseStructure.TIM_Prescaler= MY_TIM_Prescaler;
// 时钟分频因子 ,没用到不用管
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
// 计数器计数模式,设置为向上计数
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
// 重复计数器的值,没用到不用管
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
// 初始化定时器
TIM_TimeBaseInit(MY_TIM, &TIM_TimeBaseStructure);
// 清除计数器中断标志位
TIM_ClearFlag(MY_TIM, TIM_FLAG_Update);
// 开启计数器中断
TIM_ITConfig(MY_TIM,TIM_IT_Update,ENABLE);
// 使能计数器
TIM_Cmd(MY_TIM, ENABLE);
}
/**
* @brief TIM工作参数配置
* @param 无
* @retval 无
*/
void MY_TIM_Init(void)
{
MY_TIM_NVIC_Config();
MY_TIM_Mode_Config();
}
|
TIM结构体分析
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
| /**
* @brief TIM Time Base Init structure definition
* @note This structure is used with all TIMx except for TIM6 and TIM7.
*/
typedef struct
{
uint16_t TIM_Prescaler; /*!< Specifies the prescaler value used to divide the TIM clock.
This parameter can be a number between 0x0000 and 0xFFFF */
uint16_t TIM_CounterMode; /*!< Specifies the counter mode.
This parameter can be a value of @ref TIM_Counter_Mode */
uint16_t TIM_Period; /*!< Specifies the period value to be loaded into the active
Auto-Reload Register at the next update event.
This parameter must be a number between 0x0000 and 0xFFFF. */
uint16_t TIM_ClockDivision; /*!< Specifies the clock division.
This parameter can be a value of @ref TIM_Clock_Division_CKD */
uint8_t TIM_RepetitionCounter; /*!< Specifies the repetition counter value. Each time the RCR downcounter
reaches zero, an update event is generated and counting restarts
from the RCR value (N).
This means in PWM mode that (N+1) corresponds to:
- the number of PWM periods in edge-aligned mode
- the number of half PWM period in center-aligned mode
This parameter must be a number between 0x00 and 0xFF.
@note This parameter is valid only for TIM1 and TIM8. */
} TIM_TimeBaseInitTypeDef;
|
可设置范围为0 至65535,实现1 至65536 分频。
1
2
3
4
5
6
7
8
9
| /** @defgroup TIM_Counter_Mode
* @{
*/
#define TIM_CounterMode_Up ((uint16_t)0x0000) //向上计数
#define TIM_CounterMode_Down ((uint16_t)0x0010) //向下计数
#define TIM_CounterMode_CenterAligned1 ((uint16_t)0x0020) //中心对齐,只在计数器向下计数时被设置
#define TIM_CounterMode_CenterAligned2 ((uint16_t)0x0040) //中心对齐,只在计数器向上计数时被设置
#define TIM_CounterMode_CenterAligned3 ((uint16_t)0x0060) //中心对齐,在计数器向上和向下计数时均被设置
|
可设置范围为0 至65535,实现1 至65536 计数
设置定时器时钟CK_INT 频率与死区发生器以及数字滤波器采样时钟频率分频比。可以选择1、2、4 分频。
1
2
3
4
5
6
7
| /** @defgroup TIM_Clock_Division_CKD
* @{
*/
#define TIM_CKD_DIV1 ((uint16_t)0x0000)
#define TIM_CKD_DIV2 ((uint16_t)0x0100)
#define TIM_CKD_DIV4 ((uint16_t)0x0200)
|
- 重复计数器
TIM_RepetitionCounter
只在高级定时器使用,高级定时器发生上溢或下溢事件是递减重复计数器的值,只有当重复计数器为0 时才会生成更新事
中断函数
添加TIM头文件和变量到stm32f10x_it.c
1
2
| #include "my_tim.h"
extern __IO uint32_t time;
|
添加时间中断函数
1
2
3
4
5
6
7
8
9
10
11
12
13
| /**
* @brief This function handles TIM interrupt request.
* @param None
* @retval None
*/
void MY_TIM_IRQHandler (void)
{
if ( TIM_GetITStatus( MY_TIM, TIM_IT_Update) != RESET )
{
time++;
TIM_ClearITPendingBit(MY_TIM , TIM_FLAG_Update);
}
}
|
调试
添加TIM头文件main.c
和调用初始化TIM
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
79
80
| #include "stm32f10x.h"
#include "my_gpio.h"
#include "my_usart.h"
#include "my_data_queue.h"
#include "my_process_data.h"
#include "my_adc.h"
#include "my_tim.h"
extern __IO uint16_t ADC_ConvertedValue[NOFCHANEL];
Channel ch[2];
float VREF,VSENSE;
float temp;
float adcValue;
__IO uint32_t time = 0; // ms 计时变量
int main(void)
{
/* LED 端口初始化 */
LED_GPIO_Config();
Key_GPIO_Config();
/* 初始化USART 配置模式为 9600 8-N-1 */
USART_Config();
/*初始化接收数据队列*/
RX_Queue_Init();
/*初始化ADC*/
ADCx_Init();
/*初始化TIM 1ms*/
MY_TIM_Init();
printf( "\r\n Print current Temperature \r\n");
while (1)
{
if ( time >= 1000 ) /* 1000 * 1 ms = 1s 时间到 */
{
time = 0;
/* LED1 取反 */
LED1_TOGGLE;
VREF=1.2f*4096/ADC_ConvertedValue[2];
VSENSE=VREF*ADC_ConvertedValue[1]/4096;
temp=(1.43f-VSENSE)/4.3+25;
adcValue=VREF*ADC_ConvertedValue[0]/4096;
printf( "\r\n The IC current tem= %.2fC\r\n", temp);
printf( "\r\n The IC current VDDA= %.2fV\r\n", VREF);
printf( "\r\n The IC current ADC= %.2fV\r\n", adcValue);
}
Process_Usart_Data(ch);
if (Key_Scan(KEY1_GPIO_PORT, KEY1_GPIO_PIN) == KEY_ON)
{
/*LED1反转*/
LED1_TOGGLE;
}
if (Key_Scan(KEY2_GPIO_PORT, KEY2_GPIO_PIN) == KEY_ON)
{
LED2_TOGGLE;
}
if(ch[0].state==1&&ch[0].start_up==0)
{
ch[0].stop_up=0;
ch[0].start_up=1;
LED1(ON);
}
if(ch[0].state==2&&ch[0].stop_up==0)
{
ch[0].stop_up=1;
ch[0].start_up=0;
LED1(OFF);
}
if(ch[1].state==1&&ch[1].start_up==0)
{
ch[1].stop_up=0;
ch[1].start_up=1;
LED2(ON);
}
if(ch[1].state==2&&ch[1].stop_up==0)
{
ch[1].stop_up=1;
ch[1].start_up=0;
LED2(OFF);
}
}
}
|
下载调试
- 编译之后下载到开发板
- 连接开发板串口
- 打开串口助手
- 可以看到串口每1秒接收到数据,开发板上LED在1s间隔闪烁