Enunciado do exercício:
“Considerando um 8051 com um cristal de 11,0592 MHz, desenvolver um programa em C para fazer um LED piscar em uma frequência de 1 segundo.”
Solução:
- Frequência do clock externo (cristal) = 11,0592 MHz
- Frequência de 1 pulso de clock no 8051 = 11,0592 MHz / 12 = 921.600 Hz
- Período de 1 pulso de clock no 8051 = 1/921.600 = 1,0851 μs
- Consequentemene, são necessários aproximadamente 921.574 pulsos de clock para gerar um atraso de 1 segundo. O maior valor que conseguimos representar nos registradores dos temporizadores do 8051 possui 16 bits, ou seja, 65.535.
- Assim, no lugar de configurar o timer do 8051 para contar 1 segundo, vai ser necessário dividir esse valor por 1.000, e o timer será configurado para gerar um atraso de 1 ms.
- Utilizando o Timer 0 no modo 1, os registradores TH0 e TL0 são utilizados em conjunto, formando um timer de 16 bits, realizando uma contagem de 0 a 65.535 (total de 65.536 valores).
- Como 1 pulso de clock no 8051 possui um período de 1,0851 μs, logo para realizar as 65.536 contagens, o Timer 0 irá demorar: 65.536 x 1,0851 μs = 71,1066 ms.
- Vai ser necessário calcular o número de contagens do Timer 0, necessário para obter o atraso de 1 ms.
- Logo, 1ms / 1,085μs = 921,6589862 contagens
- Valor inicial a ser utilizado para obter 921,7 contagens: 65.536 – 921,7 = 64.614,3
- Esse será o valor inicial da contagem a ser carregado nos registradores TH0 e TL0 do Timer 0, visando gerar um overflow a cada aproximadamente 922 contagens (aproximadamente 1 ms).
- Para ficar mais simples na hora de escrever o programa que inicializa os registradores TH0 e TL0, esse valor deve ser convertido para hexadecimal: 64.614 = FC66H
- Os passos necessários para configurar e utilizar o Timer 0 como um temporizador de 1 ms são os seguintes:
- Configurar o Timer 0 no Modo 1 (timer/counter de 16 bits): TMOD = 0x01;
- Inicializar os registradores do Timer 0 para o atraso desejado de 1 ms: TH0 = 0xFC; e TL0 = 0x66;
- Iniciar o Timer 0 (disparar o temporizador): TR0 = 1;
- Usando polling ou interrupção, permanecer verificando se ocorreu overflow: TF0 == 1 ??
- Quando o bit TF0 do registrador TCON receber 1, isso significa que ocorreu um overflow (FFFFH -> 0000H), e se passou o tempo de 1 ms.
- Fazer TR0 = 0 (bit do registrador TCON), para garantir que a temporização de 1 ms ficará interrompida até a próxima rodada (até retornar ao passo 2).
- Se usar interrupção, o bit TF0 do registrador TCON irá receber 0 automaticamente, no momento do desvio para a rotina de tratamento de interrupção. Se usar polling, logo não vai haver desvio para a rotina de tratamento de interrupção, e o programa deverá conter uma instrução explícita de TF = 0.
- Quando ocorrer o overflow, precisa recarregar TH0 e TL0 com os valores necessários para gerar a temporização de 1 ms, ou seja, retornar ao passo 2.
- A rotina de atraso de 1 segundo deverá ser implementada de forma a executar os passos de 2 a 8 por 1.000 (mil) vezes, uma vez que esses passos foram definidos para gerar um atraso de 1 ms.
- Sugestão de solução com polling:
/* Descricao: Pisca LED com Timer usando polling Autor: Eduardo Augusto Bezerra Data: 12/07/2021 Instituicao: UFSC Entradas: Saidas: */ #include <reg51.h> void delay(unsigned int t); sbit P1_0 = P1^0; void main (void){ P0 = 0xFF; P1 = 0xFF; P2 = 0xFF; P3 = 0xFF; // Configuracao do Timer para geracao do atraso TMOD = 0x01; // Timer 0 no modo 1 while(1){ P1_0 = 1; delay(1000); P1_0 = 0; delay(1000); } } // Versao com Polling void delay(unsigned int t){ unsigned int i; for(i = 0; i < t; i++){ // Inicializa o timer para gerar temporizacao de 1 ms TH0 = 0xFC; TL0 = 0x66; TR0 = 1; // dispara a contagem while(TF0 != 1); // verifica overflow TR0 = 0; // Suspende o temporizador TF0 = 0; // Limpa o flag do temporizador } }
- Sugestão de solução com interrupção:
/* Descricao: Pisca LED com Timer usando interrupcao Autor: Eduardo Augusto Bezerra Data: 12/07/2021 Instituicao: UFSC Entradas: Saidas: */ #include <reg51.h> void delay(unsigned int t); void int_timer0 (void); unsigned char state = 0; sbit P1_0 = P1^0; void main (void){ P0 = 0xFF; P1 = 0xFF; P2 = 0xFF; P3 = 0xFF; // Configuracao do Timer para geracao do atraso TMOD = 0x01; // Timer 0 no modo 1 (temporizador de 16 bits) ET0 = 1; // Habilita interrupcao do Timer 0 EA = 1; // Habilita interrupcoes while(1){ P1_0 = 1; delay(1000); P1_0 = 0; delay(1000); } } void delay(unsigned int t){ unsigned int i; for(i = 0; i < t; i++){ // Inicializa o timer para gerar temporizacao de 1 ms TH0 = 0xFC; TL0 = 0x66; TR0 = 1; // dispara a contagem while(state != 1); // verifica overflow state = 0; TR0 = 0; // Suspende o temporizador // Nao precisa fazer TF = 0, pois isso foi feito automaticamente // ao desviar para ao tratador da interrupcao. } } // Tratador da interrupcao do Timer 0 void int_timer0 (void) interrupt 1 { state++; }