S3C2440定时器如下图所示,其时钟来源是PCLK
1.经过一个8bit的第一级预分频器对时钟频率分频(可以通过TCFG0配置)
2.然后经过第二级分频(分频系数已经固定的)(可以通过TCFG1配置)
3.通过上面的流向,最后时钟进入到控制逻辑中,作为定时器的时钟频率
下图中的TCMPB作为比较缓冲寄存器,用来存放比较值的,(可以作为当计数器计数到等于TCMPB值,使输出脉冲改变,如高电平变低电平,PWM的用途)
TCNTB作为定时器计数初值缓冲寄存器,当计数到0时,如果设置了自动加载,则会将TCNTB中的值自动加载到TCNT中
注:TCNT,TCMP为定时器控制逻辑内部的计数值和比较值。
可以通过读取TCNTO来读取定时器当前计数值
S3C2440 定时器总结:
1.经过一个8bit的第一级预分频器对时钟频率分频(可以通过TCFG0配置)
2.然后经过第二级分频(分频系数已经固定的)(可以通过TCFG1配置)
3.通过上面的流向,最后时钟进入到控制逻辑中,作为定时器的时钟频率
下图中的TCMPB作为比较缓冲寄存器,用来存放比较值的,(可以作为当计数器计数到等于TCMPB值,使输出脉冲改变,如高电平变低电平,PWM的用途)
TCNTB作为定时器计数初值缓冲寄存器,当计数到0时,如果设置了自动加载,则会将TCNTB中的值自动加载到TCNT中
注:TCNT,TCMP为定时器控制逻辑内部的计数值和比较值。
可以通过读取TCNTO来读取定时器当前计数值
S3C2440 定时器总结:
定时器0配置步骤:(其他的也类似)
1.配置TCFG0,第一级分频系数
2.配置TCFG1,第二级分频系数
3.配置TCNTB0,定时器计数初始值
4.配置TCON0,启动定时器和更新定时器计数值
如果有中断:
5.向中断向量表timer0安装中断服务函数
6.使能定时器中断,INTMSK
注意:在ISR和main函数里面都要访问的变量必须加上volatile(花了好长时间在这里调试,后看到大神讨论这问题才明白过来)
/* 程序的功能是:led以1s的间隔闪烁
使用H-Jtag烧写至Nor Flash中,位于Bank0
*/
#include "2440addr.h"
#include "config.h"
void __irq timer0ISR(void);
void timer0Init(void);
void ledInit(void);
/* 必须加volatile修饰 */
volatile int ledFlag=1;
void Main(void)
{
ledInit();
timer0Init();
while(1)
{
if (ledFlag)
{
rGPBDAT &= ~(1<<5);
}
else
rGPBDAT |= (1<<5);
}
}
void ledInit(void)
{
rGPBCON &= ~(3<<10);
rGPBCON |= (1<<10);
rGPBDAT &= ~(1<<5);
}
void timer0Init(void)
{
/* 设置中断向量表 */
pISR_TIMER0 = (unsigned int)timer0ISR;
/* 配置第一级分频系数 */
rTCFG0 &= ~(0xff);
rTCFG0 |= 99;
/* 配置第二级分频 */
rTCFG1 &= ~(0xf);
rTCFG1 |= 2;
/* 设置定时器初始值 */
rTCNTB0 = 62500;
rTCON &= ~(0xf<<0);
/* 开启定时器,手动加载,自动加载,先以手动加载*/
rTCON |= ((1<<0)|(1<<1)|(1<<3));
/* 取消手动加载,目的是先将初始值加载到TCNT中*/
rTCON &= ~(1<<1);
/* 使能中断*/
rSRCPND |= (1<<10);
rINTPND |= (1<<10);
rINTMSK &= ~(1<<10);
}
void __irq timer0ISR(void)
{
ledFlag = !ledFlag;
rSRCPND |= (1<<10);
rINTPND |= (1<<10);
}