lpc1114通用定時(shí)器-定時(shí)功能
掃描二維碼
隨時(shí)隨地手機(jī)看文章
下面我們以LED流水燈為例演示定時(shí)功能,流水的時(shí)間間隔由定時(shí)器精確控制。(看了上面的這句話就繞道的童鞋,請(qǐng)不要急著走,接下來(lái)講的不是怎么實(shí)現(xiàn)流水燈,而是怎么樣定時(shí)。)
下面我們以16位定時(shí)器0來(lái)演示。
新建一個(gè)工程,如下圖所示:
在timer.h文件中,輸入以下代碼:
#ifndef __NXPLPC11xx_TIME_H__
#define __NXPLPC11xx_TIME_H__
extern void T16B0_init(void);
extern void T16B0_delay_ms(uint16_t ms);
extern void T16B0_delay_us(uint16_t us);
#endif
在timer.c文件中,輸入以下代碼:
#include “l(fā)pc11xx.h”
#include “timer.h”
void T16B0_init(void)
{
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<7); //使能TIM16B0時(shí)鐘
LPC_TMR16B0->IR = 0x01; //MR0中斷復(fù)位,即清中斷
LPC_TMR16B0->MCR = 0x04; //MR0中斷產(chǎn)生時(shí)停止TC和PC,并停止定時(shí)器工作
}
void T16B0_delay_ms(uint16_t ms)
{
LPC_TMR16B0->TCR = 0x02; //復(fù)位定時(shí)器(bit1:寫1復(fù)位)
LPC_TMR16B0->PR = SystemCoreClock/1000-1; // 1毫秒TC+1
LPC_TMR16B0->MR0 = ms; // 注意:MR0是16位寄存器,值不要超過(guò)65535
LPC_TMR16B0->TCR = 0x01; //啟動(dòng)定時(shí)器:TCR[0]=1;
while (LPC_TMR16B0->TCR & 0x01);//等待定時(shí)器計(jì)時(shí)時(shí)間到
}
void T16B0_delay_us(uint16_t us)
{
LPC_TMR16B0->TCR = 0x02; //復(fù)位定時(shí)器(bit1:寫1復(fù)位)
LPC_TMR16B0->PR = SystemCoreClock/1000000-1; // 1微秒TC+1
LPC_TMR16B0->MR0 = us; // 注意:MR0是16位寄存器,值不要超過(guò)65535
LPC_TMR16B0->TCR = 0x01; //啟動(dòng)定時(shí)器:TCR[0]=1;
while (LPC_TMR16B0->TCR & 0x01);//等待定時(shí)器計(jì)時(shí)時(shí)間到
}
在timer.c文件中,一共定義了3個(gè)函數(shù),分別是定時(shí)器初始化函數(shù)、毫秒級(jí)定時(shí)函數(shù)和微秒級(jí)定時(shí)函數(shù)。
第3~8行為定時(shí)器初始化函數(shù),一共配置了4個(gè)寄存器。
第5行,給SYSAHBCLKCTRL寄存器的bit7寫1,開啟CT16B0時(shí)鐘。關(guān)于SYSAHBCLKCTRL寄存器的定義,詳見第一章。
第6行,給IR寄存器bit0寫1,清MR0中斷位。
第7行,給MCR寄存器bit2寫1,設(shè)置當(dāng)MR0匹配產(chǎn)生時(shí),停止PC和TC停止遞增,并使定時(shí)器停止工作。
PR是預(yù)分頻值寄存器,PC是預(yù)分頻計(jì)數(shù)器,TC是定時(shí)器計(jì)數(shù)器。單片機(jī)每個(gè)PCLK,PC都會(huì)加1,當(dāng)PC的值等于PR的值,TC的值就會(huì)+1,PC的值就會(huì)變?yōu)?,再次隨著PCLK遞增。所以PR的值決定了定時(shí)器TC的間隔時(shí)間,當(dāng)PR=0的時(shí)候,PC+1,即TC+1,如果這時(shí)候工作在50MHz,TC遞增的時(shí)間間隔即1/50000000=0.02微秒。
這個(gè)函數(shù)完全是在為定時(shí)做準(zhǔn)備。
第9~16行,毫秒級(jí)延時(shí)函數(shù)
第11行,給TCR寄存器bit1寫1,復(fù)位定時(shí)器,復(fù)位定時(shí)器后,PC=0,TC=0。
第12行,給PR寫值,確定預(yù)分頻值。SystemCoreClock是主時(shí)鐘,主時(shí)鐘是以標(biāo)準(zhǔn)單位s來(lái)說(shuō)的,因?yàn)閟 = 1/Hz,主頻除以1000,單位及毫秒,再減1,即為我們需要的數(shù)。
例如:當(dāng)主頻為50MHz時(shí),PR值就是50000000/1000-1=49999,上面講到,TC的值每PR+1遞增,即50000個(gè)PCLK,TC遞增,那TC遞增的間隔時(shí)間即為50000*0.02微秒=1毫秒。
第13行,寫入匹配值。剛才把PR值寫入,結(jié)果是TC每1毫秒遞增,所以這里直接把需要的毫秒數(shù)寫入即可。當(dāng)TC值從0數(shù)到MR0值時(shí),將執(zhí)行MCR配置好的動(dòng)作。
第14行,給TCR寄存器bit0寫1,啟動(dòng)定時(shí)器。
第15行,觀察TCR寄存器的bit0,當(dāng)bit0為變?yōu)?時(shí),定時(shí)時(shí)間到。之所以可以觀察這一位的值,是因?yàn)槲覀冊(cè)贛CR寄存器里面配置當(dāng)定時(shí)器時(shí)間到后,使TCR bit0為0.
第17~24行,微秒級(jí)延時(shí)函數(shù)
該函數(shù)大部分與前面所講的毫秒級(jí)延時(shí)函數(shù)類似,只有PR值不一樣,在這里,PR=49,即TC遞增的時(shí)間間隔是50*0.02微秒=1微秒
在main.c文件中,輸入以下代碼:
#include “l(fā)pc11xx.h”
#include “timer.h”
#define LED1_ON LPC_GPIO1->DATA &= ~(1<<0)
#define LED1_OFF LPC_GPIO1->DATA |= (1<<0)
#define LED2_ON LPC_GPIO1->DATA &= ~(1<<1)
#define LED2_OFF LPC_GPIO1->DATA |= (1<<1)
void led_init()
{
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<16); // 使能IOCON時(shí)鐘
LPC_IOCON->R_PIO1_0 &= ~0x07;
LPC_IOCON->R_PIO1_0 |= 0x01; //把P1.0腳設(shè)置為GPIO
LPC_IOCON->R_PIO1_1 &= ~0x07;
LPC_IOCON->R_PIO1_1 |= 0x01; //把P1.1腳設(shè)置為GPIO
LPC_SYSCON->SYSAHBCLKCTRL &= ~(1<<16); // 禁能IOCON時(shí)鐘
LPC_GPIO1->DIR |= (1<<0); // 把P1.0設(shè)置為輸出引腳
LPC_GPIO1->DATA |= (1<<0); // 把P1.0設(shè)置為高電平
LPC_GPIO1->DIR |= (1<<1); // 把P1.1設(shè)置為輸出引腳
LPC_GPIO1->DATA |= (1<<1); // 把P1.1設(shè)置為高電平
}
int main()
{
led_init();
T16B0_init();
while(1)
{
T16B0_delay_ms(1000);
LED1_ON;
LED2_OFF;
T16B0_delay_ms(1000);
LED1_OFF;
LED2_ON;
}
}