【STM32】定时器1:定时中断与外部时钟的使用方法

(基于江科大STM32教程)

一、理论部分

使用定时器模块基本流程如上:

1、时钟及时钟模式选择

(1)使用内部时钟

如TIM2,先初始化TIM2在APB1总线

然后用TIM_InternalClockConfig()使能TIM2的内部时钟即可。


	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	//void TIM_InternalClockConfig(TIM_TypeDef* TIMx);
	TIM_InternalClockConfig(TIM2);

(2)使用外部时钟模式1

(3)使用外部时钟模式2

如TIM2配置外部时钟模式2,TIM2的ETR引脚固定为PA0,不可随意更改

那么先需要初始化PA0的Rcc,设定GPIO,其中Mode选择上拉(参考手册8.1.11)

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x0f);

然后使用TIM_ETRClockMode2Config,外部时钟模式二,最后一个参数配置滤波器,0x0f消抖

参数定义如下:

/**
  * @brief  Configures the External clock Mode2
  * @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
  * @param  TIM_ExtTRGPrescaler: The external Trigger Prescaler.
  *   This parameter can be one of the following values:
  *     @arg TIM_ExtTRGPSC_OFF: ETRP Prescaler OFF.
  *     @arg TIM_ExtTRGPSC_DIV2: ETRP frequency divided by 2.
  *     @arg TIM_ExtTRGPSC_DIV4: ETRP frequency divided by 4.
  *     @arg TIM_ExtTRGPSC_DIV8: ETRP frequency divided by 8.
  * @param  TIM_ExtTRGPolarity: The external Trigger Polarity.
  *   This parameter can be one of the following values:
  *     @arg TIM_ExtTRGPolarity_Inverted: active low or falling edge active.
  *     @arg TIM_ExtTRGPolarity_NonInverted: active high or rising edge active.
  * @param  ExtTRGFilter: External Trigger Filter.
  *   This parameter must be a value between 0x00 and 0x0F
  * @retval None
  */
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, 
                             uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter)

2、配置时基单元

使用TIM_TimeBaseInit(),参数定义如下:

/**
  * @brief  Initializes the TIMx Time Base Unit peripheral according to 
  *         the specified parameters in the TIM_TimeBaseInitStruct.
  * @param  TIMx: where x can be 1 to 17 to select the TIM peripheral.
  * @param  TIM_TimeBaseInitStruct: pointer to a TIM_TimeBaseInitTypeDef
  *         structure that contains the configuration information for the 
  *         specified TIM peripheral.
  * @retval None
  */
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

类似于GPIO的配置,第二个参数也是结构体,包含四个参数:

(1)TIM_ClockDivision

表示分频,采样频率=Rcc频率/分频;

(2)TIM_CounterMode

表示计数方式,主选向上;

(3)TIM_Period、TIM_Prescaler

用来控制计数,前者为频率,后者为计数周期,计算时要+1,

采样频率/(TIM_Period+1)(TIM_Prescaler+1)=溢出时间;

(4)TIM_RepetitionCounter

表示重复计数器,高级定时器应用;

    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period=7200-1;
	TIM_TimeBaseInitStructure.TIM_Prescaler=10000-1;
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
	TIM_ClearFlag(TIM2, TIM_FLAG_Update);
	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

(5)TIM_ClearFlag()

根据TIM_TimeBaseInit的函数声明的更新中断的方式:Generate an update event to reload the Prescaler and the Repetition counter values immediately

在复位重装时,发送一个更新事件来重装寄存器,也就会触发一次中断,用于解决缓冲寄存器的问题,副作用是复位上电时也会导致触发一次中断。所以在init前清空一次寄存器可以使得复位上电时寄存器清零。

3、配置NVIC

如下:

//NVIC
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
	NVIC_Init(&NVIC_InitStructure);

4、中断函数模板

判断标志位后,清除标志位寄存器,执行中断函数。

void TIM2_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM2, TIM_IT_Update)==SET)
	{
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
		//执行内容,尽量无延时
	}
}

二、项目实践

1、项目内容

为同时训练到外部时钟、定时器时钟,设计如下:

计数秒表:

通过红外触发计数,模拟所需计时时间(秒、分,进位实现)

设定完成(按下按键)后,秒表开启,到达时间报警(亮灯)

2、代码实现

(1)TIM

首先编写TIM,先写两个TIM的init:

TIM2通过PA0,使用外部时钟模式2,计数60次溢出,即TIM_Period=60-1;TIM_Prescaler=1-1;

TIM3使用内部定时器时钟,1Hz。

TIM2通过counter取出的值为sec_set(设定的秒),中断执行是min_set++(设定的分),通过sec_set计数60次溢出,可实现秒向分的进位;

TIM3中断执行是sec++(秒表的秒)。

uint16_t Get_set(void)
{
	return TIM_GetCounter(TIM2);
}

uint16_t Get_sec(void)
{
	return sec;
}

void TIM2_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM2, TIM_IT_Update)==SET)
	{
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
		min_set++;
	}
}

void TIM3_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM3, TIM_IT_Update)==SET)
	{
		TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
		sec++;
	}
}

(2)其他外设

设定按键定义在PA2,指示灯定义在PA4

(3)main

int main(void)
{
	OLED_Init();
	Key_Init();
	Timer2_Init();
	LED_Init();
	while(1)
	{
		OLED_ShowNum(1, 1, min_set, 2);			//min_set
		OLED_ShowNum(1, 4, Get_set(), 2);		//sec_set
		while(Key_Judge2()==1)
		{
			Timer3_Init();
			while(1)
			{
				OLED_ShowNum(1, 1, min_set, 2);			//min_set
				OLED_ShowNum(1, 4, Get_set(), 2);		//sec_set
				OLED_ShowNum(2, 1, Get_sec(), 4);
				if(Get_sec()==min_set*60+Get_set())
				{
					LED_Action(1);
					while(1);
				}
			}
		}
	}
}

3、功能记录

正常计数

 累加到60在分位进一

按下PA2后开始计时 

计时到达报警 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值