1.簡(jiǎn)介:數(shù)字頻率計(jì)主要由四個(gè)部分組成:時(shí)基電路,整形電路,控制電路和顯示電路組成。在一個(gè)測(cè)量周期過(guò)程中,由時(shí)基電路產(chǎn)生一標(biāo)準(zhǔn)時(shí)間信號(hào)控制閥門(mén),調(diào)節(jié)時(shí)基電路中的電阻可產(chǎn)生需要的標(biāo)準(zhǔn)時(shí)間信號(hào)。信號(hào)輸入整形電路中,經(jīng)過(guò)整形,輸出一方波,通過(guò)閥門(mén)后,計(jì)時(shí)器對(duì)其計(jì)數(shù)。當(dāng)計(jì)數(shù)完畢,時(shí)基電路輸出一個(gè)上升沿,使鎖存器打開(kāi),計(jì)數(shù)器計(jì)數(shù)結(jié)果輸入譯碼器,從而讓顯示器顯示,達(dá)到測(cè)量頻率的目的。文件包括設(shè)計(jì)電路圖,設(shè)計(jì)源代碼與設(shè)計(jì)報(bào)
1.測(cè)量信號(hào)輸入幅度1V~5V方波,頻率為1kHz~10kHz,測(cè)量精度1%,信號(hào)輸入幅度1V~5V三角波,頻率為1kHz~10kHz,測(cè)量精度1%,信號(hào)輸入幅度2V~5V正弦波,頻率為1kHz~10kHz,測(cè)量精度1%;
1.測(cè)頻部分:先對(duì)輸入信號(hào)進(jìn)行波形轉(zhuǎn)換,通過(guò)一個(gè)過(guò)零比較器將三角波、正弦波轉(zhuǎn)化為方波,之后將將方波輸入單片機(jī) 口進(jìn)行波形測(cè)試。
2.限幅報(bào)警部分:輸入信號(hào)經(jīng)過(guò)D1變成半波信號(hào),之后經(jīng)過(guò)C3,C4,C5,C6,C7進(jìn)行整流成為幅值直流信號(hào),之后將信號(hào)輸入電位器進(jìn)行分壓,保證15v電壓經(jīng)過(guò)電位器后剩余3.3v電壓。最后輸出到端口上與3.3v電壓進(jìn)行比較,將比較結(jié)果輸入單片機(jī) 口。
3.單片機(jī)供電部分:通過(guò)供電模塊輸出3.3v電壓供給stm32單片機(jī)。
4.軟件設(shè)計(jì)原理:硬件部分會(huì)將所有波形統(tǒng)一成方波輸入。使用TIM3與TIM4計(jì)時(shí)器。TIM3進(jìn)行波形捕捉。TIM3捕捉波形的上升沿或者下降沿。開(kāi)始計(jì)數(shù),知道捕捉到相對(duì)應(yīng)的上升沿或者下降沿。根據(jù)所計(jì)數(shù)的多少即可計(jì)算出波形的占空比。每次捕捉到上升沿且之前為低電平,頻率計(jì)數(shù)加一。TIM4計(jì)數(shù)器用來(lái)計(jì)數(shù)一秒,當(dāng)TIM4計(jì)數(shù)滿一秒時(shí),發(fā)生TIM4中斷,根據(jù)TIM3的頻率計(jì)數(shù),即可計(jì)算出輸入波形的頻率。
5.源代碼:(帶有詳細(xì)注釋)Main函數(shù):#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "oled.h"
#include "timer.h"
#include "led.h"
#include "key.h"
extern uint16_t counter; //記錄捕獲狀態(tài)
extern uint8_t flag; //記錄計(jì)時(shí)是否滿一秒
extern uint32_t rising_time; //高電平持續(xù)時(shí)間
extern uint32_t falling_time; //低電平持續(xù)時(shí)間
int main(void)
{
delay_init(); //延時(shí)函數(shù)初始化
uart_init(115200); //串口一初始化,設(shè)置波特率為115200
LED_Init(); //報(bào)警LED初始化
KEY_Init(); //比較器輸入初始化
OLED_Init(); //OLED顯示屏初始化
OLED_Clear(); //清空顯示屏
OLED_ShowString(30,0, "Cymometer"); //在屏幕上顯示Cymometer
OLED_ShowString(20,4, "Fre:");
OLED_ShowString(93,4, "Hz");
OLED_ShowString(20,6, "Dut:");
OLED_ShowString(87,6, "%");
TIM3_Cap_Init(0xffff,72-1); //TIM3初始化 時(shí)鐘設(shè)為1M Hz用于輸入捕獲
TIM4_Int_Init(10000-1,72-1); //TIM4初始化 時(shí)鐘設(shè)為1M Hz用于計(jì)時(shí)1s
while(1)
{
if(flag== 1) //檢測(cè)計(jì)時(shí)是否滿1s
{
flag= 0;
if((rising_time!= 0) && (falling_time != 0)) //有信號(hào)輸入
{
printf("Fre:%dHz, Dut:%1.2f\r\n", counter,(float)rising_time/(rising_time + falling_time));
OLED_ShowNum(53,4, counter, 5, 16);
OLED_ShowNum(71,6, (float)rising_time/(rising_time + falling_time)*100, 2, 16);
}
else
{
printf("Fre:%d Dut:0\r\n", counter); //無(wú)信號(hào)輸入
OLED_ShowNum(53,4, counter, 5, 16);
OLED_ShowNum(71,6, 0, 2, 16);
}
counter= 0;
rising_time= 0;
falling_time= 0;
}
if(KEY== 1) //檢測(cè)比較器輸入是否為高電平
LED= 0; //報(bào)警燈亮
elseLED = 1; //報(bào)警燈不亮
}
}
計(jì)時(shí)器函數(shù):#include "sys.h"
#include "timer.h"
#include "usart.h"
void TIM3_Cap_Init(uint16_t arr, uint16_tpsc) //TIM3用于輸入捕獲
{
GPIO_InitTypeDefGPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM3_ICInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //使能TIM3時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //使能GPIOA時(shí)鐘
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //選擇6號(hào)引腳
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IPD; //輸入下拉
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA6
GPIO_ResetBits(GPIOA,GPIO_Pin_0); //PA6下拉
//初始化定時(shí)器3 TIM3
TIM_TimeBaseStructure.TIM_Period= arr; //設(shè)定計(jì)數(shù)器自動(dòng)重裝值
TIM_TimeBaseStructure.TIM_Prescaler=psc; //預(yù)分頻器
TIM_TimeBaseStructure.TIM_ClockDivision= TIM_CKD_DIV1; //設(shè)置時(shí)鐘分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode= TIM_CounterMode_Up; //TIM向上計(jì)數(shù)模式
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
//初始化TIM3輸入捕獲參數(shù)
TIM3_ICInitStructure.TIM_Channel= TIM_Channel_1; //CC1S=01選擇輸入端 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);
//中斷分組初始化
NVIC_InitStructure.NVIC_IRQChannel= TIM3_IRQn; //TIM3中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 0; //先占優(yōu)先級(jí)0級(jí)
NVIC_InitStructure.NVIC_IRQChannelSubPriority= 0; //從優(yōu)先級(jí)0級(jí)
NVIC_InitStructure.NVIC_IRQChannelCmd= ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure);
TIM_ITConfig(TIM3,TIM_IT_CC1,ENABLE);
TIM_Cmd(TIM3,ENABLE ); //使能定時(shí)器3
}
uint8_t TIM3CH1_CAPTURE_STA; //輸入捕獲狀態(tài)
uint16_t counter = 0; //記錄捕獲上升沿次數(shù)
uint8_t sec_cnt = 0; //毫秒計(jì)時(shí)
uint8_t flag = 0; //計(jì)時(shí)1s完成標(biāo)志
uint32_t rising_time; //高電平時(shí)間
uint32_t falling_time; //低電平時(shí)間
//定時(shí)器3中斷服務(wù)程序
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET) //發(fā)生捕獲事件
{
if(TIM3CH1_CAPTURE_STA& 0x80) //捕獲下降沿(已經(jīng)捕獲到上升沿)
{
rising_time= TIM_GetCapture1(TIM3); //讀取高電平時(shí)間(us)
TIM3CH1_CAPTURE_STA= 0; //清空
TIM_SetCounter(TIM3,0);
TIM3CH1_CAPTURE_STA|= 0x40; //標(biāo)記捕獲到了下降沿
TIM_OC1PolarityConfig(TIM3,TIM_ICPolarity_Rising); //設(shè)置為上升沿觸發(fā)
}
else //捕獲上升沿
{
falling_time= TIM_GetCapture1(TIM3); //低電平時(shí)間
TIM3CH1_CAPTURE_STA= 0; //清零
TIM_SetCounter(TIM3,0);
TIM3CH1_CAPTURE_STA|=0X80; //標(biāo)記捕獲到了上升沿
TIM_OC1PolarityConfig(TIM3,TIM_ICPolarity_Falling); //開(kāi)始捕獲下降沿
counter++; //頻率計(jì)數(shù)加一
}
}
TIM_ClearITPendingBit(TIM3,TIM_IT_CC1); //清除中斷標(biāo)志位
}
void TIM4_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDefNVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE); //時(shí)鐘使能
TIM_TimeBaseStructure.TIM_Period= arr; //設(shè)置在下一個(gè)更新事件裝入活動(dòng)的自動(dòng)重裝載寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler=psc; //設(shè)置用來(lái)作為TIMx時(shí)鐘頻率除數(shù)的預(yù)分頻值
TIM_TimeBaseStructure.TIM_ClockDivision= 0; //設(shè)置時(shí)鐘分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode= TIM_CounterMode_Up; //TIM向上計(jì)數(shù)模式
TIM_TimeBaseInit(TIM4,&TIM_TimeBaseStructure); //根據(jù)TIM_TimeBaseInitStruct中指定的參數(shù)初始化TIMx的時(shí)間基數(shù)單位
TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);
NVIC_InitStructure.NVIC_IRQChannel= TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 1; //先占優(yōu)先級(jí)1級(jí)
NVIC_InitStructure.NVIC_IRQChannelSubPriority= 0; //從優(yōu)先級(jí)0級(jí)
NVIC_InitStructure.NVIC_IRQChannelCmd= ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //根據(jù)NVIC_InitStruct中指定的參數(shù)初始化外設(shè)NVIC寄存器
TIM_Cmd(TIM4,ENABLE);
}
void TIM4_IRQHandler(void) //TIM3中斷,10000us中斷一次
{
if(TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) //檢查指定的TIM中斷發(fā)生與否:TIM 中斷源
{
sec_cnt++;
if(sec_cnt== 100) //計(jì)時(shí)滿1秒
{
sec_cnt= 0;
flag= 1;
}
TIM_ClearITPendingBit(TIM4,TIM_IT_Update); //清除TIMx的中斷待處理位:TIM 中斷源
}
}
LED初始化:#include "led.h"
#include "sys.h"
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); //使能GPIOC端口時(shí)鐘
GPIO_InitStructure.GPIO_Pin= GPIO_Pin_13; //LED-->PC13 端口配置
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_Out_PP; //推挽輸出
GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz; //IO口速度為50MHz
GPIO_Init(GPIOC,&GPIO_InitStructure); //根據(jù)設(shè)定參數(shù)初始化GPIOB.5
GPIO_SetBits(GPIOC,GPIO_Pin_13);
}
幅值報(bào)警初始化:#include "key.h"
#include "sys.h"
void KEY_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能PORTA時(shí)鐘
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IPD; //設(shè)置成下拉輸入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA5
}