最近一直嘗試各種方法測量一個正弦波的頻率,可是都不太理想,老差幾個hz,尤其中頻,現(xiàn)在先將自己的方法供大家研討。
第一種方法:
比較笨的方法,使用了回調(diào)函數(shù),但是要設一個變量判斷,是否符合條件。
#define F_CPU sysclk_get_main_hz()
#include
uint32_t frequence;
static void my_frq_test_callback(void)
{
if(frequence》100)
{
//如果想看結果的話,可以設置一個斷點
asm(“nop”);
PORTA.INT0MASK=~PIN1_bm;
PORTA.INTCTRL=PORT_INT0LVL_OFF_gc;
tc_write_clock_source(&TCC0,TC_CLKSEL_OFF_gc);
/*這里不用tc_disable(&TCC0),好像定時器也關掉了,再次使用時,必須使能定時器,tc_enable(&TCC0) ,然后再用tc_write_clock_source(&TCC0, TC_CLKSEL_DIV1_gc);啟動定時器就行了*/
frequence=0;
}
}
int main(void)
{
sysclk_init();
pmic_init();
//這里的IOPORT_PULL_UP加上后,不知道為什么會先產(chǎn)生個中斷,也請分析一下
ioport_configure_pin(IOPORT_CREATE_PIN(PORTA,1),IOPORT_DIR_INPUT|IOPORT_BOTHEDGES|IOPORT_PULL_UP);
//這里的定義不知道能否加到上面的定義中,請給點建議
PORTA.INT0MASK=PIN1_bm;
PORTA.INTCTRL=PORT_INT0LVL_MED_gc;
tc_enable(&TCC0);
tc_set_wgm(&TCC0, TC_WG_NORMAL);
tc_write_period(&TCC0,40000);
tc_set_overflow_interrupt_callback(&TCC0, my_frq_test_callback);
tc_set_overflow_interrupt_level(&TCC0, TC_INT_LVL_LO);
cpu_irq_enable();
do
{}while(1);
}
ISR(PORTA_INT0_vect)
{
if(frequence==0)
{
tc_write_clock_source(&TCC0, TC_CLKSEL_DIV1_gc);
}
else
{
frequence++;
}
}
第二種方法:
用2個定時器,因為定時器的period的值是uint16_t的,如果超限,會引起程序工作不正常,所以用2個定時器解決一下,第二個定時器一第一個定時器的溢出為時鐘信號,沒有用到回調(diào)函數(shù),簡單代碼如下:#define F_CPU sysclk_get_main_hz()
#include
uint32_t frq;
int main (void)
{
/* Insert system clock initialization code here (sysclk_init())。 */
board_init();
pmic_init();
sysclk_init();
//定義管腳中斷
PORTA.DIRCLR=PIN1_bm;
PORTA.PIN1CTRL=PORT_ISC_BOTHEDGES_gc;//|PORT_OPC_PULLUP_gc 此處還是不知道用不用上拉
PORTA.INT0MASK=PIN1_bm;
PORTA.INTCTRL=PORT_INT0LVL_MED_gc;
//設置及使能事件
sysclk_enable_module(SYSCLK_PORT_GEN, SYSCLK_EVSYS);
EVSYS.CH0MUX = EVSYS_CHMUX_TCC0_OVF_gc;
//TCC0為第一個定時器,它的溢出提供給TCD0做為事件時鐘
tc_enable(&TCC0);
tc_enable(&TCD0);
tc_set_wgm(&TCD0,TC_WG_NORMAL);
tc_set_wgm(&TCC0,TC_WG_NORMAL);
//因為系統(tǒng)時鐘用的是內(nèi)部2M的時鐘,除以50后,一個是好算事件,一個是最接近時鐘溢出的period,period不能超過65535,能有別的好方法 //也希望能指點一下
tc_write_period(&TCC0,sysclk_get_main_hz()/50);
tc_write_period(&TCD0,1000);
tc_set_overflow_interrupt_level(&TCC0,TC_INT_LVL_LO);
tc_enable_delay(&TCD1);
tc_write_clock_source(&TCD0,TC_CLKSEL_EVCH0_gc) ;
cpu_irq_enable();
do
{
} while (tc_is_overflow(&TCD0)==0);
frq/=4;
//可以在這里設置一個斷點看結果,應該在后面對frq置0,方便后面的程序調(diào)用,可是如果后面我把frq置0,此時就看到的值也為0,也希望給點 //建議
asm(“nop”);
/* Insert application code here, after the board has been initialized. */
do
{
} while (1);
}
ISR(PORTA_INT0_vect)
{
asm(“nop”);
if(frq==0)
{
tc_write_clock_source(&TCC0,TC_CLKSEL_DIV1_gc);
}
frq++;
}
以上就是2種測量方法的代碼,第二個方法比第一個要快。
-
正弦波
+關注
關注
11文章
643瀏覽量
55398
發(fā)布評論請先 登錄
相關推薦
評論