Timers do ATmega328 no Arduino

timers do atmega328

Introdução

Temporização é fundamental quando se trabalha com circuitos microcontrolados, seja para um simples delay ou para geração de sinais ou eventos periódicos. Desde o mais simples microcontrolador sempre está disponível pelo menos um periférico temporizador/contator. Esse periférico possui hardware dedicado para contagem de tempo e o seu correto uso, auxilia em uma programação eficiente para realização de diversos projetos.

Neste artigo vamos explorar os recursos de um dos timers do ATmega328, o TIMER1, utilizado na plataforma Arduino, entendendo seu funcionamento e o uso de seus registradores.

Timers do ATmega328

O Atmega328, utilizado na placa Arduino UNO, possui 3 timers, sendo dois de 8 bits (TIMER0 e TIMER2) e um de 16 bits (TIMER1). Esses temporizadores são importantes para diversas funcionalidades, tais como: 

  • Temporização;
  • Contagem de eventos externos;
  • Geração de sinais PWM;
  • Interrupções periódicas;
  • Medida de intervalos de pulsos.

Cada temporizador possui características próprias e são utilizados conforme os recursos disponíveis. A biblioteca do Arduino abstrai o uso destes temporizadores em muitas de suas funções. Por exemplos, as funções delay(), millis(), micros(), tone(), analogWrite() utilizam recursos de timers para o funcionamento.

O TIMER1 é utilizado somente em algumas bibliotecas no Arduino específicas, podendo ser utilizado para outras finalidades sem causar muito impacto no funcionamento do restante das funções. A seguir serão apresentadas suas características.

TIMER 1

O TIMER1 é um temporizador de 16 bits que permite a contagem de eventos, geração de sinal PWM, medida de pulsos, etc. Seu diagrama de blocos, conforme apresentado no datasheet do ATmega328  é apresentado na figura 1:

Timers do ATmega328 - Diagrama de blocos do timer1
Figura 1 – Diagrama de blocos do TIMER 1 do ATmega328

Registradores


O controle do modo de operação do TIMER1 é feito nos registradores TCCR1A e TCCR1B, conforme descrição a seguir. 

Timers do ATmega328 - TCCR1A
Figura 2 – Registrador TCCR1A

Bits 7:6 – COM1A1:0: Compare Output Mode for Channel A

Bits 5:4 – COM1B1:0: Compare Output Mode for Channel B

COM1A1:0 e COM1B1:0 controlam os pinos de Output compare (OC1A e OC1B), respectivamente, conforme tabelas a seguir:

Tabela 1: Configuração para Modo não PWM

tabela 1 - configuração para modo não PWM

Tabela 2: Configuração para modo PWM rápido

tabela 2 - Configuração para modo PWM rápido

Tabela 3: configuração para modo PWM com correção de fase e frequência 

tabela 3 - Confiração para modo PWM com fase e frequencia

Bits 1:0 WGM11:0: Waveform Generation Mode

Juntos com os bits WGM13:2 encontrados no registrador TCCR1B, controlam o funcionamento do TIMER1, conforme tabela 4 a seguir:

Tabela 4: Modos de funcionamento do TIMER 1 

tabela 4 - Confiração do timer1
Figura 3 - Registrador TCCR1B

Bit 7 – ICNC1: Input Capture Noise Canceler

Bit para habilitar filtro de ruído no pino de captura ICP1.

Bit 6 – ICES1: Input Capture Edge Select

Seleciona qual borda no pino de entrada (ICP1) será usada para disparar evento de captura.

Bit 5 – Reserved

Bit reservado, deve ser escrito zero.

Bit 4:3 – WGM13:2: Waveform Generation Mode

Conforme apresentado anteriormente e exibido na tabela 4

Bit 2:0 – CS12:0: Clock Select

Bits para seleção de clock, conforme tabela 5

Tabela 5 – Configuração para seleção de clock

tabela 5 - seleção de clock

Conforme observado na figura 1, exitem outros registradores para funcionamento do TIMER1:

TCNT1H and TCNT1L – Timer/Counter1:

Resgistradores de armazenamento de contagem do timer.

OCR1AH and OCR1AL – Output Compare Register 1 A

OCR1BH and OCR1BL – Output Compare Register 1 B:

Registradores para comparação de contagem com o TCNT1. A igualdade pode gerar uma interrupção ou gera uma saída de onda nos pinos OC1A ou OC1B.

ICR1H and ICR1L – Input Capture Register 1:

Registradores para armazenamento de captura quando um evento ocorrer no pino ICP1.

TIMSK1 – Timer/Counter1 Interrupt Mask Register:

Registrador para habilitar as interrupções disponíveis no TIMER1.

TIFR1 – Timer/Counter1 Interrupt Flag Register

Registrador para flags de interrupções.

Para mais detalhes do funcionamento dos registradores, acesse o datasheet do ATmega328.

Utilizando o TIMER1  no Arduino

Modo Normal com interrupção por overflow

O exemplo a seguir exibe como piscar o LED no pino 13, da placa Arduino UNO, em intervalos de 1 segundo e utilizando interrupção por estouro timer: 

Nesse exemplo o timer foi configurado para modo normal, com pinos OC1A e OC1B desconectados (TCCR1A = 0). Foi selecionado o prescaler para 1024 através do registrador TCCR1B.  Para que o timer estoure a cada segundo é necessário iniciar seu valor com a diferença entre o seu valor máximo (65536) e o período desejado. O período é calculado levando em consideração a frequência do oscilador e o prescaler selecionado, além da frequência de interrupção desejada. Por fim foi habilitada a interrupção de estouro do TIMER1 através do bit T0IE1 do registrador TIMSK1. A inversão do LED é feita na rotina de interrupção, note que é necessário recarregar o timer para a correta contagem.

MODO CTC interrupção por comparação

O exemplo a seguir exibe como piscar o LED, utilizando o modo CTC e gerando interrupção por comparação: 

Nesse exemplo é utilizado o modo CTC, dessa forma o valor de contagem do timer é constantemente comparado com o registrador OCR1A. Para o funcionamento foi selecionado o modo CTC, bit WGM12 = 1 e configurado o prescaler para 1024. O valor de comparação foi carregado no registrador OCR1A e por último foi habilitada a interrupção de comparação. A inversão do LED é feita na rotina de interrupção, e note que não é necessário reiniciar o timer com um valor, pois o modo CTC zera o timer quando atingido valor de comparação.

Está disponível no sites do Arduino uma biblioteca para manipulação do TIMER1. Essa biblioteca abstrai todas as configurações dos registradores facilitando o uso do TIMER1.

Saiba Mais sobre Arduino

Arduino UNO

Arduino – Entradas/Saídas digitais

Acionamento de uma lâmpada com Arduino

Saiba mais sobre Timers

Sistemas Operacionais de Tempo Real – Timers

Biblioteca de Soft Timers

Website | Veja + conteúdo

Engenheiro, especialista em sistemas embarcados. Hoje é diretor de operações do portal Embarcados, onde trabalha para levar conteúdos de eletrônica, sistemas embarcados e IoT para o Brasil.

Também atua no ensino eletrônica e programação. É entusiastas do movimento maker, da cultura DIY e do compartilhamento de conhecimento, publica diversos artigos sobre eletrônica e projetos open hardware.

Com iniciativas como o projeto Franzininho e projetos na área de educação, leva a cultura maker para o Brasil capacitando e incentivando professores e alunos a usarem tecnologia em suas vidas. Participou da residência hacker 2018 no Red Bull Basement.

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Comentários:
Notificações
Notificar
guest
7 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
Geraldo
Geraldo
12/01/2021 23:27

Caro professor,estou usando o Arduíno Uno 328 e duas pontes H 43a em um projeto utilizando 2 motores DC24 volts,minha dúvida,é possível eliminar um ruido tipo(tuuuuuuuuuuuu) nos motores?Qual tipo de filtro posso utilizar?Pelo visto este ruido é provocado pelo PWM.Fiz a leitura pelo frequencímetro na saída das pontes,obtive uma leitura de 49 a 50 hz.

Geraldo
Geraldo
Reply to  Fábio Souza
13/01/2021 14:49

Muito obrigado professor,eu não sabia desta modalidade,e vou procurar fazer esta modificação.Agradeço muito pela atenção.Um forte abraço.Gratidão.

DEIVID MACHADO AMARAL
Deivid
13/02/2018 16:52

Estou tentando usar o timer 0 e ele não aceita o TIMER0_OVF_vect tentei mudar para timer 0 e alterar os valores para 8 bits porém não consegui.

HenriqueMartins
HenriqueMartins
20/01/2018 23:15

Boa Noite! tenho algumas dúvidas: 1 – no seu código não precisou habilitar as interrupções globais com “sei()”? por que? 2 – no arduino, o fuse BOOTRST está habilitado. Então os vetores das interrupções seriam deslocados para o início da sessão de bootloader na memória de programa. Isso implica que o bit IVSEL no MCUCR deveria estar setado para que as interrupções ocorram nos endereços corretos. Por que no seu código não precisou? OBS.: Estou tendo muitos problemas ao utilizar interrupções do timer no arduino. Já tentei com e sem as opções citadas por mim acima. Se me forem sanadas… Leia mais »

Talvez você goste:

Séries

Menu