Manual

do

Maker

.

com

Configurar Timer0 do PIC como temporizador

Configurar Timer0 do PIC como temporizador

A utilização de timers é muito importante em MCUs e pode ser utilizado para diversos propósitos. Quando utilizando um clock mais preciso, auxilia na contagem de tempo para a execução de uma rotina; pode também mensurar tempo ou ser utilizado como contador, disparado a partir de uma interrupção. Vamos ver como configurar o timer0 do pic.

Nesse post vou exemplificar da forma mais simples de uso do TMR0 do PIC16F883 como temporizador.

Um pouco sobre PIC

PIC significa "Programmable Intelligent Computer" ou, "Computador Inteligente Programável". Tem uma variedade enorme de modelos e recursos, é uma MCU bastante conceituada mas não é exatamente para lazer, apesar de eu insistir em usá-lo para tal.

As séries são dividas em 10, 12, 16, 17, 18 e alguns mais. O 18 tem core de 16-bits, enquanto de 12 e 16 tem um core de 8-bits.

Normalmente ele é seguido por uma letra "C" ou "F". "C" OTP (One Time Programmable) e "F" é Flash, eletricamente reprogramável. Outra letra que tem aparecido é a "L", de LOW voltage. Essas controladoras normalmente variam de 1.8 à 3.6v. Mas apesar disso, outros PICs sem a letra "L" também podem operar em LOW voltage, como o próprio PIC16F883, que vai de 2.0v à 5.5v. Claro, para utilizá-lo em menor tensão é necessário configurar ou desabilitar o brown-out, que é um fusível pré-configurado para resetar a MCU em caso de queda de tensão (abaixo de 4.5v).

Configurando MCU

Alguns modelos de PIC tem oscilador interno e sempre prefiro utilizá-lo porque simplifica meus testes em protoboard. O PIC16F883 tem 2 osciladores internos, sendo um de 8MHz e o outro que vai até 31KHz. Já o PIC16F1827 tem um oscilador interno de 16MHz, uma verdadeira jóia!

O primeiro passo então é escolher o clock que a MCU irá operar, porque isso influenciará diretamente no cálculo do temporizador. Essa configuração é feita no registrador OSSCON, já explicado nesse post. No exemplo que seguirá, será utilizada a MCU com clock de 4MHz. Nesse caso, o registrador OSCCON ficou assim:

OSCCON = 0b01100101;

Eu fiz um temporizador para acender um LED a cada 10 segundos. A configuração do temporizador utilizando o TMR0 é feita através da configuração do OPTION_REG.

Vou explicar do bit 7 pra baixo:

RPBU

O RPBU é o resistor de pullup na PORTB. Passando o valor 1, os pullups da PORTB são desabilitados.

INTEDG

O bit 6 é a seleção de borda, para fazer a interrupção em LOW ou HIGH. Se 0, interrompe quando o valor está em baixa.

T0CS

Origem do clock. O exemplo utiliza clock interno, portanto, "0" (Fosc/4).

T0SE

Escolha de borda para o incremento do timer (não tem relação com a interrupção). Selecione 0 para incrementar em baixa.

PSA

Habilitação do prescaler. Quando em modo temporizador, deve ser utilizado.

PS2,PS1,PS0

Esses 3 bits são a seleção do prescaler. Não sei de cabeça, não se iluda com meu post; basta olhar no datasheet para saber os respectivos valores. Eu selecionei 1:4 para simplificar pra mim mesmo. Portanto, os valores atribuidos a esses bits são 001.

OPTION_REG

Você pode tanto ajustar apenas os bits diretamente (utilizando a MikroC IDE, seria algo como PS2_bit = 0) ou ajustar todos os bits do registrador de uma vez, em hexa ou binário:

OPTION\_REG = 0b10000001;

Cálculo do overflow

O TMR0 vai de 0 a 255 em sua contagem, portanto TMR0 é uma constante 256.
O tempo será representado por 't' aqui e o ciclo de máquina por 'ciclo' (Fosc/4). A fórmula do overflow é:

t = ciclo \* prescaler \* TMR0

Sendo ciclo = 4/4
No exemplo utilizado aqui com clock de 4MHz e prescaler de 1:4, o tempo será:

t = 1 \* 4 \* 256
t = 1ms

Os incrementos de segundo serão feitos na interrupção do TMR0, que deve ser limpo por software após a interrupção:

sbit TRIS\_LED at TRISC2\_bit;
sbit LED\_port at RC2\_bit;
unsigned count;
char secs = 0;

void interrupt(){
 GIE\_bit = 0;
 if (TMR0IF\_bit){ //overflow em 0-255
 TMR0 = 0;
 TMR0IF\_bit = 0;
 count++;
 }
 GIE\_bit = 1;
}
void main() {
 GIE\_bit = 1;
 PEIE\_bit = 1;
 TMR0IE\_bit = 1;
 
 TMR0 = 0;

 OPTION\_REG = 0b10000001; // 1:4
 //oscilador interno a 4MHz
 OSCCON = 0b01100101;
 TRIS\_LED = 0;
 TMR0 = 0;
 while(1){
 if (count > 999){ //se bateu 1 segundo... 
 secs++; //...incrementa
 if (secs>9){ //se for 10 segundos...
 LED\_port = !LED\_port; //inverte o estado da porta por 10 segundos
 secs=0;
 }
 count=0;
 }
 }
}


Em breve virá um post meio grande e discorrer a respeito de cada recurso individualmente permitirá reduzir o texto do que há por vir.

Espero que curta, Arduino também tem interrupções e compreendê-las aqui certamente lhe será útil, ainda que você só use Arduino.

Inscreva-se em nosso canal Dobitaobyte no Youtube!

Nome do Autor

Djames Suhanko

Autor do blog "Do bit Ao Byte / Manual do Maker".

Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.