Índice:

Microcontrolador AVR. LEDs pisca-pisca usando temporizador. Interrupções dos temporizadores. Modo CTC do temporizador: 6 etapas
Microcontrolador AVR. LEDs pisca-pisca usando temporizador. Interrupções dos temporizadores. Modo CTC do temporizador: 6 etapas

Vídeo: Microcontrolador AVR. LEDs pisca-pisca usando temporizador. Interrupções dos temporizadores. Modo CTC do temporizador: 6 etapas

Vídeo: Microcontrolador AVR. LEDs pisca-pisca usando temporizador. Interrupções dos temporizadores. Modo CTC do temporizador: 6 etapas
Vídeo: Programação do Arduino Due em C - Microcontrolador SAM3X8E 2024, Junho
Anonim
Image
Image

Olá pessoal!

Timers é um conceito importante no campo da eletrônica. Cada componente eletrônico funciona em uma base de tempo. Essa base de tempo ajuda a manter todo o trabalho sincronizado. Todos os microcontroladores funcionam em alguma frequência de clock predefinida, todos eles têm uma provisão para configurar temporizadores. AVR se orgulha de ter um cronômetro muito preciso, preciso e confiável. Ele oferece muitos recursos, tornando-o um tópico vasto. A melhor parte é que o timer é totalmente independente da CPU. Assim, ele funciona em paralelo à CPU e não há intervenção da CPU, o que torna o cronômetro bastante preciso. Nesta seção, explico os conceitos básicos dos temporizadores AVR. Estou escrevendo um programa simples em código C para controlar pisca-pisca de LED, usando temporizadores.

Etapa 1: Descrição

Declaração do problema 1: Vamos piscar primeiro LED (verde) a cada 50 ms
Declaração do problema 1: Vamos piscar primeiro LED (verde) a cada 50 ms

No ATMega328, existem três tipos de temporizadores:

Timer / Counter0 (TC0) - é um módulo de temporizador / contador de 8 bits de uso geral, com duas unidades OutputCompare independentes e suporte PWM;

Timer / Counter1 (TC1) - A unidade Timer / Counter de 16 bits permite o tempo preciso de execução do programa (gerenciamento de eventos), a geração de ondas e a medição do tempo do sinal;

Temporizador / Contador2 (TC2) - é um módulo de temporizador / contador de 8 bits de canal, de uso geral com PWM e operação assíncrona;

Etapa 2: Declaração do problema 1: Vamos piscar primeiro LED (verde) a cada 50 ms

Declaração do problema 1: Vamos piscar primeiro LED (verde) a cada 50 ms
Declaração do problema 1: Vamos piscar primeiro LED (verde) a cada 50 ms
Declaração do problema 1: Vamos piscar primeiro LED (verde) a cada 50 ms
Declaração do problema 1: Vamos piscar primeiro LED (verde) a cada 50 ms

Metodologia:

- usando um prescaler Timer0 para reduzir um sinal elétrico de alta frequência para uma frequência mais baixa por divisão inteira;

- usando uma interrupção toda vez que o Timer0 transborda;

Timer0 (8 bits) conta de 0 a 255 depois disso, eles transbordam, este valor muda a cada pulso de clock.

F_CPU = 16MHz: Período de tempo do relógio = 1000ms / 16000000Hz = 0,0000625ms

Contagem do temporizador = (atraso necessário / período de tempo do relógio) -1 = (50ms / 0,0000625ms) = 799999

O relógio já marcou 799999 vezes para dar um atraso de apenas 50 ms!

Podemos usar a técnica de divisão de frequência chamada pré-escala para diminuir a contagem do temporizador. O AVR nos oferece os seguintes valores de prescaler para escolher: 8, 64, 256 e 1024. Veja a tabela que resume os resultados do uso de diferentes prescalers.

O valor do contador deve ser sempre um número inteiro. Vamos escolher um prescaler 256!

Na maioria dos microcontroladores, existe algo chamado Interromper. Esta interrupção pode ser disparada sempre que certas condições forem atendidas. Agora, sempre que uma interrupção é disparada, o AVR para e salva sua execução da rotina principal, atende a chamada de interrupção (executando uma rotina especial, chamada de Rotina de Serviço de Interrupção, ISR) e uma vez feito com ela, retorna ao rotina principal e continua a executá-la.

Como o atraso necessário (50ms) é maior do que o atraso máximo possível: 4, 096ms = 1000ms / 62500Hz * 256, obviamente o temporizador irá estourar. E sempre que o temporizador estourar, uma interrupção é disparada.

Quantas vezes a interrupção deve ser disparada?

50ms / 4,096ms = 3125/256 = 12,207 Se o cronômetro estourou 12 vezes, 12 * 4,096ms = 49,152ms teriam passado. Na 13ª iteração, precisamos de um atraso de 50ms - 49,152ms = 0,848ms.

A uma frequência de 62500Hz (prescaler = 256), cada tick leva 0,016ms. Assim, para atingir um atraso de 0,848ms, seriam necessários 0,848ms / 0,016ms = 53 ticks. Assim, na 13ª iteração, permitimos apenas que o cronômetro conte até 53 e, em seguida, o zeramos.

Inicializar Timer0 / Contador (ver foto):

TCCR0B | = (1 << CS02) // configurar temporizador com prescaler = 256 TCNT0 = 0 // inicializar contador TIMSK0 | = (1 << TOIE0) // habilitar interrupção de estouro sei () // habilitar interrupções globais tot_overflow = 0 // inicializa a variável do contador de estouro

Etapa 3: Declaração do Problema 2: Vamos piscar o segundo LED (azul) a cada 1s

Declaração do problema 2: Vamos piscar o segundo LED (azul) a cada 1s
Declaração do problema 2: Vamos piscar o segundo LED (azul) a cada 1s
Declaração do problema 2: Vamos piscar o segundo LED (azul) a cada 1s
Declaração do problema 2: Vamos piscar o segundo LED (azul) a cada 1s
Declaração do problema 2: Vamos piscar o segundo LED (azul) a cada 1s
Declaração do problema 2: Vamos piscar o segundo LED (azul) a cada 1s

Metodologia:

- usando um prescaler Timer1 para reduzir um sinal elétrico de alta frequência para uma frequência mais baixa por divisão inteira;

- usando o modo Clear Timer on Compare (CTC);

- usando interrupções com modo CTC;

Timer1 (16 bits) conta de 0 a 65534 depois disso, eles estouram. Este valor muda a cada pulso do clock.

F_CPU = 16MHz: Período de tempo do relógio = 1000ms / 16000000Hz = 0,0000625msContagem do temporizador = (Atraso necessário / Período de tempo do relógio) -1 = (1000ms / 0,0000625ms) = 15999999

O relógio já marcou 15999999 vezes para dar um atraso de 1s!

Podemos usar a técnica de divisão de frequência chamada pré-escala para diminuir a contagem do temporizador. O AVR nos oferece os seguintes valores de prescaler para escolher: 8, 64, 256 e 1024. Veja a tabela que resume os resultados do uso de diferentes prescalers. O valor do contador deve ser sempre um número inteiro. Vamos escolher um prescaler 256!

No modo Clear timer on Compare (CTC), o registro OCR1A ou ICR1 é usado para manipular a resolução do contador. No modo CTC, o contador é zerado quando o valor do contador (TCNT1) corresponde ao OCR1A ou ao ICR1. O OCR1A ou o ICR1 definem o valor máximo do contador e, portanto, também sua resolução. Este modo permite maior controle da frequência de saída de comparação. Ele também simplifica a operação de contagem de eventos externos. Devemos dizer ao AVR para zerar o Timer1 / Contador assim que seu valor atingir o valor 62500, para atingir um atraso de 1s.

Inicializar Timer1 / Contador (ver foto):

TCCR1B | = (1 << WGM12) | (1 << CS12) // configurar temporizador com prescaler = 256 e modo CTC TCNT1 = 0 // inicializar contador TIMSK1 | = (1 << OCIE1A) // ativar interrupção de comparação OCR1A = 62500 // inicializa o valor de comparação

Etapa 4: Declaração do problema 3: vamos piscar o terceiro LED (vermelho) a cada 16 ms

Declaração do problema 3: Vamos piscar o terceiro LED (vermelho) a cada 16 ms
Declaração do problema 3: Vamos piscar o terceiro LED (vermelho) a cada 16 ms
Declaração do problema 3: Vamos piscar o terceiro LED (vermelho) a cada 16 ms
Declaração do problema 3: Vamos piscar o terceiro LED (vermelho) a cada 16 ms
Declaração do problema 3: Vamos piscar o terceiro LED (vermelho) a cada 16 ms
Declaração do problema 3: Vamos piscar o terceiro LED (vermelho) a cada 16 ms
Declaração do problema 3: Vamos piscar o terceiro LED (vermelho) a cada 16 ms
Declaração do problema 3: Vamos piscar o terceiro LED (vermelho) a cada 16 ms

Metodologia:

- usando um prescaler Timer2 para reduzir um sinal elétrico de alta frequência para uma frequência mais baixa por divisão inteira;

- usando o modo Clear Timer on Compare (CTC);

- usando o modo CTC de hardware sem interrupções;

Timer2 (8 bits) conta de 0 a 255 depois disso, eles transbordam. Este valor muda a cada pulso do clock.

F_CPU = 16MHz: Período de tempo do relógio = 1000ms / 16000000Hz = 0,0000625ms

Contagem do temporizador = (atraso necessário / período de tempo do relógio) -1 = (16ms / 0,0000625ms) = 255999

O relógio já marcou 255999 vezes para dar um atraso de 16 ms!

Veja a tabela que resume os resultados do uso de diferentes prescalers. O valor do contador deve ser sempre um número inteiro. Vamos escolher um prescaler 1024!

No modo CTC, o contador é zerado quando o valor do contador (TCNT2) corresponde ao OCR2A ou ao ICR2. O pino PB3 também é o pino de comparação de saída de TIMER2 - OC2A (consulte o diagrama).

Registro de controle do temporizador / contador2 A - TCCR2A Bit 7: 6 - COM2A1: 0 - Modo de comparação de saída para a unidade de comparação A. Como precisamos alternar o LED, escolhemos a opção: Alternar OC2A na comparação de comparação Sempre que ocorrer uma correspondência de comparação, o O pino OC2A é alternado automaticamente. Não há necessidade de verificar nenhum bit de bandeira, não há necessidade de atender a quaisquer interrupções.

Inicializar Timer2 / Contador

TCCR2A | = (1 << COM2A0) | (1 << WGM21) // configurar o pino OC2A do temporizador no modo alternar e modo CTC TCCR2B | = (1 << CS22) | (1 << CS21) | (1 << CS20) // configurar o temporizador com prescaler = 1024 TCNT2 = 0 // inicializar o contador OCR2A = 250 // inicializar o valor de comparação

Etapa 5: Escrevendo código para um programa em C. Carregando o arquivo HEX na memória Flash do microcontrolador

Escrevendo código para um programa em C. Carregando o arquivo HEX na memória Flash do microcontrolador
Escrevendo código para um programa em C. Carregando o arquivo HEX na memória Flash do microcontrolador
Escrevendo código para um programa em C. Carregando o arquivo HEX na memória Flash do microcontrolador
Escrevendo código para um programa em C. Carregando o arquivo HEX na memória Flash do microcontrolador

Escrita e construção da aplicação do microcontrolador AVR em Código C utilizando a Plataforma de Desenvolvimento Integrada - Atmel Studio.

F_CPU define a frequência do clock em Hertz e é comum em programas que usam a biblioteca avr-libc. Nesse caso, ele é usado pelas rotinas de atraso para determinar como calcular os atrasos de tempo.

#ifndef F_CPU

#define F_CPU 16000000UL // informando a frequência de cristal do controlador (16 MHz AVR ATMega328P) #endif

#include // cabeçalho para habilitar o controle do fluxo de dados sobre os pinos. Define pinos, portas, etc.

O primeiro arquivo de inclusão é parte do avr-libc e será usado em praticamente qualquer projeto AVR em que você trabalhar. io.h determinará a CPU que você está usando (é por isso que você especifica a parte ao compilar) e, por sua vez, inclui o cabeçalho de definição de IO apropriado para o chip que estamos usando. Ele simplesmente define as constantes para todos os seus pinos, portas, registros especiais, etc.

#include // cabeçalho para habilitar a interrupção

volatile uint8_t tot_overflow; // variável global para contar o número de transbordamentos

Metodologia de declaração do problema: LED pisca primeiro (verde) a cada 50 ms

- usando um prescaler Timer0 para reduzir um sinal elétrico de alta frequência para uma frequência mais baixa por divisão inteira;

- usando uma interrupção toda vez que o Timer0 transborda;

void timer0_init () // inicializar timer0, interrupção e variável

{TCCR0B | = (1 << CS02); // configura o temporizador com prescaler = 256 TCNT0 = 0; // inicializa o contador TIMSK0 | = (1 << TOIE0); // habilita o estouro nterrupt sei (); // habilita interrupções globais tot_overflow = 0; // inicializar a variável do contador de estouro}

Metodologia de declaração do problema: flash segundo LED (azul) a cada 1s

- usando um prescaler Timer1 para reduzir um sinal elétrico de alta frequência para uma frequência mais baixa por divisão inteira;

- usando o modo Clear Timer on Compare (CTC);

- usando interrupções com modo CTC;

void timer1_init () // inicializa o timer1, interrupção e variável {TCCR1B | = (1 << WGM12) | (1 << CS12); // configura o temporizador com prescaler = 256 e modo CTC TCNT1 = 0; // inicializa o contador OCR1A = 62500; // inicializa o valor de comparação TIMSK1 | = (1 << OCIE1A); // ativa a interrupção de comparação}

Metodologia de declaração do problema: Piscar o terceiro LED (vermelho) a cada 16 ms

- usando um prescaler Timer2 para reduzir um sinal elétrico de alta frequência para uma frequência mais baixa por divisão inteira;

- usando o modo Clear Timer on Compare (CTC);

- usando o modo CTC de hardware sem interrupções;

void timer2_init () // inicializa o timer2 {TCCR2A | = (1 << COM2A0) | (1 << WGM21); // configura o pino OC2A do temporizador no modo de alternância e no modo CTC TCCR2B | = (1 << CS22) | (1 << CS21) | (1 << CS20); // configura o temporizador com prescaler = 1024 TCNT2 = 0; // inicializa o contador OCR2A = 250; // inicializa o valor de comparação}

Rotina de serviço de interrupção de estouro de TIMER0 chamada sempre que TCNT0 estourar:

ISR (TIMER0_OVF_vect)

{tot_overflow ++; // manter um controle do número de transbordamentos}

Este ISR é disparado sempre que ocorre uma correspondência, portanto, alternar o próprio LED aqui:

ISR (TIMER1_COMPA_vect) {PORTC ^ = (1 << 1); // alternar conduzido aqui}

int main (vazio)

{DDRB | = (1 << 0); // conecte 1 led (verde) ao pino PB0 DDRC | = (1 << 1); // conecta 2 led (azul) ao pino PC1 DDRB | = (1 << 3); // conecta o LED 3 (vermelho) ao pino PB3 (OC2A) timer0_init (); // inicializa timer0 timer1_init (); // inicializa o timer1 timer2_init (); // inicializa o temporizador2 enquanto (1) // faz um loop para sempre {

Se o Timer0 estourou 12 vezes, 12 * 4,096ms = 49,152ms teriam passado. Na 13ª iteração, precisamos de um atraso de 50ms - 49,152ms = 0,848ms. Assim, na 13ª iteração, permitimos apenas que o cronômetro conte até 53 e, em seguida, o zeramos.

if (tot_overflow> = 12) // verifique se não. de overflows = 12 NOTA: '> =' é usado

{if (TCNT0> = 53) // verifique se a contagem do cronômetro atinge 53 {PORTB ^ = (1 << 0); // alterna o led TCNT0 = 0; // redefine o contador tot_overflow = 0; // redefinir o contador de estouro}}}}

Carregando o arquivo HEX na memória flash do microcontrolador:

digite na janela do prompt do DOS o comando:

avrdude –c [nome do programador] –p m328p –u –U flash: w: [nome do arquivo hexadecimal] No meu caso é: avrdude –c ISPProgv1 –p m328p –u –U flash: w: Timers.hex

Este comando grava o arquivo hexadecimal na memória do microcontrolador. Assista ao vídeo com uma descrição detalhada da gravação da memória flash do microcontrolador:

Gravando memória flash do microcontrolador …

OK! Agora, o microcontrolador funciona de acordo com as instruções do nosso programa. Vamos dar uma olhada!

Etapa 6: Fazendo o circuito elétrico

Fazendo o circuito elétrico
Fazendo o circuito elétrico
Fazendo o circuito elétrico
Fazendo o circuito elétrico
Fazendo o circuito elétrico
Fazendo o circuito elétrico

Conecte os componentes de acordo com o diagrama esquemático.

Recomendado: