基于STM32制作的简易测频计(二)(代码部分)

该程序设计基于STM32微控制器,利用TIM2和TIM4定时器进行频率测量。主程序包括系统初始化、频率测量和结果显示,中断程序用于计数器计时和读取测量值。通过中断服务函数TIM4_IRQHandler实现1s时间闸门,读取TIM2计数值以计算频率。同时,程序还包括按键输入功能,用于选择不同的测量范围。
摘要由CSDN通过智能技术生成

目录

main.c

Time.c

Time.h

Key.c

Key.h

其中Delay和Oled的部分采用的是B站UP主“江大科技”的代码

程序设计思路

        主程序:

        1.运行开始

        2.系统初始化

        3.频率测量

        4.显示结果

        中断程序:

        1.计数器开始

        2.满足TIM4的时间闸门(比如测量时间到达1s)

        3.读取TIM2的次数

        4.中断计数器值归零

        5.获得频率值

        6.终端结束

Time.c

#include "stm32f10x.h"                  // Device header
void TIM2_Init(void) 
{
	//时钟配置
	TIM_InternalClockConfig(TIM2);                          //采用内部时钟给 TIM2提供时钟源
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);     //使能TIM2时钟  
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); 	//使能GPIOA时钟
	//GPIO配置
	GPIO_InitTypeDef GPIO_InitStructure;  					//初始化GPIO
    GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;              //将输入口绑定为A0口  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;			//设置为下拉模式
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   	//时钟频率为50MHZ
    GPIO_Init(GPIOA, &GPIO_InitStructure);        			//完成GPIO的初始化
	//GPIO_ResetBits(GPIOA,GPIO_Pin_0);                     //下拉PA0  
	//TIM设置
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;			//初始化TIM
	TIM_TimeBaseInitStruct.TIM_Period=65536-1;              //ARR  设置为0xFFFF 或者65536-1 
	TIM_TimeBaseInitStruct.TIM_Prescaler=1-1;               //PSC  设置为0x0000 或者1-1 
    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割1分频
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;			//不重复计数
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//向上计数模式  
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);         //完成TIM的初始化设置
	//外部时钟中断设置
	TIM_ITRxExternalClockConfig(TIM2,TIM_TS_ETRF);           //配置外部触发,否则不会计数  
	TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0); //设置外部时钟中断
	//TIM2启用
	TIM_SetCounter(TIM2, 0);          						 //给定时器2的值设定为从0值开始
    TIM_Cmd(TIM2,ENABLE );                                   //启动定时器2  

}
void TIM4_Init(u16 arr ,u16 psc) 
{	
	//时钟配置
	TIM_InternalClockConfig(TIM4);							//使能TIM2时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);		//使能TIM4时钟  
	//TIM设置
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_TimeBaseInitStruct.TIM_Period=arr;                   //ARR
	TIM_TimeBaseInitStruct.TIM_Prescaler=psc;                //PSC     改标准频率fc
    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割为1分频
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;		     //不重复计数
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式  
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseInitStruct);         //完成TIM的初始化设置		
	//NVIC中断 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);			//设置中断优先组别为2  
	NVIC_InitTypeDef NVIC_InitStruct1;
	NVIC_InitStruct1.NVIC_IRQChannel=TIM4_IRQn;				// 中断源为定时器4的内置时钟中断
	NVIC_InitStruct1.NVIC_IRQChannelCmd=ENABLE;				// 中断使能
	NVIC_InitStruct1.NVIC_IRQChannelPreemptionPriority=0;   // 中断主优先级0
	NVIC_InitStruct1.NVIC_IRQChannelSubPriority=0;			// 中断字优先级0
	NVIC_Init(&NVIC_InitStruct1);							//完成NVIC中断配置
	//定时器4的启动
	TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE); 				//使能定时器4更新中断
    TIM_Cmd(TIM4,ENABLE );         							 //启动定时器4
}
int fq;//待测频率的值
void TIM4_IRQHandler(void)    
{
	if(TIM_GetITStatus(TIM4,TIM_IT_Update)==SET)  //如果TIM4定时达到1s (阀门法测频)
	{
		TIM_ClearITPendingBit(TIM4,TIM_IT_Update);	//清空TIM4中断待处理位
		fq=TIM_GetCounter(TIM2);                    //读取1s内计数器计的CNT值  即脉冲的频率                   
		TIM_SetCounter(TIM2,0);  					//清空TIM2的值,重新开始测量
	}
}

Time.h

#ifndef __Time_H
#define __Time_H
 
void TIM2_Init(void) ;
void TIM4_Init(u16 arr ,u16 psc);
void TIM4_IRQHandler(void);

#endif

Key.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#define  Key_1  GPIO_Pin_3    //低频测量按键
#define  Key_2  GPIO_Pin_5    //中高频测量按键
 void Key_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;		   //初始化GPIO
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;  //下拉输入模式
	GPIO_InitStructure.GPIO_Pin = Key_1 | Key_2;   //配置按键为Key1--B3  Key3--B5
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//时钟频率为50Mhz
	GPIO_Init(GPIOB, &GPIO_InitStructure);         //完成初始化
}

uint16_t Key_Num(void)
{
	uint16_t KeyNum = 0;
	//按下按键1(B3)  接受高电平信号
	if (GPIO_ReadInputDataBit(GPIOB, Key_1) == 1)     
	{
		Delay_ms(20);
		while (GPIO_ReadInputDataBit(GPIOB, Key_1) == 1);//高电平进入死循环,直到按键松手,输入为低电平0
		Delay_ms(20);  
		KeyNum = 1;
	}
	//按下按键2(B5)  接受高电平信号
	else if (GPIO_ReadInputDataBit(GPIOB, Key_2) == 1)     
	{
		Delay_ms(20);
		while (GPIO_ReadInputDataBit(GPIOB, Key_2) == 1); //高电平进入死循环,直到按键松手,输入为低电平0
		Delay_ms(20);
		KeyNum = 2;
	}
	return KeyNum;
}

Key.h

#ifndef __Key_H
#define __Key_H

void Key_Init(void);
uint16_t Key_Num(void);

#endif

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Time.h"
#include "Key.h"
extern int fq;
int key;
int i;
int main(void)
{
	OLED_Init();
	TIM2_Init();
	Key_Init();
	while(1) 
	{
		OLED_ShowString(1,1,"ON");   //测量运行中显示
		OLED_ShowString(2,1,"f");
		key=Key_Num(); //获取按键的状态
		if(key==1)//按下第一个按键
		{
			TIM4_Init(10000-1,7200-1);//测量上限在65536左右
			i=1;
		}
		if(key==2)//按下第二个按键
		{
			TIM4_Init(10000-1,450-1);  //测量上限在78w左右
			i=16;
		}
		OLED_ShowNum(2,3,fq*i,7);      //显示频率值
		OLED_ShowString(4,1,"Over");   //测量完毕显示
		Delay_ms(100);
	}
	
}

#include "counter.h" #include "stdio.h" #include "usart.h" /*********************************************************************************************** //上升沿捕获 ************************************************************************************************/ TIM_ICInitTypeDef TIM3_ICInitStructure; void TIM3_counter_Init(u16 arr,u16 psc) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能TIM5时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //PA7 清除之前设置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //PA7 浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_ResetBits(GPIOA,GPIO_Pin_7); //PA7 下拉 //初始化定时器5 TIM5 TIM_TimeBaseStructure.TIM_Period = arr; //设定计数器自动重装值 TIM_TimeBaseStructure.TIM_Prescaler =psc; //预分频器 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的时间基数单位 //初始化TIM5输入捕获参数 TIM3_ICInitStructure.TIM_Channel = TIM_Channel_2; // 选择输入端 IC1映射到TI1上 TIM3_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕获 TIM3_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上 TIM3_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置输入分频,不分频 TIM3_ICInitStructure.TIM_ICFilter = 0x00; //IC1F=0000 配置输入滤波器 不滤波 TIM_ICInit(TIM3, &TIM3_ICInitStructure);
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>