石龍鎮(zhèn)網(wǎng)站仿做如何制作網(wǎng)站二維碼
一、概念介紹
輸出比較:
比較電路輸入的CNT、CCR大小關(guān)系?,在通道引腳輸出高低電平
二、*頻率知識、測量方法補(bǔ)充 *
N/fc得到標(biāo)準(zhǔn)頻率的時長,也就是待測頻率的周期
測頻法代碼實(shí)現(xiàn):修改對射式紅外傳感器計次(上升沿計次)、定時器外部時鐘(1s中斷)?
測頻法:定時器中斷,并記錄捕獲次數(shù);測周法:捕獲中斷,并記錄定時器次數(shù)。
三、輸入捕獲電路分析如何實(shí)現(xiàn)測周法:
異或門其實(shí)還是為三相無刷電機(jī)服務(wù),三個霍爾傳感器檢測轉(zhuǎn)子位置,根據(jù)轉(zhuǎn)子位置進(jìn)行換相,在前三個通道接上霍爾傳感器,這個定時器就作為無刷電機(jī)的接口定時器,去驅(qū)動換相電路工作
輸入濾波器:避免毛刺
3.1設(shè)計成交叉狀的目的:
TI1FP1(TI1 Filter Polarity 1) -->IC1<--TI2FP1
TI1FP2-->IC2<--TI2FP2
(1)靈活切換后續(xù)捕獲電路輸入 CH1變成CH2? ?即一個通道切換兩個引腳
(2)把一個引腳的輸入,同時映射到兩個捕獲單元(PWMI模式經(jīng)典結(jié)構(gòu)) 即兩個捕獲單元捕獲一個引腳
舉例:
第一個捕獲通道?TI1FP1上升沿觸發(fā),用來捕獲周期
第二個捕獲通道TI1FP2下降沿觸發(fā),用來捕獲占空比
兩個通道同時對一個引腳進(jìn)行捕獲
3.2預(yù)分頻器(測周法實(shí)現(xiàn))&捕獲中斷
*設(shè)置上升沿觸發(fā),分頻后的觸發(fā)信號每來一次,CNT就會向CCR轉(zhuǎn)運(yùn)一次,又因?yàn)镃NT是內(nèi)部的標(biāo)準(zhǔn)時鐘驅(qū)動的,CNT數(shù)值就可以記錄兩個上升沿之間的時間間隔,也就是周期,取倒數(shù)得到頻率
上升沿用于觸發(fā)輸入捕獲,CNT用于計數(shù)計時
捕獲中斷:同時產(chǎn)生捕獲事件,這個事件在狀態(tài)寄存器置標(biāo)志位,同時也可以產(chǎn)生中斷
3.3應(yīng)用場景:超聲波模塊檢測電路
3.4細(xì)節(jié)問題
每次捕獲后,把CNT清零,這樣下次上升沿再捕獲,取出的CNT 才是兩個上升沿的時間間隔
用主從觸發(fā)模式自動完成
四、電路執(zhí)行細(xì)節(jié)
?注意:
CNT的值是有上限的(65535=ARRmax),若信號頻率太低,CNT計數(shù)值會溢出
?從模式的觸發(fā)源選擇:TI1FP1 TI2FP2沒有3,4 想用從模式自動清零CNT,只能用通道1和通道2,對于通道3和通道4只能開啟捕獲中斷,手動清零
-->Q:能否外部中斷? AS:概念不清,外部中斷那是CPU了啊,這里是硬件映射主模式,然后配置從模式
?也可以捕獲第二個引腳:TI2FP1 TI2FP2
五、函數(shù)學(xué)習(xí)
/*****初始化輸入捕獲單元******/
void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);//只配置一個通道void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);//配置兩個通道(PWMI模式)/*****給輸入捕獲結(jié)構(gòu)體賦初值*****/
void TIM_ICStructInit(TIM_ICInitTypeDef* TIM_ICInitStruct);*****************************選擇從模式*********************************/*****選擇從模式輸入觸發(fā)源*****/void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);
/*****選擇主模式輸出觸發(fā)源*****/
void TIM_SelectOutputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_TRGOSource);
/*****選擇從模式*****/
void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode);/*****配置分頻器*****/
結(jié)構(gòu)體里也能配置,一個效果void TIM_SetIC1Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC2Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC3Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC4Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);/*****讀取CRR*****/
輸入捕獲模式下只讀,輸出比較只寫(TIM_SetComparex),函數(shù)是不一樣的
uint16_t TIM_GetCapture1(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture2(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture3(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture4(TIM_TypeDef* TIMx);
Q&AnS
為什么ARR要大一些?
-->防止N過大計數(shù)溢出,為了防止cnt到了某個值就重裝了
psc也不能給的太小,防止測量的信號頻率過低,導(dǎo)致計數(shù)器溢出
注意:
1.濾波器 VS分頻器
濾波器計次不會改變信號原有頻率,因?yàn)闉V波器采樣頻率遠(yuǎn)遠(yuǎn)高于信號頻率,只會濾除高頻噪聲,使信號更平滑
分頻器對信號本身計次,會改變頻率
這里用上升沿觸發(fā)歸零,后邊用下降沿不觸發(fā)歸零,兩個值一減就是占空比。歸零一次是一個周期,從0開始計高電平方便得出占空比,不然還得用1再減一下
2.Fc = 72MHz/(psc+1)
?六、輸入捕獲模式測頻率代碼分析
main.c?
為什么PWM那里還是 720-1 IC卻要改72-1?
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"
#include "IC.h"int main(void)
{OLED_Init();PWM_Init();IC_Init();OLED_ShowString(1,1,"Freq:00000Hz");PWM_SetPreScaler(720-1); //Freq= 72M / (PSC+1) / 100PWM_SetCompare1(50); //Duty = CRR / 100while(1){OLED_ShowNum(1,6,IC_GetFreq(),5);}}
IC.C
#include "stm32f10x.h" // Device headervoid IC_Init(void)
{/*****STEP1 開啟時鐘*****/RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//TIM2要輸出PWM 換成3捕獲RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//TIM3_CH1 在PA6口/*****STEP2 配置GPIO*****/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);/*****STEP3 配置時基單元*****/ TIM_InternalClockConfig(TIM3);TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision =TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode =TIM_CounterMode_Up ;TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;//ARRTIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1 ;//PSC 1MHzTIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);/*****STEP 4 輸入捕獲配置*****/TIM_ICInitTypeDef TIM_ICInitStructure;TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; //選擇通道TIM_ICInitStructure.TIM_ICFilter = 0xF; //配置濾波器參數(shù),數(shù)值越大過濾效果越好TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //極性選擇TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //分頻器TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //配置數(shù)據(jù)選擇器TIM_ICInit(TIM3,&TIM_ICInitStructure);/*****STEP 5 配置主從觸發(fā)模式 *****/TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1); //觸發(fā)源選擇TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset); //配置從模式/*****STEP6 啟動定時器*****/TIM_Cmd(TIM3,ENABLE);
}uint32_t IC_GetFreq(void)
{return 1000000 / TIM_GetCapture1(TIM3); //Fc = 72MHz/(psc+1)
}
現(xiàn)象
10001Hz?
原因:
計數(shù)到1000Hz那個數(shù)信號剛好跳變,導(dǎo)致數(shù)沒記上
有朋友說是因?yàn)?#xff1a;讀取的是N,但實(shí)際上計了N+1個數(shù),因?yàn)橛嫈?shù)器CNT是從0開始計的,所以這里要加一,錯,自行探討
改進(jìn):
uint32_t IC_GetFreq(void)
{
?? ?return 1000000 /(?TIM_GetCapture1(TIM3)+1); ? ? ?//Fc = 72MHz/(psc+1)
}
七、PWMI測占空比代碼分析
與上一個代碼不同的地方:
1.輸入捕獲初始化需要升級:
兩個通達(dá)捕獲同一個引腳,比較樸素的想法就是再定義一遍結(jié)構(gòu)體參數(shù)
通道1 直連輸入,上升沿觸發(fā) 通道2 交叉輸入(通道2相當(dāng)于通道1 的交叉輸入結(jié)果)下降沿觸發(fā)
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; //選擇通道TIM_ICInitStructure.TIM_ICFilter = 0xF; //配置濾波器參數(shù),數(shù)值越大過濾效果越好TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling; //極性選擇TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //分頻器TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_IndirectTI; //配置數(shù)據(jù)選擇器TIM_ICInit(TIM3,&TIM_ICInitStructure);
簡單的辦法 (只支持通道1、2之間):
TIM_PWMIConfig(TIM3,&TIM_ICInitStructure); //自動把剩下的通道配置成相反的配置
2.占空比函數(shù)
uint32_t IC_GetDuty(void)
{return (TIM_GetCapture2(TIM3) + 1) * 100 /(TIM_GetCapture1(TIM3) + 1);
}
3.main變動
/***main 變動***/
OLED_ShowString(2,1,"Duty:00%");/***while 變動***/
OLED_ShowNum(2,6,IC_GetDuty(),2);
八、探究測頻率性能
測頻率范圍?
fc 1MHz Nmax = 65535? 最低頻率是15Hz左右
要是再想降最低頻率限制,PSC加大(這里fc=72M/(PSC+1)就是1M,當(dāng)fc越小,能夠測量的信號頻率就越小,所以你要想測頻率更小的信號,就可以減小fc,也就是增大PSC值)
頻率上限,就是標(biāo)準(zhǔn)頻率了,再高,沒法測,誤差(正負(fù)一誤差=1/計數(shù)值)大,提高上限就要降低PSC或者嘗試測頻法