一、定时器框图
1.向TCNTBn和TCMPBn中些初始值
2.设置定时器的手动更新位.推荐配置inverter on/off bit(不管用不用)
3.设置定时器的开始位来启动定时器(同时清除手动更新位)
如果定时器被强行停止,TCNTn保持计数器的值而且不会从TCNTBm中重加载.如果要设置一个新值,要执行手动更新. 不论何时TOUT inverter on/off bit被更改,在定时器运行时TOUTn的逻辑值都会改变.因此,最好在配置手动更新位的时候配置inverter on/off bit.
1.使能自动重加载功能.设置TCNTBn为160(50+110),TCMPBn为110.设置手动更新位并配置反转位(on/off)。手动更新位将TCNTn和TCMPn的值更新到TCNTBn和TCMPBn中. 接下来设置TCNTBn为80(40+40),TCMPBn为40,它们决定下一次重加载的值.
2.设置开始位,手动更新位设为0.关闭反转器,打开自动重加载.在等待时间后定时器开始计数
3.当TCNTn和TCMPn有相同的值时,TOUTn的逻辑电平由低变为高
4.当TCNTn为0时,中断请求产生,TCNTBn的值被加载到一个临时寄存器.在下次定时器周期,TCNTn会重载临时寄存器的值.
5.在中断服务例程中,TCNTBn设为80(20+60),TCMPBn设置为60,同样用于下一次周期.
6.当TCNTn和TCMPn有相同的值时,TOUTn的逻辑电平由低变为高
7.当TCNTn为0,TCNTn自动加载TCNTBn的值,触发中断请求.
8.在中断服务例程中自动重加载和中断请求被禁用,停止定时器
9.当TCNTn与TCMPn有相同值,TOUTn的逻辑电平由低变为高
10.即使TCNT0为0,因为自动重加载被禁用了所以TCNTn不会再重加载,定时器停止了
11.没有中断请求产生了
3、脉宽调制
通过使用TCMPBn来实现PWM功能.PWM的频率由TCNTBn来决定.减少TCMPBn的值可以有更高的PWM值(占空比).增加TCMPBn的值可以有更低的PWM值.如果输出反转使能了,增加和减少操作也要反转.若想输出方波(占空比50%),则TCTBn=2*TCMPBn,频率由TCTBn决定。
双缓冲功能允许在ISR中将下一次PWM的TCMPBn的值在当前PWM的周期的任何一个时间点被写入.
4、输出电平
假定反向功能时关闭的,下面的步骤描述如何保证TOUT是高还是低:
1.关闭自动重加载位。当TCNTn为0时定时器停止,TOUTn输出高电平(即上面变相器关的波形)
2.通过清除定时器的开始位来停止定时器.如果TCNTn<=TCMPn,输出高;如果TCNTn>TCMPn,输出低.
3.可以通过TCON的反转开关来决定TOUT是否反转.反转器会移除额外的电流来适应输出电平.
总结:1、在关闭反向功能时,定时器未开启时,TOUT输出高电平。2、开启反向功能,定时器未开启时,TOUT输出低电平。下面做了验证。
//====================================================
// 语法格式:void Buzzer_Freq_Set(U32 freq)
// 功能描述: 设置蜂鸣器频率函数
// 入口参数: freq
// 出口参数: 无
//====================================================
void Buzzer_Freq_Set(U32 freq)
{
rGPBCON &= ~3; //设置GPB口 B0为TOUT0输出 PWM输出管脚
rGPBCON |= 2;
rTCFG0 &= ~0xff;
rTCFG0 |= 15; //prescaler = 15+1 timer0的时钟频率为25M/16 = 1.562MHz
rTCFG1 &= ~0xf;
rTCFG1 |= 2; //mux = 1/8 timer0的时钟频率为25M/16/8 = 0.195MHz
rTCNTB0 = (PCLK/128)/freq; //设置timer0初值 ,
//产生freq频率时初值TCNTB0=定时器输入时钟频率/freq
//(PCLK/((预分频值+1)*时钟分频器系数))/freq
rTCMPB0 = rTCNTB0>>1; // 50%
rTCON &= ~0x1f;
rTCON |= 0xb; //自动重载, 反向关闭, 手动刷新, 启动timer0
rTCON &= ~2; //关闭手动刷新
}
//====================================================
// 语法格式:void Buzzer_Stop(void)
// 功能描述: 停止蜂鸣器发声函数
// 入口参数: 无
// 出口参数: 无
//====================================================
void Buzzer_Stop(void)
{
rGPBCON &= ~3;//设置GPB口 B0为输出
rGPBCON |= 1;
rGPBDAT &= ~1;//B0输出低电平,三极管关闭即蜂鸣器停止
}
main()
{
SetSysFclk(FCLK_400M); //设置系统时钟 400M
ChangeClockDivider(2, 1); //设置分频FCLK:HCLK:PCLK=400:50:25= 1:8:16
CalcBusClk(); //计算总线频
Buzzer_Freq_Set(2000); //设置频率为2000Hz 验证结果如下图。
}
使用逻辑分析仪测试-输出波形:
四、验证
PWM中输出电平
1、关闭反向
void TOUT0_Freq_Set(void)
{
rGPBCON &= ~3; //设置GPB口 B0为TOUT0输出 PWM输出管脚
rGPBCON |= 2;
rTCFG0 &= ~0xff;
rTCFG0 |= 15; //prescaler = 15+1 timer0的时钟频率为25M/16 = 1.562MHz
rTCFG1 &= ~0xf;
rTCFG1 |= 2; //mux = 1/8 timer0的时钟频率为25M/16/8 = 0.195MHz
rTCNTB0 = 100; //设置timer0初值100,比较值25.占空比=高电平/脉宽=25/100=25%
rTCMPB0 = 25; //
rTCON &= ~0x1f;
rTCON |= 0xb; //自动重载, 反向关闭, 手动刷新, 启动timer0
rTCON &= ~2; //clear manual update bit
}
输出波形:
1、在反向关闭时,未启动定时器时Tout0为高电平;而刚启动定时器时,Tout0为低电平(下图中1表示定时器启动点)
2、图中1--2表示计数值TCNT0由100减至25,同TCMP0相同(即时间t=75*1/定时器输入时钟=75/0.195=384us=0.384ms 与测试值一致),此时Tout0反转高电平。
3、图2 到TCNT0减至0,时间=25/0.195=133us=0.133ms
反向关闭时输出波形
2、开启反向
void TOUT0_Freq_Set(void)
{
rGPBCON &= ~3; //设置GPB口 B0为TOUT0输出 PWM输出管脚
rGPBCON |= 2;
rTCFG0 &= ~0xff;
rTCFG0 |= 15; //prescaler = 15+1 timer0的时钟频率为25M/16 = 1.562MHz
rTCFG1 &= ~0xf;
rTCFG1 |= 2; //mux = 1/8 timer0的时钟频率为25M/16/8 = 0.195MHz
rTCNTB0 = 100; //设置timer0初值100,比较值25.占空比=高电平/脉宽=75/100=75%
rTCMPB0 = 25; //
rTCON &= ~0x1f;
rTCON |= 0xf; //自动重载, 反向开启, 手动刷新, 启动timer0
rTCON &= ~2; //clear manual update bit
}
输出波形:
1、在反向开启时,未启动定时器时Tout0为低电平;而刚启动定时器时,Tout0为高电平(下图中1表示定时器启动点)
2、图中1--2表示计数值TCNT0由100减至25,同TCMP0相同(即时间t=25*1/定时器输入时钟=75/0.195=384us=0.384ms与测试值一致),此时Tout0反转高电平。
3、图2 到TCNT0减至0,时间=25/0.195=133us=0.133ms