全部博文(92)
分类: 嵌入式
2010-03-25 20:19:42
PWM AND TIMER
定时器有两种使用方式:
1. TCNTBn每次减1,直到等于TCMPBn,TOUTn数值翻转。
2. TCNTBn每次减1,直到等于0,中断触发。
首先要解决定时器的频率问题,即TCNTBn每次减一所需的时间(即定时器输出频率),具体的计算公式如下:
定时器输出时钟频率=PCLK/(prescaler+1)/devider
其中prescaler值由TCFG0决定,diveder值由TCFG1决定,而prescaler只能取0~255之间的 整数,diveder只能取2,4,8和16。比如已知PCLK为50MHZ,而我们想得到某一定时器输出时钟频率为25KHZ,则依据公式可以使prescaler等于249,divider等于8。于是通过设置TCNTBn我们可以得到任意与0.04毫秒成整数倍的时间间隔。例如我们想得到1秒的延时,则使TCNTBn为25000
现在就用两种方法解决问题(1.自翻转法 2.中断法)用定时器0,让蜂鸣器每2秒钟响一次,持续0.5秒。
1.自翻转法
void Test_PWM(void)
{
rGPBCON &= ~3; //设置GPB口 B0为TOUT0输出 PWM输出管脚
rGPBCON |= 2;
rGPBDAT &=~1; //设置开始状态,蜂鸣器不响
rTCFG0 &= ~0xff;
rTCFG0 |= 249; //prescaler = 249+1
rTCFG1 &= ~0xf;
rTCFG1 |= 2; //mux = 1/8 timer0的时钟频率为50M/250/8 = 0.025MHz(0.04毫秒)
rTCFG0 &= ~0xff;
rTCFG0 |= 249; //prescaler = 249+1
rTCFG1 &= ~0xf;
rTCFG1 |= 2; //mux = 1/8 timer0的时钟频率为50M/250/8 = 0.025MHz(0.04毫秒)
rTCNTB0 =50000; //设置timer0初值,62500*0.04=2秒
rTCMPB0 =37500; // 当计数到1.5秒时TOUT0翻转,并保持0.5秒,当TCNTB0减到0时TOUT0又发生翻转
rTCON &= ~0x1f;
rTCON |= 0xf; //自动重载, 反向打开, 手动刷新, 启动timer0
rTCON &= ~2; //clear manual update bit
}
3. 中断法
#define EnableIrq(bit) rINTMSK &= ~(bit)
__inline void ClearPending(int bit)
{
register i;
rSRCPND = bit;
rINTPND = bit;
i = rINTPND;
}
void __irq Timer0_Handler(void);
{
static int count;
count ++;
ClearPending(BIT_TIMER0);
if(count%4==0)
{
rGBDAT &=~1;
rGBDAT |=1; //蜂鸣器响
}
else
rGBDAT &=~1;
}
void Main(void)
{
pISR_TIMER0 = (unsigned)Timer0_Handler; //中断函数的入口地址
rGPBCON &= ~3; //设置GPB口 B0为TOUT0输出 PWM输出管脚
rGPBCON |= 2;
rGPBDAT &=~1; //设置开始状态,蜂鸣器不响
ClearPending(BIT_TIMER0);
EnableIrq(BIT_TIMER0);
rTCFG0 &= ~0xff;
rTCFG0 |= 249; //prescaler = 249+1
rTCFG1 &= ~0xf;
rTCFG1 |= 2; //mux = 1/8 timer0的时钟频率为50M/250/8 = 0.025MHz(0.04毫秒)
rTCNTB0 =12500; //设置timer0初值,12500*0.04=0.5秒
rTCON &= ~0x1f;
rTCON |= 0xb; //自动重载, 反向关闭, 手动刷新, 启动timer0
rTCON &= ~2; //clear manual update bit
}
参考网页: