stm32定时器级联(一个定时器作为另一个的预分频器

stm32定时器级联(一个定时器作为另一个的预分频器

在网上找了许多代码看了许多资料,都没有找到理想的,有些不是用标准库的,有些只写出了想法并没有具体的操作,经过多次修改笔者终于成功运行。

该代码的实现功能是:TIM2和TIM3的级联,TIM2用内部时钟源,每秒产生一个中断(执行NUM1++)和更新事件(作为TRGO输出到TIM3),TIM3以触发输入为时钟,每传来两次信号后进入中断(执行NUM2++)

Timer.c

#include "stm32f10x.h"                  // Device header


void Timer_Init(void)
{
	/*
		TIM2
	*/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	TIM_InternalClockConfig(TIM2);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 10000-1;
	TIM_TimeBaseInitStructure.TIM_Prescaler = 7200-1;
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
	
	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//打开更新中断
	TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);//设置更新事件,触发输出
	
	/*
		TIM3
	*/ 
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	TIM_SelectInputTrigger(TIM3, TIM_TS_ITR1);//TIM3的触发输入
	TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_External1);//选择TIM3的从模式

	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 2-1;
	TIM_TimeBaseInitStructure.TIM_Prescaler = 1-1;
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
	TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
	
	/*
		NVIC
	*/
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStrucutre;

	NVIC_InitStrucutre.NVIC_IRQChannel = TIM3_IRQn;
	NVIC_InitStrucutre.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStrucutre.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStrucutre.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStrucutre);
	
	NVIC_InitStrucutre.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStrucutre.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStrucutre.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStrucutre.NVIC_IRQChannelSubPriority = 2;
	NVIC_Init(&NVIC_InitStrucutre);
	
	TIM_Cmd(TIM2, ENABLE);
	TIM_Cmd(TIM3, ENABLE);
}

Timer.h

#ifndef __TIMER_H_
#define __TIMER_H_

void Timer_Init(void);

#endif

main.c

#include "stm32f10x.h"                  // Device header
#include "OLED.h"
#include "Timer.h"

uint16_t Num1, Num2;

int main(void)
{
	OLED_Init();
	Timer_Init();
	
	while (1)
	{
		OLED_ShowString(1, 1, "NUM1:");
		OLED_ShowNum(1, 6, Num1 ,5);
		
		OLED_ShowString(2, 1, "NUM2:");
		OLED_ShowNum(2, 6, Num2 ,5);
	}
}

void TIM2_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
	{
		Num1++;
		TIM_ClearFlag(TIM2, TIM_IT_Update);
	}
}

void TIM3_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM3, TIM_IT_Update) == SET)
	{
		Num2++;
		TIM_ClearFlag(TIM3, TIM_IT_Update);
	}
}

先看看手册中给出的方法:

stm32定时器级联(一个定时器作为另一个的预分频器_第1张图片

可以归结为一下几点:
①配置TIM1为主模式,配置内部时钟,时基单元,产生的更新事件映射到TRGO口。
②配置TIM2为从模式,从ITRx引脚输入时钟,设置外部时钟模式,设置时基单元。
③开启TIM1和TIM2。

几点感悟:

①主从模式并不是需要配套使用的,可以只有TIM3的从模式,这也算是笔者学习的一个误区,自以为主从模式是配套的,有主就得有从。
②从其他时钟触发输入选择的时钟模式,应该由TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_External1)函数确定,不应该设置外部时钟模式1(TIM_ETRClockMode1Config)。笔者产生这个误会来自下图。实际上应该看下图。
stm32定时器级联(一个定时器作为另一个的预分频器_第2张图片stm32定时器级联(一个定时器作为另一个的预分频器_第3张图片
③定时器的更新中断和更新事件可以同时允许。

附上定时器框图和定时器的内部连接:
stm32定时器级联(一个定时器作为另一个的预分频器_第4张图片
stm32定时器级联(一个定时器作为另一个的预分频器_第5张图片

你可能感兴趣的:(stm32,单片机,嵌入式硬件)