×
嵌入式 > 技术百科 > 详情

NEC V850 之 定时器TAB (计数溢出功能)

发布时间:2020-06-15 发布时间:
|
之前说过了比较简单的TMM0 ,只有一个溢出功能,简单实用,今天把TAB的溢出功能说明一下。TAB是一个比较高级的定时器,有输入捕获和输出比较,他的比较溢出功能也比较有特点,这次Kiwi项目就是用了这个特点才完成了间隔发送CAN信息的功能。首先TAB是能够自动重装的,另外它有2个定时器单元TAB0和TAB1,每个定时器单元有4个中断源。

定时器的使用还是蛮简答的,首先初始化定时器,然后把定时器的使能端和屏蔽位全部都打开,就可以使用了,因为其是自动重装定时器,在中断服务函数里面也不需要进行数值的重装。

定时的初始化有如下步骤:(以TAB0为例,TAB1同TAB0)

  1. 关闭定时器所有功能的使能位以及清零相应的中断标志位,这些寄存器还是在中断里使用xxMKn及xxIFn;
  2. 设置4个中断源的中断优先级,操作对应的寄存器xxICn;
  3. 设置中断的时钟,4个中断源共用一个时钟源,所以这个只需要设置一次,其相关寄存器为TABnCTLx;
  4. 设置4个定时器中断的计数时间,其相关寄存器为TABnCCRx。

通过上面4步定时器就初始化好了,下面是初始化代码:


代码源自 Timer_TAB.c 
void TAB0_Init(void)
{
TAB0CE = 0; /* TAB0 operation disable */
TAB0CCMK0 = 1; /* INTTAB0CC0 interrupt disable */
TAB0CCIF0 = 0; /* clear INTTAB0CC0 interrupt flag */
TAB0CCMK1 = 1; /* INTTAB0CC1 interrupt disable */
TAB0CCIF1 = 0; /* clear INTTAB0CC1 interrupt flag */
TAB0CCMK2 = 1; /* INTTAB0CC2 interrupt disable */
TAB0CCIF2 = 0; /* clear INTTAB0CC2 interrupt flag */
TAB0CCMK3 = 1; /* INTTAB0CC3 interrupt disable */
TAB0CCIF3 = 0; /* clear INTTAB0CC3 interrupt flag */
TAB0OVMK = 1; /* INTTAB0OV interrupt disable */
TAB0OVIF = 0; /* clear INTTAB0OV interrupt flag */

/* Set INTTAB0CC0 level 2 priority */
TAB0CCIC0 &= 0xF8;
TAB0CCIC0 |= 0x02;
/* Set INTTAB0CC1 level 2 priority */
TAB0CCIC1 &= 0xF8;
TAB0CCIC1 |= 0x02;
/* Set INTTAB0CC2 level 2 priority */
TAB0CCIC2 &= 0xF8;
TAB0CCIC2 |= 0x02;
/* Set INTTAB0CC3 level 2 priority */
TAB0CCIC3 &= 0xF8;
TAB0CCIC3 |= 0x02;

/* Interval timer mode setting */
TAB0CTL0 = TAB_INTERNAL_CLOCK6;
TAB0CTL1 = TAB_INTERNAL_CLOCK | TAB_MODE_INTERVAL;
TAB0CCR0 = TAB0_CCR0_VALUE;
TAB0CCR1 = TAB0_CCR1_VALUE;
TAB0CCR2 = TAB0_CCR2_VALUE;
TAB0CCR3 = TAB0_CCR3_VALUE;
}
初始化完定时器后,我们把我们用到的中断源给打开就好了,这里只使用了4个溢出中断源,下面是代码:


代码源自 Timer_TAB.c
void TAB0_Start(void)
{
TAB0CCIF0 = 0; /* clear INTTAB0CC0 interrupt flag */
TAB0CCMK0 = 0; /* INTTAB0CC0 interrupt enable */
TAB0CCIF1 = 0; /* clear INTTAB0CC1 interrupt flag */
TAB0CCMK1 = 0; /* INTTAB0CC1 interrupt enable */
TAB0CCIF2 = 0; /* clear INTTAB0CC2 interrupt flag */
TAB0CCMK2 = 0; /* INTTAB0CC2 interrupt enable */
TAB0CCIF3 = 0; /* clear INTTAB0CC3 interrupt flag */
TAB0CCMK3 = 0; /* INTTAB0CC3 interrupt enable */
TAB0CE = 1; /* TAB0 operation enable */
}
这两步操作完成后,定时器就在计数了,然后在各自计数值到后,就会进入相应的中断向量,下面是中断向量的代码,也看下:


代码源自:Timer_TAB.c

#pragma vector = INTTAB0CC0_vector
__interrupt void MD_INTTAB0CC0(void)
{/*中断向量0 服务函数*/}
#pragma vector = INTTAB0CC1_vector
__interrupt void MD_INTTAB0CC1(void)
{/*中断向量1 服务函数*/}
#pragma vector = INTTAB0CC2_vector
__interrupt void MD_INTTAB0CC2(void)
{/*中断向量2 服务函数*/}
#pragma vector = INTTAB0CC3_vector
__interrupt void MD_INTTAB0CC3(void)
{/*中断向量3 服务函数*/}
由代码可见,上面的中断向量0~3就是我们之前说的一个定时器内有4个中断向量分别为CC0,CC1,CC2,CC3。但是这4个中断向量的关系是比较奇特的。虽然它有4个中断源,但是只有CC0这个中断来的时候定时计数器才会置零重新计数,CC1~CC3中断都是过程中断,所以CC0~CC3的定时间隔都是一样的,比如100ms来一次中断,CC0~CC3都是每隔100ms中断一次,他们的区别在于可以在这个定时间隔内的不同的时间点进行触发中断,如下图时间轴所示:
   |________|______________|________________|________________________|
   0ms    10ms(CC1)     30ms(CC2)        60ms(CC3)                 100ms(CC0)(计数器溢出)  
上图显示的CC1,CC2,CC3就是所谓的过程中断。然后结合到实际的使用环境来说,我们需要的是在不同的时间段上定时发送不同的CAN信息,这种定时方式正好适用,如果两个CAN信息发送间隔都是100ms,我一个信息在第10ms发送另外一个信息在第30ms发送,这个就把整个发送过程在时间轴上错开,也保证了每个CAN信息稳定的发送出去。
 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
中国国产第三代核电实现并网发电