Plano de Aula. 1 o semestre. Aula número 009 Interrupções. Fazer uso das interrupções externas no Arduíno

Documentos relacionados
Plano de Aula. 1 o semestre. Aula número 010 Interrupções Internas Timers. Uso de interrupções internas produzidas pelos timers

Atividade de laboratório 004. Prof: Carlos Eduardo de Brito Novaes 6 de maio de Alunos RA Nome Curso Semestre

Atividade de laboratório 003. Prof: Carlos Eduardo de Brito Novaes 29 de abril de Alunos RA Nome Curso Semestre

Plano de Aula. 1 o semestre. Aula número 012 Periféricos Comunicação Serial. Conhecer os princípios de comunicação serial

Plano de Aula. 1 o semestre. Cronômetro Interrupções, Timers. Utilizar interrupções para criar um cronômetro com parciais

Lista de Exercícios A2

Atividade de laboratório 005. Prof: Carlos Eduardo de Brito Novaes 20 de maio de Alunos RA Nome Curso Semestre

Atividade de laboratório 001. Prof: Carlos Eduardo de Brito Novaes 18 de março de Alunos RA Nome Curso Semestre

Arquitetura Von Neumann Dados e instruções são obtidos da mesma forma, simplificando o desenho do microprocessador;

Descrição dos pinos de entrada e saída e de funções especiais. Descrição dos modos de acesso: individual e por porto

Plano de Aula. 1 o semestre. Aula número 011 Periféricos Display LCD, Conversor AD e conversor DA (PWM)

Atividade de laboratório 007. Prof: Carlos Eduardo de Brito Novaes 10 de junho de Alunos RA Nome Curso Semestre

Atividade de laboratório 002. Prof: Carlos Eduardo de Brito Novaes 1 de abril de Alunos RA Nome Curso Semestre

Microprocessadores TIMER/COUNTER I

SEL 0415 INTROD. À ORGANIZAÇÃO DE COMPUTADORES

Introdução. O que é o Arduino?

Microcontroladores. Interrupções no Prof. Guilherme Peron Prof. Heitor S. Lopes Prof. Ronnier Rohrich Prof. Rubão

Microprocessadores e Microcontroladores. Professor Lucas Araujo do Nascimento

Organização de Memórias

Curso introdutório de microcontroladores - Plataforma Arduino

Projeto 01. Adriano Joaquim de Oliveira Cruz Instituto de Matemática UFRJ 2015 Adriano Cruz. 30 de agosto de 2015

- Tarefas Práticas de Programação usando Arduino - Imagem do Robô com Legendas

MINICURSO ARDUINO BÁSICO

Aula 1 Apresentação e Conceitos Iniciais. Wellington Cássio Faria fb.com/wellingtoncf

AULA 6 - INTRODUÇÃO AO ARDUINO Revisão de Eletrônica Digital e introdução aos Sistemas Computacionais.

Controladores do IBM-PC. Gustavo G. Parma

LABORATÓRIO DE ARQUITETURA DE COMPUTADORES PREPARAÇÃO 03: INTERRUPÇÕES

Arduino - Primeiros Passos

Prof. Adilson Gonzaga

Arduino. Gilmar Aquino

Mundo Arduino: Vamos começar a programar?

Lista de Exercícios A1

Microcontroladores. Contadores e Temporizadores. Prof. Guilherme Peron Prof. Heitor S. Lopes Prof. Ronnier Rohrich Prof. Rubão

Disciplina: Laboratório de Fis26

Enviando Dados Pela Porta Serial na placa LaunchPad MSP430 Utilizando o ambiente ENERGIA

Robótica com Arduino Professor: Paulo Marcos Trentin

Programação do Arduino. Parte 1. IDE Wiring

UTFPR Departamento Acadêmico de Eletrônica Curso Técnico em Eletrônica Microcontroladores 1 - Prof. Cion nov/2010 (atualizado em jul 2015)

Interrupção. Prof. Adilson Gonzaga

INTRODUÇÃO AO ARDUINO DUE, CANAL DIGITAL, FUNÇÃO DELAY

Interrupções. O que é uma interrupção? Como funciona uma interrupção no AVR?

Revisão da Linguagem C Prof. Evandro L. L. Rodrigues

Nível da Arquitetura do Conjunto das Instruções

Sistemas Embarcados:

Acetatos de apoio às aulas teóricas

Universidade Federal Fluminense - UFF Escola de Engenharia - TCE Curso de Engenharia de Telecomunicações - TGT

Plano de Trabalho Docente Ensino Técnico

OFICINA Uso da plataforma Arduino no Ensino de Ciências

Introdução à Plataforma ARDUINO

1º minicurso de Arduino no IFUSP 4 a 22 de maio de 2015 Prof. Alexandre Suaide

- Trabalho Prático de Algoritmos e Programação usando Robô Arduino -

PCS-2529 Introdução aos Processadores. Prof. Dr. Paulo Sérgio Cugnasca

ARDUINO BÁSICO E T A P A 1 O QUE É ARDUINO? Prof. Amadeu Zanon Neto

ALGORITMOS, ARQUITETURA E ARDUINO

ROBÓTICA 1 INTRODUÇÃO A PROGRAMAÇÃO NO ARDUINO

Microcontroladores PROF. ME. HÉLIO ESPERIDIÃO

Microprocessadores CPU. Unidade de Controle. Prof. Henrique

SEL-614 MICROPROCESSADORES E APLICAÇÕES. Adilson Gonzaga

CANAL ANALÓGICO

Sistemas Operacionais de Tempo Real - Teclados Matriciais

Programação em Linguagem C

Sistemas Reativos. Interrupções em microcontroladores (baseado no Atmega328p Arduino Uno)

Interrupções 8051 Porta Serial

Ex.: Rotinas de tempo

Anatomia do Arduino Bootloader

Plano de Trabalho Docente Ensino Técnico

Projeto No. 19 Contador Binário com Chave Rotativa

Tutoriais PET-Tele. Introdução à Amostragem de Sinais com o kit Arduino (Versão: A2016M06D21)

1.2 Registradores relacionados as Interrupções. 3. TOSE Sentido da transição da borda do sinal aplicado am TMR0

Universidade Federal de Campina Grande Unidade Acadêmica de Sistemas e Computação Curso de Bacharelado em Ciência da Computação.

of Arduino Slide: Bruno Aricó

Por Fernando Koyanagi 1

Lista de Exercícios 2

Introdução ao Arduino ESCOLA DE ARTES VISUAIS DO PARQUE LAGE. Núcleo de Arte e Tecnologia. julio lucio martin. Aula 01

Estrutura Básica da Linguagem Arduino

ENG-1450 Microcontroladores e Sistemas Embarcados. Lab02 Apresentação Kit PicGenios Interrupção e Timers

Capítulo 14. Expandindo as portas de comunicação 8031 com a PPI Interface PPI 8255

Programação Básica em Arduino Aula 2

Lista de Exercícios 1

Temporização da CPU SEL-433 APLICAÇÕES DE MICROPROCESSADORES I. Ciclos de Máquina. Ciclos de Máquina. Temporização Interrupções Rotinas de Atraso

29/03/2017. Temporização da CPU SEL-433 APLICAÇÕES DE MICROPROCESSADORES I. Ciclos de Máquina. Ciclos de Máquina

Sensor óptico em quadratura: leitura via Arduino

Temporização Interrupções. Prof: Evandro L. L. Rodrigues. Rotinas de Atraso

Comunicação Serial II. Prof. Clayrton Henrique Microprocessadores Aula 31 Rev.03

EXPERIÊNCIA 5: IMPLEMENTAÇÃO DE UM CRONÔMETRO COM INTERRUPÇÃO

O que você pode fazer com o Arduino

Arduino. Conectores, Fonte, USB, LEDs. Compilador, Bibliotecas, Editor, Burner

SSC510 Arquitetura de Computadores 1ª AULA

LABORATÓRIO DE PROCESSAMENTO DIGITAL DE SINAIS II. Filtros FIR utilizando matlab e arduino duo LAB 1 (LPF)

Aula 10 Microcontrolador Intel 8051 Parte 1

INTRODUÇÃO: MICROCONTROLADORES

ELE Microprocessadores I

14/3/2016. Prof. Evandro L. L. Rodrigues

Laboratório de Microprocessadores e Microcontroladores

Acendendo o Led com Arduino.

Oficina de Programação utilizando a plataforma Arduino

Plano de Trabalho Docente Ensino Técnico

Transcrição:

Diretoria de Curso Plano de Aula 1 o semestre Nome do curso Eng. Ciências da Computação + TI + TADS + Eng. Elétrica Nome da Unidade Curricular Microprocessadores e Microcontroladores Aula número 009 Tema Interrupções Período Turma Noturno Tópicos O que são interrupções Uso de interrupções no Arduíno Objetivos Compreender o que são e para que servem as interrupções em um sistema microprocessado Fazer uso das interrupções externas no Arduíno Habilidades Utilização das rotinas de configuração das interrupções externas Aplicação prática, leitura de um encoder incremental Bases Tecnológicas Plataforma online 123d.circuits.io 1

Recomendada Bibliografia Primeiros passos com o Arduíno - Massimo Banzi e Michael Shiloh Microcontrolador 8051 Detalhado - Denys E. C. Nicolosi Parte II - Capítulo 6 Documentação oficial do Arduíno https://www.arduino.cc/en/reference/attachinterrupt https://www.arduino.cc/en/reference/detachinterrupt https://www.arduino.cc/en/reference/interrupts https://www.arduino.cc/en/reference/nointerrupts 2

1 Interrupções Interrupção é um evento, externo ou interno ao microcontrolador, que o obriga a suspender temporariamente suas atividades para atender a este evento que o interrompe. Toda vez que uma interrupção ocorre, o microprocessador irá se desviar para outra parte do código, o chamado serviço de interrupção, adequado para tratar a interrupção gerada. Após completar a execução do serviço de interrupção (que costuma ser um trecho de código bem pequeno e rápido), o microprocessador deve voltar para o código que executava antes de ser interrompido. Repare que a chamada ao serviço de interrupção é semelhante à chamada a uma função ou sub-rotina comum, a grande diferença esta no fato de que uma interrupção não é um evento previsto. Uma analogia válida é pensar no trabalho em escritório para compreender como funcionam as interrupções. Suponha que você esteja trabalhando em uma determinada tarefa A e em um dado momento não programado, seu chefe lhe solicita a execução imediata de uma outra tarefa B. Você é então obrigado a parar completamente a tarefa A, atende a solicitação para executar a tarefa B e, apenas quando esta última estiver concluída, você pode então retornar para o ponto onde parou na execução da tarefa A. 1.1 Propriedades de uma interrupção Vetorada ou não vetorada: Quando o microprocessador é interrompido, ele desvia para o endereço onde se encontra o serviço adequado para tratar a interrupção. Se esse endereço é fixo, chamamos de interrupção não vetorada. Por outro lado, se esse endereço pode ser especificado pelo dispositivo que gera a interrupção, chamamos de interrupção vetorada. Mascaramento: Por meio do mascaramento, realizado via software ou também via hardware, podemos habilitar ou desabilitar uma ou mais interrupções. Isso é especialmente útil na realização de tarefas críticas onde por alguma razão o microprocessador não possa ser interrompido em hipótese alguma. Prioridade: Geralmente um microprocessador pode aceitar diversas interrupções diferentes. Neste caso, é possível programar a prioridade de cada evento de interrupção, de modo que não haja conflitos ou disputas entre elas. Origem: No caso de microcontroladores, a interrupção pode ser interna caso seja gerada por algum periférico interno ao chip (timer ou UART por exemplo), ou externa, caso venha de um dispositivo externo ao chip. Tipo de disparo: É uma propriedade das interrupções externas ao chip, pode-se programar um pino para gerar interrupções de acordo com o nível lógico (0 ou 1) ou de acordo com a borda (transição de 0 para 1 ou transição de 1 para 0). 2 Interrupções externas no Arduíno Uno O Arduíno Uno possui dois pinos capazes de gerar interrupções externas, são os pinos digitais 2 e 3. Além disso, a biblioteca padrão do Arduíno já oferece algumas rotinas para simplificar bastante a programação de interrupções externas void attachinterrupt(int interrupt, int isr, int mode): Configura a interrupção interrupt para chamar a rotina isr (interrupt service routine), segundo o modo de operação mode. Esta rotina não retorna nenhum valor e recebe três parâmetros: interrupt: A interrupção a ser utilizada. No caso de interrupções externas, vamos utilizar o valor retornado pela chamada à função digitalpintointerrupt(pino), onde pino pode assumir o valor 2 ou 3. isr: O nome da rotina que vai tratar a interrupção gerada, é o nosso serviço de interrupção ou interrupt service routine. Deve ser declarada como uma função que não receberá nem retornará parâmetros, por exemplo: void meu_isr ( ) { / / Código do s e r v i ç o de i n t e r r u p ç ã o v a r _ g l o b a l = v a r _ g l o b a l + 1 ; Devemos observar que a rotina isr deve ser pequena e executar rapidamente. Além disso, ao tratar 3

uma interrupção, ou seja, dentro da rotina isr, outras interrupções não podem ocorrer. Isso implica que o código dentro da isr não pode ser interrompido externamente, mas também que funções como delay() e millis() também não irão funcionar (essas duas funções da biblioteca do Arduíno utilizam interrupções internas para operar). Se for imprescindível realizar algum tipo de delay dentro da isr, podemos utilizar a rotina delaymicroseconds(), que recebe um valor em microssegundos, isso permite alguma sincronização para eventos muito rápidos. Outro ponto muito importante é que a isr não recebe nem retorna valores. Assim, qualquer tipo de comunicação entre a isr e o programa principal deve ser realizada por meio de variáveis globais, declaradas como voláteis. Para isso utilizamos a palavra reservada volatile, que diz ao compilador que a variável declarada a seguir pode ser alterada por outros meios além do programa principal. Isso vai desligar qualquer otimização que o compilador julgaria viável em outras situações. mode: O modo de disparo da interrupção. Podemos configurar para um dos quatro valores predefinidos: LOW: Dispara a interrupção quando o pino esta em nível lógico baixo; CHANGE: Dispara a interrupção quando o nível lógico do pino muda; RISING: Dispara a interrupção quando o nível lógico do pino sofre uma transição de 0 para 1; FALLING: Dispara a interrupção quando o nível lógico do pino sofre uma transição de 1 para 0; void detachinterrupt(int interrupt): Desabilita a interrupção em questão. No caso de interrupções externas, devemos utilizar o valor retornado pela chamada à função digitalpintointerrupt(pino), onde pino pode assumir o valor 2 ou 3. interrupts(): Habilita todas as interrupções nointerrupts(): Desabilita todas as interrupções. Essas duas funções podem ser utilizadas para executar partes críticas de um código, onde não será permitida a ocorrência de interrupções. Por exemplo: void s e t u p ( ) { void loop ( ) { n o I n t e r r u p t s ( ) ; / / p a r t e c r í t i c a do c ó d i g o i n t e r r u p t s ( ) ; / / p a r t e não c r í t i c a 2.1 Exemplo No exemplo a seguir, vamos configurar interrupções do tipo RISING nos pinos 2 e 3. Vamos também declarar duas rotinas isr, uma para cada pino gerador de interrupção. O funcionamento do programa será o seguinte. Vamos configurar uma variável do tipo int (inteiro) como um contador. Ao ocorrer uma interrupção no pino 2, esse valor deve ser resetado imediatamente, já ao ocorrer uma interrupção no pino 3, o contador deve assumir o valor 100. Observe que a variável de contagem deve ser declarada como volatile para que não ocorram problemas. 4

/ / v a r i a v e l de contagem / / s e r á m o d i f i c a d a d e n t r o das r o t i n a s i s r / / e n t ã o deve s e r d e c l a r a d a como v o l a t i l e v o l a t i l e i n t c o n t a d o r ; void s e t u p ( ) { / / vamos c o n f i g u r a r as i n t e r r u p ç õ e s a t t a c h I n t e r r u p t ( d i g i t a l P i n T o I n t e r r u p t ( 2 ), i s r _ p i n o 2, RISING ) ; a t t a c h I n t e r r u p t ( d i g i t a l P i n T o I n t e r r u p t ( 3 ), i s r _ p i n o 3, RISING ) ; void loop ( ) { / / a r o t i n a loop v a i i n c r e m e n t a r a v a r i á v e l de contagem / / a cada 1 segundo d e l a y ( 1 0 0 0 ) ; c o n t a d o r ++; / / D e c l a r a ç ã o das duas ISRs void i s r _ p i n o 2 ( ) { c o n t a d o r = 0 ; void i s r _ p i n o 3 ( ) { c o n t a d o r = 100; 5

2.2 Exercícios 2.2.1 Crie um programa utilizando interrupção externa do tipo FALLING no pino 2. O programa deve configurar o pino 0 como uma saída digital e o nível lógico escrito neste pino deve ser trocado (de 1 para 0 ou de 0 para 1) quando ocorrer a interrupção / / v a r i a v e l do n í v e l l ó g i c o / / s e r á m o d i f i c a d a d e n t r o das r o t i n a s i s r / / e n t ã o deve s e r d e c l a r a d a como v o l a t i l e v o l a t i l e i n t n i v e l ; void s e t u p ( ) { / / vamos c o n f i g u r a r as i n t e r r u p ç õ e s a t t a c h I n t e r r u p t ( d i g i t a l P i n T o I n t e r r u p t ( 2 ), i s r _ p i n o 2, FALLING ) ; / / vamos c o n f i g u r a r o pino 0 como s a í d a d i g i t a l pinmode ( 0, OUTPUT ) ; / / c o n f i g u r a r um n í v e l l ó g i c o i n i c i a l n i v e l = LOW; void loop ( ) { d i g i t a l W r i t e ( 0, n i v e l ) ; / / D e c l a r a ç ã o das duas ISRs void i s r _ p i n o 2 ( ) { i f ( n i v e l ==LOW) { n i v e l = HIGH ; n i v e l = LOW; 6

2.2.2 Crie um programa utilizando interrupção externa do tipo RISING no pino 3. O programa deve incrementar um contador do tipo inteiro sempre que uma interrupção for gerada / / v a r i a v e l de contagem / / s e r á m o d i f i c a d a d e n t r o das r o t i n a s i s r / / e n t ã o deve s e r d e c l a r a d a como v o l a t i l e v o l a t i l e i n t c o n t a d o r ; void s e t u p ( ) { / / vamos c o n f i g u r a r as i n t e r r u p ç õ e s a t t a c h I n t e r r u p t ( d i g i t a l P i n T o I n t e r r u p t ( 3 ), i s r _ p i n o 3, RISING ) ; / / c o n f i g u r a r um v a l o r i n i c i a l c o n t a d o r = 0 ; void loop ( ) { / / D e c l a r a ç ã o da ISR void i s r _ p i n o 2 ( ) { c o n t a d o r ++; 7

2.3 Aplicação prática, leitura de encoder incremental Encoders incrementais são comumente utilizados para monitorar mudanças de posição. Diferentemente dos encoders absolutos, um encoder incremental não fornece uma leitura absoluta da posição, mas permite detectar a sua mudança. No entanto, se assumirmos uma dada posição como sendo o referencial zero, ou seja, devemos fazer o setup ou zeramento do encoder, é possível utilizar encoders incrementais para monitorar posições absolutas. Tipicamente, um encoder incremental disponibiliza dois canais onde monitoramos o nível lógico por mudanças que representam um incremento ou um decremento na posição. A tabela 1 ilustra passo a passo os níveis lógicos ao se avançar a posição do encoder Posição Canal A Canal B X+0 0 0 X+1 0 1 X+2 1 1 X+3 1 0 X+4 0 0 X+5 0 1 X+6 1 1 X+7 1 0 X+8 0 0......... Tabela 1: Encoder incremental ao se avançar as posições A tabela 2 exibe os níveis lógicos ao se retroceder a posição do encoder Posição Canal A Canal B X+0 0 0 X-1 1 0 X-2 1 1 X-3 0 1 X-4 0 0 X-5 1 0 X-6 1 1 X-7 0 1 X-8 0 0......... Tabela 2: Encoder incremental ao se avançar as posições Note que a cada posição, apenas um dos canais muda seu nível lógico. Para determinar a posição atual, devemos verificar a configuração atual e a configuração anterior dos canais A e B do encoder. Assim, se anteriormente tínhamos os canais A e B em nível lógico baixo (zero) e agora verificamos que o canal A apresenta nível lógico alto (um) e o canal B continua com nível lógico baixo, então verificamos que houve um decremento de uma posição na leitura do encoder. Com base nessas informações e nas tabelas 1 e 2, podemos resumir o incremento ou decremento da posição de acordo com a tabela 3 A leitura de um encoder incremental é um caso típico onde é interessante fazer uso de interrupções. Perceba que se deixarmos de monitorar os canais do encoder por um tempo muito longo, podem ocorrer mais de uma mudanças de posição e, neste caso, perderemos a contagem. Por outro lado, monitorar frequentemente os canais do encoder pode demandar muito tempo de processamento, tempo que poderia ser utilizado em outras funções e cálculos. 8

Leitura Anterior Leitura Atual Canal A Canal B Canal A Canal B Ação 0 0 0 0 Não Muda 0 0 0 1 Incrementa 0 0 1 0 Decrementa 0 0 1 1 Erro 0 1 0 0 Decrementa 0 1 0 1 Não Muda 0 1 1 0 Erro 0 1 1 1 Incrementa 1 0 0 0 Incrementa 1 0 0 1 Erro 1 0 1 0 Não Muda 1 0 1 1 Decrementa 1 1 0 0 Erro 1 1 0 1 Decrementa 1 1 1 0 Incrementa 1 1 1 1 Não Muda Tabela 3: Ação no encoder conforme mudança nos canais A e B A seguir apresentamos uma possível implementação para a leitura de um encoder incremental utilizando interrupções. Este código pode ser testado online em https://123d.circuits.io/circuits/2076667-leitor-de-encoder-incremental. Inicie a simulação e abra o monitor serial localizado dentro da aba do editor de código. No monitor serial será possível visualizar a indicação da posição lida pelo encoder. 9

/ / E s t e programa f a z uso de i n t e r r u p ç õ e s p a r a m o n i t o r a r um / / e n c o d e r i n c r e m e n t a l l i g a d o aos p i n o s 2 e 3 do Arduíno UNO. / / Ao o c o r r e r uma mudança, a v a r i á v e l e n c o d e r é a t u a l i z a d a / / e a i n f o r m a ç ã o é d i s p o n i b i l i z a d a na p o r t a s e r i a l / / v a r i á v e i s g l o b a i s e v o l á t e i s / / e n c o d e r armazena o v a l o r da p o s i ç ã o do e n c o d e r / / c a n a l _ a armazena o e s t a d o l ó g i c o a n t e r i o r do c a n a l A / / c a n a l _ b armazena o e s t a d o l ó g i c o a n t e r i o r do c a n a l B / / change s i n a l i z a se houve mudança de e s t a d o, usada / / apenas p a r a a t u a l i z a r a i n f o r m a ç ã o na p o r t a s e r i a l v o l a t i l e long i n t e n c o d e r = 0 ; v o l a t i l e b y t e c a n a l _ a = LOW; v o l a t i l e b y t e c a n a l _ b = LOW; v o l a t i l e b y t e change = LOW; / / r o t i n a de s e t u p void s e t u p ( ) { / / C o n f i g u r a a p o r t a s e r i a l p a r a monitorarmos / / Configuramos uma t a x a de 9600 bauds S e r i a l. b e g i n ( 9 6 0 0 ) ; / / Mensagem de a p r e s e n t a ç ã o do programa S e r i a l. p r i n t l n ( ) ; S e r i a l. p r i n t l n ( T e s t e Encoder : ) ; / / c o n f i g u r a as i n t e r r u p ç õ e s nos p i n o s / / pino 2 > c a n a l A / / pino 3 > c a n a l B a t t a c h I n t e r r u p t ( d i g i t a l P i n T o I n t e r r u p t ( 2 ), i s r _ c a n a l _ a, CHANGE) ; a t t a c h I n t e r r u p t ( d i g i t a l P i n T o I n t e r r u p t ( 3 ), i s r _ c a n a l _ b, CHANGE) ; / / r o t i n a p r i n c i p a l void loop ( ) { / / se houve mudança, e n v i a novo v a l o r p a r a p o r t a s e r i a l i f ( change == HIGH) { S e r i a l. p r i n t ( e n c o d e r = ) ; S e r i a l. p r i n t l n ( e n c o d e r ) ; change = LOW; 10

/ / r o t i n a s de s e r v i ç o de i n t e r r u p ç ã o ISRs void i s r _ c a n a l _ a ( ) { change = HIGH ; i f ( c a n a l _ a == LOW) { i f ( c a n a l _ b == LOW) { / / AB e r a 00 e f o i p a r a 10, d e c r e m e n t a o e n c o d e r encoder ; c a n a l _ a = HIGH ; / / AB e r a 01 e f o i p a r a 11, i n c r e m e n t a o e n c o d e r e n c o d e r ++; c a n a l _ a = HIGH ; i f ( c a n a l _ b == LOW) { / / AB e r a 10 e f o i p a r a 00, i n c r e m e n t a o e n c o d e r e n c o d e r ++; c a n a l _ a = LOW; / / AB e r a 11 e f o i p a r a 01, d e c r e m e n t a o e n c o d e r encoder ; c a n a l _ a = LOW; void i s r _ c a n a l _ b ( ) { change = HIGH ; i f ( c a n a l _ a == LOW) { i f ( c a n a l _ b == LOW) { / / AB e r a 00 e f o i p a r a 01, d e c r e m e n t a o e n c o d e r e n c o d e r ++; c a n a l _ b = HIGH ; / / AB e r a 01 e f o i p a r a 00, d e c r e m e n t a o e n c o d e r encoder ; c a n a l _ b = LOW; i f ( c a n a l _ b == LOW) { / / AB e r a 10 e f o i p a r a 11, d e c r e m e n t a o e n c o d e r encoder ; c a n a l _ b = HIGH ; / / AB e r a 11 e f o i p a r a 10, i n c r e m e n t a o e n c o d e r e n c o d e r ++; c a n a l _ b = LOW; 11