s3c2440x系统时钟设置及定时器的设置与应用

一、s3c2440时钟介绍

s3c2440中有三种时钟:FCLK,HCLK,PCLK。

FCLK用于CPU核;HCLK用于AHB(Advanced High Performance Bus)总线上的设备,如CPU核、存储器控制器、中断控制器、LCD控制器、DMA和USB主机模块等;PCLK用于APB(Advanced Peripheral Bus)总线上的设备,如WATCHDOG、IIS、I2C、PWM定时器、MMC接口、ADC、UART、GPIO、RTC和SPI。

s3c2440中有两个PLL来设置时钟,分别为:MPLL和UPLL。MPLL用于设置上述的三种时钟,而UPLL专用于USB设备。

下面介绍MPLL是如何工作的,先看下图。

(1)在上电时,PLL没有启动,FCLK即等于外部输入的时钟,称为Fin(在我用的mini2440板子上,Fin=12MHz)。

(2)上电几毫秒后,晶振(OSC)输出稳定,FCLK=Fin,nRESET信号恢复高电平以后,CPU开始执行命令。

(3)程序中设置MPLL的相关寄存器,来设定FCLK的值和FCLK、HCLK和PCLK的比例。程序执行到此处后,MPLL启动。此时需要一段时间(Lock Time),MPLL输出才会稳定。

(4)Lock Time之后,MPLL输出正常,CPU工作在新的FCLK之下。

二、时钟设置方式

设置时钟需要设置以下四个寄存器。其中:

LOCKTIME用来设置锁定时长,

MPLLCON用来设置FCLK的值,

CLKDIVN和CAMDIVN这两个寄存器来设置HCLK和PCLK的值(它们为FLCK的分频)。

1.LOCKTIME

这个寄存器时设置上面提到的那个LockTime的长短的,一般设为默认就好。

2.MPLLCON

上面的PLLCON其实代表MPLLCON和UPLLCON两个寄存器,它们的格式一样。

这个寄存器用来设置FCLK的值,它的值是根据这个寄存器和Fin来确定的,确定方式如下公式:

上面的Fout的值即为FCLK的值。上面的MDIV、PDIV、SDIV和上面寄存器中的位相对应。

如果我们要设置FCLK为200MHz,那么根据公式,我们需要设置MPLLCON寄存器为:0x0005c012。

3.CLKDIVN

这个寄存器中的[3]位用来设置UCLK;[2:1]位用来设置HCLK与FCLK的比例;[0]位用来设置PCLK和HCLK的比例。

4.CAMDIVN

这个寄存器一般只需要用到[9]HCLK4_HALF和[8]HCLK3_HALF,这两位结合CLKDIVN寄存器中的[2:1]HDIVN和[0]PDIVN来设置FCLK、HCLK和PCLK的分频比例。这四个参数的设置和比例的关系如下图:

若我们需要配置三者的分频比例为1:2:4,那么就要设置CLKDIVN寄存器为:0x00000003;CAMDIVN为默认。

至此,我们就完成了FCLK HCLK PCLK这三个时钟的设置。

注意:韦东山的《嵌入式linux应用开发完全手册》一书中说“如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode”,这可以通过如下指令来完成。。。”所以我们在程序中需要加上下面的代码。

上面提到的指令:mrc p15, 0, r0, c1, c0, 0

orr   r0,   r0, #R1_nF : OR : R1_iA     @R1_nF : OR : R1_iA 等于 0xC0000000.

mrc p15, 0, r0, c1, c0, 0

三、PWM定时器的使用

s3c2440中有5个16位定时器,其中定时器0、1、2/3具有PWM的功能,即它们都有一个输出引脚,可以通过定时器来控制引脚周期性的高、低电平变化;定时器4没有输出引脚。

定时器的使用步骤:

(1)以PCLK通过设置TCFG0和TCFG1来确定某个定时器的工作频率。

(2)通过TCNTBn、TCMPBn寄存器来确定计数初值和比较值。

(3)通过设置TCON寄存器来设定各个定时器工作方式。

(4)通过设置TCON寄存器来手动装入计数初值和比较值。

(5)通过设置TCON寄存器来开启定时器。

(6)通过读TCNTO寄存器中的数据来获取当前定时器中的数值。

下图为定时器工作流程

定时器的具体使用步骤如下:

1.设置定时器的工作频率

定时器部件的时钟源为PCLK,该时钟信号先经过8位预分频(通过配置TCFG0寄存器来确定预分频倍数),然后再经过一次分频(通过配置TCFG1寄存器来确定分频倍数),这次的分频倍数只能是2、4、8、16中的一个。经过两次分频,得到定时器的工作频率。

若PCLK=50MHz,我们想设置Timer0的工作频率为31500Hz,那么50MHz/(99+1)/16=31500Hz。根据上面的数值我们需要设置TCFG0为99,TCFG1为0x03。

2.设置定时器初值

设定定时器的两个初值,分别为初始计数值、比较值。初始计数值由TCNTBn(n为0-4,表示5个定时器)来决定,比较值由TCMPBn来决定。下面用定时器0为例。

计数初值和比较值需要先手动传入定时器内部的寄存器中,然后当计数器启动后,内部计数寄存器在初值基础上进行不断地减一操作。当减到比较值时,如果我们设定了输出反转(用TCON寄存器设置)的话,输出电平会反转。计数值继续减一,减到0时,如果设置了翻转,那么电平会翻转,如果使能了对应定时器中断(取消INTMSK寄存器中对应定时器的中断屏蔽,并且通过设置状态寄存器CSRP开启总中断),那么会产生中断。然后根据设定(用TCON寄存器设置),确定是否自动装入初值和比较值。这些操作在后面会详细介绍。

上面设置工作频率为315MHz,由于计数初值进行减一操作,如果希望每0.5s为一个计数周期,那么计数初值应设为15625,即TCNTB0=15625。如果我们想控制PWM的占空比,我们可以设置比较值来控制,如占空比为50%,比较值就为初值的一半,即TCMPB0=7812。

3.设置定时器的工作方式,并手动传入初值,然后开启定时器

通过TCON寄存器来设置定时器工作方式的设置包括:输出是否反转,是否自动重装。手动传入初值和开启/关闭定时器也都是通过TCON寄存器完成的。

这里只截取了其中关于Timer0的[0-7]位,它的[8-22]位是关于Timer1-4的。

[0]开启或关闭定时器0

[1]手动更新计数初值和比较值,即:将TCNTB0和TCMPB0的值传入Timer0的内部寄存器。

[2]输出是否反转

[3]是否自动重装,当内部寄存器计数值为零时,如果该位是能,那么计数初值和比较值会自动传入定时器中。

[4]死区使能,这个我没用到,没有研究。

启动定时器0的步骤如下:

(1)用TCON设置好是否反转,是否自动重装

(2)通过INTMSK寄存器开启/屏蔽Timer0的中断请求,通过状态寄存器CPSR开启/屏蔽IRQ/FIQ中断响应。

(3)使能TCON的[1]位,手动更新。

(4)使能TCON的[0]位,开启定时器0,此处注意[1]位应为0(关掉手动更新)。

4.通过TCNTO寄存器来获取当前定时器中的计数数值。

至此,PWM发生器的设置与启动就完成了。下面贴出了上文相关的一些程序代码。完整的程序我已经上传到了CSDN的下载区(不需要下载积分),链接如下:

点击打开原程序资源链接

该程序是以我上上篇博客中的程序为基本写的,有不明白的地方可以点击下面的链接进行查看:

点击打开博客链接

时钟设置程序(head2.S文件):

FCLK=200MHz,HCLK=100MHz,PCLK=50MHz

<span style="color:#996633;">clock_init:
        ldr r1, =0x00000003     @FCLK:HCLK:PCLK=1:2:4
        ldr r0, =0x4c000014     @address of register named CLKDIVN
        str r1, [r0]

        mrc p15, 0, r1, c1, c0, 0
        orr r1, r1, #0xc0000000
        mcr p15, 0, r1, c1, c0, 0

        ldr r1, =0x0005c012     @FCLK=200MHZ
        ldr r0, =0x4c000004     @address of register named MPLLCON
        str r1, [r0]
        mov pc, lr</span>

定时器0的初始化程序(init.c文件):

设置Timer0和Timer1两个定时器的定时周期均为0.5s,Timer0设置了比较值,而且板子上Timer0连接到蜂鸣器上,当TOUT0(Timer0的PWM输出端口)输出为高电平时,蜂鸣器响。Timer1对应的中断开启。

/*
 * enable timer1 interrupt
 */
void init_irq( )
{
    INTMSK   &= (~(1<<11));
}
<span style="color:#996633;">/*
 *init timer0 to auto load initial numbers and every 0.5s to produce an interrupt
 */
void timer_init(void)
{
        GPBCON |= GPB0_TOUT0;
        TCFG0 = 99;
        TCFG1 = 0x33;
        TCNTB0 = 15625;
        TCMPB0 = 13000;
        TCNTB1 = 15625;
        TCON |= ((1<<1) | (1<<9));
        TCON = 0x090d;
}</span>

Timer1的中断服务程序(timer.c文件):

当中断发生时,连接LED的GPIO口电平会反转,即mini2440上的LED灯会每隔0.5s进行亮灭交替。

<span style="color:#996633;">void Timer1_Handle(void)
{
        if(INTOFFSET ==11)
        {
                GPBDAT = ~GPBDAT;
        }

        SRCPND = 1<<INTOFFSET;
        INTPND = INTPND;
}</span>
时间: 2024-10-03 23:15:54

s3c2440x系统时钟设置及定时器的设置与应用的相关文章

实时时钟、系统时钟和CPU时钟的区别

http://blog.sina.com.cn/s/blog_68f909c30100pli7.html 实时时钟:RTC时钟,用于提供年.月.日.时.分.秒和星期等的实时时间信息,由后备电池供电,当你晚上关闭系统和早上开启系统时,RTC仍然会保持正确的时间和日期. 系统时钟:是一个存储于系统内存中的逻辑时钟.用于系统的计算,比如超时产生的中断异常,超时计算就是由系统时钟计算的.这种时钟在系统掉电或重新启动时每次会被清除. CPU时钟:即CPU的频率,当然这里的时钟频率指的是工作频率,即外频,还

7th.关于系统时钟的设置

言简意赅版本: 开启MPLL 设置LOCKTIME寄存器 (设置锁定时间) 设置MPLLCON寄存器(设置主频与FCLK的关系) 设置CLKDIVN寄存器(设置FCLK,HCLK,UCLK的倍数关系) MPLLCON参照官方提供参数配置即可. 详细情况 开发板在没有开启时钟前,整个开发板全靠一个12MHz的晶振提供频率来运行,当MPLLCON存入初值,并开始生效后,S3C2440A可以正常工作在400MHz下.开发板的主板上的外设和CPU也有一个频率限度,ARM920T内核的S3C2440的最高

linux之路的第一篇之常用系统命令之系统时钟设置详解

系统时钟通常是非常有用的,所以一定要熟记date 用来显示和修改当前系统日期时间,主要用于时间管理,这是系统时间软件时钟date 月日时分年.秒  MMDDhhmm[cc|yy].ss date 121212122013.34 2013年12月12日12分34秒 年和秒可以不指定,默认是当前年和00秒date +%D 显示日期 月日年     +%Y/%y 都可以 只显示年小y显示两位年份     +%T 小时分钟秒     +%F 年月日     +%H 小时     +%M 分钟     +

Linux硬件时钟和系统时钟设置

Linux时钟分为系统时钟(System Clock)和硬件时钟(Real Time Clock,简称RTC).系统时钟是指当前Linux Kernel中的时钟:而硬件时钟则是主板上由电池供电的时钟,硬件时钟可以在BIOS中进行设置.当Linux启动时,系统时钟会去读取硬件时钟的设置,然后系统时钟就会独立于硬件时钟运作. Linux关于时间的设置的shell命令有date和hwclock两种: 嵌入式s3c6410 ARM开发板中Linux时间设置: 1. date  -- 用来读取或设置系统时

LINUX使用一个定时器实现设置任意数量定时器

本例子参考 Don Libes的Title: Implementing Software Timers例子改写 为什么需要这个功能,因为大多数计算机软件时钟系统通常只能有一个时钟触发一次中断.当运行多个任务时,我们会想要多个定时器 的时钟跟踪并发这样可以生成正确的时间重叠,操作系统这样做. 本例子是为了实现使用Linux下的一个定时器,实现任一数量的定时器功能. 首先我们需要一些数据类型用来描述时钟数据结构 #include <stdio.h> #include<time.h> #

S3C2440 的定时器的设置(转)(笔记)

在前面的几篇文章中,每当程序需要延时时,我们是利用循环语句来实现.这种方法的延时简单,但不是很精确,就是说不能得到确切的一段时间的延时.因此当需要精确延时时,就不能采用这种方法了.一般是利用定时器来实现.在这里,我们就介绍一下s3c2440定时器的使用方法. 在讲解之前,先介绍一下s3c2440时钟系统.一般来说,MCU的主时钟源主要是外部晶振或外部时钟,而用的最多的是外部晶振.在正确情况下,系统内所使用的时钟都是外部时钟源经过一定的处理得到的.由于外部时钟源的频率一般不能满足系统所需要的高频条

系统时钟和定时器

一. @****************************************************************************** @ File:head.S @ 功能:初始化,设置中断模式.系统模式的栈,设置好中断处理函数 @****************************************************************************** .extern main .text .global _start _start

STM32通用定时器库函数设置

通用定时器 STM32的通用定时器为:TIM2.TIM3.TIM4和TIM5 在使用通用定时器时利用库函数直接设置定时器如下: 1.使能定时器TIM_X的时钟:(X=2.3.4.5) RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIMX,ENABLE); 2.计算要定时的时间,根据定时时间来设定分频数和最大计数值(以向上计数为例子),其中计算关系如下: 系统时钟(一般为72MHZ) = 定时器分频数 * 计数值 假如分频数为7200,则定时器时钟为:72MHZ/7

ASP.NET中设置一个定时器来定时更新 转

asp.net 定时器 比较少用,  中国红木网这是一个相当实用的功能,有了RSS博客镜像,就不需要在多处同时发布博客日志了.比如你同时在新浪上有自己的博客,又同时有自己的个人博客站点,那么你只需要在新浪上发布博客日志,而个人博客站点通过RSS博客镜像功能将新浪博客上发布的新日志自动更新到站点中.我们在ASP.NET的,至于asp,由于其天生的局限性,可能无法直接在Web应用程序中完成这一功能,而需要额外的Windows应用程序的支持.1. 管理RSS博客镜像首先我们需要在RSS博客镜像,需要管