s3c2410 Timer

原创 2007年09月14日 10:26:00

s3c2410提供了516TimerTimer0~Timer4),其中Timer0~Timer3支持Pulse Width Modulation—— PWM(脉宽调制)。Timer4是一个内部定时器(internal timer),他没有输出引脚(output pins)。
下面是Timer的工作原理图。

clip_image002.gif (34.3 KB)

2007-3-23 21:32


[attach]60[/attach]
如上图所示,PCLKTimer的信号源,我们通过设置每个Timer相应的PrescalerClock DividerPCLK转换成输入时钟信号传送给各个Timer的逻辑控制单元(Control Logic),事实上每个Timer都有一个称为输入时钟频率(Timer input clock Frequency的参数,这个频率就是通过PCLKPrescalerClock Divider确定下来的,每个Timer 的逻辑控制单元就是以这个频率在工作。下面给出输入时钟频率的公式:

Timer input clock Frequency = PCLK / {prescaler value+1} / {clock divider }
{prescaler value} = 0~255
{ clock divider } = 2, 4, 8, 16


然而并不是每一个Timer都有对应的PrescalerClock Divider,从上面的原理图我们可以看到Timer0,Timer1共用一对PrescalerClock Divider,Timer2,Timer3,Timer4共用另一对PrescalerClock Dividers3c2410的整个时钟系统模块只存在两对PrescalerClock Divider

我曾经在讨论watchdog的文章中提到,watchdog也是一种定时器,他的工作就是在一个单位时间内对一个给定的数值进行递减和比较的操作,而我们这篇文章讨论的定时器他的工作内容和watchdog在本质上是一样的。定时器在一个工作周期(Timer input clock cycle内的具体工作内容主要有3个。分别是:

1
        对一个数值进行递减操作
2
        把递减后的数值和另一个数值进行比较操作
3
        产生中断或执行DMA操作


在启用Timer之前我们会对Timer进行一系列初始化操作,这些操作包括上面提到的设置PrescalerClock Divider,其中还有一个非常重要的就是要给Timer两个数值,我们分别称之为Counter(变量,用于递减)Comparer(定值,用于比较),Counter会被Timer 加载到COUNT BUFFER REGISTERTCNTB,Comparer会被Timer 加载到和COMPARE BUFFER REGISTERTCMPB),每个Timer都有这样两个寄存器。当我们设置完毕启动Timer之后,Timer在一个工作周期内所做的就是先把TCNTB中的数值(Counter)减1,之后把TCNTB中的数值和TCMPB中的数值(Comparer)进行对比,若Counter已经被递减到等于Comparer,发生计数超出,则Timer产生中断信号(或是执行DMA操作)并自动把Counter重新装入TCNTB(刷新TCNTB以重新进行递减)。以上就是Timer的工作原理。

下面我们结合代码具体说明如何对Timer0进行初始化并开启它。
首先我假设我的PCLK50700000Hz

// define Timer register
#define rTCFG0 (*(volatile unsigned int *)0x51000000)
#define rTCFG1 (*(volatile unsigned int *)0x51000004)
#define rTCON (*(volatile unsigned int *)0x51000008)
#define rTCNTB0 (*(volatile unsigned int *)0x5100000C)
#define rTCMPB0 (*(volatile unsigned int *)0x51000010)
#define rTCNTO0 (*(volatile unsigned int *)0x51000014)
#define rTCNTB1 (*(volatile unsigned int *)0x51000018)
#define rTCMPB1 (*(volatile unsigned int *)0x5100001C)
#define rTCNTO1 (*(volatile unsigned int *)0x51000020)
#define rTCNTB2 (*(volatile unsigned int *)0x51000024)
#define rTCMPB2 (*(volatile unsigned int *)0x51000028)
#define rTCNTO2 (*(volatile unsigned int *)0x5100002C)
#define rTCNTB3 (*(volatile unsigned int *)0x51000030)
#define rTCMPB3 (*(volatile unsigned int *)0x51000034)
#define rTCNTO3 (*(volatile unsigned int *)0x51000038)
#define rTCNTB4 (*(volatile unsigned int *)0x5100003C)
#define rTCNTO4 (*(volatile unsigned int *)0x51000040)


void timer0_config()
{

/*
                Timer0
prescalerrTCFG0 0~7 bit决定
                Prescaler=119
*/
                rTCFG0=119        
/*
                Timer0
divider valueTCFG1 0~3 bit决定,设置为3表示divider value = 1/16
                rTCFG1
的第20~23bit用于决定Timer计数超出后所采取的响应,我们使用了中断模式(20~23bit全部为0),
               
即计数超出后产生中断
*/
                rTCFG1=3;
        
                rTCNTB0=26406;
                rTCMPB0=0;
}

由于我们的PCLK50700000Hz, 根据Timer input clock Frequency的计算公式我们如下计算Timer0的时钟输入频率:

prescaler value = 119
divider value = 1/16
PCLK= 50700000
Timer input clock Frequency =50700000/ (119+1)/(1/16)=26406

也就是说通过设置prescalerdivider value之后,Timer0的工作频率为26406,也就是说一秒内Timer0会进行26406次递减和比较操作,假设我们现在是要让Timer01秒产生一次中断的话,我们应该设置Counter=26406Camparer=0,既:
rTCNTB0=26406;
rTCMPB0=0;

如果我们要让Timer00.5秒产生一次中断,则我们应该设置Counter=26406/2Camparer=0,既:
rTCNTB0=13203;
rTCMPB0=0;

如果我们要让Timer00.25秒产生一次中断,则我们应该设置Counter=26406/4Camparer=0,既:
rTCNTB0=6601;
rTCMPB0=0;

初始化完Timer后我们要开启它。

void timer0_start()
{

/*
               Update TCNTB0 & TCMPB0
               rTCON
寄存器的第1位是刷新Timer0COUNT BUFFER REGISTERTCNTB)和
                COMPARE BUFFER REGISTER
TCMPB),由于是第一次加载CounterComparer
               
所以我们需要手动刷新它们
*/
               rTCON|=1<<1;
/*
               
rTCON0位为1,开启Timer0
               
rTCON1位置为0,停止刷新TCNTB0 TCMPB0
               
rTCON3位为1,设置Counter的加载模式为自动加载(auto reload),这样每当
               Timer
计数超出之后(此时TCNTB的值等于TCMPB的值),Timer会自动把原来我们给
               
定的Counter重新加载到TCNTB
*/
        rTCON=0x09;        
}


要使你的Timer能够正常的工作,除了调用timer0_config()timer0_start()之外,我们还必须设置Timer的中断服务例程并取消对Timer的中断的屏蔽.这些操作可以参考<<s3c2410 中断异常处理>>一文.
另外OS实验区提供的源代码中有更为详细的代码,需要的朋友可以参考,关于Timer的代码存在于timer.c timer.h文件中

 

 

Linux下IIS音频驱动程序分析(基于S3C2410+ UDA1341)

原文地址::http://os.chinaunix.net/a2009/0901/997/000000997053.shtml     armlinux学习笔记--IIS音频驱动程序分析[z] ...

基于S3C2410A的MDB/ICP协议的实现

基于S3C2410A的MDB/ICP协议的实现 发布:2011-05-17 | 作者: | 来源: limaosheng | 查看:761次 | 用户关注: MDB/ICP广泛应用于自助售...

S3C2410看门狗驱动分析

根据linux中总线、设备和驱动这个模型来看,所有的设备驱动都挂在总线上,并且驱动应该是和平台无关的。唯一和平台有关的一类驱动应该是芯片内部的各个控制器的驱动,例如芯片内部I2C控制器,芯片内部LCD...

I实验箱s3c2410子板led驱动程序编译运行

开发板:EDUKIT-III实验箱,S3C2410+LINUX2.4.18,实验箱随箱光盘提供的Zimage,nor flash启动。 主机:ubnutn10.4LTS,arm-linux-gc...

S3C2410驱动分析之LCD驱动

作者:刘昊昱  博客:http://blog.csdn.net/liuhaoyutz 内核版本:2.6.36 源码路径:drivers/video/s3c2410fb.c   本文分析...

S3C2410&nbsp;MMU技术精解【转】

许多年以前,当人们还在使用DOS或是更古老的操作系统的时候,计算机的内存还非常小,一般都是以K为 单位进行计算,相应的,当时的程序规模也不大,所以内存容量虽然小,但还是可以容纳当时的程序。但随着图形界...

嵌入式Linux下S3C2410的调色板彩色显示

摘 要:嵌入式应用中,由于计算能力以及硬件资源的限制,常需要降低颜色深度,以获得较高的分辨率,因此调色板彩色显示是一种很重要的手段。在此以ARM9核的S3C2410芯片为例,探讨分析调色板的概念及配置...

s3c2410触摸屏驱动的介绍

.  S3C2410的触摸屏控制                                 (1).基础知识 要正确使用触摸屏,首先就要正确获取触摸屏的坐标。上一节我们已经介绍了触摸屏的...

基于ARM S3C2410的TSLIB1.4的移植过程详解

一、在ubuntu下编译tslib1.4 1、下载tslib-1.4.tar.gz http://download.csdn.net/detail/it_newborn/5675271 2、解压ts...

S3C2410 && WinCE6.0的中断处理分析

原文 地址:http://www.cnblogs.com/we-hjb/archive/2008/11/08/1329830.html S3C2410的内核是ARM920T,所以,这里先介绍一下AR...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:s3c2410 Timer
举报原因:
原因补充:

(最多只允许输入30个字)