Обмен технологиями

04: Таймер

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina


Когда используется таймер, для подсчета он полагается на схему внутреннего генератора. При настройке на использование таймера значение памяти счетчика увеличивается на 1 каждый машинный цикл.

1. Как установить таймер

1. Кварцевый генератор (кварцевый генератор) излучает импульсы и записывает количество импульсов для синхронизации.
2. Частота импульса — это тактовая частота, а обратная этой частоте — период колебаний (тактовый цикл), который также является наименьшей единицей времени в компьютере.
Вставьте сюда описание изображения

Как показано на рисунке: частота кварцевого генератора 11,0592МГц, то его такт составляет 1/11,0592МГц (секунда), то есть столько-то секунд занимает один такт импульса.

3. Машинный цикл — это цикл ЦП, а время, необходимое для базовой операции, называется машинным циклом. Обычно машинный цикл состоит из нескольких тактов. Обычно это 12 раз/6 раз.
Вставьте сюда описание изображения

Вставьте сюда описание изображения

  • Сколько времени прошло с момента добавления 1?
    Когда частота кварцевого генератора составляет 11,0592 МГц, она равна 11059,2 кГц = 11059200 Гц.
    Машинные циклы = 12 х тактовые циклы = 12 х (1/тактовая частота) секунд = 12 / тактовая частота секунд = 12 / 11059200 секунд = 12 000 000 / 11059200 микросекунд = 1,085 (мкс)
    То есть: при использовании кратного 12 счетчик будет +1 каждые 1,085 мкс.

2. Как реализовать подсчет?

Путем настройки соответствующих регистров: На следующем рисунке показаны соответствующие регистры таймера.
Вставьте сюда описание изображения

  • Как показано на рисунке, имеется 2 регистра: первый — TCON, а второй — TCOM, оба по 8 бит каждый.
  • Как показано на рисунке, существует два типа таймеров: первый — битовый таймер Т0, а второй — таймер Т1. Оба они по 16 бит.

2.1. Регистр управления ТКОН.

Вставьте сюда описание изображения

TF0:定时器T0溢出中断标志,当定时器0开始计数时,计数到规定的时间时,定时器产生了溢出。TF0自动由0变位1(由硬件置1)。
如果不用中断,需要手动清零。

TR0:定时器T0的控制位,当为1时,定时器T0才能计数,相当于T0的开关(由软件控制)。
  • 1
  • 2
  • 3
  • 4

2.2. Регистр режимов работы ТКОМ.

Вставьте сюда описание изображения

GATE:门控制位,当GATE=0时:计数条件只有TR1一个(TR1=1就计数,TR1=0就不计数)。
			   当GATE=1时:是否计数不仅取决于TR1还取决于INT1引脚
C/T :时钟输入选择为,为1时,时钟从外部引脚P3.5口输入;为0时,时钟从内部输入
M1      M0
0        0        :13位定时器,使用高8位和低5位
0        1        :16位定时器,全用
1        0        :8位自动重装载定时器,当溢出时将TH1存放的值自动重装入TL1.
1        1        :定时器无效
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

2.3. Таймер Т0.

Вставьте сюда описание изображения

Таймер T0 имеет в общей сложности 16 бит, разделенных на 8 старших битов TH0 и 8 младших битов TL0. Таким образом, всего можно посчитать 2^16 чисел (65536), а цикл подсчета 1 числа составляет 1,085 мкс, поэтому по умолчанию счет начинается с 0, а совокупное время составляет около 71 мс.

3. Случай: Используйте таймер T0 для управления включением и выключением светодиода с интервалом в 1 секунду.

Код ①:

#include <REGX52.H>

sbit LED1 = P3^7;
void main(void)
{
	int cnt = 0;
	LED1 = 1;//先让灯熄灭的状态
	
/*1、选择定时器T0,并配置为16位定时器*/
	TMOD =0x01;							// 0000 0001
	
/*
	2、定一个10ms的时间,数1下需要1.085us
	10ms需要数则需要数9216下,那从65536-9126=56320
	从56320这里开始数,数9216下就到了65536。当超过了
	65536时就报表了,控制寄存器TCON的TF0由0变为1	
*/
	TL0 = 0x00; //0000 0000
	TH0 = 0xDC;//1101 1100
	
/*3、打开定时器T0*/
	TR0 = 1;
	
	TF0 = 0;//先个溢出标志清零
	while(1)
	{
		if(TF0 == 1)//10ms报表了
		{	
			TF0 = 0;//软件清零,现在不使用中断
			TL0 = 0x00; //重新给初值
			TH0 = 0xDC;
			cnt++;
			if(cnt == 100)//数100次,相当于1s
			{
				cnt = 0;
				LED1 = !LED1;
			}
		}
	}
}
  • 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

【Примечание】

  • После каждого отчета таймеру должно быть присвоено новое начальное значение.
  • cnt увеличивается на 1 каждые 10 миллисекунд. Когда cnt увеличивается до 100, это означает, что прошла 1 секунда.

Оптимизация кода②:

#include <REGX52.H>

sbit LED1 = P3^7;

void Timer0_Init_10ms(void)//定时器初始化10ms
{
	TMOD =0x01;							
	
	TL0 = 0x00; //0000 0000
	TH0 = 0xDC;//1101 1100
	
	TR0 = 1;
	TF0 = 0;
}

void main(void)
{ 
	int cnt = 0;
	LED1 = 1;//先让灯熄灭的状态
	Timer0_Init_10ms();
	
	while(1)
	{
		if(TF0 == 1)//10ms报表了
		{	
			TF0 = 0;//软件清零,现在不使用中断
			TL0 = 0x00; //重新给初值
			TH0 = 0xDC;
			cnt++;
			if(cnt == 100)//数100次,相当于1s
			{
				cnt = 0;
				LED1 = !LED1;
			}
			
		}
	}
}
  • 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

Инкапсулируйте инициализацию таймера T0 в функцию и вызывайте ее напрямую при необходимости.
Но использование TMOD = 0x01 имеет и недостатки:

假如定时器T1正在使用,且为16位定时器。则TMOD的高4位应该为:0x1(0001)
而我们使用定时器T0时TMOD初始为0x01,则TMOD的高4位为0x0(0000),则把定时器T1变为一个13位定时器了。所以还需要改进
  • 1
  • 2

Оптимизация кода ③:

#include <REGX52.H>

sbit LED1 = P3^7;

void Timer0_Init_10ms(void)		//10毫秒@11.0592MHz
{
	//AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x00;		//设置定时初值
	TH0 = 0xDC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
}

void main(void)
{ 
	int cnt = 0;
	LED1 = 1;//先让灯熄灭的状态
	Timer0_Init_10ms();
	
	while(1)
	{
		if(TF0 == 1)//10ms报表了
		{	
			TF0 = 0;//软件清零,现在不使用中断
			TL0 = 0x00; //重新给初值
			TH0 = 0xDC;
			cnt++;
			if(cnt == 100)//数100次,相当于1s
			{
				cnt = 0;
				LED1 = !LED1;
			}
			
		}
	}
}
  • 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

Мы обнаруживаем, что инициализация TMOD:

TMOD &= 0xF0;		//设置定时器模式
TMOD |= 0x01;		//设置定时器模式
  • 1
  • 2

Каковы преимущества такой инициализации?

假如定时器T1正在使用,且为16位定时器。则TMOD的高4位应该为:0x1(0001),而要使用定时器T0,且也为16位定时器,则TMOD =  0x11;
TMOD &= 0xF0;表示TMOD = TMOD & 0xf0,则与出来的TMOD = 0x10,由此可见,这一步就是让TMOD的高4位不变,低4位清零。
TMOD |= 0x01;表示TMOD = TMOD | 0x01,则或出来的TMOD = 0x11,由此可见,这一步就是让TMOD的高4位不变,低4位初始化。
通过这样初始化,既保证了TMOD的高4位不变(不改变定时器T1的初始化),由对低4位进行了改变(对定时器T0初始化)。
当然:也可以直让TMOD = 0x11;
  • 1
  • 2
  • 3
  • 4
  • 5