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

Микроконтроллер Puzhong 51: подробное объяснение и применение таймеров и счетчиков (7)

2024-07-12

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

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

введение

Таймеры и счетчики — это аппаратные модули, используемые для измерения временных интервалов или подсчета событий. Их можно использовать во многих приложениях, таких как создание точных временных задержек, измерение частот, подсчет внешних событий и т. д. Таймер 51 микроконтроллера относится к внутренним ресурсам микроконтроллера, а подключение и работа его схемы осуществляются внутри микроконтроллера. В этой статье подробно описаны принцип работы, метод настройки и применение таймеров и счетчиков в микроконтроллере 51.

В этой главе будут рассмотрены сведения, связанные с прерываниями. Для получения более подробной информации см.:Объяснение системы прерываний

Примечание. Ресурсы таймера связаны с моделью микроконтроллера. Различные модели микроконтроллеров могут иметь разное количество таймеров и методов работы, но, вообще говоря, методы работы T0 и T1 являются общими для всех 51 микроконтроллеров.

Как работает таймер

Таймер похож на небольшой будильник внутри микроконтроллера. В соответствии с выходным сигналом часов значение счетной единицы увеличивается на единицу каждую «одну секунду». Когда значение счетчика увеличивается до «установленного времени напоминания о тревоге», счетчик выдает запрос на прерывание в систему прерываний, генерирует «кольцевое напоминание» и заставляет программу перейти к функции обслуживания прерываний для выполнения. .

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

Регистр режима работы таймера/счетчика TMOD

Функции синхронизации и счета управляются битами управления специального функционального регистра TMOD. CT Csqrt{T}СТ Чтобы сделать выбор, информация регистра TMOD приведена в следующей таблице. Видно, что два таймера/счетчика имеют четыре режима работы, выбираемых через M1 и M0 TMOD. Режимы 0, 1 и 2 двух таймеров/счетчиков одинаковы, но режим 3 отличается. Функции в каждом режиме следующие:
Вставьте сюда описание изображения

Режим работы таймера

При установке M1 и M0 в регистре TMOD таймер/счетчик 0 и 1 имеет четыре разных режима работы.

Режим 0 (13-битный таймер/счетчик)

Вставьте сюда описание изображения
Схема рабочих режимов выглядит следующим образом:
Вставьте сюда описание изображения

Режим 1 (16-битный таймер/счетчик)

Режим 1 точно такой же, как режим 0, за исключением того, что используются все 16 бит TH0 и TL0. В этом режиме 8-битное переполнение TL0 переносится в TH0, а переполнение TH0 устанавливает флаг переполнения TF0 в TCON.

Когда GATE=0(TMOD.3), если TR0=1, таймер считает. Когда GATE=1, внешний вход INTO может управлять таймером 0, чтобы можно было измерить ширину импульса. TRO — это бит управления в регистре TCON. Подробное описание функций каждого бита регистра TCON см. в описании регистра TCON в предыдущем разделе.

Примечание. Таймер микроконтроллера серии STC89C51RC/RD+ имеет две скорости счета: один — режим 12T, добавляющий 1 каждые 12 тактов, как и традиционный микроконтроллер 8051, другой — режим 6T, добавляющий 1 каждые 6 тактов, скорость Скорость T0, которая в 2 раза выше, чем у традиционного микроконтроллера 8051, устанавливается в программаторе STC-ISP при записи пользовательской программы.

Режим 2 (8-битный режим автоматической перезагрузки)

В этом режиме таймер/счетчик может автоматически перезагружать 8-битный счетчик. Переполнение TL0 не только устанавливает TF0, но также перезагружает содержимое TH0 в TL0. (TH0 можно установить первым, и содержимое TH0 останется неизменным во время переустановки)
Вставьте сюда описание изображения

Режим 3 (два 8-битных счетчика)

Для Таймера 0 в этом режиме Таймер 1 прекращает отсчет, и эффект такой же, как при установке TR1 на 0.


Для таймера 0 в этом режиме TL0 и TH0 таймера 0 функционируют как два независимых 8-битных счетчика. На рисунке ниже показана логическая схема таймера 0 в режиме 3. TL0 занимает бит управления таймера 0: CT Csqrt{T}СТ , GATE, TRO, INTO и TFO. THO ограничен функцией таймера (период счетчика) и занимает TR1 и TF1 таймера 1. В это время TH0 управляет прерыванием таймера 1.

Режим 3 предназначен для добавления дополнительного 8-битного таймера/счетчика, предоставляя микроконтроллеру три таймера/счетчика. Режим 3 применим только к таймеру/счетчику 0. Когда таймер T1 находится в режиме 3, он эквивалентен TR1-0 и прекращает счет, а T0 можно использовать как два таймера.
Вставьте сюда описание изображения

Процесс настройки таймера

  1. Присвойте значения TMOD, чтобы определить, как работают T0 и T1.
  2. Рассчитайте начальное значение в соответствии со временем, которое необходимо замерить, и запишите его в TH0, TL0 или TH1, TL1.
  3. Если используются прерывания, присвойте значение EA и откройте таймер общего прерывания.
  4. Установите TR0 или TR1, чтобы запустить отсчет времени или счета таймера/счетчика.

Примечание. Инструмент программирования STC-ISP поставляется с начальным значением времени, которое необходимо рассчитать. Вы можете скопировать код в соответствии с выбранным вами режимом.
Вставьте сюда описание изображения

Демонстрация кода — светодиод LED1 мигает с интервалом в 1 секунду.

Индикатор LED1 мигает с интервалом в 1 секунду через прерывание таймера 0. Физическая схема подключена: D1 подключен к выводу P2_0. Используется тактовый сигнал 12.000 МГц. Прерывание срабатывает с интервалом в одну миллисекунду. каждый раз для подсчета используется функция триггера прерывания. Когда оно равно 1000, это одна секунда.

#include <REGX52.H>

sbit LED1 = P2^0;

void External0_ISR(void) interrupt 1
{
	static unsigned int count = 0;
	TL0 = 0x18;	//需要手动复原			
	TH0 = 0xFC;	//需要手动复原
    // 中断处理代码
	if(count == 1000)
	{
		count = 0;
		LED1 = !LED1;
	}
	count++;
}


void Timer0_Init(void)		//1毫秒@12.000MHz
{
	TMOD &= 0xF0;			//设置定时器模式
	TMOD |= 0x01;			//设置定时器模式
	TL0 = 0x18;				//设置定时初始值
	TH0 = 0xFC;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	ET0 = 1;//打开T0中断
	EA = 1;//打开总中断
	TR0 = 1;				//定时器0开始计时
}


void main()
{
	Timer0_Init();
	while(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

Демонстрация кода — кнопка 1 управляет состоянием светодиодных ходовых огней

В этой демонстрации используются функции смещения _crol_left и _cror_right в библиотеке INTRINS.H. При нажатии кнопки KEY1 светодиодный ходовой огонь переключает состояние направления и мигает. Физическое подключение изображения: K1 подключен к контакту P0_0, а восемь светодиодов вставлены в контакт P2.

  • крор(беззнаковый символ val, беззнаковый символ n): поворот символов вправо и поворот значения val вправо на n бит.
  • кроль(беззнаковый символ, беззнаковый символ n): поворот символов влево, поворот значения влево на n битов.
#include <REGX52.H>
#include <INTRINS.H>

sbit KEY1 = P0^0;
sbit KEY2 = P0^1;
unsigned char LEDMode;

void DelayXms(unsigned int xms)	//@12.000MHz
{
	unsigned char data i, j;
	
	while(xms)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}
}

void Timer0_Init(void)		//1毫秒@12.000MHz
{
	TMOD &= 0xF0;			//设置定时器模式
	TMOD |= 0x01;			//设置定时器模式
	TL0 = 0x18;				//设置定时初始值
	TH0 = 0xFC;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	ET0 = 1;//打开T0中断
	EA = 1;//打开总中断
	TR0 = 1;				//定时器0开始计时
}

void External0_ISR(void) interrupt 1
{
	static unsigned int count = 0;
	TL0 = 0x18;	//需要手动复原			
	TH0 = 0xFC;	//需要手动复原
    // 中断处理代码
	if(count == 1000)
	{
		count = 0;
		if(LEDMode == 0)
			P2 = _crol_(P2,1);
		if(LEDMode == 1)
			P2 = _cror_(P2,1);

	}
	count++;
}

unsigned char Getkey()
{
	unsigned char keyNumber = 0;
	if(KEY1 == 0)
	{
		DelayXms(5);
		while(KEY1 == 0);
		DelayXms(5);
		keyNumber = 1;
	}
	if(KEY2 == 0)
	{
		DelayXms(5);
		while(KEY2 == 0);
		DelayXms(5);
		keyNumber = 2;
	}
	return keyNumber;
}


void main()
{
	unsigned char keyNum = 0;
	P2 = 0xfe;
	Timer0_Init();
	while(1)
	{
		keyNum = Getkey();
		if(keyNum)
		{
			if(keyNum == 1)
			{
				LEDMode++;
				if(LEDMode>=2)
				{
					LEDMode = 0;	
				}
			}
		}
	}
}
  • 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
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95

Демонстрация кода — дисплей таймера LCD1602

В этом демонстрационном коде в качестве дисплея используется модуль LCD1602. Модуль LCD1602 не будет подробно объясняться, а специальные инструкции будут представлены позже. Если вам нужна библиотека LCD1602, вы можете написать мне лично. Физическое подключение изображения: просто подключите модуль LCD1602 к плате.

#include <REGX52.H>
#include "LCD1602.h"

unsigned char Sec=55,Min=59,Hour;//秒分时

void DelayXms(unsigned int xms)	//@12.000MHz
{
	unsigned char data i, j;
	
	while(xms)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}
}

void Timer0_Init(void)		//1毫秒@12.000MHz
{
	TMOD &= 0xF0;			//设置定时器模式
	TMOD |= 0x01;			//设置定时器模式
	TL0 = 0x18;				//设置定时初始值
	TH0 = 0xFC;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	ET0 = 1;//打开T0中断
	EA = 1;//打开总中断
	TR0 = 1;				//定时器0开始计时
}

void External0_ISR(void) interrupt 1
{
	static unsigned int count = 0;
	TL0 = 0x18;	//需要手动复原			
	TH0 = 0xFC;	//需要手动复原
    // 中断处理代码
	if(count == 1000)
	{
		count = 0;
		Sec++;
		if(Sec == 60)
		{
			Sec = 0;
			Min++;
			if(Min == 60)
			{
				Min = 0;
				Hour++;
				if(Hour == 24)
				{
					Hour = 0;
				}
			}

		}
	}
	count++;
}

void main()
{
	Timer0_Init();
	LCD_Init();
	LCD_ShowString(1,1,"Time:");
	LCD_ShowString(2,1,"00:00:00");
	while(1)
	{
		LCD_ShowNum(2,1,Hour,2);
		LCD_ShowNum(2,4,Min,2);
		LCD_ShowNum(2,7,Sec,2);
	}	
}
  • 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
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75