定時(shí)器按鍵消抖
之前的延時(shí)消抖,是直接借助delay函數(shù)進(jìn)行的,但是這樣會(huì)浪費(fèi)CPU的性能。我們采用延時(shí)函數(shù)的方式實(shí)現(xiàn),可以實(shí)現(xiàn)快進(jìn)快出。
?定時(shí)器消抖,必須是在t3的時(shí)間點(diǎn)才可以,當(dāng)在t1,t2的時(shí)間點(diǎn)每次進(jìn)入中斷函數(shù)都要重新開啟定時(shí)器的計(jì)時(shí)
但是,這兩個(gè)時(shí)間點(diǎn)的時(shí)間小于定時(shí)器設(shè)定的10ms,所以不會(huì)產(chǎn)生定時(shí)器中斷,也會(huì)避免這種情況的發(fā)生。只有在t3的時(shí)刻開啟,才會(huì)產(chǎn)生定時(shí)器中斷【時(shí)間夠長(zhǎng)】,這便是定時(shí)器的消抖原理。
void filtertimer_init(unsigned int value)
{
EPIT1->CR = 0; //先清零
/*
* CR寄存器:
* bit25:24 01 時(shí)鐘源選擇Peripheral clock=66MHz
* bit15:4 0 1分頻
* bit3: 1 當(dāng)計(jì)數(shù)器到0的話從LR重新加載數(shù)值
* bit2: 1 比較中斷使能
* bit1: 1 初始計(jì)數(shù)值來(lái)源于LR寄存器值
* bit0: 0 先關(guān)閉EPIT1
*/
EPIT1->CR = (1<<24 | 1<<3 | 1<<2 | 1<<1);
/* 計(jì)數(shù)值 */
EPIT1->LR = value;
/* 比較寄存器,當(dāng)計(jì)數(shù)器值和此寄存器值相等的話就會(huì)產(chǎn)生中斷 */
EPIT1->CMPR = 0;
GIC_EnableIRQ(EPIT1_IRQn); /* 使能GIC中對(duì)應(yīng)的中斷 */
/* 注冊(cè)中斷服務(wù)函數(shù) */
system_register_irqhandler(EPIT1_IRQn, (system_irq_handler_t)filtertimer_irqhandler, NULL);
}
?對(duì)定時(shí)器進(jìn)行設(shè)置,上一章節(jié)已經(jīng)詳細(xì)說(shuō)明了,不多贅述。核心其實(shí)計(jì)時(shí)定時(shí)器設(shè)定了10ms開啟定時(shí)器中斷。因?yàn)檫x擇時(shí)鐘主頻是66MHZ【計(jì)一個(gè)數(shù)=1/66000000s】,所以倒計(jì)時(shí)的時(shí)間是time = (66000000/100/66000000 = 10ms)。
高精度延時(shí)實(shí)驗(yàn)
GPT定時(shí)器
GPT是一個(gè)32位的向上定時(shí)器【0X00000000】,也可以和一個(gè)數(shù)值進(jìn)行比較,當(dāng)計(jì)數(shù)值和這個(gè)數(shù)值相等的話就會(huì)發(fā)生比較事件,產(chǎn)生比較中斷,也存在一個(gè)12位的分頻器【1-4096】。
存在三個(gè)輸出比較寄存器,三個(gè)是輸出比較中斷
兩種模式:
重新啟動(dòng)(restart)模式:
自由運(yùn)行(free-run)模式:

SWR(bit15):向此位寫 1 就可以復(fù)位 GPT 定時(shí)器,當(dāng) GPT 復(fù)位完成以 后此為會(huì)自動(dòng)清零
FRR(bit9):當(dāng)此位為 0 的時(shí)候比較通道 1 工作在重新啟動(dòng)(restart)模式。當(dāng)此位為 1 的時(shí)候所有的三個(gè)比較通道均工作在自由運(yùn)行模式(free-run)CLKSRC(bit8:6):GPT 定時(shí)器時(shí)鐘源選擇位,為 0 的時(shí)候關(guān)閉時(shí)鐘源;為 1 的時(shí)候選擇 ipg_clk 作為時(shí)鐘源;為 2 的時(shí)候選擇 ipg_clk_highfreq 為時(shí)鐘源;為 3 的時(shí)候選擇外部時(shí)鐘為 時(shí)鐘源;為 4 的時(shí)候選擇 ipg_clk_32k 為時(shí)鐘源;為 5 的時(shí)候選擇 ip_clk_24M 為時(shí)鐘源。ENMOD(bit1) : GPT 使能模式,此位為 0 的時(shí)候如果關(guān)閉 GPT 定時(shí)器,計(jì)數(shù)器寄存器保存定時(shí)器關(guān)閉時(shí)候的計(jì)數(shù)值。此位為 1 的時(shí)候如果關(guān)閉 GPT 定時(shí)器,計(jì)數(shù)器寄存器就會(huì)清零。EN(bit) : GPT 使能位,為 1 的時(shí)候使能 GPT 定時(shí)器,為 0 的時(shí)候關(guān)閉 GPT 定時(shí)器
?文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-629847.html
PRESCALER(bit11:0): 這就是 12 位分頻值, 可設(shè)置 0~4095 ,分別對(duì)應(yīng) 1~4096 分頻
?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-629847.html
ROV(bit5) : 回滾標(biāo)志位,當(dāng)計(jì)數(shù)值從 0XFFFFFFFF 回滾到 0X00000000 的時(shí)候此位置 1 。IF2~IF1(bit4:3) : 輸入捕獲標(biāo)志位,當(dāng)輸入捕獲事件發(fā)生以后此位置 1 ,一共有兩路輸入捕獲通道。如果使用輸入捕獲中斷的話需要在中斷處理函數(shù)中清除此位。OF3~OF1(bit2:0) :輸出比較中斷標(biāo)志位,當(dāng)輸出比較事件發(fā)生以后此位置 1 ,一共有三路輸出比較通道。如果使用輸出比較中斷的話需要在中斷處理函數(shù)中清除此位
高精度延時(shí)的原理:
void delayus(unsigned int usdelay)
{
unsigned long oldcnt,newcnt;
unsigned long tcntvalue = 0; /* 走過(guò)的總時(shí)間 */
oldcnt = GPT1->CNT;
while(1)
{
newcnt = GPT1->CNT;
if(newcnt != oldcnt)
{
if(newcnt > oldcnt) /* GPT是向上計(jì)數(shù)器,并且沒有溢出 */
tcntvalue += newcnt - oldcnt;
else /* 發(fā)生溢出 */
tcntvalue += 0XFFFFFFFF-oldcnt + newcnt;
oldcnt = newcnt;
if(tcntvalue >= usdelay)/* 延時(shí)時(shí)間到了 */
break; /* 跳出 */
}
}
}
/*
* @description : 毫秒(ms)級(jí)延時(shí)
* @param - msdelay : 需要延時(shí)的ms數(shù)
* @return : 無(wú)
*/
void delayms(unsigned int msdelay)
{
int i = 0;
for(i=0; i<msdelay; i++)
{
delayus(1000);
}
}
到了這里,關(guān)于linuxARM裸機(jī)學(xué)習(xí)筆記(5)----定時(shí)器按鍵消抖和高精度延時(shí)實(shí)驗(yàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!