NEC V850 之 定時(shí)器TMM0
先說(shuō)說(shuō)這個(gè)TMM的時(shí)鐘特性吧,有一個(gè)16位的比較寄存器(TM0CMP0),最大計數范圍就是0~65535了。另外定時(shí)器TMM0不支持自動(dòng)重裝初值,所以在中斷服務(wù)函數里除了要清標志位還要重新裝入初值。然后這個(gè)定時(shí)器機器簡(jiǎn)單只有一個(gè)可屏蔽中斷就是溢出中斷。
本文引用地址:http://dyxdggzs.com/article/201612/325100.htm下面說(shuō)下他的計數時(shí)間的計算方法。關(guān)于系統時(shí)鐘和內部設備時(shí)鐘在上一篇博文里說(shuō)過(guò)了,系統時(shí)鐘如果是32MHz,那么內部設備時(shí)鐘也是32MHz,如果想分頻只有在具體的外設分頻器處分頻。
系統時(shí)鐘是32MHz;
TMM0分頻系數為不分頻,則TMM0的時(shí)鐘是32MHz;
一個(gè)時(shí)鐘定時(shí)器記一次數,則記一次數的時(shí)間是1 / 32MHz = 0.03125 us;
假如我現在需要定時(shí)1ms就是1000us,需要的計數次數就是 1000us / 0.03125us = 32000 次。
所以應該給比較寄存器(TM0CMP0)賦值(32000 - 1)次,因為在定時(shí)器計時(shí)開(kāi)始時(shí)需要消耗3~4個(gè)時(shí)鐘周期,所以我們不減去1,直接給比較寄存器賦值32000次,做為誤差補償,但是隨著(zhù)計時(shí)時(shí)長(cháng)的增加,誤差會(huì )在一定程度上積累。大家要根據具體需要來(lái)進(jìn)行設置校準。
現在我們知道在系統時(shí)鐘為32MHz時(shí),TMM0不分頻的最大計時(shí)為65536 * 0.03125 = 2.048 ms,如果我們需要定時(shí)的時(shí)長(cháng)比較長(cháng),就需要對TMM0的時(shí)鐘進(jìn)行分頻,如果我們需要的定時(shí)時(shí)長(cháng)為1s,
系統時(shí)鐘是32MHz;
TMM0分頻系數設置為512分頻,則TMM0的時(shí)鐘是 32000000Hz / 512 = 62500Hz;
定時(shí)器記一次數的時(shí)間就是 1 / 62500Hz = 0.000016s = 16 us;
我們需要的定時(shí)時(shí)長(cháng)是1s,需要的計數次數為 1s = 1000000us / 16us = 62500 次。
定時(shí)器的定時(shí)范圍是有最大值的,同時(shí)要注意的是,他也是有最小值的,這就是他的I/O口翻轉速率,經(jīng)過(guò)測試,70f3630這款MCU在定時(shí)器TMM0下,最小計數單元為5us,如果再低就意味著(zhù)I/O口的翻轉速率更高,則會(huì )得到比較大的誤差值,下面有一個(gè)對照表來(lái)列舉一組測試說(shuō)明,并會(huì )附圖。
計算定時(shí)時(shí)長(cháng) | 比較寄存器(TM0CMP0)值 | 實(shí)際測量時(shí)長(cháng) | 備注 |
1us | 32 (TMM0 = fxx) | 2.0625us | 附圖1 |
5us | 160 (TMM0 = fxx) | 5.063us | 附圖2 |
10us | 320 (TMM0 = fxx) | 10.031us | |
30us | 960 (TMM0 = fxx) | 30.001us | |
50us | 1600 (TMM0 = fxx) | 50.06us | |
1ms | 32000(TMM0 = fxx) | 1.000ms | 附圖3 |
1s | 62500(TMM0 = fxx/512) | 999.9ms |



- 可屏蔽中斷控制寄存器(定時(shí)器M ) TM0EQIC0
- TMM0 比較寄存器0 TM0CMP0
- TMM0 控制寄存器0 TM0CTL0
程序操作上有3部分,分別是 開(kāi)始定時(shí)器 , 關(guān)閉定時(shí)器 , 定時(shí)器初始化。
- 開(kāi)始定時(shí)器(TMM0_Start)
- 清TMM0中斷標志位,設置寄存器 TM0EQIC0 的第7位 TM0EQIF0 為 0 ;
- 允許響應TMM0中斷,設置寄存器 TM0EQIC0 的第6位 TM0EQMK0 為 0;
- 開(kāi)定時(shí)器使能端,設置寄存器TM0CTL0 的第7位 TM0CE 為 1 。
- 關(guān)閉定時(shí)器(TMM0_Stop)
- 關(guān)定時(shí)器使能端,設置寄存器TM0CTL0 的第7位 TM0CE 為 0;
- 禁止響應TMM0中斷,設置寄存器 TM0EQIC0 的第6位 TM0EQMK0 為 1;
- 清TMM0中斷標志位,設置寄存器 TM0EQIC0 的第7位 TM0EQIF0 為 0 。
- 定時(shí)器初始化(TMM0_Init)
- 關(guān)閉定時(shí)器,執行TMM0_Stop;
- 設置中斷優(yōu)先級,設置寄存器 TM0EQIC0 的后3位 ,確定TMM0的中斷優(yōu)先級;
- 設置定時(shí)器分頻系數,設置寄存器 TM0CTL0 的后3位,確定TMM0的運行時(shí)鐘;
- 設置比較寄存器初值,設置寄存器 TM0CMP0的值,確定觸發(fā)溢出中斷的計數次數。
有了上面的準備,下面我們在main函數里先初始化定時(shí)器然后再調用開(kāi)始定時(shí)器,一定不要忘記開(kāi)總中斷;然后在中斷服務(wù)程序里寫(xiě)入用戶(hù)代碼加上重新賦初值和清標志位的操作就可以了,這樣定時(shí)器就能夠正常工作了,下面是部分代碼,請參閱:
代碼出處:timer.c
/*******************************************************************************
* Function Name : TMM0_Start
* Description : 開(kāi)始TMMO計數
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void TMM0_Start( void )
{
TM0EQIF0 = 0; // 設置TM0EQIC0 的第7位中斷標志位位 0 ,清除定時(shí)器M0的中斷響應標志
TM0EQMK0 = 0; // 設置TM0EQIC0 的第6位中斷屏蔽位為 0 ,允許產(chǎn)生定時(shí)器M0中斷
TM0CE = 1; // 設置TM0CTL0 的最高位TM0CE為 1 ,定時(shí)器計數啟動(dòng)
}
/*******************************************************************************
* Function Name : TMM0_Stop
* Description : 停止TMM0計數
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void TMM0_Stop( void )
{
TM0CE = 0; // 設置TM0CTL0 的最高位TM0CE為 0 ,禁止定時(shí)器時(shí)鐘啟動(dòng)
TM0EQMK0 = 1; // 設置TM0EQIC0 的第6位中斷屏蔽位為 1 ,禁止產(chǎn)生定時(shí)器M0中斷
TM0EQIF0 = 0; // 設置TM0EQIC0 的第7位中斷標志位位 0 ,清除定時(shí)器M0的中斷響應標志
}
/*******************************************************************************
* Function Name : TMM0_Init
* Description : TMM0初始化
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void TMM0_Init( void )
{
TMM0_Stop(); // 首先禁止定時(shí)器
TM0EQIC0 |= 0x07; // 設置TM0EQIC0 的低3位 中斷優(yōu)先級值 全為1,為最低中斷優(yōu)先級
TM0CTL0 = TMM_INTERNAL_CLOCK0 ; // 設置TMOCTL0 的低3位TMM0預分頻器值 全為0 ,不分頻
TM0CMP0 = 32000; // 設置TM0CMP0 定時(shí)器計數比較寄存器 的值為32000,初值定時(shí)為1ms
}
/*******************************************************************************
* Function Name : TMM0_ChangeTimerCondition
* Description : 修改定時(shí)器計數變量值
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void TMM0_ChangeTimerCondition( unsigned short regvalue )
{
TM0CMP0 = regvalue; // 設置TM0CMP0 定時(shí)器計數比較寄存器
}
/*******************************************************************************
* Function Name : MD_INTTM0EQ0
* Description : 定時(shí)器TMM0溢出中斷服務(wù)函數
* Input : None
* Output : None
* Return : None
*******************************************************************************/
#pragma vector = INTTM0EQ0_vector
__interrupt void MD_INTTM0EQ0(void)
{
P9L_bit.no4 = ~P9L_bit.no4 ; // 端口P94翻轉,LED閃爍
TM0CMP0 = 32000; // 定時(shí)器TMM0不支持自動(dòng)重裝初值,一定要在執行完用戶(hù)程序后重裝初值
TM0EQIF0 = 0; // 清除定時(shí)器中斷標志位
}
在高亮處更改TMM0分頻系數。
代碼出處:main.c
void main( void )
{
SystemClkInit(); // 初始化系統時(shí)鐘為32MHz
/* PCL setting */
PCLM = CG_PCL_DISABLE; // 關(guān)閉可編程時(shí)鐘輸出
__DI(); // 關(guān)閉總中斷
PMC9L_bit.no4 = 0 ; // 設置P94為輸入輸出口模式
PM9L_bit.no4 = 0 ; // 設置P94端口方向為輸出
TMM0_Init(); // 定時(shí)器TMM0初始化
__EI(); // 打開(kāi)總中斷
TMM0_Start(); // 定時(shí)器TMM0開(kāi)始計數
while (1);
}
最后把相關(guān)寄存器的datasheet截圖上傳下:



評論