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 决定占空比。
阅读(3253) | 评论(0) | 转发(1) |