表1.18 函数TimerIntEnable( )
功能 原型
使能Timer的中断
void TimerIntEnable(unsigned long ulBase, unsigned long ulIntFlags) ulBase:Timer模块的基址,取值TIMERn_BASE(n为0、1、2或3)
ulIntFlags:被使能的中断源,应当取下列值之一或者它们之间的任意“或运算”组合形式: TIMER_TIMA_TIMEOUT // TimerA超时中断
TIMER_CAPA_MATCH // TimerA捕获模式匹配中断
参数
TIMER_CAPA_EVENT // TimerA捕获模式边沿事件中断 TIMER_TIMB_TIMEOUT // TimerB超时中断 TIMER_CAPB_MATCH // TimerB捕获模式匹配中断 TIMER_CAPB_EVENT // TimerB捕获模式边沿事件中断 TIMER_RTC_MATCH // RTC匹配中断
返回
无
表1.19 函数TimerIntDisable( )
功能 原型 参数 返回
禁止Timer的中断
void TimerIntDisable(unsigned long ulBase, unsigned long ulIntFlags) ulBase:Timer模块的基址,取值TIMERn_BASE(n为0、1、2或3) ulIntFlags:被禁止的中断源,取值与表1.18当中的参数ulIntFlags相同 无
表1.20 函数TimerIntClear( )
功能 原型 参数 返回
清除Timer的中断
void TimerIntClear(unsigned long ulBase, unsigned long ulIntFlags) ulBase:Timer模块的基址,取值TIMERn_BASE(n为0、1、2或3) ulIntFlags:被清除的中断源,取值与表1.18当中的参数ulIntFlags相同 无
表1.21 函数TimerIntStatus( )
功能 原型
获取当前Timer的中断状态
unsigned long TimerIntStatus(unsigned long ulBase, tBoolean bMasked) ulBase:Timer模块的基址,取值TIMERn_BASE(n为0、1、2或3)
参数
bMasked:如果需要获取的是原始的中断状态,则取值false
返回
如果需要获取的是屏蔽的中断状态,则取值true
中断状态,数值与表1.18当中的参数ulIntFlags相同
表1.22 函数TimerIntRegister( )
功能 原型
注册一个Timer的中断服务函数
void TimerIntRegister(unsigned long ulBase, unsigned long ulTimer, void (*pfnHandler)(void))
10
ulBase:Timer模块的基址,取值TIMERn_BASE(n为0、1、2或3)
参数
ulTimer:指定的Timer,取值TIMER_A、TIMER_B或TIMER_BOTH pfnHandler:函数指针,指向Timer中断出现时调用的函数
返回
无
表1.23 函数TimerIntUnregister( )
功能 原型 参数 返回
注销Timer中断服务函数
void TimerIntUnregister(unsigned long ulBase, unsigned long ulTimer) ulBase:Timer模块的基址,取值TIMERn_BASE(n为0、1、2或3) ulTimer:指定的Timer,取值TIMER_A、TIMER_B或TIMER_BOTH 无
1.4 Timer例程
1. 32位单次触发定时
程序清单1.1是Timer模块32位单次触发定时器模式的例子。程序运行后,Timer初始化为32位单次触发定时器,并使能超时中断。在主循环里,当检测到KEY按下时,启动Timer定时1.5秒,同时点亮LED以表示单次定时开始。当Timer倒计时到0时自动停止,并触发超时中断。在中断服务函数里翻转LED亮灭状态,由于原先LED是点亮的,因此结果是LED熄灭。如果再次按下KEY,则再次点亮LED并定时1.5秒,如此反复循环。如果不再按KEY,则LED一直保持熄灭状态,说明Timer是单次触发的,中断不会被触发,因此在中断服务函数里的翻转LED操作也不会被执行到。
程序清单1.1 Timer例程:32位单次触发定时
#include \#include
// 定义LED
#define LED_PERIPH SYSCTL_PERIPH_GPIOG #define LED_PORT GPIO_PORTG_BASE #define LED_PIN GPIO_PIN_2
// 定义KEY
#define KEY_PERIPH
SYSCTL_PERIPH_GPIOD
#define KEY_PORT GPIO_PORTD_BASE #define KEY_PIN GPIO_PIN_1
// 主函数(程序入口) int main(void) {
11
jtagWait( ); clockInit( );
// 防止JTAG失效,重要! // 时钟初始化:晶振,6MHz
SysCtlPeriEnable(LED_PERIPH); // 使能LED所在的GPIO端口 GPIOPinTypeOut(LED_PORT, LED_PIN); // 设置LED所在的管脚为输出 GPIOPinWrite(LED_PORT, LED_PIN, 1 << 2); // 熄灭LED
SysCtlPeriEnable(SYSCTL_PERIPH_TIMER0); // 使能Timer模块
TimerConfigure(TIMER0_BASE, TIMER_CFG_32_BIT_OS); // 配置Timer为32位单次触发
TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
for (;;) {
SysCtlDelay(10 * (TheSysClock / 3000)); // 延时,消除松键抖动
TimerLoadSet(TIMER0_BASE, TIMER_A, 9000000); // 设置Timer初值,定时1.5s TimerEnable(TIMER0_BASE, TIMER_A); // 使能Timer计数 GPIOPinWrite(LED_PORT, LED_PIN, 0x00); // 点亮LED,定时开始 }
// TimerA的中断服务函数 void Timer0A_ISR(void) {
ulStatus = TimerIntStatus(TIMER0_BASE, true); // 获取当前中断状态 TimerIntClear(TIMER0_BASE, ulStatus); // 清除全部中断状态
if (ulStatus & TIMER_TIMA_TIMEOUT) // 如果是超时中断 {
ucVal = GPIOPinRead(LED_PORT, LED_PIN); // 反转LED GPIOPinWrite(LED_PORT, LED_PIN, ~ucVal);
unsigned char ucVal; unsigned long ulStatus;
}
}
while (GPIOPinRead(KEY_PORT, KEY_PIN) == 0x00); // 等待按键抬起
if (GPIOPinRead(KEY_PORT, KEY_PIN) == 0x00) {
// 如果复位时按下KEY
IntEnable(INT_TIMER0A); IntMasterEnable( );
// 使能Timer超时中断 // 使能Timer中断 // 使能处理器中断
SysCtlPeriEnable(KEY_PERIPH);
// 使能KEY所在的GPIO端口
GPIOPinTypeIn(KEY_PORT, KEY_PIN); // 设置KEY所在管脚为输入
SysCtlDelay(10 * (TheSysClock / 3000)); // 延时,消除按键抖动
12
} }
2. 32位周期定时
程序清单1.2是Timer模块32位周期定时器模式的例子。程序运行后,配置Timer为32位周期定时器,定时0.5秒,并使能超时中断。当Timer倒计时到0时,自动重装初值,继续运行,并触发超时中断。在中断服务函数里翻转LED亮灭状态,因此程序运行的最后结果是LED指示灯每秒钟就会闪亮一次。
程序清单1.2 Timer例程:32位周期定时
#include \#include
// 定义LED
#define LED_PERIPH SYSCTL_PERIPH_GPIOG #define LED_PORT GPIO_PORTG_BASE #define LED_PIN GPIO_PIN_2
// 主函数(程序入口) int main(void) {
SysCtlPeriEnable(LED_PERIPH); // 使能LED所在的GPIO端口 GPIOPinTypeOut(LED_PORT, LED_PIN); // 设置LED所在管脚为输出
SysCtlPeriEnable(SYSCTL_PERIPH_TIMER0); // 使能Timer模块
TimerConfigure(TIMER0_BASE, TIMER_CFG_32_BIT_PER); // 配置Timer为32位周期定时器 TimerLoadSet(TIMER0_BASE, TIMER_A, 3000000UL); // 设置Timer初值,定时500ms
TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
TimerEnable(TIMER0_BASE, TIMER_A); // 使能Timer计数
for (;;) { } }
// 定时器的中断服务函数
IntEnable(INT_TIMER0A); IntMasterEnable( );
// 使能Timer超时中断 // 使能Timer中断 // 使能处理器中断
jtagWait( ); clockInit( );
// 防止JTAG失效,重要! // 时钟初始化:晶振,6MHz
13
void Timer0A_ISR(void) {
ulStatus = TimerIntStatus(TIMER0_BASE, true); // 读取中断状态
TimerIntClear(TIMER0_BASE, ulStatus); // 清除中断状态,重要!
if (ulStatus & TIMER_TIMA_TIMEOUT) // 如果是Timer超时中断 {
ucVal = GPIOPinRead(LED_PORT, LED_PIN); // 反转LED GPIOPinWrite(LED_PORT, LED_PIN, ~ucVal); } }
unsigned char ucVal; unsigned long ulStatus;
3. 32位RTC定时
程序清单1.3是Timer模块32位RTC定时器模式的例子。程序运行后,要求输入RTC初始时间,格式为“hh:mm:ss”,即“时:分:秒”。比如我们输入9:59:45,然后回车
程序清单1.3已在EasyARM1138开发板上调试通过。由于在该开发板上并没有提供32.768KHz时钟源,因此我们特意在程序里安排了一个pulseInit( )函数,利用6MHz晶振提供的系统时钟在PF6/CCP1管脚产生一个接近于32.768KHz的PWM方波信号,标称频率为32786.885Hz。实际做实验时,需要短接PF6/CCP1和PF7/CCP4管脚,CCP4是RTC时钟源输入管脚。在其它开发板上,如EasyARM615或EasyARM8962,提供有32.768KHz时钟源,则可以不必使用函数pulseInit( )来产生RTC时钟源。
在程序清单1.3里,用到了一个新的头文件
程序清单1.3 Timer例程:32位RTC定时
#include \#include \#include
14