TMR0 In PIC16F877A (Theoretical basis) EN/ES

avatar

In all the articles we have seen so far we have been using the delay_ms(time) instruction to generate delays when necessary. This instruction will count the time indicated in time before going to the next line and this count can only be interrupted by internal or external interruptions programmed in the microcontroller.

We could find in some process the need to supervise some variable every some time but before each supervision the microcontroller must be doing some other tasks, we can't use delay_ms(time) because while this instruction is executed the microcontroller can't do anything else and it is needed to keep executing other tasks, so.... How do we do to keep track of time without affecting the execution of other tasks in the microcontroller?

Today we will learn how to do this using the TMR0 interrupt and in the process we will learn about the features and some utilities of this timer.


En todos los artículos que hemos visto hasta ahora hemos estado usando la instrucción delay_ms(time) para generar retardos cuando ha sido necesario. Esta instrucción contará el tiempo se indique en time antes de pasar a la siguiente línea y este conteo solo puede ser interrumpido por las interrupciones internas o externas que se programen en el microcontrolador.

Podríamos encontrar en algún proceso la necesidad de supervisar alguna variable cada cierto tiempo pero antes de cada supervisión el microcontrolador debe estar realizando algunas otras tareas, no podemos usar delay_ms(time) porque mientras esta instrucción se ejecute el microcontrolador no podrá hacer nada más y se necesita que se mantenga ejecutando otras tareas, así que... ¿Cómo hacemos para llevar el control del tiempo sin afectar la ejecución de otras tareas en el microcontrolador?

Hoy aprenderemos a hacer esto mediante la interrupción TMR0 y en el proceso conoceremos las características y algunas utilidades de este temporizador.


Pixabay

Time base on a microcontroller

When we program a microcontroller we are indicating the instructions to be executed in each line, the pointer goes from line to line executing instructions one after another but how long does it take to execute each instruction? What makes it go from one line to the next?

The engine of a microcontroller is the oscillator, it is who generates the pulses for the occurrence of events, the oscillators for microcontrollers must have frequencies between 4MHz and 20MHz.

The oscillator also known as clock delivers the pulses that measure the time and make the microcontroller work, for an instruction to be executed there must be four cycles of the clock between which the information is processed and executed internally.

From the above we get a variation which we call "machine cycle" which is the time it takes the microcontroller to execute an instruction. This time can be calculated with the following equation:


Cuando programamos un microcontrolador estamos indicando las instrucciones que se ejecutarán en cada línea, el puntero va de línea en línea ejecutando instrucciones una tras otra pero ¿Cuanto tiempo tarda en ejecutar cada instrucción? ¿Qué hace que pase de una línea a la siguiente?

El motor de un microcontrolador es el oscilador, es quien genera los pulsos para la ocurrencia de eventos, los osciladores para microcontroladores deben tener frecuencias entre 4MHz y 20MHz.

El oscilador también conocido como reloj entrega los pulsos que miden el tiempo y hacen que el microcontrolador trabaje, para que se ejecute una instrucción deben ocurrir cuatro ciclos del reloj entre los cuales se procesa y ejecuta la información internamente.

De lo anterior sacamos una variación a la cual llamamos "ciclo máquina" que es el tiempo que tarda el microcontrolador en ejecutar una instrucción. Este tiempo se puede calcular con la siguiente ecuación:

Where TCM is the time it takes to execute an instruction (machine cycle time), 4 implies that it is executed in four clock cycles and Fosc refers to the frequency of the oscillator. To know how long it takes to execute an instruction it would be enough to know the frequency of the oscillator we are using and apply this formula.


Donde TCM es el tiempo que tarda en ejecutarse una instrucción (Tiempo de un ciclo máquina), 4 implica que lo hace en cuatro ciclos del reloj y Fosc se refiere a la frecuencia del oscilador. Para conocer cuanto tarda en ejecutarse una instrucción bastaría conocer la frecuencia del oscilador que estemos usando y aplicar está fórmula.


TMR0 operation

Los microcontroladores presentan registros cuya función es operar aplicaciones usando la variable tiempo, estos son concidos como temporizadores y para el caso del PIC16F877A contamos con 3: TMR0, TMR1 y TMR2.

Microcontrollers have registers whose function is to operate applications using the time variable, these are known as timers and in the case of the PIC16F877A we have 3: TMR0, TMR1 and TMR2.

It is not possible to generate delays or time related applications without using any of these timers.

TMR0: It is an 8-bit register that can be used as a timer or as a counter, in the second case it will count the pulses arriving to the RA4 pin.

The way in which time can be kept with TMR0 is when its count reaches 255 since it is an 8-bit register it can only count from 0 to 255 and when it reaches that value the next count produces an "overflow" which activates a check bit in a register.


No se pueden generar retardos o aplicaciones relacionadas con el tiempo sin usar alguno de estos temporizadores.

TMR0: Es un registro de 8bits que se puede usar como temporizador o como contador, en el segundo caso contará los pulsos que lleguen al pin RA4.

La forma en que se puede llevar el tiempo con TMR0 es cuando su cuenta llega a 255 dado que es un registro de 8 bits solo puede contar de 0 a 255 y al llegar a ese valor la siguiente cuenta produce un "desborde" lo que activa un bit de verificación en un registro.


In the TMR0 register the desired value between 0 and 255 is loaded, since when it reaches 255 it overflows and generates a warning that indicates the fulfillment of the count, the higher the value loaded the lower the measured time will be.

The OPTION_REG register has 8 bits and is used to configure the operation of TMR0.


En el registro TMR0 se carga el valor deseado entre 0 y 255, dado que al llegar a 255 desborda y genera un aviso que indica el cumplimiento de la cuenta, mientras mayor sea el valor cargado menor será el tiempo medido.

En el registro OPTION_REG presenta 8 Bits y se usa para configurar el funcionamiento del TMR0.



alldatasheet

Setting TMR0

For our future applications with TMR0 we will take into account only the bits PS2, PS1 and PS0 which are called prescaler, this is because we are programming in C and the compiler takes care of the other settings with the instructions we write.

In order to calculate time we will need to load a value in the prescaler and another in the TMR0 since the time measurement depends on these two values together with TCM and they are all related by the following formula:


Para nuestras aplicaciones futuras con TMR0 vamos a tomar en cuenta solo los bits PS2, PS1 y PS0 los cuales reciben el nombre de preescaler, esto es así porque estamos programando en C y el compilador se encarga de las demás configuraciones con las instrucciones que escribimos.

Para poder calcular tiempo necesitaremos cargar un valor en el preescaler y otro en el TMR0 ya que la medición de tiempo depende de estos dos valores junto con TCM y todos están relacionados mediante la siguiente fórmula:



T_ is the time, TCM we already described that it represents a machine cycle and we can calculate it knowing the oscillation frequency of the clock that we always choose and set, therefore Fosc will always be a known value. Prescaler is the value that we load in the OPTION_REG register by means of the PS2, PS1 and PS0 bits and can reach a maximum of 256 values and TMR0 is a register of 8 bits in which we can load a value from 0 to 255 (256 values in total).

Knowing this data we can look at the formula carefully and notice that the higher the value loaded in TMR0 the lower the value of T, however the higher the value loaded in the prescaler the higher the value of T.

We can calculate the maximum time we can measure with the TMR0 by loading the optimal values that maximize the value of T, i.e. 256 in the prescaler and 0 in TMR0, we will assume a Fosc of 20MHz since it is the one we have been using all this time.


T es el tiempo, TCM ya describimos que representa un ciclo máquina y podemos calcularlo conociendo la frecuencia de oscilación del reloj que siempre somos nosotros quienes elegimos y cofiguramos por lo tanto Fosc siempre será un valor conocido. Preescaler es el valor que cargamos en el registro OPTION_REG mediante los bits PS2, PS1 y PS0 pudiendo llegar a un máximo de 256 valores y TMR0 es un registro de 8 bits en el que podemos cargar un valor de 0 a 255 (256 valores en total).

Conociendo esos datos podemos mirar la fórmula detenidamente y notar que mientras mayor sea el valor cargado en TMR0 menor será el valor de T, sin embargo mientras mayor sea el valor cargado en el preescaler mayor será el valor de T.

Podemos calcular el tiempo máximo que podemos medir con el TMR0 cargando los valores optimos que máximizan el valor de T, es decir, 256 en el preescaler y 0 en TMR0, supondremos una Fosc de 20MHz ya que es la que hemos estado usando todo este tiempo.



If we solve the mathematical problem we will obtain as a result 0.0131072 which implies the value of the time measured in seconds and that we can also express as 13.1 ms.

But if the maximum time we can measure with TMR0 is 13.1ms, how do we do when we need to count a value greater than that time?

What we do is to configure TMR0 to count a value that is easy to multiply, for example 1ms or 10ms, then we create a variable and each time that TMR0 overflows we increment in 1 that variable, then we create a conditional so that when TMR0 has overflowed the amount of times that meet the needed time the instruction is executed.

For example for 1s we need 1000ms so if our time is 10ms we can increment a variable up to 100 and when its value is 100 it means that a 1s has elapsed (10ms x 100).


Si resolvemos el problema matemático obtendremos como resultado 0.0131072 lo que implica el valor del tiempo medido en segundos y que también podemos expresar como 13.1 ms.

Pero si el tiempo máximo que podemos medir con TMR0 es de 13.1ms ¿Cómo hacemos cuando necesitamos contar un valor mayor a ese tiempo?.

Lo que se hace es configurar el TMR0 para que cuente un valor que sea fácil de multiplicar, por ejemplo 1ms o 10ms, luego creamos una variable y cada vez que el TMR0 se desborde incrementamos en 1 esa variable, luego creamos un condicional para que cuando TMR0 se haya desbordado la cantidad de veces que cumplen con el tiempo necesitado se ejecute la instrucción.

Por ejemplo para 1s necesitamos 1000ms así que si nuestro tiempo es de 10ms podemos incrementar una variable hasta 100 y cuando su valor sea 100 significa que ha transcurrido un 1s (10ms x 100).

Searching for the value of TMR0

We have already calculated the maximum time we can generate with TMR0 and we know how to make longer times with an accompanying variable, but how do we know what data to put in to form the time I want (less than the maximum) to meet my needs?

Since the values of the Prescaler and TMR0 are assigned by us we can assign the maximum to the Prescaler and clear TMR0 from the equation, then use the resulting equation to calculate the value of TMR0 for whatever value we need in T within the allowed range.


Ya cálculamos el tiempo máximo que podemos generar con TMR0 y sabemos como hacer tiempos mayores acompañandolo con una variable, pero ¿cómo saber que datos colocar para formar el tiempo que yo quiera (inferior al máximo) para satisfacer mis necesidades?

Dado que los valores del Preescaler y el TMR0 los asignamos nosotros podemos asignarle el máximo al Preescaler y despejar TMR0 de la ecuación, luego usar la ecuación resultante para calcular el valor de TMR0 para cualquier valor que necesitemos en T dentro del rango permitido.




Since we know the value of Fosc and we loaded the maximum value in the prescaler (256) we only need to replace T by the value of the time we want to achieve (less than the maximum we just calculated) and this will give us the value we need to load to TMR0 to measure that time. 😎


Como sabemos el valor de Fosc y cargamos el valor máximo en el preescaler (256) solo debemos reemplazar T por el valor del tiempo que queremos lograr (menor al máximo que acabamos de calcular) y esto nos arrojará el valor que debemos cargarle a TMR0 para medir ese tiempo. 😎




0
0
0.000
7 comments
avatar

Congratulations @electronico! You have completed the following achievement on the Hive blockchain And have been rewarded with New badge(s)

You got more than 200 replies.
Your next target is to reach 300 replies.

You can view your badges on your board and compare yourself to others in the Ranking
If you no longer want to receive notifications, reply to this comment with the word STOP

Check out our last posts:

The Hive Gamification Proposal Renewal
0
0
0.000