Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1122417
  • 博文数量: 141
  • 博客积分: 2853
  • 博客等级: 少校
  • 技术积分: 2266
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-04 12:03
文章分类

全部博文(141)

文章存档

2014年(3)

2013年(12)

2012年(126)

分类: 嵌入式

2012-05-23 21:59:54

void Buzzer_Freq_Set( U32 freq )
{
        rGPBCON &= ~3;                        //set GPB0 as tout0, pwm output
        rGPBCON |= 2;
                
        rTCFG0 &= ~0xff;
        rTCFG0 |= 15;                        //prescaler = 15+1
        rTCFG1 &= ~0xf;
        rTCFG1 |= 2;                        //mux = 1/8
        rTCNTB0 = (PCLK>>7)/freq;
        rTCMPB0 = rTCNTB0>>1;        // 50%
        rTCON &= ~0x1f;
        rTCON |= 0xb;                        //disable deadzone, auto-reload, inv-off, update TCNTB0&TCMPB0, start timer 0
        rTCON &= ~2;                        //clear manual update bit
}
PWM测试主要在这个函数,对Timer0的设置,对照Datasheet其他都不难理解,有疑惑的是下面2局
      rTCNTB0 = (PCLK>>7)/freq;

      rTCMPB0 = rTCNTB0>>1;        // 50%
     根据Datasheet,TCNTOn会自动加载rTCNTB0 的值递减到0产生一次中断,也就是说rTCNTB0 为两次PWM中断的间隔时间,也可以理解为一个PWM输出的脉冲周期,因为定时器输出时钟频率=PCLK ÷ (prescaler+1) ÷ divider=PCLK/16/8,则TCNTOn每递减一个数所需时间为T=1000/(PCLK/16/8)ms。回到 rTCNTB0 = (PCLK>>7)/freq来,一直不理解为什么PCLK要移7位,化成算式后明白了,PCLK>>7不就等效于PCLK/0x80吗,而PCLK/16/8也是PCLK/0x80,这样子算起来就方便了,设产生一次PWM的时间为t,则t/T= TCNTOn= rTCNTB0。化简后t=1000/freq ms.使用示波器验证,freq=800时,一个脉冲周期为1.25ms,freq=10时,一个脉冲周期为100ms,占空比为50%。
     为什么占空比为50%呢,TCMPB0 = rTCNTB0>>1;又是怎么理解的呢?该句等效于rTCMPB0 = rTCNTB0/2.就是说计数一半了翻转。 那么究竟是高变低还是低变高呢。我改成了rTCMPB0 = rTCNTB0>>2;就是除4了,用示波器一看,明白了,高电平占用了1/4,低电平占用了3/4。总结如下:高电平到了rTCMPB0 就翻转成低电平直到下一个脉冲周期开始才翻转回高电平( 应该是低电平到了rTCMPB0 就翻转成高电平直到下一个脉冲周期开始才翻转回低电平 。 

rTCNTB0决定了PWM脉冲周期,rTCMPB0 决定占空比。

阅读(3178) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~