一、定时器框图
S3c2440 有5 个16 位的定时器。由下面框图可知:
1、定时器0、1、2、3 有脉宽调制功能(PWM)。定时器4有一个没有输出引脚的内部定时器。定时器0 有一个用于大电流设备的死区生成器。
2、PCLK时钟首先经过8bit预分频器:定时器0 和1 共享一个8 位的预分频器,定时器2,3,4 共享另一个8 位预分频器
3、定时器时钟输入通道可选(通过MUX多选一开关):
1、内部时钟:经过预分频的1/2、1/4、1/8、1/16分频
2、外部时钟TLCK0 、TLCK1。
4、TCMPBn----定时器n比较缓冲寄存器
TCNTBn-----定时器n计数缓冲寄存器
二、定时器工作流程
1、设置定时器的输入时钟频率。
定时器的时钟源为PCLK,首先经过预分频器降低频率后,进入第二个分频.可以生成5 种不同的分频信号
即输入时钟频率=PCLK/(预分频值+1)/(分频值);预分频值在TCFG0设置,范围0-255,而分频值在TCFG1设
(1/2,1/4,1/8,1/16 和TCLK)
2、设置定时器n的比较值TCMPBn和初始计数值TCNTBn
3、设置定时器控制TCON寄存器,启动定时器。这时,TCMPBn、TCNTBn的值被装入其内部寄存器TCMPn、TCNTn。
在定时器n的工作频率下,TCNTn开始减一计数,其值可以通过TCNTOn寄存器获知。
疑问:
1、为什么将TCMPBn传入TCMPn中,而不是直接使用TCMPBn值做比较值?因为如果在计数过程中改变了比较值TCMPBn,输出波形会出现突变情况,导致不稳定。采用这种双缓冲模式。当改变TCMPBn值时,而TCMPn不会改变。
2、触发重载TCMPn和TCNTn值方式:1、TCNTn减计数至0时自动重载 2、手动更新(启动定时器使用)
4、当TCNTn值等于TCMPn的值时,定时器n的输出引脚TOUTn反转;TCNTn继续减一计数
5、当TCNTn的值到达0时,其输出引脚TOUTn再次反转,并触发定时器n的中断。
6、当TCNTn的值到达0时,如果在TCON寄存器中将定时器n设为“自动加载”,则TCMPBn、TCNTBn的值自动被装入其内部寄存器TCMPn、TCNTn,下一个计数开始。
注:
1、如何启动一个定时器:
1.向TCNTBn和TCMPBn中些初始值
2.设置定时器的手动更新位.推荐配置inverter on/off bit(不管用不用)
3.设置定时器的开始位来启动定时器(同时清除手动更新位)
如果定时器被强行停止,TCNTn保持计数器的值而且不会从TCNTBm中重加载.如果要设置一个新值,要执行手动更新. 不论何时TOUT inverter on/off bit被更改,在定时器运行时TOUTn的逻辑值都会改变.因此,最好在配置手动更新位的时候配置inverter on/off bit.
启动定时器时,需要手动更新将TCMPBn、TCNTBn的值被装入其内部寄存器TCMPn、TCNTn。
2、定时器操作
上面的图是下面操作的结果:
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输出低电平。下面做了验证。
三、程序
定时器启动后,TCNTn开始减一计数,当TCNTn 等于TCMPn时, TOUTn 反转, TCNTn继续减数.
当TCNTn= 0 时, TOUTn 再次反转,并触发中断(中断已经使能).若TCON 设为自动加载, TNCTn/TCMPNn 的值被重装.
寄存器:
TCFG0: 设置预分频
TCFG1:用于设置第二个分频.
TCON: 定时器控制寄存器
TCNTBn :设置一个被装载到递减计数器中的初始值。
TCMPBn: 设置一个被装载到比较寄存器中用来和递减计数器的值作比较的初始值。
TCNTOn : 通过读取其可以得到TCNTBn 的值
电路图:利用Tout0控制蜂鸣器
GPB的B0是Tout0输出引脚
定时器初始化示例:
//====================================================
// 语法格式: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表示计数值T
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』