微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 系统时钟和定时器——PWM定时器

系统时钟和定时器——PWM定时器

时间:11-11 来源:互联网 点击:
时钟控制逻辑给整个芯片提供3种时钟:FCLK用于CPU核;HCLK用于AHB总线设备,比如CPU核、存储器控制器、中断控制器、DMA和USB主机模块等;PCLK用于APB总线上的设备,比如WATCHDOG、IIS、IIC、PWM、MMC、ADC、RTC等等。

S3C2440 CPU核的工作电压为1.2V时,主频可以达到300MHz;工作电压为1.3V时,主频可以达到400MHz。开发板为12MHz,需要通过时钟控制逻辑的PLL提高系统时钟

S3C2440有两个PLL:MPLL和UPLL。UPLL专用于USB设备,MPLL用于设置FCLK、HCLK、PCLK。

图1 上电后MPLL的启动过程

LocK Time的长短由寄存器LOCKTIME设定。一般采用默认值。

查看芯片手册,MPLL计算公式如下图:

其中 m=Mdiv+8, p=Pdiv+2, s=Sdiv

CLKdivN寄存器:用于设置FCLK、HCLK、PCLK 三者比例。各种时钟比例对应的寄存器设置如下图所示:

1、 PWM(Pulse Width Modulation)定时器

S3C2440 有5个16位定时器。其中定时器0、1、2、3有PWM功能,即他们都有一个引脚,可以用过定时器来控制引脚周期性的高低电平变化;定时器4没有输出引脚。定时器时钟源为PCLK。内部结构如图所示:

定时器0 、1 共用第一个预分频器定时器2 、3、 4 共用第2个预分频器。预分频器的输出进入第二级分频器,它有5种频率的时钟:2、4、8、16分频。预分频通过TCFG0设置,分频值(2、4、8、16)通过TCFG1设置。

现在我们可以归结启动一个PWM功能可以分为以下几步:

1、设置TOUT0-TOUT3,这需要配置相关外部引脚为TOUT模式。外部引脚GPB与TOUT为复用引脚

2、设置定时器的输出频率,并且通过TCFG0设置prescaler(预分频)的值。通过TCFG1设置divider的值。

3、具体脉冲宽度要通过TCMPBn与TCNTBn两个寄存器的设置来完成。这步涉及到寄存器内部逻辑的工作流程。如下:

将TCMPBn和TCNTBn装入初始值,在设置TCON寄存器之后会启动定时器,这时将过TCMPBn与TCNTBn两个寄存器的值装入内部寄存器TCMPn和TCNTn中,在定时器n的工作频率下,TCNTn开始减一计数,在TCNTn的值等于TCMPn的值的时候,TOUTn翻转,当TCNTn的值达到0的时候,再次翻转,就这样周而复始,形成了脉冲。并且触发定时器n的中断(如果设置中断的话)。

4、具体控制要交给TCON寄存器。它有以下几个功能:(先看一下数据手册)

由此可以看出,它有以下4个作用:

1、定时器的开始/停止。TCON[0]

2、手动更新。用于手动更新TCNTBn和TCMPBn,这里要注意的是在开始定时时,一定要把这位清零,否则是不能开启定时器。TCON[1]

3、输出反转。TOUTn不反转(0)/反转(1)TCON[2]

4、自动加载。当定时器计数到0时,TCMPBn和TCNTBn寄存器的值自动装入内部寄存器TCMPn和TCNTn中。TCON[3]
程序分析如下:(这程序是赵春江老师的程序)

#include "2440addr.h"

#define U32 unsigned int

typedef unsigned char BOOL;

#define TRUE 1

#define FALSE 0

BOOL stop;

static void __irq Key3_ISR(void) /*暂停键,关闭蜂鸣器*/

{

rSRCPND = rSRCPND | (0x1<2); /*定义EINT2*/

rINTPND = rINTPND | (0x1<2);

rTCON &= ~0x8; /*禁止定时器自动重载,即关闭定时器0111*/

stop = TRUE;

}

void __irq Key2_ISR(void) /*重启键,开启蜂鸣器*/

{

rSRCPND = rSRCPND | 0x1; /*定义EINT0*/

rINTPND = rINTPND | 0x1;

stop = FALSE;

}

void delay(int a)

{

int k;

for(k=0;k

;

}

void Main(void)

{

int freq;

rGPBCON = 0x155556; /*B0为TOUT0,B5~B8为输出,给LED 0001 0101 0101 0101 0101 0110*/

rGPBUP = 0x7ff; /*0111 1111 1111关闭上拉使能*/

rGPFCON = 0xaaaa; /*F口为EINT,给按钮 1010 1010 1010 1010*/

/*按钮的一些必要配置*/

rSRCPND = 0x0f; /*中断设置*/

rINTMSK = ~0x0f;

rINTPND =0x0f;

rEXTINT0 = 0x2222; /*EINT0/EINT1均设置为下降沿触发*/

freq = 2500;

rTCFG0 &= 0xFFFF00;

rTCFG0 |= 0x31; /*prescal 是49 3*16+1=49 timer0 and timer1*/

rTCFG1 &= ~0xF; /*低四位清零 divider value=1/2,因为PCLK为50MHz,所以50MHz/50/2=500kHz/

rTCNTB0 = 5000; /*定时器计数初始值*/

rTCMPB0 = freq; /*定时器比较值*/

rTCON &= ~0x1F;

rTCON |= 0xf; /*死区无效,自动装载,电平反转,手动更新,定时器开启*/

rTCON &= ~0x2 ; /*手动更新位清零,PWM开始工作*/

pISR_EINT0 = (U32)Key2_ISR;

pISR_EINT2 = (U32)Key3_ISR;

stop = FALSE;

rGPBDAT = ~0x60; /*两个LED亮*/

while(1)

{

/*频率递增*/

for ( ; freq<4950 ; )

{

freq+=10;

rTCMPB0 = freq; /*重新赋值*/

delay(20000);

while (stop == TRUE) /*是否暂停*/

{

delay(1000);

if (stop ==FALS

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top