s3c2440_Clock & Timer
2014-03-19 12:38
225 查看
2440时钟模块能够产生3种时钟,分别为:FCLK、PCLK、HCLK。
FCLK:Frame Clock 帧时钟,供CPU使用。
HCLK:给AHB高性能总线上的设备使用:存储控制器、中断控制器、LCD控制器、DMA、DM9000和USB模块。
PCLK:给APB外围总线上的设备使用:ADC、UART、GPIO、RTC、看门狗、IIC、IIS、PWM定时器、MMC接口和SPI串行外设接口。
s3c2440系统时钟设置步骤:
(1)启动MPLL,即配置MPLLCON,设置主频值。MDIV[19:12]、PDIV[9:4]、SDIV[1:0]。这三个值的设定可以参考2440芯片手册里面的经典值。具体的计算公式是:
(2)设置分频比:配置CLKDIVN和CAMDIVN对应的位,由芯片手册可知当HCLK和FCLK不等时,即CLKDIVN的HDIVN位不为00时,cpu需要从快总线模式切换到异步总线模式,这时候就需要嵌入一段汇编指令了。
(3)以上寄存器都设置好了之后设置锁定时间LOCKTIME寄存器,它的初始值是0xFFFFFFFF,一般使用初始值。
系统时钟就是这样设置。
定时器Timer主要有两个用途:脉宽调制PWM功能和触发时间中断。2440有5个16位Timer,其中Timer0-3用作PWM,Timer4没有输出引脚用作内部定时器,Timer0还可以用作死区生成器驱动大电流设备。5个定时器都可以触发时间中断。
Timer用于PWM功能时涉及的寄存器有:配置寄存器TCFGn,控制寄存器TCON,计数缓存寄存器TCNTBn,比较缓存寄存器TCMPBn,计数观察寄存器TCNTOn;触发时间中断时还要中断相关的寄存器,比如中断等待寄存器SRCPND和INTPND(用于清中断),中断屏蔽寄存器INTMSK(开关功能)。
下面是定时器0中断的设置步骤:
(1)设置Timer0预先输入的时钟频率(使用预分频器0),可以理解为一级减频。
(2)设置Timer0最终的使用频率(用到的是MXU多路转换器),理解成二级减频。
(3)频率设置好了,现在就是要考虑定时多久(数多少次)的问题了。只需往数数缓存寄存器TCNTB0里面填数值,当你Timer0正常工作后它会自动送入16位的递减计数器中。【数数的相关的事还涉及一个比较缓存寄存器TCMPBn:用来设置脉宽调制,当递减计数器的值和TCMPBn匹配时,定时器控制逻辑将输出电平反转,这个寄存器明显是在使用PWM时候用】
(4)是时候使能Timer0了,配置TCON的Bit[4:0]。首次开始计时当然要手动update一下数数缓存寄存器,然后关掉手动update,用auto update,并使能Timer0
(5)以上是定时器的初始化,因为要用时间中断功能,所以接着使能Timer0中断,将INTMSK寄存器对应位置0即可。
(6)定义中断处理函数。首先要看看INTOFFSET的值,确定是发生了Timer0中断,进入处理,处理完了清中断,依次将SRCPND和INTPND置位。
看代码时间:启动文件和外部中断例程序基本一样,这里不再赘述。
init.c文件:初始化Timer0,设置中断函数
#define rWTCON (*(volatile unsigned *)0x53000000)
#define rLOCKTIME (*(volatile unsigned *)0x4c000000)
#define rMPLLCON (*(volatile unsigned *)0x4c000004)
#define rCLKCON (*(volatile unsigned *)0x4c00000c)
#define rCLKSLOW (*(volatile unsigned *)0x4c000010)
#define rCLKDIVN (*(volatile unsigned *)0x4c000014)
#define rCAMDIVN (*(volatile unsigned *)0x4c000018)
#define rTCFG0 (*(volatile unsigned *)0x51000000)
#define rTCFG1 (*(volatile unsigned *)0x51000004)
#define rTCON (*(volatile unsigned *)0x51000008)
#define rTCNTB0 (*(volatile unsigned *)0x5100000c)
#define rTCMTB0 (*(volatile unsigned *)0x51000010)
#define rINTOFFSET (*(volatile unsigned *)0x4A000014)
#define rSRCPND (*(volatile unsigned *)0x4A000000)
#define rINTPND (*(volatile unsigned *)0x4A000010)
#define rINTMSK (*(volatile unsigned *)0x4A000008)
#define rGPBDAT (*(volatile unsigned *)0x56000014)
#define rGPBCON (*(volatile unsigned *)0x56000010)
#define rGPBUP (*(volatile unsigned *)0x53000018)
void disable_watch_dog(void)
{
rWTCON = 0;
}
void clock_init(void)
{
rLOCKTIME = 0xFFFFFFFF;
rCLKDIVN = 0x03;//ratio=1:2:4,FCLK=200M,HCLK=100M,PCLK=50M
__asm__
(
"mrc p15,0,r1,c1,c0,0\n"
"orr r1,r1,#0xc0000000\n"
"mcr p15,0,r1,c1,c0,0\n"
);
rMPLLCON = ((0x5c<<12)|(0x01<<4)|(0x02));//MPLL_200M
}
void timer0_init(void)
{
rTCFG0 = 99;
rTCFG1 = 0x03;
rTCNTB0 = 31250;//1s trigger
rTCON |= (1<<1);
rTCON =0x09;
}
void timer0_irq_init(void)
{
rINTMSK &= (~(1<<10));
}
void gpio_init(void)
{
rGPBUP &= ~(0xf<<5);//enable pull up funtion
rGPBCON &= ~(0xff<<10);
rGPBCON |= (1<<10)|(1<<12)|(1<<14)|(1<<16);//set gpio5-8 to output
rGPBDAT &= ~(0xf<<5);//light up all of the leds
}
void Timer0_Handle(void)
{
if(rINTOFFSET==10)//ensure the timer0 then deal with it
{
rGPBDAT = ~(rGPBDAT & (0xf<<5));//opposite the leds status
}
rSRCPND = 1<<rINTOFFSET;
rINTPND = rINTPND;
}
FCLK:Frame Clock 帧时钟,供CPU使用。
HCLK:给AHB高性能总线上的设备使用:存储控制器、中断控制器、LCD控制器、DMA、DM9000和USB模块。
PCLK:给APB外围总线上的设备使用:ADC、UART、GPIO、RTC、看门狗、IIC、IIS、PWM定时器、MMC接口和SPI串行外设接口。
s3c2440系统时钟设置步骤:
(1)启动MPLL,即配置MPLLCON,设置主频值。MDIV[19:12]、PDIV[9:4]、SDIV[1:0]。这三个值的设定可以参考2440芯片手册里面的经典值。具体的计算公式是:
(2)设置分频比:配置CLKDIVN和CAMDIVN对应的位,由芯片手册可知当HCLK和FCLK不等时,即CLKDIVN的HDIVN位不为00时,cpu需要从快总线模式切换到异步总线模式,这时候就需要嵌入一段汇编指令了。
(3)以上寄存器都设置好了之后设置锁定时间LOCKTIME寄存器,它的初始值是0xFFFFFFFF,一般使用初始值。
系统时钟就是这样设置。
定时器Timer主要有两个用途:脉宽调制PWM功能和触发时间中断。2440有5个16位Timer,其中Timer0-3用作PWM,Timer4没有输出引脚用作内部定时器,Timer0还可以用作死区生成器驱动大电流设备。5个定时器都可以触发时间中断。
Timer用于PWM功能时涉及的寄存器有:配置寄存器TCFGn,控制寄存器TCON,计数缓存寄存器TCNTBn,比较缓存寄存器TCMPBn,计数观察寄存器TCNTOn;触发时间中断时还要中断相关的寄存器,比如中断等待寄存器SRCPND和INTPND(用于清中断),中断屏蔽寄存器INTMSK(开关功能)。
下面是定时器0中断的设置步骤:
(1)设置Timer0预先输入的时钟频率(使用预分频器0),可以理解为一级减频。
(2)设置Timer0最终的使用频率(用到的是MXU多路转换器),理解成二级减频。
(3)频率设置好了,现在就是要考虑定时多久(数多少次)的问题了。只需往数数缓存寄存器TCNTB0里面填数值,当你Timer0正常工作后它会自动送入16位的递减计数器中。【数数的相关的事还涉及一个比较缓存寄存器TCMPBn:用来设置脉宽调制,当递减计数器的值和TCMPBn匹配时,定时器控制逻辑将输出电平反转,这个寄存器明显是在使用PWM时候用】
(4)是时候使能Timer0了,配置TCON的Bit[4:0]。首次开始计时当然要手动update一下数数缓存寄存器,然后关掉手动update,用auto update,并使能Timer0
(5)以上是定时器的初始化,因为要用时间中断功能,所以接着使能Timer0中断,将INTMSK寄存器对应位置0即可。
(6)定义中断处理函数。首先要看看INTOFFSET的值,确定是发生了Timer0中断,进入处理,处理完了清中断,依次将SRCPND和INTPND置位。
看代码时间:启动文件和外部中断例程序基本一样,这里不再赘述。
init.c文件:初始化Timer0,设置中断函数
#define rWTCON (*(volatile unsigned *)0x53000000)
#define rLOCKTIME (*(volatile unsigned *)0x4c000000)
#define rMPLLCON (*(volatile unsigned *)0x4c000004)
#define rCLKCON (*(volatile unsigned *)0x4c00000c)
#define rCLKSLOW (*(volatile unsigned *)0x4c000010)
#define rCLKDIVN (*(volatile unsigned *)0x4c000014)
#define rCAMDIVN (*(volatile unsigned *)0x4c000018)
#define rTCFG0 (*(volatile unsigned *)0x51000000)
#define rTCFG1 (*(volatile unsigned *)0x51000004)
#define rTCON (*(volatile unsigned *)0x51000008)
#define rTCNTB0 (*(volatile unsigned *)0x5100000c)
#define rTCMTB0 (*(volatile unsigned *)0x51000010)
#define rINTOFFSET (*(volatile unsigned *)0x4A000014)
#define rSRCPND (*(volatile unsigned *)0x4A000000)
#define rINTPND (*(volatile unsigned *)0x4A000010)
#define rINTMSK (*(volatile unsigned *)0x4A000008)
#define rGPBDAT (*(volatile unsigned *)0x56000014)
#define rGPBCON (*(volatile unsigned *)0x56000010)
#define rGPBUP (*(volatile unsigned *)0x53000018)
void disable_watch_dog(void)
{
rWTCON = 0;
}
void clock_init(void)
{
rLOCKTIME = 0xFFFFFFFF;
rCLKDIVN = 0x03;//ratio=1:2:4,FCLK=200M,HCLK=100M,PCLK=50M
__asm__
(
"mrc p15,0,r1,c1,c0,0\n"
"orr r1,r1,#0xc0000000\n"
"mcr p15,0,r1,c1,c0,0\n"
);
rMPLLCON = ((0x5c<<12)|(0x01<<4)|(0x02));//MPLL_200M
}
void timer0_init(void)
{
rTCFG0 = 99;
rTCFG1 = 0x03;
rTCNTB0 = 31250;//1s trigger
rTCON |= (1<<1);
rTCON =0x09;
}
void timer0_irq_init(void)
{
rINTMSK &= (~(1<<10));
}
void gpio_init(void)
{
rGPBUP &= ~(0xf<<5);//enable pull up funtion
rGPBCON &= ~(0xff<<10);
rGPBCON |= (1<<10)|(1<<12)|(1<<14)|(1<<16);//set gpio5-8 to output
rGPBDAT &= ~(0xf<<5);//light up all of the leds
}
void Timer0_Handle(void)
{
if(rINTOFFSET==10)//ensure the timer0 then deal with it
{
rGPBDAT = ~(rGPBDAT & (0xf<<5));//opposite the leds status
}
rSRCPND = 1<<rINTOFFSET;
rINTPND = rINTPND;
}
相关文章推荐
- cuda中计时程序 cutCreatTimer& clock
- S3C2440(1) Clock&Power Management
- Timer&TimerTask原理分析
- 对S3C2440读取NAND&nbsp;Flash的总结
- qt下的时钟程序(简单美丽,继承自QWidget的Clock,用timer调用update刷新,然后使用paintEvent作画就行了,超详细中文注释)good
- STM32 System and Timer Clock Configurations
- java spring 定时器 Exception in thread "Timer-1"
- python ClockProcess timer
- Date , Timer & Timerask & Schedule
- Android练习之AnalogClock && DigitalClock && 自定义数字时钟
- JDK Timer & TimerTask
- S3C2440 clock 工作原理
- Forrest M Mims, «Engineer's Mini-Notebook - 555 Timer IC Circuits» (Reupload)
- S3C2440 clock研究
- 一步一步学android控件(之十五) —— DegitalClock & AnalogClock
- Timer&&TimerTask
- Timer与TimerTask的真正原理&使用介绍
- java自带定时任务功能(Timer&TimerTask)
- PWM Timer的使用---S3C2440的数据手册
- A07_TimePicker & DatePicker & AnalogClock & DigitalClock 的设置小结