STM32 使用中断模拟计算频率

测试环境

stm32f105rc。

main.c

	LibTIM1_SysTimerInit(20,7200); 	//Init 2MS 系统计时器初始化  ((arr+1)*(psc+1))/Tclk;

LibTimer.c

/*******************************************************************************
* 定时器1中断服务程序
*******************************************************************************/
void TIM1_UP_IRQHandler(void)   //TIM1中断
{
	u8 i=0;
	if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 
	{
		TIM_ClearITPendingBit(TIM1, TIM_IT_Update);  //清除TIMx的中断待处理位:TIM 中断源 

		//系统运行逻辑定时器10个
		LibVarSystemIntTimer2Ms[0]++;
		LibVarSystemIntTimer2Ms[1]++;
		LibVarSystemIntTimer2Ms[2]++;
		LibVarSystemIntTimer2Ms[3]++;
		LibVarSystemIntTimer2Ms[4]++;
		LibVarSystemIntTimer2Ms[5]++;
		LibVarSystemIntTimer2Ms[6]++;
		LibVarSystemIntTimer2Ms[7]++;
		LibVarSystemIntTimer2Ms[8]++;
		LibVarSystemIntTimer2Ms[9]++;
		LibVarSystemIntTimer2Ms[10]++;
		//系统时间
		LibVarSystemTimer2Ms++;
		LibVarSystemTimer10Ms = LibVarSystemTimer2Ms/5;
		//50MS
		if((LibVarSystemTimer2Ms%25)==0)
		{
				LibVarPiCounterArray[19] = LibVarPiCounterArray[18];
				LibVarPiCounterArray[18] = LibVarPiCounterArray[17];
				LibVarPiCounterArray[17] = LibVarPiCounterArray[16];
				LibVarPiCounterArray[16] = LibVarPiCounterArray[15];
				LibVarPiCounterArray[15] = LibVarPiCounterArray[14];
				LibVarPiCounterArray[14] = LibVarPiCounterArray[13];
				LibVarPiCounterArray[13] = LibVarPiCounterArray[12];
				LibVarPiCounterArray[12] = LibVarPiCounterArray[11];
				LibVarPiCounterArray[11] = LibVarPiCounterArray[10];
				LibVarPiCounterArray[10] = LibVarPiCounterArray[9];
				LibVarPiCounterArray[9] = LibVarPiCounterArray[8];
				LibVarPiCounterArray[8] = LibVarPiCounterArray[7];
				LibVarPiCounterArray[7] = LibVarPiCounterArray[6];
				LibVarPiCounterArray[6] = LibVarPiCounterArray[5];
				LibVarPiCounterArray[5] = LibVarPiCounterArray[4];
				LibVarPiCounterArray[4] = LibVarPiCounterArray[3];
				LibVarPiCounterArray[3] = LibVarPiCounterArray[2];
				LibVarPiCounterArray[2] = LibVarPiCounterArray[1];
				LibVarPiCounterArray[1] = LibVarPiCounterArray[0];
				LibVarPiCounterArray[0] = LibVarPiCounterOrg;
				LibVarPiCounterOrg = 0;

				switch(LibVarPiSampleTime[0])
				{
					case 1000:
						LibVarPiFreNow = LibVarPiCounterArray[0];
						LibVarPiFreNow += LibVarPiCounterArray[1];
						LibVarPiFreNow += LibVarPiCounterArray[2];
						LibVarPiFreNow += LibVarPiCounterArray[3];
						LibVarPiFreNow += LibVarPiCounterArray[4];
						LibVarPiFreNow += LibVarPiCounterArray[5];
						LibVarPiFreNow += LibVarPiCounterArray[6];
						LibVarPiFreNow += LibVarPiCounterArray[7];
						LibVarPiFreNow += LibVarPiCounterArray[8];
						LibVarPiFreNow += LibVarPiCounterArray[9];
						LibVarPiFreNow += LibVarPiCounterArray[10];
						LibVarPiFreNow += LibVarPiCounterArray[11];
						LibVarPiFreNow += LibVarPiCounterArray[12];
						LibVarPiFreNow += LibVarPiCounterArray[13];
						LibVarPiFreNow += LibVarPiCounterArray[14];
						LibVarPiFreNow += LibVarPiCounterArray[15];
						LibVarPiFreNow += LibVarPiCounterArray[16];
						LibVarPiFreNow += LibVarPiCounterArray[17];
						LibVarPiFreNow += LibVarPiCounterArray[18];
						LibVarPiFreNow += LibVarPiCounterArray[19];
						LibVarPiFreNow /= 2;
						break;
					case 500:
						LibVarPiFreNow = LibVarPiCounterArray[0];
						LibVarPiFreNow += LibVarPiCounterArray[1];
						LibVarPiFreNow += LibVarPiCounterArray[2];
						LibVarPiFreNow += LibVarPiCounterArray[3];
						LibVarPiFreNow += LibVarPiCounterArray[4];
						LibVarPiFreNow += LibVarPiCounterArray[5];
						LibVarPiFreNow += LibVarPiCounterArray[6];
						LibVarPiFreNow += LibVarPiCounterArray[7];
						LibVarPiFreNow += LibVarPiCounterArray[8];
						LibVarPiFreNow += LibVarPiCounterArray[9];
						break;
					case 200:
						LibVarPiFreNow = LibVarPiCounterArray[0];
						LibVarPiFreNow += LibVarPiCounterArray[1];
						LibVarPiFreNow += LibVarPiCounterArray[2];
						LibVarPiFreNow += LibVarPiCounterArray[3];
						LibVarPiFreNow *= 5;
						LibVarPiFreNow /= 2;
						break;
					case 100:
						LibVarPiFreNow = LibVarPiCounterArray[0];
						LibVarPiFreNow += LibVarPiCounterArray[1];
						LibVarPiFreNow *= 5;
						break;
				}
		}

	}
}

/* ******************************************************
** 函数名称:LibTIM1_SysTimerInit
** 功能描述:TIM1中断初始化配置--系统计时器
** 传入参数:无
** 返回数据:无
** *************************************************** */
void LibTIM1_SysTimerInit(u16 arr,u16 psc)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	TIM_TimeBaseStructure.TIM_Period = (arr - 1); //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	 计数到5000为500ms
	TIM_TimeBaseStructure.TIM_Prescaler =(psc - 1); //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;//重复计数设置
	TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位	
  TIM_ClearFlag(TIM1, TIM_FLAG_Update);//清中断标志位

	TIM_ITConfig(TIM1, TIM_IT_Update,ENABLE); //使能指定的TIM1中断,允许更新中断和触发中断

	NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;  //TIM1中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //从优先级0级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

	TIM_Cmd(TIM1, ENABLE);  //使能TIMx外设
}

LibPI.c

#include "LibVar.h"
#include "LibFun.h"

static u8 VarPB8StatusNow = 0;
static u8 VarPB8StatusLast = 0;

static void LibGpioConfig_DO(void);
static void LibTIM3_PiInit(u16 arr,u16 psc);

///* ******************************************************
//** 函数名称:TIM3_IRQHandler
//** 功能描述: 定时器3中断服务程序
//** 传入参数:无
//** 返回数据:无
//** 创建时间:胡棕亮 2018-11-07
//** *************************************************** */
void TIM3_IRQHandler(void)   //TIM4中断
{

	LibVarSystemTimer200Us++;

	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 
	{
		TIM_ClearITPendingBit(TIM3 , TIM_IT_Update);  //清除TIMx的中断待处理位:TIM 中断源

		VarPB8StatusNow = GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_2);
		if(VarPB8StatusNow>0 && VarPB8StatusLast==0)
		{
			LibVarPiCounterOrg++;
		}
		else if(VarPB8StatusNow==0 && VarPB8StatusLast==1)
		{
			LibVarPiCounterOrg++;
		}
		VarPB8StatusLast = VarPB8StatusNow;
	}

}

/* ******************************************************
** 函数名称:LibGpioConfig_DO
** 功能描述:DO GPIO配置
** 传入参数:无
** 返回数据:无
** *************************************************** */
static void LibGpioConfig_DO(void)
{
	#ifndef __RCC_ENABLE_TIM3
	#define __RCC_ENABLE_TIM3
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能TIM3
	#endif

	#ifndef __RCC_ENABLE_GPIOD
	#define __RCC_ENABLE_GPIOD
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); //使能GPIOD
	#endif

	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_StructInit(&GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; 	//PI0:PD2 
  GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_IPU;
  GPIO_Init(GPIOD, &GPIO_InitStructure);
	GPIO_ResetBits(GPIOD,GPIO_Pin_2); //拉低
}
/* ******************************************************
** 函数名称:LibTimer4Init
** 功能描述:TIM4 配置
** 传入参数:arr:自动重装值,psc:时钟预分频数
** 返回数据:无
** *************************************************** */

static void LibTIM3_PiInit(u16 arr,u16 psc)
{
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	TIM_TimeBaseStructure.TIM_Period = (arr - 1); //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	 计数到5000为500ms
	TIM_TimeBaseStructure.TIM_Prescaler =(psc - 1); //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断

	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

	//TIM_ETRClockMode2Config(TIM3,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,0);
  //TIM_SetCounter(TIM3, 0);   // 清零计数器CNT
	TIM_Cmd(TIM3, ENABLE);  //使能TIMx外设
}

/* ******************************************************
** 函数名称:LibPiInit
** 功能描述:PI初始化
** 传入参数:无。
** 返回数据:无。
** *************************************************** */
void LibPiInit(void)
{
	LibGpioConfig_DO();
	LibTIM3_PiInit(3600,4);//200us
}
/* ******************************************************
** 函数名称:LibPiSetSampleTime
** 功能描述:设置PI采样时间
** 传入参数:Channal,通道号,取值范围0;SampleTime,采样时间,单位毫秒,取值范围100/200/500/1000。
** 返回数据:为0则设置成功,为1则通道号错误。
** *************************************************** */
u16 LibPiSetSampleTime(u8 Channal,u16 SampleTime)
{
	if(Channal<1)
	{
		switch(SampleTime)
		{
			case 1000:
			case 500:
			case 200:
			case 100:
				LibVarPiSampleTime[Channal] = SampleTime;
				break;
		}
		return 	0;
	}
	else
	{
		return 1;
	}
}
/* ******************************************************
** 函数名称:LibPiReadFrequency
** 功能描述:读取当前PI采样频率
** 传入参数:无
** 返回数据:无
** *************************************************** */
u16 LibPiReadFrequency(u8 Channal)
{
	return LibVarPiFreNow;
}

LibFun.c

	/******************************************************************/
	//PI操作函数
	/******************************************************************/
	extern void LibPiInit(void);
	extern u16 LibPiSetSampleTime(u8 Channal,u16 SampleTime);
	extern u16 LibPiReadFrequency(u8 Channal);

LibVar.c

	/******************************************************************/
	//PI变量
	/******************************************************************/
	u16 LibVarPiSampleTime[1]= {500};// PI采样时间,单位ms     
	u16 LibVarPiCounterOrg = 0;     // PI计数值
	u16 LibVarPiCounterArray[20];   // PI计数值
	u16 LibVarPiFreNow = 0; //Hz

LibVar.h

	/******************************************************************/
	//PI变量
	/******************************************************************/
	extern u16 LibVarPiSampleTime[1];// PI采样时间,单位ms   
	extern u16 LibVarPiCounterOrg;    // PI计数值
	extern u16 LibVarPiCounterArray[20];
	extern u16 LibVarPiFreNow; //Hz
02-01 07:04