全部博文(36)
分类: 嵌入式
2012-08-29 10:09:08
定时器的应用,这是第三个实验。在前面我们延时的时候,都是用的循环,也就是意思意思,达不到非常准确。我们要向准备的控制延时,我们就可以使用定时器。
上图即是2440的时钟产生框图。主时钟源一般是外部晶振或者外部时钟,多数用得是外部晶振。我们mini2440上也是12M的外部晶振,这个可以通过OM[3:2]位来配置。但是这个频率还是不能满足需求,所以通过PLL锁存器来进行倍频,有分为MPLL和UPLL,后者给USB使用,提供48M频率。而MPLL处理后得到3个时钟,FCLK,HCLK,PCLK.从上图可以看出,FCLK是主频时钟,用于ARM920T内核;HCLK用于AHB总线设备,如ARM920T,内存控制,中断控制,LCD控制,DMA以及USB主模块;PCLK用于APB总线设备,如外围设备的看门狗,IIS,I2C,PWM,MMC接口,ADC,UART,GPIO,RTC以及SPI。
三个系统时钟是有一定比例关系的,这个关系就是通过CLKDIVN寄存器中的HDIVN位和PDIVN位来控制,因此知道了FCLK的话,其他两个也就知道了。
而FCLK又如何得到呢?这个时钟经过MPLL倍率后,经过一个计算公式得到,这个计算公式需要三个参数MDIV,PDIV,SDIV,这个可以通过用户手册查看,这三个参数是经过寄存器MPLLCON配置得到的。
Mini2440上面外部晶振是12M,倍率后的FCLK位400MHZ,而FCLK,HCLK,PCLK的比例为1:4:8
因为HCLK为100M,PCLK为50MHZ。我们在启动文件中,已经把相关的寄存器已经设置好了,这里你只需要了解它的原理。
了解了时钟控制部分,那么我们就可以看定时器中断了。
首先看时钟,它是由PCLK引出来的,在它的基础上,经过一个八位分频和一个时钟分频。所以得到定时器的输出时钟频率为PCLK ÷ (prescaler+1) ÷ divider 其中prescaler值由TCFG0决定,divider值由TCFG1决定,而prescaler只能取0~255之间的整数,divider只能取2、4、8和16。
比如已知PCLK为50MHz,而我们想得到某一定时器的输出时钟频率为25kHz,则依据公式可以使PCLK ÷ (prescaler+1) ÷ divider prescaler等于249,divider等于8。
25Khz 这个频率是用来给计数器TCNTB0使用的,如果设置TCNTB0等于25000,那么TCNTB0从25000减到0就是1秒。
当它减到0的时候,那么就会产生定时器中断,当然你的把中断相关的屏蔽打开,定时中断服务程序。并且在TCON中更新你设置的TCNTB0的值,然后启动定时器。
这个寄存器我们需要认真看一下,首先自动重载功能,这个就是说,你的TCNTB0会自动重载TCNT0中的值,那么刚开始的话你就需要设置一个初始值给TCNTB0,后面你可以改动它,它会自动重载新的值。然后就是手动更新位,这个主要就是刚开始使用的时候,你把你的初始值更新给它,然后关闭这一位,必须关闭,不然出问题。接下来就是启动了。
我们这次这个实验的话,利用定时器来控制蜂鸣器,让它前面隔一秒叫一声,第五次之后,就把频率改变。在中断服务程序,我们改变TCNTB0的值来改变它的频率,由于自动重载,那么它就会重载我新设置的值。
下面贴出主要程序代码。
int dat = 0;
void __irq interupt(void)
{
static int i=0;
rSRCPND |= (1<<14);
rINTPND |= (1<<14);
dat = ~dat;
rGPBDAT = dat ;
i++;
if(i == 5 )
rTCNTB4 = 250;//改变它的值,那么将会重载这个新设置的值,beep响的频率也//是加快
}
void Main(void)
{
Set_Clk();
MMU_Init();
rGPBCON &= ~3;
rGPBCON |= 1;
rINTMSK &= ~(1<<14);
//50M / 250 =200k
rTCFG0 &=~(0xff<<8);
rTCFG0 |=(249<<8);
//200k / 8 =25k
rTCFG1 &=(0xf<<16);
rTCFG1 |=(2<<16);
//1s = 25000*1/25k
rTCNTB4 = 25000;
//更新TCNTB4
rTCON |= (3<<21);
//关闭更新
rTCON &= ~(1<<21);//这里必须要关闭更新,不然效果出不来,2440用户手册上也//说明了
//中断服务程序
pISR_TIMER4 = (U32)interupt;
//启动定时器4
rTCON |= 1<<20;
while(1);
}