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++;
}