系统时钟和定时器——PWM定时器
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
系统时钟定时器PWM定时 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)