目录
其中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);
}
}