新闻中心

EEPW首页>嵌入式系统>设计应用> 系统时钟和定时器——PWM定时器

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

作者: 时间:2016-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提高系统时钟

本文引用地址://m.amcfsurvey.com/article/201611/316624.htm

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为输出,给LED0001 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 ==FALSE) /*判断是否重启*/

{

rTCON &= ~0x1F;

rTCON |= 0xf;

rTCON &= ~0x2 ; /*恢复PWM功能*/

}

}

/*4个LED随着频率的高低,时灭时亮。灯亮的数目4-3-2-1*/

if(freq == 100)

rGPBDAT = ~0x560; /*0001 1110 0000 取反之后1110 0001 1111*/

if(freq == 1300)

rGPBDAT = ~0x160; /*1110 0000取反之后 0001 1111*/

if(freq == 2500)

rGPBDAT = ~0x60; /*0110 0000取反之后 1001 1111*/

if(freq == 3700)

rGPBDAT = ~0x20; /*0010 0000取反之后 1101 1111*/

if(freq == 4900)

rGPBDAT = ~0x0; /*0000取反之后 1111111111*/

}

/*频率递减*/

for( ; freq>50 ; )

{

freq-=10;

rTCMPB0 = freq;

delay(20000);

while (stop == TRUE)

{

delay(1000);

if (stop ==FALSE)

{

rTCON &= ~0x1F;

rTCON |= 0xf;

rTCON &= ~0x2 ;

}

}

if(freq == 100)

rGPBDAT = ~0x560;

if(freq == 1300)

rGPBDAT = ~0x160;

if(freq == 2500)

rGPBDAT = ~0x60;

if(freq == 3700)

rGPBDAT = ~0x20;

if(freq == 4900)

rGPBDAT = ~0x0;

}

}

}

TOUT输出的波形是:

        
上图是频率上升时的大致波形图。由此可以看出高电平在每个周期中维持的时间越来越长,低电平时间越来越短。频率下降时的波形图正好相反。


评论


技术专区

关闭