时钟的工作搞定了,下面便是和时刻有联系的守时器了。看了下有3个守时器分别是AA,AB,M。其间M是最简略的一个,只要一个功用便是计数。感觉和STM32的systick有异曲同工之妙。便是为操作体系留的心跳时钟啊。所以先搞他吧。
先说说这个TMM的时钟特性吧,有一个16位的比较寄存器(TM0CMP0),最大计数规模便是0~65535了。别的守时器TMM0不支持主动重装初值,所以在中止服务函数里除了要清标志位还要从头装入初值。然后这个守时器机器简略只要一个可屏蔽中止便是溢出中止。
下面说下他的计数时刻的核算方法。关于体系时钟和内部设备时钟在上一篇博文里说过了,体系时钟假设是32MHz,那么内部设备时钟也是32MHz,假设想分频只要在详细的外设分频器处分频。
体系时钟是32MHz;
TMM0分频系数为不分频,则TMM0的时钟是32MHz;
一个时钟守时器记一次数,则记一次数的时刻是1 / 32MHz = 0.03125 us;
假设我现在需求守时1ms便是1000us,需求的计数次数便是 1000us / 0.03125us = 32000 次。
所以应该给比较寄存器(TM0CMP0)赋值(32000 – 1)次,由于在守时器计时开端时需求耗费3~4个时钟周期,所以咱们不减去1,直接给比较寄存器赋值32000次,做为差错补偿,可是跟着计时时长的添加,差错会在必定程度上堆集。咱们要根据详细需求来进行设置校准。
现在咱们知道在体系时钟为32MHz时,TMM0不分频的最大计时为65536 * 0.03125 = 2.048 ms,假设咱们需求守时的时长比较长,就需求对TMM0的时钟进行分频,假设咱们需求的守时时长为1s,
体系时钟是32MHz;
TMM0分频系数设置为512分频,则TMM0的时钟是 32000000Hz / 512 = 62500Hz;
守时器记一次数的时刻便是 1 / 62500Hz = 0.000016s = 16 us;
咱们需求的守时时长是1s,需求的计数次数为 1s = 1000000us / 16us = 62500 次。
守时器的守时规模是有最大值的,一起要注意的是,他也是有最小值的,这便是他的I/O口翻转速率,通过测验,70f3630这款MCU在守时器TMM0下,最小计数单元为5us,假设再低就意味着I/O口的翻转速率更高,则会得到比较大的差错值,下面有一个对照表来罗列一组测验阐明,并会附图。
核算守时时长 | 比较寄存器(TM0CMP0)值 | 实践丈量时长 | 补白 |
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 |
上面这个表阐明晰,在守时时长很小的时分差错很大,在守时时长很大的时分,尽管相对差错小,可是也有比较大的绝对差错,所以这其间的数值补偿要根据实践情况详细问题详细分析。下面来看下附图:
- 可屏蔽中止操控寄存器(守时器M ) TM0EQIC0
- TMM0 比较寄存器0 TM0CMP0
- TMM0 操控寄存器0 TM0CTL0
程序操作上有3部分,分别是 开端守时器 , 封闭守时器 , 守时器初始化。
- 开端守时器(TMM0_Start)
- 封闭守时器(TMM0_Stop)
- 守时器初始化(TMM0_Init)
-
- 封闭守时器,履行TMM0_Stop;
- 设置中止优先级,设置寄存器 TM0EQIC0 的后3位 ,确认TMM0的中止优先级;
- 设置守时器分频系数,设置寄存器 TM0CTL0 的后3位,确认TMM0的运转时钟;
- 设置比较寄存器初值,设置寄存器 TM0CMP0的值,确认触发溢出中止的计数次数。
有了上面的预备,下面咱们在main函数里先初始化守时器然后再调用开端守时器,必定不要忘掉开总中止;然后在中止服务程序里写入用户代码加上从头赋初值和清标志位的操作就可以了,这样守时器就可以正常工作了,下面是部分代码,请参阅:
代码出处:timer.c
/*******************************************************************************
* Function Name : TMM0_Start
* Description : 开端TMMO计数
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void TMM0_Start( void )
{
TM0EQIF0 = 0; // 设置TM0EQIC0 的第7位中止标志位位 0 ,铲除守时器M0的中止呼应标志
TM0EQMK0 = 0; // 设置TM0EQIC0 的第6位中止屏蔽位为 0 ,答应发生守时器M0中止
TM0CE = 1; // 设置TM0CTL0 的最高位TM0CE为 1 ,守时器计数发动
}
/*******************************************************************************
* Function Name : TMM0_Stop
* Description : 中止TMM0计数
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void TMM0_Stop( void )
{
TM0CE = 0; // 设置TM0CTL0 的最高位TM0CE为 0 ,制止守时器时钟发动
TM0EQMK0 = 1; // 设置TM0EQIC0 的第6位中止屏蔽位为 1 ,制止发生守时器M0中止
TM0EQIF0 = 0; // 设置TM0EQIC0 的第7位中止标志位位 0 ,铲除守时器M0的中止呼应标志
}
/*******************************************************************************
* Function Name : TMM0_Init
* Description : TMM0初始化
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void TMM0_Init( void )
{
TMM0_Stop(); // 首要制止守时器
TM0EQIC0 |= 0x07; // 设置TM0EQ%&&&&&%0 的低3位 中止优先级值 全为1,为最低中止优先级
TM0CTL0 = TMM_INTERNAL_CLOCK0 ; // 设置TMOCTL0 的低3位TMM0预分频器值 全为0 ,不分频
TM0CMP0 = 32000; // 设置TM0CMP0 守时器计数比较寄存器 的值为32000,初值守时为1ms
}
/*******************************************************************************
* Function Name : TMM0_ChangeTimerCondition
* Description : 修正守时器计数变量值
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void TMM0_ChangeTimerCondition( unsigned short regvalue )
{
TM0CMP0 = regvalue; // 设置TM0CMP0 守时器计数比较寄存器
}
/*******************************************************************************
* Function Name : MD_INTTM0EQ0
* Description : 守时器TMM0溢出中止服务函数
* 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; // 守时器TMM0不支持主动重装初值,必定要在履行完用户程序后重装初值
TM0EQIF0 = 0; // 铲除守时器中止标志位
}
在高亮处更改TMM0分频系数。
代码出处:main.c
void main( void )
{
SystemClkInit(); // 初始化体系时钟为32MHz
/* PCL setting */
PCLM = CG_PCL_DISABLE; // 封闭可编程时钟输出
__DI(); // 封闭总中止
PMC9L_bit.no4 = 0 ; // 设置P94为输入输出口形式
PM9L_bit.no4 = 0 ; // 设置P94端口方向为输出
TMM0_Init(); // 守时器TMM0初始化
__EI(); // 翻开总中止
TMM0_Start(); // 守时器TMM0开端计数
while (1);
}
最终把相关寄存器的datasheet截图上传下: