Sistemas Operacionais de Tempo Real – Timers

 Relogios-660x364

 Introdução

Estava desenvolvendo algumas idéias para um novo artigo técnico, quando encontrei perdida, no fundo de uma gaveta virtual, uma biblioteca de rotinas em C que desenvolvi há algum tempo. É uma preciosidade!!! Eu mesmo já utilizei essas funções em vários projetos. Estou aqui disponibilizando esse material para você.

Vou contar um pouco a história dessa biblioteca. Houve uma época em que o meu trabalho era focado em projetos de desenvolvimento de sistemas dedicados baseados em processadores da família 8051. Desenvolvemos uma célula de carga digital, um sistema de monitoramento ambiental, um mini CLP, um sistema de monitoramento e controle de um processo químico, sistema de controle de elevadores etc. Daí surgiu a ideia de elaborar funções e rotinas padronizadas, pois quase todos esses sistemas tinham alguma coisa em comum, como por exemplo teclas, displays etc. e deveriam operar em tempo real. O objetivo foi diminuir o tempo gasto para o desenvolvimento de um novo projeto. Antes de prosseguir, recomendo a leitura do artigo Sistemas Operacionais de Tempo Real – Introdução, onde são abordados alguns conceitos que serão aplicados neste artigo.

É necessário apresentar aqui alguns esclarecimentos a respeito  da filosofia usada na elaboração dessas rotinas. Eu parti do princípio de que os nossos sistemas são de tempo real e que realizam periodicamente algumas funções rotineiras, tais como verificar um teclado, atualizar displays, administrar LEDs de sinalização, realizar medidas, etc. Outras ações são tomadas por demanda, ou seja, apenas quando ocorrem. Essas demandas podem ser periódicas ou assíncronas (aleatórias). Daí já reconhecemos o primeiro elemento a ser implementado no nosso Sistema Oeracional: um temporizador (Timer). Para quem não sabe, os processadores tradicionais da família 8051 têm apenas 2 temporizadores, enquanto outras versões oferecem pelo menos mais um. Antes de continuar, acho interessante recordarmos a arquitetura dos microcontroladores da família MCS-51 e os modos de operação dos seus temporizadores. Na parte final desse artigo será desenvolvido um pequeno exemplo prático, cujo código poderá ser compilado e simulado. 

TIMERS da família MCS-51

 Para ilustrar o que será abordado aqui, vamos nos referenciar aos microcontroladores de fabricação da ATMEL, com a arquitetura baseada no 8051, cujo documento completo você pode consultar aqui: ATMEL 8051 Microcontrollers Hardware Manual. Na Figura 1 podemos observar a arquitetura interna de um microcontrolador AT89S8253, que continua sendo produzido, mostrando em destaque o bloco dos temporizadores.

 Arquitetura_8253

 Figura 1: Diagrama em blocos da arquitetura interna de um microcontrolador AT89S8253

Sem entrar nos detalhes referentes aos contadores / temporizadores Timer 0 e Timer 1 dessa família de microcontroladores, basta dizer que eles podem ser programados para funcionarem em 4 modos distintos de operação:

  • Modo 0: O temporizador é configurado como um contador de 13 bits, que pode receber um valor inicial e conta para cima. Na transição do valor limite superior 0x1FFF para  0x0000, é acionado um flag de sinalização;
  • Modo 1: Similar ao modo 0, porém é configurado o contador para 16 bits;
  • Modo 2: O temporizador é configurado como um contador de 8 bits, com um registro de 8 bits associado para recarregar o valor inicial automaticamente. Na transição, é acionado um flag;
  • Modo 3: Nesse modo de operação, o Timer 0 opera como 2 contadores distintos de 8 bits, enquanto o Timer 1 nesse modo de operação permite que se congele a contagem.

 Convenções para o uso dos Timers

Para o objetivo de projetar uma biblioteca com rotinas padronizadas, foi definido que o Timer 0 seria o temporizador padrão do sistema e o Timer 1 também poderia ser usado para isso, se acaso não fosse necessário usá-lo para gerar baud-rate da comunicação serial.

O período de interrupção do temporizador deve ser o maior possível e baixo o suficiente para atender às necessidades prioritárias do sistema. Para que se entenda o motivo disso, observe o seguinte exemplo:

 Suponhamos que:

  • Um microcontrolador que, por restrições de sua arquitetura e do oscilador (clock)  utilizado, possa executar no máximo 10.000 instruções por segundo;
  • Uma rotina de interrupção provocada pelo temporizador execute 20 instruções na média a cada interrupção.

Se numa hipótese absurda o temporizador for dimensionado para gerar 500 interrupções por segundo, a rotina de interrupção vai consumir todo o tempo disponível para executar as instruções do microcontrolador (500 x 20 = 10.000)! Se por exemplo esse número puder cair para 50 interrupções por segundo, sem prejudicar a operação do sistema, a rotina de interrupção vai consumir apenas 10% do total disponível (1.000), deixando os outros 90% para as demais atividades do microprocessador.

A compreensão do que foi ilustrado nesse exemplo é fundamental. As rotinas que são executadas com maior frequência devem ser otimizadas para serem executadas no menor tempo possível e na menor frequência possível tembém. Voltando ao exemplo das 500 interrupções, se acaso a rotina de interrupção executasse apenas 18 instruções ao invés das 20, já sobrariam 1.000 instruções por segundo que poderiam ser executadas por outras atividades. Em muitos casos isso é suficiente. Note que para esse exemplo em particular, só analisamos uma das soluções possíveis para viabilizar a operação do sistema. Poderia-se também lançar mão de outros recursos, como por exemplo aumentar a frequência do oscilador do microcontrolador.

Assim a frequência da interrupção do nosso timer deve ser dimensionada de modo que:

  • A função que deverá ser executada com maior frequência possa ser atendida pelas interrupções do timer no menor tempo necessário para isso (e maior possível), definindo assim as especificações do timer de referência do sistema;
  • Outras temporizações mais lentas sejam realizadas como múltiplos da interrupção do timer e implementadas por meio de temporizadores virtuais de software.

Um temporizador virtual de software é uma estrutura no programa em que a cada temporizador é associado um valor inicial, que se traduz num número inteiro de interrupções do Timer 0, e um flag de sinalização. A cada interrupção do Timer 0, o temporizador de software é decrementado e testado se zero. Se for zero, é ligado o flag para avisar que a contagem de software foi terminada e o temporizador é reinicializado para o seu valor inicial. O tratamento do final de contagem é realizado no programa principal, testando-se o flag e reinicializando-o depois.

O timer de referência deverá funcionar no modo 2 de operação. Observe que a programação do Timer 0 depende da frequência de clock do microcontrolador, do fator de divisão do clock, que nas CPUs tradicionais do MCS-51 é de 12 vezes, e da frequência requerida de interrupção. Um último limitante é que o valor inicial do Timer nessa configuração é de no máximo 255 (8 bits). Na biblioteca também foi desenvolvido um padrão para a programação do Timer 1, especialmente se não for usado para gerar baud-rate.

Detalhes da Biblioteca em C

O código em C a seguir foi desenvolvido para o compilador KEIL C51 μVision, na versão de avaliação. Se você quiser testar o programa exemplo que desenvolveremos no final deste artigo, recomendo que você baixe e instale esse programa.  O arquivo de biblioteca com os trechos de código em C para a utilização dos timers de forma padronizada está dividido em segmentos. O primeiro segmento define uma série de constantes, que podem ser ajustadas conforme as especificações do projeto. Veja o trecho do código a seguir.

//*******************************************************************************
//*                                                                             *
//*		ROTINAS PADRONIZADAS PARA USO EM APLICAÇÕES                     *
//*	 	DE SISTEMAS MICROCONTROLADOS (FAMÍLIA 8051)                     *
//*			    (Resp. Engº Puhlmann)                               *
//*                                                                             *
//*			(31/05/2000 - Rev. 14/06/2000)                          *
//*                                                                             *
//*******************************************************************************


//===============================================================================
//=                                                                             =
//=		ROTINAS PADRONIZADAS PARA PROGRAMAÇÃO DOS TIMERS                =
//=                                                                             =
//===============================================================================

//Para manter alguma padronização até na utilização dos timers, vamos definir
// que sempre utilizaremos o Timer 0 para gerar interrupções periódicas, funcionando
// como um relógio interno, para temporizar a todas as funções que necessitem de serem
// executadas com alguma periodicidade. E tb para gerenciar os timers de software, que 
// eventualmente forem necessários
//
//	O Timer 1, será reservado para realizar a geração de Baud Rate
//   

//===============================================================================
//
//	ROTINA DE PROGRAMACAO DO TIMER GLOBAL PARA GERAÇÃO DE TEMPORIZAÇÕES
//				(Timer 0 e Timer 1)
//
// OBS: Utilizar só o Timer 0, para essa função, se for utilizar a interface serial...
//      na serial, utiliza-se o Timer 1, como gerador de Baud Rate
//================================================================================

// Aqui faz-se necessário incluir o "header file" do componente a ser utilizado 

#include <reg51.h>

//----------------------------

#define DESLIGA	0
#define LIGA	1

// Define-se aqui a freqüência de clock da CPU

#define FREQUENCIA_DO_CLOCK_DA_CPU	   12.0e+6   // Hz ----> 12 MHz por exemplo

// Define o pre-scaler

#define FATOR_DE_ESCALA_CLOCK_TIMER    12.0f     // Divide o clock por 12

// Define a freqüência de interrupção do timer

#define FREQUENCIA_DE_INTERRUPCAO_TIMER_0 5.0e+3  // Hz ---- > 5 kHz por exemplo

//--------------

// Definição de variáveis referentes aos timers

//------- Timer 0 ----------

#define MASCARA_CT_0					0xfb

// Definição utilizada apenas quando o timer estiver no modo 2 de operação
// se acaso nao for usado no modo 2, comentar a linha abaixo

#define TIMER0_MODO2					1

#ifdef TIMER0_MODO2

// A conta desse preset tem que dar um número de 0 a 255, senão não funciona... 
 
#define PRESET_TIMER_0_MODO_2       (255 - (unsigned char)((FREQUENCIA_DO_CLOCK_DA_CPU/(FATOR_DE_ESCALA_CLOCK_TIMER * FREQUENCIA_DE_INTERRUPCAO_TIMER_0))+ 0.5))

#endif

#define MASCARA_DO_MODO_DO_TIMER_0      0xfc
#define MODO_0_TIMER_0                  0x00
#define MODO_1_TIMER_0                  0x01
#define MODO_2_TIMER_0                  0x02
#define MODO_3_TIMER_0                  0x03

//------------ Timer 1 ------

// No caso de usar-se o timer 1 no modo 2 também, define-se a frequência de interrupção

#define FREQUENCIA_DE_INTERRUPCAO_TIMER_1 5e+3  // Hz, 5 kHz por exemplo

// A conta desse preset tem que dar um número de 0 a 255, senão não funciona... 

#define MASCARA_CT_1			0xbf
 
// Definição utilizada apenas quando o timer estiver no modo 2 de operação

#define TIMER1_MODO2					1

#ifdef TIMER1_MODO2

// A conta desse preset tem que dar um número de 0 a 255, senão não funciona... 
 
#define PRESET_TIMER_1_MODO_2          (255 - (unsigned char)((FREQUENCIA_DO_CLOCK_DA_CPU/(FATOR_DE_ESCALA_CLOCK_TIMER * FREQUENCIA_DE_INTERRUPCAO_TIMER_1))+0.5))

#endif

#define MASCARA_DO_MODO_DO_TIMER_1      0xcf
#define MODO_0_TIMER_1                  0x00
#define MODO_1_TIMER_1                  0x10
#define MODO_2_TIMER_1                  0x20

//******************** Fim das definições das variáveis referentes aos timers **************

Nesse código há alguns parâmetros que precisam ser alterados, conforme o projeto:

  • #define   FREQUENCIA_DO_CLOCK_DA_CPU 12.0e+6 // Hz —->  12 MHz, por exemplo. Inicializar essa constante com o valor do clock do seu microcontrolador;
  • #define   FATOR_DE_ESCALA_CLOCK_TIMER    12.0f     // Divide o clock por 12 (Valor do pre-scaler);
  • #define   FREQUENCIA_DE_INTERRUPCAO_TIMER_0 5e+3  // Hz —- > 5 kHz, por exemplo. Define a frequência da interrupção do timer.

São apenas esses três parâmetros que devem ser inicializados. Não é necessário alterar outras partes do código!

O segundo segmento da biblioteca refere-se às inicializações dos timers, conforme o modo de operação, e os comandos para iniciar a operação do temporizador. Observe que nesse segmento é mostrada a rotina principal (void main(void)) e indicado onde devem ser inseridos os trechos do código.

//******************************************************************************************
//********* O Bloco seguinte refere-se às inicializações, conforme o modo de operação ******
//*********																			  ******

// No bloco principal, onde são realizadas as inicializações globais, ou na rotina de inicialização
// insere-se os seguintes blocos, apenas um, conforme o modo de operação:

void main(void)
{
   .
   .
   .
   .
//********************* Inicialização *************


//************************ TIMER 0	********************************************
//************************ inicio 	*********************************************

//***************************** MODO 0 ******************************************

// Inicializa os bits do timer 0 - 13 bits

TR0   = DESLIGA;						// Desliga Timer
TMOD &= MASCARA_CT_0;					// Seleciona função de "timer"
TMOD &= MASCARA_DO_MODO_DO_TIMER_0;		// Seta M1 e M0 para timer 0 - modo 0
TMOD |= MODO_0_TIMER_0;

//********************************************************************************

//***************************** MODO 1 ******************************************

// Inicializa os bits do timer 0 - 16 bits

TR0   = DESLIGA;
TMOD &= MASCARA_CT_0;					// Seleciona função de "timer"
TMOD &= MASCARA_DO_MODO_DO_TIMER_0;		// Seta M1 e M0 para timer  0 - modo 1
TMOD |= MODO_1_TIMER_0;

//********************************************************************************

//***************************** MODO 2 ******************************************


#define FREQUENCIA_DO_CLOCK_DA_CPU	   12.0e+6   // Hz
#define FREQUENCIA_DE_INTERRUPCAO_TIMER_0 5e+3  // Hz

// A conta desse preset tem que dar um número de 0 a 255, senão não funciona... 
 
#define PRESET_TIMER_0_MODO_2          (255 - (unsigned char)((FREQUENCIA_DO_CLOCK_DA_CPU/(FATOR_DE_ESCALA_CLOCK_TIMER * FREQUENCIA_DE_INTERRUPCAO_TIMER_0))+0.5))
*/

// Inicializa os bits do timer 0

TR0   = DESLIGA;
TMOD &= MASCARA_CT_0;					// Seleciona função de "timer"

T2CON = 0x00;
TR2   = DESLIGA;
T2MOD &= 0x0f;							// Seleciona função de "timer"


TH0	  = PRESET_TIMER_0_MODO_2;			// Inicializa o preset do contador
TL0   = PRESET_TIMER_0_MODO_2;

TMOD &= MASCARA_DO_MODO_DO_TIMER_0;		// Seta M1 e M0 para timer 0 - modo 2
TMOD |= MODO_2_TIMER_0;


//************************ TIMER 0 	*********************************************
//************************ fim   	*********************************************


//************************ TIMER 1	********************************************
//************************ inicio 	*********************************************


//***************************** MODO 0 ******************************************

// Inicializa os bits do timer 1 - 13 bits

TR1   = DESLIGA;						// Desliga Timer
TMOD &= MASCARA_CT_1;					// Seleciona função de "timer"
TMOD &= MASCARA_DO_MODO_DO_TIMER_1;		// Seta M1 e M0 para timer 1 - modo 0
TMOD |= MODO_0_TIMER_1;

//********************************************************************************

//***************************** MODO 1 ******************************************

// Inicializa os bits do timer 1 - 16 bits

TR1   = DESLIGA;
TMOD &= MASCARA_CT_1;					// Seleciona função de "timer"
TMOD &= MASCARA_DO_MODO_DO_TIMER_1;		// Seta M1 e M0 para timer  1 - modo 1
TMOD |= MODO_1_TIMER_1;

//********************************************************************************

//***************************** MODO 2 ******************************************


#define FREQUENCIA_DO_CLOCK_DA_CPU	   12.0e+6   // Hz
#define FREQUENCIA_DE_INTERRUPCAO_TIMER_1 5e+3  // Hz

// A conta desse preset tem que dar um número de 0 a 255, senão não funciona... 
 
#define PRESET_TIMER_1_MODO_2          (255 - (unsigned char)((FREQUENCIA_DO_CLOCK_DA_CPU/(FATOR_DE_ESCALA_CLOCK_TIMER * FREQUENCIA_DE_INTERRUPCAO_TIMER_1))+0.5))


// Inicializa os bits do timer 0

TR1   = DESLIGA;
TMOD &= MASCARA_CT_1;					// Seleciona função de "timer"

TH1	  = PRESET_TIMER_1_MODO_2;			// Inicializa o preset do contador
TL1   = PRESET_TIMER_1_MODO_2;

TMOD &= MASCARA_DO_MODO_DO_TIMER_1;		// Seta M1 e M0 para timer 1 - modo 2
TMOD |= MODO_2_TIMER_1;

//************************ TIMER 1 	*********************************************
//************************ fim   	*********************************************

 .
 .
 .
 .

//******************************************************************************************
//*** O bloco seguinte deve ser inserido imediatamente antes do "loop principal ************
//*** ************

 .
 .

//********************************************************************************
//
// TIMER 0
//
// Este bloco deve ser colocado no programa principal, para iniciar a operação do timer


TR0 = LIGA; // Liga o timer
ET0 = LIGA; // Libera a interrupção do timer
EA = LIGA; // Habilita as interrupções

//*******************************************************************************


//********************************************************************************
//
// TIMER 1
//
// Este bloco deve ser colocado no programa principal, para iniciar a operação do timer


TR1 = LIGA; // Liga o timer
ET1 = LIGA; // Libera a interrupção do timer
EA = LIGA; // Habilita as interrupções

//*******************************************************************************
 .
 .
 .

for(;;;)
{
}
 .
 .
 .
 .
 .
}

O terceiro segmento mostra como são definidas as rotinas de interrupção.

//*******************************************************************************************************
//******************************* Rotinas de interrupção dos timers *************************************
//*******************************									*************************************

//*******************************************************************************
//								 TIMER 0 	
//							rotina de interrupção
//

void vInterrupcaoTimer0() interrupt 1 
{
}

//*******************************************************************************
//								 TIMER 1 	
//							rotina de interrupção
//

void vInterrupcaoTimer1() interrupt 3 
{
}

EXEMPLO

A seguir vamos desenvolver o nosso programa de exemplo. Nesse programa, será programado o Timer 0 no modo 2 de operação, com o microcontrolador operando com um clock de 4 MHz e uma frequência de interrupção de 1,5 kHz. Confira o código no quadro abaixo.

//***************************************************************************
//**                                                                       **
//**         ROTINA EXEMPLO PARA TESTE DO USO DO TIMER                     **
//**         PARA SISTEMAS OPERACIONAIS DE TEMPO REAL                      **
//**                   (Resp. Eng. Puhlmann)                               **
//**                                                                       **
//**              (27/08/2014 - rev. 28/08/2014)                           **
//**                                                                       **
//***************************************************************************

#include <reg8253.h>                   // AT89S8253

//----------------------------

#define DESLIGA	0
#define LIGA	1

// Define-se aqui a freqüência de clock da CPU

#define FREQUENCIA_DO_CLOCK_DA_CPU	   4.0e+6   // Hz ----> 4 MHz

// Define o pre-scaler

#define FATOR_DE_ESCALA_CLOCK_TIMER    12.0f     // Divide o clock por 12

// Define a freqüência de interrupção do timer

#define FREQUENCIA_DE_INTERRUPCAO_TIMER_0 1.5e+3  // Hz ---- > 1,5 kHz

//--------------

// Definição de variáveis referentes aos timers

//------- Timer 0 ----------

#define MASCARA_CT_0					0xfb

// Definição utilizada apenas quando o timer estiver no modo 2 de operação
// se acaso nao for usado no modo 2, comentar a linha abaixo

// Define o Timer 0 como operando no modo 2
// A conta desse preset tem que dar um número de 0 a 255, senão não funciona... 
 
#define PRESET_TIMER_0_MODO_2          (255 - (unsigned char)((FREQUENCIA_DO_CLOCK_DA_CPU/(FATOR_DE_ESCALA_CLOCK_TIMER * FREQUENCIA_DE_INTERRUPCAO_TIMER_0))+ 0.5))


#define MASCARA_DO_MODO_DO_TIMER_0      0xfc
#define MODO_0_TIMER_0                  0x00
#define MODO_1_TIMER_0                  0x01
#define MODO_2_TIMER_0                  0x02
#define MODO_3_TIMER_0                  0x03


//=============== Fim da definição dos parâmetros do Timer 0 ===========

#define PRESET_TIMER_DE_SOFTWARE        10        // Define o valor inicial do temporizador de software
int nTimerDeSoftware = PRESET_TIMER_DE_SOFTWARE;  // Inicializa o temporizador de software com 10
bit bFlagTimerDeSoftware = DESLIGA;               // Inicializa a sinalização de término de contagem



//*******************************************************************************
//								 TIMER 0 	
//							rotina de interrupção
//

void vInterrupcaoTimer0() interrupt 1 
{
	nTimerDeSoftware--;                            // Decrementa o temporizador de software
	if(nTimerDeSoftware == 0)
	{
		bFlagTimerDeSoftware = LIGA;                 // Sinaliza que terminou a temporização de software
		nTimerDeSoftware = PRESET_TIMER_DE_SOFTWARE; // Reinicializa o temporizador
		
	}
}



//================================================================================
//
//                   PROGRAMA PRINCIPAL

void main(void)
{
	int nContadorSemFuncao = 0;
	
	//********************* Inicializações *************
  
	//************************ TIMER 0	********************************************
	// Inicializa os bits do timer 0

	TR0   = DESLIGA;
	TMOD &= MASCARA_CT_0;					// Seleciona função de "timer"

	T2CON = 0x00;
	TR2   = DESLIGA;
	T2MOD &= 0x0f;							// Seleciona função de "timer"


	TH0	  = PRESET_TIMER_0_MODO_2;			// Inicializa o preset do contador
	TL0   = PRESET_TIMER_0_MODO_2;

	TMOD &= MASCARA_DO_MODO_DO_TIMER_0;		// Seta M1 e M0 para timer 0 - modo 2
	TMOD |= MODO_2_TIMER_0;
    
	//******
	
	//********** Fim das Inicializações ******************

		
	//********************************************************************************
    //
    //						   TIMER 0
    //
    // Este bloco deve ser colocado no programa principal, para iniciar a operação do timer


    TR0 = LIGA;								// Liga o timer
    ET0 = LIGA;								// Libera a interrupção do timer
    EA  = LIGA;								// Habilita as interrupções

    //****

	for(;;)                              // Loop principal
	{
		nContadorSemFuncao++;              // Soma um no contador. Essa instrução foi inserida aqui apenas para não dar a impressão que a simulação está parada             
		
		if(bFlagTimerDeSoftware == LIGA)   // Verifica se terminou a temporização por software (10 vezes a interrupção do Timer 0)
		{
			P3_1 = ~P3_1;					           // Inverte o bit 1 da porta 3 - ;
			bFlagTimerDeSoftware = DESLIGA;  // Desliga a sinalização de término
		}
	}
	
}

Simulação do Exemplo

Se você quiser simular o programa exemplo acima e explorá-lo um pouco mais, siga os seguintes passos:

  • Instale o KEIL C51 μVision;
  • Baixe o arquivo Testa_Timer.zip;
  • Instale os arquivos de Testa_Timer.zip num diretório para testes;
  • Navegue até o diretório de testes e acione o arquivo Testa_Timer.uvproj (2 “clickes”)  (Figura 1).

 Diretorio-Projeto

 Figura 1: Arquivos no diretório de teste

Nesse instante deverá abrir o programa Keil e a tela deverá ser a retratada na Figura 2. Esse painel permite navegar no código em C, editá-lo e compilá-lo. Não é necessário fazer isso para realizar a simulação, mas você poderá posteriormente alterar alguns parâmetros do código e testar o programa com as novas alterações.

 Keil_Abriu

  Figura 2: Programa Keil pronto com o programa exemplo carregado

A seguir coloque o programa no modo de Debug (Figura 3, Figura 4 e Figura 5) para que se possa iniciar a simulação.

Keil_Seleciona_Debug

Figura 3: Selecionando o modo Debug do programa

Antes de entrar no modo de depuração, aparece na tela a mensagem da Figura 4. “Clicke” no  “OK” para continuar.

Keil_warning

Figura 4: Aviso de que no modo de avaliação, o código fica limitado a 2K

 Keil_Debug

 Figura 5: Modo Debug de operação

Observe que já estão destacados os painéis de monitoramento do Timer 0 e do Port 3, cujo bit 1 deverá ser alternado a cada término de contagem do temporizador de software. As duas variáveis principais (bFlagTimerDeSoftware e nTimerDeSoftware) poderão ser monitoradas na janela Watch 1 durante a simulação.

É possível utilizar as teclas de função F11 para executar o programa passo a passo ou F5 para entrar em execução. Recomendo que você inicie a simulação utilizando o passo  a passo para poder observar detalhadamente como que funciona o mecanismo de operação desse programa.

Resumo

Neste artigo técnico foram apresentados alguns conceitos relativos à utilização de temporizadores de hardware de um microcontrolador associados a temporizadores de software para a implementação de arquiteturas de software típicas de  sistemas operacionais de tempo real. Também foi apresentada e explicada uma biblioteca padronizada para a utilização dos timers de microcontroladores da família MCS-51, codificada em C, para ser compilada no programa da Keil. Depois foi desenvolvido um programa exemplo para que você possa simular o que foi apresentado e observar os detalhes dessa implementação.

Este artigo é o segundo de série de artigos que abordam algumas funções comuns em projetos de sistemas embarcados de tempo real. Confira os demais artigos (em breve).

Sistemas Operacionais de Tempo Real

Bibliotecas de funções e rotinas padronizadas em linguagem C para MCS-51

  • Timers (este artigo) – É apresentada uma biblioteca desenvolvida em linguagem C para a inicialização e o uso dos Timers do MCS-51.
  • Displays de 7 segmentos – É apresentada uma biblioteca desenvolvida em linguagem C para a inicialização e o uso em displays de 7 segmentos.
  • Teclados Matriciais – É apresentada uma biblioteca desenvolvida em linguagem C para varredura, leitura, debounce, identificação da tecla acionada e desvio para a rotina de tratamento. A forma como as rotinas foram escritas, permitem sua fácil reutilização em outros projetos.
  • Periféricos – É apresentada uma biblioteca desenvolvida em linguagem C para a inicialização e o uso de alguns periféricos, tais como conversores A/D, sensor de temperatura e memórias seriais.

Licença Creative Commons
Esta obra, “Sistemas Operacionais de Tempo Real – Timers“, de Henrique Frank W. Puhlmann, foi licenciada sob uma Licença Creative Commons Atribuição-NãoComercial-CompartilhaIgual 3.0 Não Adaptada.

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s