当前位置:   article > 正文

HT66F018定时器0(STM)定时器/计数器功能使用教程_合泰定时器如何设置

合泰定时器如何设置


一、定时器介绍

1、标准型 TM – STM

合泰单片机HT66F018有三个定时器,定时器0即标准型TM-STM是一个16位的定时器。本篇博客主要讲的是TM0的定时器/计数器功能,深度剖析技术文档,从寄存器到中断一路详细介绍,再到完成程序编写。

在这里插入图片描述
在这里插入图片描述


2、寄存器介绍

标准型 TM 的所有工作模式由一系列寄存器控制。一对只读寄存器用来存放 16位计数器的值,一对读 / 写寄存器存放 16 位 CCRA 的值。一个读 / 写寄存器存放 8 位 CCRP 的值,剩下两个控制寄存器设置工作模式。
在这里插入图片描述

①、TM0C0寄存器

TM0C0寄存器我们需要用到它的6、5、4、3位。
在这里插入图片描述

②、TM0C1寄存器

由于我们着重介绍的定时器/计数器功能,所以TM0C1寄存器我们只需要看7、6、0位。

在这里插入图片描述
在这里插入图片描述

③、TM0DL和TM0DH寄存器

在这里插入图片描述

④、TM0AL和TM0AH寄存器

在这里插入图片描述
在这里插入图片描述

⑤、TM0RP寄存器

由于我们这里没用到P匹配,不展开介绍。
在这里插入图片描述

3、寄存器工作模式

①、定时/计数器模式

定时 / 计数器模式与比较输出模式操作方式相同,并产生同样的中断请求标志。不同的是,在定时 / 计数器模式下 TM 输出脚未使用。因此,比较匹配输出模式中的描述和时序图可以适用于此功能。该模式中未使用的 TM 输出脚用作普通 I/O 脚或其它功能。
在这里插入图片描述

②、比较匹配输出模式

在这里插入图片描述

③、比较匹配输出模式(A匹配注意事项)

在这里插入图片描述


4、中断介绍

①、中断寄存器

在这里插入图片描述

②、中断操作

在这里插入图片描述

③、中断向量表

从中断向量表中可以看出来,TM0中断属于多功能中断。
在这里插入图片描述


④、多功能中断和TM中断

当多功能中断中任何一种中断请求标志 MF0F~MF2F 被置位,多功能中断请求产生。当中断使能,堆栈未满,包括在多功能中断中的任意一个中断发生时,将调用多功能中断向量中的一个子程序。当响应中断服务子程序时,相关的多功能请求标志位会自动复位且 EMI 位会自动清零以除能其它中断。

在中断响应时,虽然多功能中断标志会自动复位,但多功能中断源的请求标志位,即 TM 中断,LVD 中断和 EEPROM 中断的请求标志位不会自动复位,必须由应用程序清零

在这里插入图片描述
在这里插入图片描述

⑤、INTC0 寄存器

在这里插入图片描述

⑥、MFI0 寄存器

在这里插入图片描述

5、系统时钟

SMOD寄存器
在这里插入图片描述
在这里插入图片描述


二、程序编写

有了以上的基础知识后,就可以开始我们的程序编写了。

1、系统初始化

新建main.c,必须导入HT66F018.h

#include "HT66F018.h"
  • 1

配置选项中,Vdd选择的是5V,OSC我选择的是internal RC + IO1/IO2(内部RC振荡器),HIRC选择的是8MHz @Vdd=5V,fsub选择的是LIRC
进行系统初始化,如选择系统时钟源。

//fH = 8MHz
//fLIRC = 32kHz
_wdtc = 0xA8;	//关闭看门狗
_hlclk = 1;		//系统时钟8MHz@Vdd=5V,系统时钟不分频,查看SMOD寄存器
_acerl = 0x00;	//禁止所有AD

_pbc0 = 0;		//pb0配置为输出,用于演示输出效果

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

2、TM0初始化

定时器0初值计算方法:
1、需要定时 time = 1ms = 1000us
2、系统时钟不分频,所以 fsys = 8MHz
3、TM0 计数时钟位为 fsys / 4,所以 Tfreq = 8 / 4 = 2MHz
4、定时器初值TM0A = Tfreq * time(us) = 2 * 1000 = 2000
5、_tm0al = 2000 & 0x00FF;         _tm0ah = 2000 >> 8;

由此同理可得:
1、需要定时 time = 0.3ms = 300us
2、fH = 12MHz,系统时钟4分频,所以 fsys = 12 / 4 = 3MHz
3、TM0 计数时钟位为 fsys,所以 Tfreq = fsys = 3MHz
4、定时器初值TM0A = Tfreq * time(us) = 3 * 300 = 900
5、_tm0al = 900 & 0x00FF;         _tm0ah = 900 >> 8;

//定时器0初始化函数
void tm0_init(void)
{
    _t0ck2 = 0; _t0ck1 = 0; _t0ck0 = 0;	//选择TM0计数时钟位为fsys/4

    _t0m0 = 1;//定时/计数器模式
    _t0m1 = 1;
    _t0cclr = 1;//A匹配

    //fH=8MHz@Vdd=5V, fsys=不分频, TM 时钟源 = fsys/4, 定时器初值 = ((fsys=不分频) / 4 * (1000us))
    //此处例程定时时间为1ms
    _tm0al = 2000 & 0x00FF; //设置定时器0的A匹配低八位值	
    _tm0ah = 2000 >> 8;	//高八位值


    _t0af = 0;//中断请求标志位
    _t0on = 1;//定时器开始计时
    _mf0e = 1;//多功能中断请求标志
    _t0ae = 1;//中断使能
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

3、TM0中断服务程序

//定时器0中断
void __attribute((interrupt(0x0C))) Timer0_ISR(void)
{
	if(1 == _t0af){	//TM0的A匹配中断
		_t0af = 0;	//手动清除T0中断标志位
    	count++;
    	if(count == 500){
    		count = 0;
    		_pb0 = ~_pb0;
    	}
	}
    //一旦中断子程序被响应,系统将自动清除EMI位,所有其它的中断将被屏蔽
    _emi = 1;   //手动打开总中断

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

4、主函数

//主函数
void main()
{
	//fH = 8MHz
	//fLIRC = 32kHz
	_wdtc = 0xA8;	//关闭看门狗
	_hlclk = 1;	//系统时钟8MHz@Vdd=5V
	_acerl = 0x00;	//禁止所有AD

	_pbc0 = 0;		//pb0作为演示效果IO,可以外接一个LED查看效果
	tm0_init();

	//开启总中断
	_emi = 1;

	//用户代码
	while(1);


}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

5、完整代码

#include "HT66F018.h"

volatile unsigned int count = 0;	//中断计数器


//定时器0初始化函数
void tm0_init(void)
{
    _t0ck2 = 0; _t0ck1 = 0; _t0ck0 = 0;	//选择TM0计数时钟位为fsys/4

    _t0m0 = 1;//定时/计数器模式
    _t0m1 = 1;
    _t0cclr = 1;//A匹配

    //fH=8MHz@Vdd=5V, fsys=不分频, TM 时钟源 = fsys/4, 定时器初值 = ((fsys=不分频) / 4 * (1000us))
    //此处例程定时时间为1ms
    _tm0al = 2000 & 0x00FF; //设置定时器0的A匹配低八位值	
    _tm0ah = 2000 >> 8;	//高八位值


    _t0af = 0;//中断请求标志位
    _t0on = 1;//定时器开始计时
    _mf0e = 1;//多功能中断请求标志
    _t0ae = 1;//中断使能
}

//主函数
void main()
{
	//fH = 8MHz
	//fLIRC = 32kHz
	_wdtc = 0xA8;	//关闭看门狗
	_hlclk = 1;	//系统时钟8MHz@Vdd=5V
	_acerl = 0x00;	//禁止所有AD

	_pbc0 = 0;
	tm0_init();

	//开启总中断
	_emi = 1;

	//用户代码
	while(1);


}

//定时器0中断
void __attribute((interrupt(0x0C))) Timer0_ISR(void)
{
	if( 1 == _t0af){	//T0的A匹配中断
		_t0af = 0;		//手动清除T0中断标志位
    	count++;
    	if(count == 500){	//500ms反转一次pb0的电平
    		count = 0;
    		_pb0 = ~_pb0;
    	}
	}
    //一旦中断子程序被响应,系统将自动清除EMI位,所有其它的中断将被屏蔽
    _emi = 1;   //手动打开总中断

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/565802
推荐阅读
相关标签
  

闽ICP备14008679号