2012年9月7日星期五

【Final】如何使用W7100A的計時器/計數器(三)


這篇應用手冊主要介紹W7100A單片機的內部計時器/計數器、看門狗計時器和基本的示例程式。今天我們介紹本文的最後一部份內容,希望能幫到大家喔~


第一部份在這裡:

如何使用W7100A的計時器/計數器(一)

第二部份在這裡:

如何使用W7100A的計時器/計數器(二)

 

3.11 定时器1 8位自动重装计数器 软件门控
void main(void)
{
TMOD = 0×60; // 定时器1,模式2,8自动重装,软件门控
TH1 = Reload Value; //重载TH1的值
TL1 = Initial Value; //初始化TL1的值
ET1 = 1; //允许定时器1中断
EA = 1; //开放全局中断
TR1 = 1; //启动定时器1
while(1);
}
void int_test(void) interrupt 3
{
EA = 0;
TF1 = 0; //复位定时器0中断标志位
P0_3 = ~P0_3; //对P0_3取反
EA = 1;
}
通过TMOD寄存器将定时器1设置为8位自动重装定时器、软件门控方式,然后利用TH1和TL1来设置中断事件循环周期的大小。将重装值赋给TH1,并且初始化TL1的值。在设置完成后,置位TR1位来启动计时器1。如果有中断发生,执行中断处理函数来复位定时器1中断标志位;然后执行用户设定的中断事件。在本文档中,对Port0.3端口进行取反操作。
3.12 定时器1 8位自动重装计数器 硬件门控
void main(void)
{
TMOD = 0xE0; // 定时器1,模式2,8位自动重装, 硬件门控
TH1 = Reload Value; //重装TH1的值
TL1 = Initial Value; //初始化TL1的值
ET1 = 1; //允许定时器1中断
EA = 1; //开放全局中断
TR1 = 1; //启动定时器1
while(1);
}
void int_test(void) interrupt 3
{
EA = 0;
TF1 = 0; //复位定时器0中断标志位
P0_3 = ~P0_3; //对P0_3取反
EA = 1;
}
所有的步骤都和3.11节相同,除了TMOD寄存器的硬件门控部分。在这种模式, 计数器1只有在GATE1引脚置位时可以执行。
4. 定时器2/计数器2
图4.1是定时器2/计数器2的结构图:自动重装的16位定时器/计数器。一旦定时器/计数器启动,当TL2寄存器和TH2寄存器发生溢出时,中断产生。内部时钟速度为88.4736MHz,T2作为计数输入,T2CON.1为定时器/计数器的选择位,同时T2CON.2为定时器2的启动位。如图4.1,在右侧的T2EX引脚为定时器2的捕获/重载触发器,它在下降沿时执行操作。T2CON.3为T2EX引脚的使能位,T2CON.0为捕获/重载的选择位,当这一位为1时表示处于捕获模式。
图4.2是定时器2/计数器2的结构图:16位捕获模式的定时器/计数器。通过T2CON.3打开捕获信号并且在T2EX的下降沿时,TL2和TH2每个寄存器的值捕获赋值给RLDL和RLDH寄存器。EXF2为外部标志,当外部引脚被捕获时置为1。
如图4.3是定时器2波特率发生器模式。波特率发生器可以由定时器1和定时器2来驱动。
SMOD0为定时器1波特率速度控制位。
4.1 定时器2 16位自动重装定时器
void main(void)
{
T2CON = 0×00; // 定时器2,16位上/下自动重装
TH2 = MSB Initial Value; //初始化TH2的值
TL2 = LSB Initial Value; //初始化TL2的值
RLDH = MSB Reload Value; //重装RLDH的值
RLDL = LSB Reload Value; //重装RLDL的值
ET2 = 1; //允许定时器2中断
EA = 1; //开放全局中断
TR2 = 1; //启动定时器2
while(1);
}
void int_test(void) interrupt 5
{
EA = 0;
TF2 = 0; //复位定时器2中断标志位
P0_3 = ~P0_3; //对P0_3取反
EA = 1;
}
通过T2CON寄存器将定时器2设置为16位自动重装定时器,并且分别将MSB和LSB的初始值赋给TH2和TL2。同时,将这些值重装以防RLDH和RLDL发生中断。然后,置位TR2来启动定时器2。如果有中断发生,执行中断处理函数来复位定时器1中断标志位;然后执行用户设定的中断事件。在本文档中,对Port0.3端口翻转。
4.2 定时器2 16位上/下自动重装计数器
void main(void)
{
T2CON = 0×00; // 定时器2 16位上/下自动重装
CT2 = 1; // 计数器模式打开
TH2 = MSB Initial Value; //初始化TH2的值
TL2 = LSB Initial Value; //初始化TL2的值
RLDH = MSB Reload Value; //重装RLDH的值
RLDL = LSB Reload Value; //重装RLDL的值
ET2 = 1; //允许定时器2中断
EA = 1; //开放全局中断
TR2 = 1; //启动定时器2
while(1);
}
void int_test(void) interrupt 5
{
EA = 0;
TF2 = 0; //复位定时器2中断标志位
P0_3 = ~P0_3; //对P0_3取反
EA = 1;
}
通过T2CON寄存器将定时器2设置为16位自动重装定时器,并且设置T2CON的第2位CT2位切换到计数器模式。由位来分类的方法是可行的,但是除了W7100A.h文件外还需要相关的代码。然后将MSB和LSB的初始值赋给TH2和TL2,并将这些值设置为重装防止RLDH和RLDL发生中断。之后,置位TR2位来启动定时器2。如果中断发生,复位中断函数复位定时器2的中断标志位,然后执行用户设定的中断事件。本文档中,对Port0.3端口进行取反操作。
4.3 定时器2 16位捕获定时器
void main()
{
T2CON = 0×00; // 定时器2, 16位,上/下自动重装
EXEN2 = 1; //使能T2EX引脚 (下降沿激活)
CPRL2 = 1; //捕获模式打开
TH2 = 0; TL2 = 0; // TH2, TL2赋初值
RLDH = 0; RLDL = 0; // 清除捕获变量RLDH,RLDL
EA = 1; ET2 = 1; // 允许中断设置
TR2 = 1; // 启动定时器2
while(1);
}
void int_test2(void) interrupt 5
{
EA = 0;
if(EXF2) // 如果EXF2 = 1 (捕获标志位)
{
RLDH_tmp = RLDH; //保存捕获到的值(RLDH) 到当前变量(RLDH_tmp)
RLDL_tmp = RLDL; // 保存捕获到的值(RLDL)到当前变量(RLDL_tmp)
}
EXF2 = 0; //复位捕获标志位
TF2 = 0; // 复位定时器2中断标志位
P0_3 = ~P0_3; // 对P0_3取反
}
EA = 1;
}
利用T2CON寄存器将定时器2设置为16位自动重装定时器,并且置位T2CON寄存器的第2位EXEN2位来激活T2EX引脚。注意T2EX引脚在1=>0过渡时工作。然后置位T2CON寄存器的第0位CPRL2位,激活捕获模式。用T2CON寄存器的位来分类的方法是可行的,但是除了W7100A.h文档外还需要定义其它代码程序。设置TH2和TL2的值来设置中断事件。之后,置位TR2位启动定时器2。
当定时器2运行并且T2EX引脚的下降沿(1=>0)到来时,捕获TH2和TL2的值,并且保存到RLDH和RLDL中。当定时器2中断发生时,确认捕获动作是否发生。如果有捕获值,将这些值分别保存到RLDH_tmp和RLDL_tmp中,之后复位捕获标志位和定时器2的中断标志位。当定时器2中断发生时,Port0.3会被取反。
4.3 定时器2 16位捕获计数器
void main()
{
T2CON = 0×00; // 定时器2 16位上/下自动重装
CT2 = 1; // 计数器模式打开
EXEN2 = 1; // 置位T2EX引脚(下降沿激活)
CPRL2 = 1; // 捕获模式打开
TH2 = 0; TL2 = 0; // TH2, TL2赋初值
RLDH = 0; RLDL = 0; // 清除捕获变量RLDH,RLDL
EA = 1; ET2 = 1; // 中断置位
TR2 = 1; // 启动定时器2
while(1);
}
void int_test2(void) interrupt 5
{
EA = 0;
if(EXF2) // 如果EXF2 = 1 (捕获标志位)
{
RLDH_tmp = RLDH; // 保存捕获到的值RLDH) 到当前变量(RLDH_tmp)
RLDL_tmp = RLDL; // 保存捕获到的值(RLDL)到当前变量(RLDL_tmp)
}
EXF2 = 0; // 复位捕获标志位
TF2 = 0; //复位定时器2中断标志位
P0_3 = ~P0_3; // 对P0_3取反
}
EA = 1;
}
利用T2CON寄存器将定时器2设置为16位自动重装定时器,并且置位T2CON寄存器的第1位CT2位来激活T2EX引脚。注意T2EX引脚在1=>0过渡时工作。然后置位T2CON寄存器的第0位CPRL2位,启动捕获模式。用T2CON寄存器的位来分类的方法是可行的,但是除了W7100A.h文档外还需要定义其它代码程序。设置TH2和TL2的值来设定中断时间,最后置位TR2位启动定时器2。
当定时器2运行并且T2EX引脚的下降沿(1=>0)到来时,捕获TH2和TL2的值,并且保存到RLDH和RLDL中。当定时器2中断发生时,确认捕获动作是否发生。如果有捕获值,将这些值分别保存到RLDH_tmp和RLDL_tmp中,之后复位捕获标志位和定时器2的中断标志位。当定时器2中断发生时,端口Port0.3会被取反。
4.5 定时器2 波特率发生器
void main()
{
T2CON = 0×00; // 定时器2 16位上/下自动重装
RCLK = 1; // 由定时器2溢出脉冲计时UART0接收端
TCLK = 1; // 由定时器2溢出脉冲计时UART0发送端
TH2 = 0; TL2 = 0; // 设置TH2, TL2的值
RLDH = 0xFF; RLDL = 0xE8; //设置波特率的值为115200bps
ET2 = 0; //禁止定时器2中断
TR2 = 1; // 定时器2启动为波特率发生器
}
本节主要介绍UART波特率发生器模式,以定时器2为例。关于更多UART设置的其它寄存器的详细信息请参考W7100A数据手册。首先,初始化T2CON;然后设置T2CON寄存器的第4位和第5位为UART的波特率发生器。同时,设置TH2和TL2的初始值。对于波特率的设置,需要分别设置RLDH和RLDL的值。在例子中,由于波特率的值为1152000bps,所以RLDH和RLDL的值分别设置为0xFF和0xEB。更多关于波特率设置的详细信息请参考W7100A数据手册第6章UART。之后,禁止Timer2发生中断并且置位T2CON寄存器的第2位TR2位来运行波特率发生器。
5. 看门狗定时器
如图5.1所示为看门狗定时器的结构图。设置CKCON寄存器的WD1和WD0位,来决定超时循环周期。周期性地发生超时,可以依据EWT位的设置发生中断。一旦中断发生WDIF被置位。置位EWT可以来复位W7100A。当复位发生时,WTRF被置位。如果在超时发生之前RWT被周期性地置位,看门狗定时器也会周期性的初始化并且不会发生超时。CLK是88.4736MHz的内部时钟。用户必须在清除或者设置看门狗寄存器之前完成时序访问过程(TA = 0xAA; TA = 0×55;)。
5.1 看门狗定时器中断应用
void main()
{
CKCON = 0xC0; //看门狗间隔设置
TA = 0xAA; //设置时序访问寄存器以阻止意外写
TA = 0×55; //更多的详细信息,请参考W7100A数据手册
WDCON = 0×00; //初始化WDCON
EA = 1; //开放全局中断
TA = 0xAA;
TA = 0×55;
EWDI = 1; //允许看门狗中断
TA = 0xAA;
TA = 0×55;
EWT = 0; //通过看门狗超时禁止W7100A复位
while(1);
}
void int_test3(void) interrupt 12
{
EA = 0;
TA = 0xAA;
TA = 0×55;
WDIF = 0; //复位看门狗定时器中断标志位g
P0_3 = ~P0_3; //对P0_3取反
EA = 1;
}
上面的代码显示了如何将看门狗定时器当作普通定时器来使用。利用CKCON寄存器的第6和第7位设置看门狗的时间间隔,然后设置时序访问寄存器为不可预知的情形做准备。初始化WDCON寄存器,置位EIE寄存器的第4位EWDI位开放全局中断,以此来允许看门狗中断。由于这个例子没有使用看门狗定时器复位,EWT位保持禁止。同时,因为开发板在打开或者复位时,看门狗定时器就是一直打开的所以这个例子中不需要使用看门狗定时器的复位。如果看门狗发生中断,通过中断清除函数来对端口P0_3取反。
5.2 看门狗定时器复位应用
void main()
{
CKCON |= 0xC0; //看门狗间隔设置
TA = 0xAA; //设置防止意外写发生的时序寄存器
TA = 0×55; //更多信息,请参考W7100A数据手册
WDCON = 0×00; //初始化WDCON
TA = 0xAA;
TA = 0×55;
EWDI = 1; //看门狗超时允许复位W7100A
TA = 0xAA;
TA = 0×55;
EWT = 1; //禁止看门狗定时器复位
while(1);
}
上面的代码显示了如何通过看门狗定时器来周期性地复位W7100A。利用CKCON寄存器的第6和第7位设置看门狗时间间隔,然后设置时序访问寄存器为不可预知的情形做准备。初始化WDCON寄存器,设置WDCON寄存器的EWT位在看门狗超时发生时允许复位。看门狗超时发生之前如果用户周期性地设置RWT位,就会阻止W7100A复位。
6. 运行实例
这一章节将会介绍如何下载以及运行iMCU7100EVB应用手册中关于定时器/计数器的示例程序。所有的代码都是基于Keil编译器用C语言是实现的。有两种方法可以将Keil工程中的HEX文件下载到iMCU7100EVB开发板。一种是用WizISP程序,另外一种是用W7100Debugger程序。更多详细信息,请参考‘iMCU7100EVB用户指南’,‘WizISP程序用户指南’和‘W7100 Debugger指南’。
为了能够在iMCU7100EVB开发板上运行‘iMCU7100EVB应用手册定时器/计数器’中的示例程序,用户必须按照下面的操作顺序:
  1. 创建KEIL工程,输入定时器/计数器程序代码
  2. 用Keil编译器编译,创建HEX文件
  3. 用ISP程序或者Debugger程序下载HEX文件到iMCU7100EVB开发板
  4. 复位开发板,运行定时器/计数器示例代码,检查电源指示灯LED0(P0_3)是否亮起。
下面的章节将依次介绍以上各步的结果。
6.1 创建Keil工程
用户可以创建自己的Keil工程,或者打开附件中的Keil工程。
6.2 编译生成HEX文档
输入代码、编译,生成HEX文件。
6.3 下载HEX文件到iMCU7100EVB
通过ISP程序或者Debugger程序下载HEX文件到iMCU7100EVB开发板。如下图是ISP程序的界面。由于ISP程序只能下载BIN文件,需要将HEX文件先转换成BIN文件。更多的详细信息,请参阅WIZISP程序指南。
6.4 运行定时器/计数器
HEX文件下载完成后,首先复位iMCU7100EVB开发板,然后运行定时器/计数器。如果代码程序没有错误,开发板上的LED1将会闪烁。由于时钟频率太快,LED1看起来是持续亮的状态。

 

本文內容已全部介紹完畢,謝謝大家閱讀!

對我的帖子如有疑問,儘管放馬過來,我在這裡恭候著你!^@^


更多有關W7100A的文章請參考:

 

没有评论:

发表评论