Technology Sharing

General 51 single chip microcomputer: detailed explanation and application of timer and counter (Part 7)

2024-07-12

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

insert image description here

introduction

Timers and counters are hardware modules used to measure time intervals or count events. They can be used in many applications, such as generating precise time delays, measuring frequencies, counting external events, etc. The timer of the 51 MCU belongs to the internal resources of the MCU, and its circuit connection and operation are completed inside the MCU. This article will introduce the working principle, configuration method and application of the timer and counter in the 51 MCU in detail.

This chapter will involve knowledge related to interrupts. For details, please refer to:Interrupt system explanation

Note: The timer resources are related to the model of the microcontroller. Different models of microcontrollers may have different numbers and operating methods of timers, but generally speaking, the operating methods of T0 and T1 are common to all 51 microcontrollers.

How timers work

The timer is like a small alarm clock inside the microcontroller. According to the output signal of the clock, the value of the counting unit increases by one every "one second". When the value of the counting unit increases to the "set alarm reminder time", the counting unit will send an interrupt request to the interrupt system, generate a "ring reminder", and make the program jump to the interrupt service function for execution.

The working principle of timer/counter is based on clock pulse. In timer mode, they use internal clock source to count; in counter mode, they use external pulse source to count. Each timer/counter has a register to store the current count value.

TMOD timer/counter operating mode register

The timing and counting functions are controlled by the control bits of the special function register TMOD. C T Csqrt{T} CT The information of each bit of the TMOD register is listed in the following table. It can be seen that the two timers/counters have four operating modes, which are selected by M1 and M0 of TMOD. Modes 0, 1 and 2 of the two timers/counters are the same, while mode 3 is different. The functions of each mode are as follows:
insert image description here

Timer working mode

By setting M1 and M0 in the TMOD register, timer/counter 0 and 1 have four different operating modes.

Mode 0 (13-bit timer/counter)

insert image description here
The working mode diagram is as follows:
insert image description here

Mode 1 (16-bit timer/counter)

Mode 1 is identical to Mode 0 except that all 16 bits of TH0 and TL0 are used. In this mode, the 8-bit overflow of TL0 carries to TH0, and the overflow flag TF0 in TCON is set when TH0 overflows.

When GATE=0 (TMOD.3), if TR0=1, the timer counts. When GATE=1, the external input INTO is allowed to control timer 0, so that pulse width measurement can be achieved. TRO is the control bit in the TCON register. The specific function description of each bit of the TCON register can be found in the introduction of the TCON register in the previous section.

Note: The timer of STC89C51RC/RD+ series MCU has two counting rates: one is 12T mode, adding 1 every 12 clocks, which is the same as the traditional 8051 MCU; the other is 6T mode, adding 1 every 6 clocks, which is twice the speed of the traditional 8051 MCU. The T0 rate is set in the STC-ISP programmer when burning the user program.

Mode 2 (8-bit auto-reload mode)

In this mode, the timer/counter can automatically reload the 8-bit counter. The overflow of TL0 not only sets TF0, but also reloads the contents of TH0 into TL0. (TH0 can be set first, and the contents of TH0 will not change during reloading)
insert image description here

Mode 3 (two 8-bit counters)

For Timer 0, in this mode, Timer 1 stops counting, which has the same effect as setting TR1 to 0.


For Timer 0, in this mode, TL0 and TH0 of Timer 0 are used as two independent 8-bit counters. The following figure is the logic diagram of Timer 0 in Mode 3. TL0 occupies the control bits of Timer 0: C T Csqrt{T} CT , GATE, TRO, INTO and TFO. THO is limited to the timer function (counter cycle) and occupies TR1 and TF1 of timer 1. At this time, TH0 controls the timer 1 interrupt.

Mode 3 is provided to add an additional 8-bit timer/counter, so that the microcontroller has three timers/counters. Mode 3 is only applicable to timer/counter 0. When timer T1 is in mode 3, it is equivalent to TR1-0 and stops counting, while T0 can be used as two timers.
insert image description here

Timer Configuration Process

  1. Assign values ​​to TMOD to determine the working mode of T0 and T1.
  2. Calculate the initial value according to the desired timing time and write it into TH0, TL0 or TH1, TL1.
  3. If interrupts are used, assign values ​​to EA and enable the timer interrupt.
  4. Set TR0 or TR1 to start the timer/counter timing or counting.

Note: The STC-ISP programming tool comes with a built-in calculation of the initial value of the timing time. You can copy the code according to the mode you choose.
insert image description here

Code Demonstration - LED1 flashes every 1 second

The LED1 indicator light is controlled to flash at intervals of 1 second through the timer 0 interrupt. The physical connection diagram is as follows: D1 is connected to the P2_0 pin. A 12.000MHz clock is used. The interrupt is triggered every 1 millisecond. The interrupt trigger function is counted. When it reaches 1000, it is one second.

#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

Code demonstration - button 1 controls the LED running light status

In this demonstration, the _crol_left shift and _cror_right shift functions in the INTRINS.H library are used. When the KEY1 button is pressed, the LED water light will switch the direction state and flash. Physical connection: K1 is connected to the P0_0 pin, and the eight LED lights are inserted into the P2 pin.

  • cror(unsigned char val, unsigned char n): Rotate val right by n positions.
  • crol(unsigned char val, unsigned char n): Character circular left shift, circular left shift val n positions
#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

Code Demonstration - LCD1602 Timer Clock Display

This demo code uses LCD1602 module as display. I won't explain the LCD1602 module in detail. A special chapter will be provided later. If you need LCD1602 library, you can chat with me. Physical connection: Just plug in the LCD1602 module on the board.

#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