PWM(Pulse Width Modulation)——脉宽调制,它是利用微控制器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用于测量、通信、功率控制与变换等许多领域。
s3c2440芯片中一共有5个16位的定时器,其中有4个定时器(定时器0~定时器3)具有脉宽调制功能,因此用s3c2440可以很容易地实现PWM功能。下面就具体介绍如何实现PWM功能。
它是通过寄存器TCON来实现的,一般来说每个定时器主要有4个位要配置(定时器0多一个死区位):启动/终止位,用于启动和终止定时器;手动更新位,用于手动更新TCNTBn和TCMPBn,这里要注意的是在开始定时时,一定要把这位清零,否则是不能开启定时器的;输出反转位,用于改变输出的电平方向,使原先是高电平输出的变为低电平,而低电平的变为高电平;自动重载位,用于TCNTn减为零后重载TCNTBn里的值,当不想计数了,可以使自动重载无效,这样在TCNTn减为零后,不会有新的数加载给它,那么TOUTn输出会始终保持一个电平(输出反转位为0时,是高电平输出;输出反转位为1时,是低电平输出),这样就没有PWM功能了,因此这一位可以用于停止PWM。
(这段话摘自:http://blog.csdn.net/zhaocj/archive/2010/02/20/5312359.aspx)
下面程序是自己编写的通过定时器0输出的一个PWM方波,来驱动蜂鸣器。
#include "def.h"
#include "2440addr.h"
#include "2440lib.h"
#include "2440slib.h"
#include "mmu.h"
#include "def.h"
#include "Option.h"
/* 这一段程序主要是让定时器产生一个PWM方波,方波驱动蜂鸣器发生,由于其用的时钟PCLK
*/
void irq_init() //中断初始化
{
rINTMSK = ~(0x1<<10);
rINTMOD=0;
}
void time0_init() // 定时器0的初始化
{
rGPBCON = 0x1555e; //B0 TOUT0输出,驱动蜂鸣器;B5~B8输出,给LED
rGPBUP = 0x7ff;
rGPBDAT = 0x1e0; //蜂鸣器不响,LED灭
rTCFG0 =249; // prescaler等于249
rTCFG1 =0x02; //divider等于8,则设置定时器0的时钟频率为25kHz
rTCNTB0 = 125000; //让定时器0每隔5秒中断一次
rTCMPB0 = rTCNTB0>>1;// 50% 即占空比
rTCON |=(1<<1);//手动更新
rTCON =0x0d ; //定时器0开始工作
}
void __irq time0_isr(void)
{
if(rINTOFFSET==10)
{
rGPBDAT=~(rGPBDAT & (0xf<<5)); //每次进入中断的时候灯闪烁
}
rSRCPND=1<<rINTOFFSET;
rINTPND=rINTPND;//清除中断
}
void Main()
{
MMU_Init();// 不开启MMU的话 无法进入中断
time0_init();//定时器初始化
irq_init();//中断初始化
pISR_TIMER0 = (unsigned int) time0_isr;//中断入口
while(1);
}