ÍNDICE DE CONTEÚDO
Os timers são periféricos muito importantes nos microcontroladores. Podemos usá-los para temporização, contagem de eventos, PWM, medir pulsos externos, etc. O ATtiny85 possui 2 timers, chamados de Timer0 e Timer1. Nesse exemplos vamos focar no uso do Timer0 como temporizador.
Características do Timer0
O Timer0 é um módulo temporizador/contador de 8 bits de uso geral. Isso significa que ele pode contar de 0 a 255. A funcionalidade de temporização pode ser estendida ainda mais usando os periféricos de comparação, que permitem que o temporizador conte eventos, gere sinais PWM e assim por diante. Assim é possível gerar temporizações precisas, ondas e sinais PWM independentes da CPU.
A figura a seguir exibe o diagrama de blocos simplificado do Timer0:
Resumo de recursos do Timer0
- Duas unidades de comparação de saída independentes;
- Registradores de comparação de saída com buffer duplo;
- Limpa cronômetro na comparação de correspondência (recarregamento automático);
- Modulador de largura de pulso com correção de fase (PWM) livre de glitch;
- Período PWM variável;
- Gerador de frequência;
- Três fontes de interrupção independentes (TOV0, OCF0A e OCF0B);
Usando o Timer0 como temporizador
Nesse exemplos vamos usar o Timer0 para gerar um delay de 1s para piscar um LED.
Recursos necessários
- Placa Franzininho DIY(com Micronucleus)
- LED
- Resistor 470 Ohms
- Jumpers
- Computador com as ferramentas de software instaladas
Passos para configurar o Timer0 como temporizador
Passo 1: Configurar o Timer0 para trabalhar no modo normal. Nesse modo o timer iniciará a contagem em 0 e irá até máximo de 255. Quando atingido o máximo é gerado um flag de sinalização de overflow e o timer volta a contar a partir do zero.
Para configurar o modo de operação normal, devemos configurar o registrador TCCR0A – Timer/Counter Control Register A da seguinte forma:
- COM0A[1:0] e COM0B[1:0] = 0
- WGM0[1:0] = 0 e TCCR0B – WGM02 = 0
Deve-se escrever o seguinte valor em TCCR0A – Timer/Counter Control Register A:
TCCR0A = 0b00000000;
Passo 2: Ajustar o prescaler do clock interno para 1024:
Para ajustar o prescale precisamos configurar os bits CS02,CS01 e CS00 do TCCR0B:
- TCCR0B – CS0[2:0]
Deve-se escrever o seguinte valor em TCCR0B – Timer/Counter Control Register B:
TCCR0B = 0b00000101;
Calculo do delay
Estamos trabalhando com o clock interno do ATtiny85 em 16.5Mhz. Essa é a fonte de clock para o Timer0 em modo de operação normal. Como selecionamos o prescaler para dividir o clock por 1024, temos o incremento do timer0 em:
- tempo por incremento do Timer0 = 1/(16.5M/1024) = 62 us
Assim, o tempo para o Timer0 estourar (overflow) é:
- tempo para o Timer0 estourar = 62us x 256 = 15,89ms
Portanto, para ter um delay de 1 segundo precisamos ter:
- quantidade de overflows do timer0 = 1/15,89ms ≃ 63 vezes
Passos para monitorar o overflow do timer e gerar o delay de 1s
- Passo 0: Colocar TCNT0 em zero.
- Passo 1: Aguardar a contagem do Timer0 verificando quando TOV0 vai para 1.
- Passo 2: Limpar a flag TOV0 escrevendo 1 nela (Isso mesmo escrevendo 1).
- Passo 3: Repetir passos 1 e 2, 63 vezes para atingir 1 segundo.
- Passo 4: Passou um segundo – Inverter LED
Código exemplo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
/** * * @file main.c * @author Fábio Souza * @brief Exibe como usar o timer zero para temporização * @version 0.1 * @date 2021-02-13 * * @copyright Franzininho * This example code is in the Public Domain (or CC0 licensed, at your option.) * Unless required by applicable law or agreed to in writing, this * software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. * */ #include <avr/io.h> #include <util/delay.h> #define F_CPU 16500000L #define setBit(valor,bit) (valor |= (1<<bit)) #define clearBit(valor,bit) (valor &= ~(1<<bit)) #define toogleBit(valor,bit) (valor ^= (1<<bit)) #define testBit(valor,bit) (valor & (1<<bit)) /** * @brief Função main * * @return int */ int main(void) { unsigned char tempo = 0; //contador auxiliar setBit(DDRB,PB1); // Configura Pino PB1 como saída (Pino do LED) //configuração do timer0 para overflow a aproximadamente 15,89 ms //t = (1/16.5Mhz) x 1024 x 256 = 15,89 ms TCCR0A=0x00; //Modo Normal TCCR0B=0x00; TCCR0B |= (1<<CS00)|(1<<CS02); //prescaler de 1024 TCNT0=0; //inicia timer com 0 /** * @brief loop infinito * */ while (1) { if(testBit(TIFR,TOV0)) //se timer estourou { setBit(TIFR,TOV0); //limpa flag tempo++; //incrementa contador auxiliar if(tempo >=63) //se passaram-se 63 x 15,89 ms = 1 s { toogleBit(PORTB,PB1); //inverte LED tempo = 0; //reinicia contador } } } return (0); } |
Simulação do exemplo
O exemplo acima pisca o LED em intervalos de 1s. Fizemos a configuração do Timer0 para operar no modo normal e com divisor de 1024. Para gerar o delay de 1s foi necessário obter 63 overflows. Após as 63 contagens de overflow é invertido o valor do PORTB1, que está ligado o LED. A configuração do pino PB1 como saída foi feito colocando o bit1 de DDRB em 1.
Projeto disponível em: https://github.com/Franzininho/exemplos-avr-libc
Parabéns pelo desenvolvimento.