Prévia do material em texto
Periféricos integrados
Os periféricos internos essenciais dos microcontroladores, as formas de acioná-los por meio de
programação para realização de sistemas de monitoração e controle na plataforma Arduino e com
microcontroladores da família PIC.
Prof. Marcos Santana Farias
1. Itens iniciais
Propósito
Compreender o uso dos dispositivos internos dos microcontroladores, auxiliares da Unidade Central de
Processamento (UCP) na criação de sistemas de monitoração e controle − fator essencial para a formação do
projetista de sistemas embarcados.
Preparação
Antes de iniciar o conteúdo deste tema, tenha instalado o compilador CCS, o ambiente MPLAB e o simulador
PicSimLab, além de um cadastro no simulador Tinkercad.
Objetivos
Empregar as portas de entrada e saída dos microcontroladores para a interação com dispositivos
externos.
Aplicar conversores analógico-digitais para criação de sistemas de aquisição de dados com
microcontroladores.
Identificar a importância do uso de temporizadores e contadores para o desenvolvimento de sistemas
de tempo real com microcontroladores.
Esquematizar o uso da Modulação por Largura de Pulso (PWM) para o controle de dispositivos
externos.
Introdução
Os microcontroladores têm mais dispositivos internos além de uma UCP, RAM e memória de programa. Eles
contêm circuitos que são usados para interagir com sistemas fora do microcontrolador, bem como interagir
direta e indiretamente com seus arredores no mundo por meio de sensores, acionadores de motor ou
interfaces humanas − como mostradores, teclados ou botões. Esses componentes são conhecidos
coletivamente como periféricos.
Alguns periféricos são úteis porque permitem que um desenvolvedor descarregue o processamento para eles,
evitando ter que lidar com tudo no software.
Semelhante a como um desenvolvedor de desktop descarregaria o processamento gráfico em uma placa de
vídeo, os desenvolvedores de sistemas embarcados podem descarregar algumas tarefas nos periféricos,
permitindo que a CPU gaste seu tempo fazendo outra coisa importante ou não fazendo nada para economizar
energia.
Neste tema, veremos os periféricos internos mais comuns de um microcontrolador, estudando as técnicas
para configurá-los e acioná-los usando registradores específicos, além de aprender sobre as limitações dos
mesmos.
Dessa forma, veremos como utilizar instruções em C para controlar periféricos internos em projetos de
sistemas embarcados, com exemplos para as plataformas Arduino e PIC de microcontroladores.
•
•
•
•
1. As portas de entrada e saída dos microcontroladores para a interação com dispositivos externos
Portas digitais de entrada e saída
Os microcontroladores precisam ter a
capacidade de monitorar e controlar um
dispositivo externo a ele, sendo esta a sua
principal característica como dispositivo de
controle. Vamos, primeiramente, verificar as
portas digitais usadas como entrada e saída (E/
S).
Os pinos de E/S digital de um microcontrolador
podem ser acessados individualmente. Mas,
geralmente, são agrupadas também em portas de 8 pinos, que podem ser acessadas com um único byte. Os
pinos podem ser apenas de entrada, apenas de saída ou, mais comumente, bidirecionais − ou seja, capazes
de entrada e saída.
Além de seus recursos de E/S digital, a maioria dos pinos tem uma ou mais funções alternativas para manter o
chip pequeno. Assim, muitos módulos do microcontrolador que requerem pinos de E/S, como um módulo de
comunicação ou um temporizador, podem usar funções alternativas dos pinos de E/S digitais.
Saiba mais
O programador do aplicativo pode selecionar qual função deve ser usada para o pino, habilitando a
funcionalidade dentro do módulo apropriado. Obviamente, se um pino for usado para um módulo de
comunicação, ele será perdido para E/S digital e vice-versa. Portanto, o projetista do hardware deve
escolher cuidadosamente quais pinos usar para quais funções.
Vamos nos concentrar na capacidade de E/S digital dos pinos, mas, antes, vamos relembrar o que queremos
dizer com “digital”.
Digital descreve a tecnologia eletrônica que gera, armazena e processa dados em termos de dois
estados ou níveis lógicos: positivo e não positivo (ou zero). Positivo é expresso ou representado pelo
número 1 e não positivo, pelo número 0.
Assim, os dados transmitidos ou armazenados
com tecnologia digital são expressos como uma
sequência de 0's e 1's. Cada um desses dígitos
de estado é o nosso conhecido bit. Então,
quando falamos sobre E/S digital, queremos
dizer que o valor do pino, da perspectiva do
controlador, é de nível lógico 0 ou 1.
As portas de E/S digitais, assim como os
demais periféricos, são conectadas ao
microcontrolador por alguns registradores
especiais. Os diferentes registradores podem
ser de dois tipos:
Registradores de dados
Que contêm alguns dados, digamos, o byte que representa o estado de uma porta.
Registradores de status e controle
São usados para configurar o periférico de acordo com sua necessidade e para controlá-lo a partir de
seu programa. Por exemplo, o registrador que controla se os pinos de uma porta serão usados como
entrada ou saída.
É desejável que se configure os pinos de um microcontrolador na direção desejada (entrada ou saída) no início
do software que é executado quando ele é ligado ou reinicializado. Os registradores para esse propósito
podem ser configurados na programação por funções específicas dentro de um ambiente, como a função
pinMode() para Arduino.
Depois de configurar qualquer pino de E/S, é possível ler seu estado (se for um pino de entrada) ou alterar seu
estado lógico (se for um pino de saída). Funções específicas também são usadas para alterar o registrador
corresponde a um pino. Assim, o valor que é escrito para, ou lido desse registrador, especifica o estado lógico
dos pinos correspondentes (alto ou baixo).
Lendo dos pinos digitais
A funcionalidade de entrada digital é utilizada sempre que queremos monitorar um sinal e interpretá-lo
digitalmente, ou seja, quando esse sinal muda apenas entre os dois estados: alto (correspondendo à lógica 1)
e baixo (correspondendo a 0).
A leitura do estado lógico de um pino de entrada requer conexões de hardware adicionais para
garantir um comportamento estável do sistema.
Sabemos que um pino típico pode ser conduzido para nível alto ou baixo, no entanto, não se deve deixar um
pino de E/S flutuando, desde que seja usado como uma entrada para o sistema. Por esse motivo, os pinos de
entrada geralmente são puxados para baixo (pino em pull-down) ou para cima (pino em pull-up).
Saiba mais
Existem microcontroladores que, ao terem um pino configurado como entrada, podem selecionar esta
para a configuração pull-up internamente, não necessitando de ligação externa para garantir a mesma.
Confira as características dos pinos de entrada:
Pinos de entrada em pull-up
Nessa configuração, o pino é sempre puxado para o nível alto (lógica 1) até que ocorra um evento
para acioná-lo para nível baixo (lógica 0). Tudo que é preciso é ter um resistor conectado entre o pino
de entrada e o VSS (+ 5V), como mostrado na Figura 1a. O estado lógico do pino é sempre 1 até que o
botão seja pressionado, ocasião em que é ligado diretamente com o terra e se torna 0. Isso é
chamado de entrada de lógica negativa, pois a ação do usuário (pressionando o botão) transfere o
estado do pino digital de alto para baixo.
Pinos de entrada em pull-down
Nesta configuração, o pino é sempre baixado (lógica 0) até que ocorra um evento para acioná-lo
como nível alto (lógica 1). Tudo que é necessário é um resistor conectado entre o pino de entrada e o
terra como mostrado na Figura 1b. O estado lógico do pino é sempre 0 até o botão ser pressionado,
então ele é ligado diretamente com VCC (+ 5V) e se torna 1. Isso é chamado de entrada lógica
positiva, pois a ação do usuário (pressionando o botão) transfere ao pino o estado de baixo para alto.
Você consegue comparar a configuração dos pinos de entrada observando a imagem abaixo:
Imagem 1: ConfiguraçãoI.
E
Somente II.
A alternativa A está correta.
A modulação por largura de pulso, o PWM, trabalha variando o tempo de sinal ativo (ligado) em relação ao
inativo (desligado). Assim, quanto maior o tempo ligado em relação ao tempo desligado, maior é o ciclo de
trabalho. 100% de ciclo de trabalho significa o sinal sempre ligado, fornecendo potência máxima à uma
carga externa. 50% de ciclo de trabalho significa o sinal metade do tempo ligado e metade desligado,
fornecendo uma potência que a metade da máxima a uma carga externa. A frequência do sinal não se
altera durante a operação, o que significa que o tempo total do sinal ligado mais o seu tempo desligado
permanece o mesmo, independentemente do ciclo de trabalho.
Questão 2
Para que pode ser usado um sinal PWM?
I − Para controlar um braço de robô.
II − Para controlar a velocidade de uma bicicleta elétrica.
III – Para controlar a vazão com bombas hidráulicas.
Está(ão) correto(s) o(s) item(n)s:
A
I, II e III.
B
Somente II.
C
II e III.
D
I e III.
E
I e II.
A alternativa A está correta.
As aplicações mencionadas possuem motores DC com acionadores de movimento, portanto, a modulação
por largura de pulso, PWM, pode ser usada em todas elas.
5. Conclusão
Considerações finais
Neste tema, discutimos os tipos mais comuns de periféricos internos dos microcontroladores, considerando
suas aplicações em sistemas de monitoração e controle. Exemplificamos como programá-los em
microcontroladores da família PIC e da plataforma Arduino e, por fim, mostramos como testar esses códigos
em simuladores.
Podcast
Para encerrar, ouça sobre Periféricos Integrados.
Conteúdo interativo
Acesse a versão digital para ouvir o áudio.
Explore +
Para saber mais sobre os assuntos tratados neste tema, leia:
Projeto e desenvolvimento de um medidor digital de energia elétrica monofásico para aplicações
residenciais, de Bruno Raniere Araújo Diniz, Artur Almeida Evangelista e Auzuir Ripardo de Alexandria.
A plataforma Arduino e suas aplicações, de Eduardo Ferroni et al.
Referências
MONK, S. Programação com Arduino: começando com sketches. 1. ed. Porto Alegre: Bookman, 2017.
OLIVEIRA, A. S. de; ANDRADE, F. S de. Sistemas embarcados: hardware e firmware na prática. 1. ed. São
Paulo: Érica, 2010.
PECKOL, J. K. Embedded systems: a contemporary design tool. 1. ed. Nova Jersey: Wiley, 2019.
ZANCO, W. da S. Microcontroladores PIC18 com Linguagem C: uma abordagem prática e objetiva. São Paulo:
Érica, 2010.
•
•
Periféricos integrados
1. Itens iniciais
Propósito
Preparação
Objetivos
Introdução
1. As portas de entrada e saída dos microcontroladores para a interação com dispositivos externos
Portas digitais de entrada e saída
Saiba mais
Registradores de dados
Registradores de status e controle
Lendo dos pinos digitais
Saiba mais
Pinos de entrada em pull-up
Pinos de entrada em pull-down
Escrevendo nos pinos digitais
Exemplo
Portas analógicas
Exemplo
Saiba mais
Programando E/S digitais em microcontroladores
PIC
AVR ATMega
Atenção
Configuração do microcontrolador via software
Exemplo
Exemplo para PIC
Exemplo para a plataforma Arduino
Comentário
Simulando a comunicação com portas de entradas e saídas
Conteúdo interativo
Verificando o aprendizado
Questão 2
2. Conversores analógico-digitais
O que é a aquisição de dados?
Comentário
Conversor analógico-digital
Exemplo
Exemplo
Atenção
Exemplo
Comentário
ADC de aproximações sucessivas
Passo 1
Passo 2
Passo 3
Programando ADCs em microcontroladores
Exemplo
Saiba mais
Exemplo para a plataforma Arduino
Exemplo para PIC
PIC16f628
PIC18F4550
Registradores associados
Principais funções
Comentário
Simulando conversores analógico-digitais
Conteúdo interativo
Verificando o aprendizado
3. A importância do uso de temporizadores e contadores para o desenvolvimento de sistemas de tempo real com microcontroladores
Aplicações de temporizadores e contadores
Exemplo
Atenção
Configurações dos temporizadores e contadores
Exemplo
Comentário
Relógio do sistema (relógio interno)
Prescaler
Pulso externo (acumulador de pulso)
Cristal externo (modo assíncrono)
Captura de entrada e comparação de saída
Atenção
Contador/temporizador nos microcontroladores
Timer 0
Timer 1
Timer 2
Programando temporizadores em microcontroladores
Temporizadores e interrupção no PIC
Comentário
Temporizadores e interrupção no Arduino
Simulando temporizadores e contadores
Conteúdo interativo
Verificando o aprendizado
Em um programa para microcontroladores PIC, deseja-se criar uma interrupção para apagar ou acender um led a cada 2 segundos usando temporizador. Sabe-se que o ciclo de máquina é de 0,5us, o período é de 65536 e o valor do prescaler é de 1. Qual deve ser o valor X no código a seguir, que mostra a rotina de interrupção do timer feita no CCS C?
Foi solicitado a você um programa para microcontrolador que verifica o número de pulsos elétricos de tensão advindos de um detector de radiação a cada segundo, o que corresponde a uma taxa de radiação. Qual/quais circuito(s) interno(s) ao microcontrolador você deve utilizar para realizar a tarefa?
4. O uso da Modulação por Largura de Pulso (PWM) para o controle de dispositivos externos
Sistema eletrônico
Motor DC
Curiosidade
Aplicações de motores DC
Motores DC para ventiladores
Motores DC para bombas
Motores DC para brinquedos
Motores DC para carros elétricos
Motores DC para robôs
Motores DC para bicicletas
Acionamento de motores DC com PWM
Atenção
Programando PWM em microcontroladores
Saídas com PWM em microcontroladores da plataforma Arduino
Atenção
Saídas com PWM em microcontroladores PIC
Simulando o uso de modulação por largura de pulso (PWM)
Conteúdo interativo
Verificando o aprendizado
5. Conclusão
Considerações finais
Podcast
Conteúdo interativo
Explore +
Referênciasdos pinos de entrada em pull-up e pull-down.
Escrevendo nos pinos digitais
A funcionalidade de escrita digital é usada para definir os pinos de saída para determinados níveis de tensão.
Os níveis correspondentes a alto e baixo são novamente especificados pelo microcontrolador e dependem da
tensão de operação deste.
Assim, sempre que um pino é definido como de saída, o microcontrolador o aciona de acordo com o
valor fornecido no registrador correspondente.
Um pino de saída deve ser conectado a algum dispositivo externo − que pode ser referido como uma carga −
para fazer algo útil.
Carga
Uma carga real pode ser um LED, uma lâmpada, um relé ou algum outro elemento do circuito.
Geralmente, existem duas maneiras de conectar um pino de saída a uma carga. A primeira é onde o
microcontrolador − referido como a fonte − fornece a corrente elétrica para acionar o dispositivo. A corrente
flui do microcontrolador para o pino de saída (P0), através da carga e para o GND, a referência do circuito.
Essa configuração é mostrada na figura abaixo.
Imagem 2: Microcontrolador fornecendo corrente para a carga.
Em outra configuração, o pino do microcontrolador consome corrente conforme mostrado na Figura 3. A
corrente flui da fonte de alimentação (5V) através da carga e através do pino P0 para o GND. É importante que
a carga seja conectada à mesma linha de fonte de alimentação que o microcontrolador, ou este pode ser
destruído.
Imagem 3: Microcontrolador consumindo corrente de uma fonte.
Os pinos, quando usados com saída, são mais críticos do que quando usados como entrada no sentido de que
dependem muito da proteção de corrente externa. Afinal, seria possível conectar um pino de saída
diretamente ao GND e, em seguida, defini-lo como 1, criando, assim, um curto-circuito.
Embora os controladores tendam a tolerar esses curtos-circuitos por um breve período de tempo (geralmente
menos de um segundo), isso acabará por destruir o circuito de saída desse pino do microcontrolador, até
mesmo inviabilizando o chip. Portanto, o projetista deve garantir que o hardware externo não produza um
curto-circuito.
Os microcontroladores, portanto, são dispositivos um tanto delicados, e as linhas de E/S podem
carregar apenas uma quantidade relativamente pequena de corrente. O limite atual dependerá do
tipo de microcontrolador e do pino específico.
Geralmente, haverá uma corrente total máxima que os pinos de uma única porta de 8 bits podem suportar,
bem como um limite para todas as saídas de todo o microcontrolador. Exceder os limites irá destruí-lo . A
maioria deles pode manipular apenas 20 a 25 mA (miliampère). Isso é suficiente para acender um LED, mas os
circuitos que exigem mais corrente devem isolar a carga de corrente mais alta dos pinos de E/S do
microcontrolador.
Exemplo
Em aplicações industriais, por exemplo, a maioria dos níveis de fornecimento e lógica ainda estão em +
24V. Essas tensões maiores são usadas em ambientes operacionais ruidosos onde é necessária alta
imunidade a ruído elétrico para que a interface tolere picos de corrente alta, interferência magnética,
descarga estática etc.
Em muitos casos pode haver um fator de 10 em termos de corrente ou tensão entre o microcontrolador e o
mundo industrial. Isso representa um desafio para o projetista de hardware isolar e traduzir o nível de sinal
entre os dois mundos. Significa mudar os níveis lógicos do microcontrolador de tão baixo quanto + 3,3V para
+ 24V nas saídas ou na outra direção para as entradas. Para isso, são usados conversores de nível lógico.
Portas analógicas
Um nível de tensão aplicado a uma porta digital de um microcontrolador será percebido como um valor
discreto 0 ou 1.
Por exemplo, para microcontroladores que funcionam com 5V, uma entrada a partir de 2,7V será levada para o
valor lógico 1. Abaixo de 0,7V, como 0. Valores entre 0,7V e 2,7V serão indeterminados, podendo ser
percebidos como 0 ou 1.
Embora isso já seja muito útil, existem situações em que a tensão real da linha transporta
informações.
Exemplo
Por exemplo, ao usar um foto-transistor como sensor de luz: a queda de tensão produzida em sua saída
é diretamente proporcional à quantidade de luz que incide sobre o transistor e, para avaliar
adequadamente a saída do sensor, o microcontrolador deve lidar com o valor analógico.
Por outro lado, o microcontrolador é inerentemente digital, portanto, precisamos de meios apropriados para
converter sinais analógicos no mundo digital e vice-versa. Esse problema é resolvido por portas analógicas do
microcontrolador.
Assim, uma entrada analógica é uma entrada que pode ler uma tensão variável, tipicamente de 0
volts até a tensão máxima que alimenta o próprio microcontrolador.
Portas analógicas também podem ser de saída. Nesses casos, o microcontrolador deve possuir um circuito
chamado conversor digital-analógico (DAC). Esse circuito gera uma tensão em um pino que é proporcional a
um valor digital.
Saiba mais
Os DACs podem ser usados para acionar pequenos motores ou drivers, que geram correntes mais altas.
Eles não são comuns na maioria das famílias de microcontroladores, por isso uma solução alternativa aos
DACs são as saídas com modulação por largura de pulso (PWM).
Programando E/S digitais em microcontroladores
Vamos exemplificar a programação de portas de E/S digitais em dois microcontroladores distintos:
PIC
Em microcontroladores da família PIC usaremos
o simulador PicSimLab. Ele funciona a partir do
arquivo executável para o microcontrolador, um
arquivo com extensão .hex (hex de
hexadecimal) que é gerado na compilação dos
arquivos fonte que iremos mostrar nos
exemplos. Então, para gerá-los , teremos que
usar um compilador C para PIC.
Os programas fontes que serão apresentados
foram criados para o compilador CCS C, da
empresa CSS (Custom Computer Services), de
soluções para microcontroladores PIC. Esse foi
um dos primeiros e é um dos melhores
compiladores para iniciantes, pois inclui muitas
bibliotecas integradas que permitem programar
um microcontrolador PIC sem profundo
conhecimento de sua arquitetura interna. O
compilador CCS C é acionado a partir de uma
IDE (Integrated Development Environment ou
Ambiente de Desenvolvimento Integrado). O IDE
usado para desenvolver aplicativos embutidos
em microcontroladores PIC nos nossos
exemplos será o MPLAB.
AVR ATMega
Em microcontroladores da família AVR ATMega,
utilizados pela plataforma Arduino, poderemos
usar o simulador online Tinkercad. Os arquivos
fonte dos exemplos podem ser compilados e
executados no ambiente online do Tinkercad,
que apresentará a simulação de uma placa
Arduino Uno diretamente na janela do
navegador.
Existem diferenças na forma de configurar os microcontroladores e nas funções usadas em cada família. Essas
diferenças serão uma constante no aprendizado da programação para esses dispositivos.
Atenção
É fundamental durante o aprendizado a flexibilidade em se passar de uma plataforma para outra,
aprendendo funções específicas de cada compilador para cada família de microcontrolador.
Isso porque na vida profissional será muito comum o trabalho com diferentes microcontroladores, e estar
familiarizado e com a adaptabilidade para pesquisar e desenvolver códigos para plataformas diferentes será
sempre necessário.
Configuração do microcontrolador via software
Como em qualquer projeto − um projeto gráfico, por exemplo −, existem alguns ajustes que devem ser feitos
no início, como dimensões, fundo, cores etc. Esses ajustes são chamadas de configurações, que, idealmente,
não serão alterados até o final.
Da mesma forma, no projeto de software embarcado (firmware), também existem algumas configurações para
cada microcontrolador usado em todo o projeto.
Exemplo
Por exemplo, o tipo de oscilador do clock (interno/externo), se será utilizado um watchdog (Peça de
hardware que pode ser usada para detectar erros de software) ou não; se haverá um pino de
reinicialização ou não, e assim por diante.
Essas configurações são controladas por meio de registradoresespecíficos no microcontrolador.
Cada bit nesses registradores controla um recurso específico e, por isso, são frequentemente chamados de
bits de configuração. Alguns compiladores e fabricantes chamam esses bits de fusíveis (fuses).
O CCS C, que usaremos como compilador para PIC, usa a diretiva #fuses para configurar o
microcontrolador.
Exemplo para PIC
O exemplo a seguir pode ser utilizado na placa 1 (MCLAB1) do simulador PicSimLab, que usa um
microcontrolador modelo PIC16F628A, cuja pinagem é mostrada abaixo:
Imagem 4: Pinagem do microcontrolador PIC16F628A.
O código-fonte implementa um contador de acionamentos de um botão (push button) que fecha um contato
toda vez que é apertado. No programa, cada vez que se aperta o botão RA1(PIN_A1) da placa, o valor da
variável contador será incrementado. Esse valor é passado para a porta B do microcontrolador pela função
output_b, que o escreve de forma binária na porta, acendendo os leds em correspondência ao valor.
As primeiras três linhas do programa utilizam diretivas da linguagem. A diretiva #include é bem conhecida na
linguagem C, indicando o uso de uma biblioteca, no caso, a do modelo de microcontrolador PIC que é usado
na placa, o 16F628A. A diretiva #fuses XT configura o microcontrolador para usar o cristal ressonador externo,
e a diretiva #use informa que o clock do microcontrolador será de 4MHz.
python
#include
#fuses XT
#use delay( clock=4MHz )
void main () {
int contador = 0;
int1 btn1;
while(TRUE) {
btn1 = input(PIN_A1 );
if (btn1 == 0) {
contador++;
output_b (contador);
delay_ms(500);
}
}
}
Dentro da função principal, main(), inicializa-se uma variável contador do tipo int e uma variável btn1 do tipo
int1. Essa é uma forma particular de inicializar uma variável de um único bit, para economizar memória.
A estrutura de repetição while recebe o parâmetro TRUE. Isso diz ao compilador que aquele trecho de código
se processará indefinidamente, o que chamamos de loop infinito. Essa é uma condição sempre encontrada em
programas para microcontroladores. A instrução seguinte, btn1 = input(PIN_A1), verifica se o botão ligado ao
pino RA1 foi apertado.
Veja que a função input recebe o parâmetro PIN_A1 para verificar o estado do pino correspondente no
microcontrolador PIC16F628A (RA1 – pino 18 da figura 4).
Em seguida, a instrução if (btn1 == 0) testa se esse pino está apertado. A montagem dos botões da placa 1
(MCLAB1) do simulador, que configura uma ligação aos pinos RA1, RA2, RA3 e RA4 do microcontrolador, está
conforme a Figura 1a. Ou seja, ao se apertar o botão, o pino é ligado ao GND, indicando o nível lógico 0. Por
isso, se btn1 é igual a 0 (if (btn1 == 0)), a variável contador é incrementada (contador++).
A função seguinte envia o valor do contador para acender os leds na porta B (output_b (contador)),
mostrando, portanto, quantas vezes o botão foi apertado. Em seguida, cria-se um atraso de 500ms
(delay_ms(500)) antes de se voltar a verificar se o botão está apertado.
Criando um projeto no ambiente MPLAB, compilando o código com o CCS C e simulando o código executável
(.hex) na placa 1 do simulador PicSimLab, será possível checar o resultado e fazer outros testes alterando o
código.
Exemplo para a plataforma Arduino
É possível realizar o mesmo projeto usado na placa 1 (MCLAB1) do simulador PicSimLab no
simulador Tinkercad para a plataforma Arduino.
Para isso, deve-se realizar a montagem do botão de pressão e dos leds conforme o diagrama elétrico
mostrado na figura a seguir. Cada vez que se clica no botão, o valor de um contador deve ser incrementado e
passado para a porta (pinos 0 a 7) onde os leds estão ligados. Estes devem acender para mostrar o valor
binário do contador em cada instante.
Imagem 5: Diagrama para montagem do projeto no Tinkercad.
Vamos analisar o código para realizar o projeto, que deve ser colocado na área de código em texto no
simulador.
python
int contador = 0;
void setup(){
DDRD = B11111111;
pinMode(12, INPUT_PULLUP);
}
void loop(){
if (digitalRead(12) == LOW){
contador++;
PORTD = contador;
delay(500);
}
}
Nos programas na IDE para Arduino utilizamos com frequência a função pinMode() para definir a direção
(entrada ou saída) pino a pino. Para definir como entrada utilizamos o parâmetro INPUT, e OUTPUT para
definir como saída.
Comentário
No código anterior fizemos isso com o pino 12, onde está ligado o botão, com o parâmetro
INPUT_PULLUP, ou seja, ligando um resistor de pull-up interno do microcontrolador.
Essa função está sendo chamada dentro da função setup(), que na IDE para Arduino é chamada uma única
vez no início do programa, permitindo que se realizem as configurações do microcontrolador.
Mas como definir a configuração de todos os pinos de uma porta de uma só vez? E mais: como
escrever o valor de um contador (incrementado a cada vez que o botão é pressionado) para vários
pinos ou uma porta de uma só vez?
As funções mais utilizadas da IDE do Arduino não ajudam neste cenário. É nesse ponto que precisamos olhar
com mais detalhe o microcontrolador usado no Arduino Uno, o ATMega328.
A imagem abaixo mostra a correspondência entre os pinos do microcontrolador e da placa Arduino Uno:
Imagem 6: Correspondência entre os pinos do microcontrolador ATMega328 e a
placa Arduino Uno.
As saídas digitais 0 a 7 do Arduino (digital pin 0 a digital pin 7) correspondem às portas PDx (PD0 a PD7) do
ATMega328. Os pinos estão agrupados como PORTB (PBx), PORTC (PCx) e PORTD (PDx). Cada porta tem um
correspondente DDR (registrador de direção de dados) que especifica se um pino nessa porta é configurado
com saída ou entrada. Um "1" no bit de um DDR corresponde a uma saída, enquanto um "0", a uma entrada no
pino. Assim, uma instrução de mais baixo nível, que escreve direto no registrador do microcontrolador, é
necessária para realizarmos o código de forma semelhante ao que fizemos para o PIC no exemplo anterior:
python
DDRD = B11111111;
A instrução DDRD escreve no registrador DDR da porta D o valor binário, onde os oito 1s indicam que todos os
pinos da porta devem ser de saída.
O pino 12, onde está ligado o botão, é lido com a função digitalRead(12). Se essa leitura indicar um nível lógico
0 (LOW), mostra que o botão está pressionado e, assim, o programa deve incrementar a variável contador.
A instrução:
python
PORTD = contador;
Escreve o valor do contador nos 8 pinos da porta D em valor binário, mostrando, portanto, quantas vezes o
botão foi apertado. A função seguinte cria um atraso de 500ms (delay(500)) antes de voltar a verificar se o
botão está apertado. Esse retorno ao início da função loop() é criado automaticamente pelo compilador da IDE
do Arduino, que cria um loop infinito para as instruções que a integram.
Simulando a comunicação com portas de entradas e saídas
Acompanhe, no vídeo a seguir, uma simulação de comunicação com as portas de entradas e saídas.
Conteúdo interativo
Acesse a versão digital para assistir ao vídeo.
Verificando o aprendizado
Questão 1
Você está em um projeto com microcontrolador e tem de escrever instruções para saber se um botão foi
pressionado ou não. Um colega de trabalho lhe diz que colocou a entrada do botão em configuração pull-
down. Qual teste deverá ser feito no programa para saber se esse botão BTN foi pressionado?
A
if (BTN = 0)
B
if (BTN == 0)
C
if (BTN == 1)
D
if (BTN != 1)
E
if (BTN = 1)
A alternativa C está correta.
A configuração pull-down mantém a entrada do microcontrolador em 0 (nível baixo), garantindo que esta
vai para 1 (nível alto) quando o botão é pressionado. Dessa forma, o teste na variável BTN, que guarda o
estado do botão para saber se ele foi pressionado, deve verificar se esta é igual a 1 com a instrução if (BTN
== 1).
Questão 2
O que faz o programa para Arduino a seguir quando um led é ligado ao pino 13 e outro ao pino 12?
python
int pin = 12;
void setup(){
pin = 13;
pinMode(pin, INPUT);
}
void loop()
{
digitalWrite(pin, HIGH);
}
A
Só o led em 12 fica aceso.
B
Só o led em 13 fica aceso.
C
Os dois acendem.
D
Os dois ficam apagados.
E
O led em 13 pisca e em 12 fica aceso.
A alternativa D está correta.
Os dois ficam apagados porque, para acender o led, o parâmetro da função pinMode deveria ser OUTPUT,
indicando que vamos escrever um dado no pino correspondente.
2. Conversores analógico-digitais
O que é a aquisição de dados?
Com o passar dos anos, o uso de sistemas
computadorizados para medir, controlar e
testar processos e equipamentos se tornou a
norma. Isso inclui processos nas indústrias de
manufatura e automação, processos de teste e
medição em laboratórios de pesquisa, além de
uma infinidade de sistemas de monitoração que
nos cercam em nossas casas e ruas das
cidades.
Uma área primordial para esses sistemas é
a aquisição de dados, comumente também
conhecida como DAQ (Data Acquisition).
Atualmente, muitos sistemas de aquisição de dados são baseados em computador pessoal (PC) e são
capazes de lidar com uma gama muito ampla de aplicações.
Aquisição de dados
A aquisição de dados é definida como o processo geral pelo qual fenômenos do mundo real são
capturados e gravados em formato digital. Em um sistema baseado em PC, o computador executa o
software de aquisição de dados, que processa e registra os mesmos.
Os dispositivos de aquisição de dados podem assumir muitas formas e implementações diferentes. Muitos dos
de entrada do sistema, como os sensores e transdutores, são dispositivos analógicos que geram sinais
elétricos. Nesses casos, o hardware para aquisição de dados deve realizar a conversão de sinais analógicos
para digitais. A maioria desses dispositivos não só incorpora recursos de entrada analógica, mas também
inclui disposições para gerar saídas analógicas, entradas e saídas digitais e várias funções de contagem e
temporização.
Comentário
Pela descrição dada, vemos que os microcontroladores mais modernos podem integrar um sistema de
aquisição de dados, pois incorporam os recursos para isso. Vamos tratar da aquisição de dados baseada
na conversão analógica-digital e nas características dos circuitos que a realizam, bem como nas formas
de acionar esses circuitos por meio da programação nos microcontroladores.
Conversor analógico-digital
Se o valor da tensão elétrica for importante para o seu sistema − se quisermos usar um sensor de temperatura
para determinar o aquecimento de um forno, por exemplo −, uma simples entrada digital de um
microcontrolador não é suficiente. Em vez disso, precisamos de uma maneira de representar o valor analógico
em formato digital. Para esse propósito, muitos microcontroladores incluem um conversor analógico-digital
(ADC) que converte um valor de entrada analógica em um valor binário.
A imagem a seguir mostra o princípio básico da conversão analógica-digital. A tensão de entrada analógica,
no intervalo de 0 volts até uma tensão de referência (Vref), é dividido em 2n valores discretos, os degraus da
imagem, onde n é o número de bits usados para representar o valor digital. Cada degrau corresponde a um
código digital de 0 a 2n - 1. Cada um dos infinitos valores analógicos será representado por um degrau.
2n
2 elevado a n
Imagem 7: Princípio básico da conversão analógico-digital.
O valor n fornecerá o número de bits do ADC e definirá a sua resolução.
Os valores típicos para n são 8 ou 10 bits, mas é possível encontrar ADCs de 12 bits ou mais.
A resolução representa a diferença de tensão que pode ser distinguida pelo ADC, sendo igual a Vref/ 2n.
Exemplo
Um ADC de 10 bits que trabalhe com uma tensão de referência de 5 volts terá uma resolução de 5/1024,
ou seja, 48,8 mV.
Como é possível ver na Imagem 7, no valor de resolução calculado, a conversão introduz algumas imprecisões
na visão do microcontrolador do valor analógico real. Em primeiro lugar, o mapeamento do valor analógico em
degraus resulta em perda de informação no domínio do valor. Flutuações do valor analógico dentro de um
degrau passam despercebidas.
Exemplo
Por exemplo, variações de 20 mV no ADC de 10 bits trabalhando com 5 V são mapeadas para o mesmo
código binário ao microcontrolador.
Naturalmente, essa situação pode ser melhorada reduzindo o valor da resolução, tornando n maior, por
exemplo. Como alternativa, a resolução pode ser melhorada reduzindo o Vref, ao custo de um intervalo de
entrada menor.
Outra imprecisão que deve ser considerada na conversão analógica-digital é a referente ao tempo de
conversão, que é diferente de zero.
Tempo de conversão
O tempo de conversão é o tempo desde o início de uma conversão até que o resultado desta esteja
disponível.
Atenção
Em consequência, temos certo período de tempo entre a amostragem de duas conversões sucessivas,
resultando em uma perda de informação no domínio do tempo. As mudanças de valor entre duas
conversões são perdidas, portanto, se o sinal lido varia mais rapidamente que o tempo entre conversões,
a sua reconstrução digital será imprecisa.
O limite superior da frequência de entrada máxima que pode ser amostrado e reconstruído por um ADC é
dado pelo teorema de amostragem segundo o critério de Nyquist. Este afirma que a frequência máxima do
sinal de entrada deve ser menor que a metade da frequência de amostragem, que expressa um intervalo em
uma unidade de tempo ou uma taxa em Hertz.
Exemplo
Um intervalo de amostragem de 1 ms significa que o instrumento faz a amostragem uma vez a cada
milissegundo ou 1000 vezes por segundo. O mesmo instrumento pode ser descrito como uma
especificação de taxa de 1 kHz.
É possível facilmente fazer a transição de taxas e intervalos de amostragem tomando o inverso do valor
declarado. Ou seja, uma taxa de amostragem especificada de 1 kHz significa uma amostra a cada 1/1000
segundos, ou um milissegundo.
Comentário
Independentemente de se ver a amostragem como uma taxa ou um intervalo, deve se tomar cuidado
para escolher as especificações do ADC para corresponder à excursão mais rápida esperada dos sinais
que se deseja medir.
ADCs vêm em várias arquiteturas básicas e existem muitas variações para cada tipo. Assim, diferentes tipos
de equipamentos de teste precisam de tipos diferentes de ADCs. Por exemplo, um osciloscópio digital precisa
de alta taxa de amostragem para a reconstrução mais precisa do sinal, mas pode sacrificar a resolução. Por
outro lado, a amostragem de dados de temperatura precisa de maior resolução, podendo sacrificar a taxa de
amostragem.
Quem precisa amostrar a temperatura, com um sensor como um termopar, a uma taxa de 10 kHz
(uma amostragem a cada 100 µS), sendo que esta é uma grandeza de alteração lenta?
ADC de aproximações sucessivas
Um ADC baseado em registrador de aproximação sucessiva é a arquitetura mais popular, com muitas opções
disponíveis, cobrindo uma ampla faixa de resolução e velocidade a um custo acessível.
Esses ADCs modernos estão disponíveis em resoluções de 8–18 bits, com taxas de amostragem de
até dezenas de mega amostras por segundo.
A entrada analógica desse ADC é comparada sucessivamente com a tensão gerada por um conversor digital-
analógico (DAC). A entrada digital para DAC, que fica armazenada no registrador de aproximação sucessiva, é
ajustada de acordo com o resultado de cada comparação. Se o conversor for de n bits, o processo de
conversão requer n comparações, e o resultado da conversão é o valor final armazenado no registrador.
O processo de conversão para esse ADC é o seguinte:
Passo 1
O bit mais significativo do SAR é definido com valor 1, fazendo com que a saída DAC interno vá para o
meio da escala.
Passo 2
A saída do decodificador é comparada com o sinal analógico de entrada. Se o sinal analógico for
maior que a saída do DAC, então um 1 lógico é registrado para o bit mais significativo. Se o sinal for
menor que a saída DAC, o valor do bit é substituído por um zero lógico.
Passo 3
O registrador de aproximação então vai para o próximobit e tenta a lógica 1 para o mesmo, que define
a saída DAC para a escala 1⁄4 ou escala 3⁄4, que é comparada ao sinal de entrada. Esse processo de
comparação é repetido por n bits até que o sinal seja convertido.
Programando ADCs em microcontroladores
Para testar os ADCs em microcontroladores, é preciso alterar a tensão de entrada nos pinos correspondentes.
Veremos como fazer isso usando potenciômetros, que trabalham como divisores de tensão − circuitos
passivos simples que aproveitam o efeito da queda das tensões nos componentes conectados em série. Eles
são úteis para fornecer diferentes níveis de tensão a partir de uma tensão de alimentação comum.
Exemplo
Por exemplo, pode-se colocar uma resistência em um circuito e passar uma corrente através dela, de
modo que se possa ver a variação resultante.
Na imagem 8, os dois resistores (R1 e R2) estão em série e a tensão de saída (Vsaída), que pode ir para a
entrada ADC do microcontrolador, é proporcional à relação dos resistores. Se eles são iguais, então a tensão
de saída é metade da tensão de entrada (Ventrada).
Imagem 8: Divisor de tensão.
Saiba mais
O potenciômetro, que é um resistor variável com um contato deslizante, é o exemplo mais básico de um
divisor de tensão, pois podemos aplicar uma tensão em seus terminais e produzir uma tensão de saída
em proporção à posição mecânica de seu contato deslizante.
Exemplo para a plataforma Arduino
Como já vimos, nem todas as entradas de um
microcontrolador têm a capacidade de fazer
conversões analógicas para digitais. Na placa
do Arduino Uno são seis entradas, que têm um
"A" na frente de sua etiqueta (A0 a A5).
ADCs podem variar muito em suas
especificações entre os microcontroladores. O
ADC no Arduino Uno é de 10 bits, o que
significa que tem capacidade para detectar
1.024 (210) níveis analógicos discretos. Assim, o
ADC do Arduino Uno com 5 V na sua entrada
converte para um valor binário de 1023. Os
valores intermediários serão proporcionais.
A taxa de amostragem em uma placa de Arduino Uno depende, em primeiro lugar, do clock usado. Para um
Arduino de 16 MHz, o clock do ADC é ajustado para 16 MHz/128 = 125 KHz. Cada conversão leva 13 ciclos de
clock do ADC, ou 125 KHz /13 = 9615 Hz. Essa é, portanto, a taxa de amostragem máxima possível. Porém, a
taxa de amostragem real depende do intervalo entre as chamadas de conversões sucessivas.
As principais funções para acionar o ADC na IDE do Arduino são:
analogRead(): Lê o valor do pino analógico especificado.
analogReference(): Configura a tensão de referência usada para entrada analógica, ou seja, o valor
usado como o topo do intervalo de entrada. As opções são:
DEFAULT: a referência analógica padrão de 5 volts (em placas 5 V Arduino) ou 3.3 volts (em placas 3.3
V Arduino).
INTERNAL: uma referência interna, igual a 1,1 volts no ATmega328P.
EXTERNAL: a tensão aplicada ao pino AREF (apenas 0 a 5 V) é usada como referência.
•
•
•
•
•
O código a seguir pode ser testado no simulador Tinkercad com a montagem mostrada na Imagem 9. Ele faz a
leitura da entrada analógica A0 da placa Arduino, onde está ligado o terminal central de um potenciômetro.
Esse terminal tem a sua tensão variada entre 5 V e 0 V quando se gira o potenciômetro. Em seguida, o valor
lido que está na variável sensorValor é convertido para o valor de tensão correspondente entre 0 V e 5 V. Esse
valor, na variável tensao, é enviado para o terminal serial do simulador com a função Serial.println(tensao).
c
void setup() {
Serial.begin(9600);
}
void loop() {
int sensorValor = analogRead(A0);
// Converte a leitura analógica (que vai de 0 - 1023) para tensão (0 - 5V):
float tensao = sensorValor * (5.0 / 1023.0);
Serial.println(tensao); //Envia dado pela porta serial
}
Imagem 9: Diagrama para montagem do projeto no Tinkercad.
Observe que um simulador de multímetro foi montado no circuito para comparar com o valor convertido e
enviado para o terminal serial, que deve ser o mesmo da leitura do multímetro.
Exemplo para PIC
PIC16f628
Esse modelo, que é usado na placa 1 do PICSimLab, possui comparadores, não ADC. A saída do comparador é
um sinal digital que indica qual das entradas tem o maior valor. Por não possui ADC, a placa 1 do PicSimLab
não poderá ser usada neste exemplo. Usaremos a placa 4, que possui um modelo de microcontrolador com
ADC interno.
Comparadores
Comparador, na linguagem eletrônica, é um dispositivo analógico que compara dois valores de tensão.
PIC18F4550
Vários modelos de PIC possuem ADC. Um deles é o PIC18F4550, que pode ser usado no PicSimLab na placa
4. O microcontrolador PIC18F4550 possui 13 canais ADC de 10 bits.
Sobre o controle do ADC no compilador CCS C, veja:
Registradores associados
Os registradores associados ao controle do ADC no compilador CCS C são:
ADCON0: Usado para ligar o ADC, selecionar a frequência de amostragem e também iniciar a
conversão.
ADCON1: Usado para configurar os pinos E/S para o ADC.
ADRESH: Mantém o byte mais alto do resultado do ADC.
ADRESL: Mantém o byte mais baixo do resultado do ADC.
Principais funções
As principais funções para acionar o ADC no compilador CCS C são:
setup_adc( ADC_CLOCK_INTERNAL ): Configura o conversor AD.
setup_adc_ports( AN0 ): Configura as portas usadas pelo conversor AD. No caso, a porta AN0.
set_adc_channel(0): Determina o canal a ser utilizado.
O código que usaremos irá medir a variação de tensão na entrada RA0 da placa 4 do PicSimLab. Ele pode ser
usado para perceber uma variação no potenciômetro 1 da placa 4 do PicSimLab.
Comentário
Veja que os dados são enviados para um mostrador de cristal líquido LCD (Liquid Crystal Display)
integrado à placa, para que possamos ver o resultado da conversão.
A função para acionar o LCD no compilador CCS C é a bem conhecida printf(). Para que ela funcione, é
preciso definir a ligação dos pinos de dados e controle do LCD aos pinos corretos do microcontrolador,
conforme a ligação da placa 4 do simulador. A linha 1 do LCD apresenta a leitura em valor de 0 a 1023 e a linha
2, a tensão correspondente.
•
•
•
•
•
•
•
c
#include
#device adc=10
#fuses HS, MCLR, NOWDT
#use delay(clock=20MHz)
#define LCD_DB0 PIN_D0
#define LCD_DB1 PIN_D1
#define LCD_DB2 PIN_D2
#define LCD_DB3 PIN_D3
#define LCD_DB4 PIN_D4
#define LCD_DB5 PIN_D5
#define LCD_DB6 PIN_D6
#define LCD_DB7 PIN_D7
#define LCD_E PIN_E1
#define LCD_RS PIN_E2
#include
void main () {
unsigned int16 valor;
float tensao;
lcd_init();
setup_adc( ADC_CLOCK_INTERNAL );
setup_adc_ports( AN0 );
set_adc_channel(0);
while(true) {
valor = read_adc();
tensao = valor / 1023.0 * 5.0;
printf(LCD_PUTC, "\fValor: %lu\n", valor);
printf(LCD_PUTC, "Tensao: %f", tensao);
delay_ms(100);
}
}
Simulando conversores analógico-digitais
Assista ao vídeo a seguir e acompanhe uma simulação dos conversores analógico-digitais.
Conteúdo interativo
Acesse a versão digital para assistir ao vídeo.
Verificando o aprendizado
Questão 1
O seu colega de projeto informa que precisa amostrar um sinal a cada 1 µs (microssegundo). Qual o tipo de
especificação do ADC que você deve procurar e qual o valor dessa especificação?
A
Taxa de amostragem de pelo menos 1 MHz (mega Hertz).
B
Resolução de pelo menos 12 bits.
C
Taxa de amostragem de pelo menos 100 kHz (kilo Hertz).
D
Resolução de pelo menos 1 μs.
E
Intervalo de amostragem de pelo menos 1MHz (mega Hertz).
A alternativa A está correta.
A amostragem de um sinal a cada indica o intervalo de amostragem. O inverso do intervalo é a taxa
de amostragem, que é dada em unidade de frequência (Hertz). Para um intervalo de ( )
temos uma frequência de
ou seja, 1 MHz.
Questão 2
O microcontrolador PIC18F4550 é de 8 bits e possui ADCs de 10bits. Como ele armazena os 10 bits do
resultado da conversão do ADC?
A
O resultado é guardado na memória.
B
O resultado é guardado em registrador especial de 10 bits.
C
O resultado é guardado em dois registradores específicos de 8 bits.
D
O resultado é guardado em um só registro em intervalo de tempo diferente.
E
Dois bits do resultado são dispensados.
A alternativa C está correta.
É comum que microcontroladores precisem guardar informações com mais bits do que os seus
registradores podem guardar, como em conversões analógica-digitais com mais bits em microcontroladores
de famílias com menos. Nesses casos, como o do modelo PIC18F4550, devem existir registradores
específicos para guardar os 8 bits menos significativos, e os bits mais significativos que sobrarem, em
outro. No caso do PIC18F4550, são os registradores ADRESL e ADRESH.
3. A importância do uso de temporizadores e contadores para o desenvolvimento de sistemas de tempo
real com microcontroladores
Aplicações de temporizadores e contadores
Contadores e temporizadores são provavelmente os periféricos complexos mais comumente usados em um
microcontrolador.
Um temporizador é um dispositivo periférico extremamente comum que pode medir intervalos de
tempo.
Ele pode ser usado para gerar eventos em intervalos de tempo específicos ou para determinar a duração entre
dois eventos externos.
Exemplo
Exemplos de aplicações que exigem a geração
de eventos incluem manter um semáforo verde
por um período especificado ou comunicar bits
em série entre dispositivos em uma taxa
específica. Já um exemplo de aplicação que
determina a duração entre eventos é o de
calcular a velocidade de um carro medindo o
tempo que este leva para passar por dois
sensores separados em uma estrada.
Outras aplicações podem incluir medir a
rotação do motor de um carro, cronometrar um período de tempo exato − como o necessário para
cronometrar a velocidade de uma bala −, produzir tons para criar música, acionar o sistema de ignição de um
carro ou fornecer uma largura de pulso ou unidade de frequência variável para controlar a velocidade de um
motor.
Um contador é uma versão mais geral de um temporizador.
Em vez de pulsos de clock, conta pulsos em algum outro sinal de entrada. Pode, por exemplo, ser usado para
contar o número de carros que passam por um sensor de estrada ou o número de pessoas que passam por
uma catraca. Muitas vezes combinamos contadores e temporizadores para medir as taxas, como contar o
número de vezes que a roda de um carro gira em um segundo, a fim de determinar a velocidade de um carro.
Atenção
Embora esses circuitos sejam usados em dois modos distintos, temporização e contagem, eles são
simplesmente contadores binários. Quando usados no modo de temporização, os contadores binários
estão contando períodos de tempo (pulsos que ocorrem em um sinal de clock de entrada com um
período conhecido) aplicados à sua entrada. No modo de contador eles estão contando os eventos ou
pulsos ou algo dessa natureza.
A principal vantagem dos temporizadores e contadores é que eles funcionam de forma independente da CPU
do microcontrolador, e os valores do temporizador podem ser lidos sempre que necessário. Basicamente, um
microcontrolador padrão possui um ou mais módulos de temporizadores de hardware de diferentes
comprimentos em bits.
Configurações dos temporizadores e contadores
Cada temporizador é basicamente um contador que é incrementado ou decrementado a cada ciclo do clock. A
direção (contador para cima ou para baixo) é fixa ou configurável. O valor de contagem atual pode ser lido por
meio de um registrador de contagem e pode ser definido como um valor específico pelo usuário. Para uma
resolução de temporizador de n, o valor da contagem está dentro de [0, 2n - 1].
Deve-se ter cuidado quando o comprimento do temporizador excede o comprimento da palavra do
microcontrolador, por exemplo, ao usar um temporizador de 16 bits em um controlador de 8 bits. Nesse caso,
o acesso ao valor de contagem de 16 bits deve ser feito em duas passagens, o que pode levar a valores
inconsistentes.
Exemplo
Tomemos como exemplo um temporizador com o valor 0x00FF que mudará para 0x0100 no próximo
ciclo. Ao ler o byte superior primeiro e o byte inferior com a próxima instrução, obteremos 0x0000. Se
fizermos ao contrário, acabaremos com 0x01FF, o que não é melhor. Para combater esses problemas,
alguns microcontroladores − como o ATmega16, por exemplo − usam um registrador de buffer para
armazenar o byte alto do temporizador. Assim, sempre que o programa lê o byte inferior do registrador
de contagem, o byte superior é simultaneamente armazenado no buffer e pode ser lido no próximo ciclo.
Em geral, os temporizadores podem gerar uma interrupção sempre que houver um estouro (overflow) do valor
de contagem. Isso pode ser usado para implementar um sinal periódico rudimentar, definindo o valor de
contagem para um determinado valor inicial e, em seguida, aguardando o estouro. No entanto, esse método
não fornece um período preciso porque, após o overflow, o temporizador deve ser configurado para seu valor
inicial pelo programa. Em consequência, o tempo do estouro até o valor inicial ser recarregado no
temporizador deve ser considerado e incorporado ao valor inicial, ou o período será mais longo do que o
desejado.
Comentário
Para evitar essa desvantagem, alguns temporizadores fornecem um modo de módulo que recarrega
automaticamente o valor inicial quando o temporizador gerar overflow.
Embora o temporizador geralmente seja cronometrado pela mesma fonte que o próprio microcontrolador, este
não precisa ser o caso. Os microcontroladores podem permitir uma ou mais das seguintes fontes para
cronometrar o temporizador:
Relógio do sistema (relógio interno)
Nesse modo, que é o padrão, o temporizador é incrementado a cada ciclo do clock do sistema. O
termo “interno” se refere apenas ao fato de que essa é a fonte de clock que todo o microcontrolador
usa. O oscilador responsável por isso pode muito bem ser externo.
Prescaler
Esse modo também usa o relógio do sistema, mas filtrado por um prescaler − outro contador de
comprimento variável (8 ou 10 bits são valores típicos), que é incrementado com o clock do sistema.
O próprio temporizador, entretanto, é cronometrado por um dos bits do prescaler. O módulo do
temporizador fornece bits de modo que permitem ao usuário selecionar alguns valores predefinidos
(8, 64, 256 etc.) que são usados para dividir a frequência de entrada.
É importante perceber que, embora o prescaler seja útil para estender o intervalo do temporizador,
isso tem o custo de uma granularidade mais grosseira do mesmo.
Por exemplo, ao usar um temporizador de 8 bits a 1 MHz, seu intervalo será de 255 μs e sua
granularidade será de 1 μs. O mesmo temporizador, com um prescaler de 1024, terá um intervalo de
aproximadamente 260 ms, mas sua granularidade será de apenas cerca de 1 ms. Portanto, um
temporizador pré-escalado é capaz de medir durações mais longas, mas o erro de medição também é
maior.
Assim, um temporizador pré-escalado permite que o programa espere por um período de tempo mais
longo, mas quanto maior o valor pré-escalado, menos provável será o cronômetro conseguir esperar
precisamente por um determinado período arbitrário. Como consequência, geralmente é prudente, ao
medir as durações, usar o menor valor do prescaler que se adapte às necessidades da aplicação para
obter a melhor granularidade das opções disponíveis.
Pulso externo (acumulador de pulso)
Neste modo, o temporizador obtém seu clock de um sinal externo que está conectado a um
determinado pino de entrada do controlador. O temporizador aumenta o seu valor de contagem de
acordo com o sinal, por exemplo, sempre que uma borda ascendente no pino de entrada for
observada. Visto que o sinal externo é amostrado como qualquer outro sinal de entrada, o tempo
entre as bordas deve ser maior do que um ciclo de clock do sistema.
Cristal externo (modo assíncrono)
O temporizador é cronometrado porum cristal externo que é conectado a dois pinos de entrada do
controlador. Esse modo é geralmente projetado para um clock de cristal de 32,768 kHz, que pode ser
usado para implementar um clock em tempo real (RTC). O contador é incrementado de acordo com o
sinal externo e opera de forma assíncrona com o resto do microcontrolador.
Captura de entrada e comparação de saída
O recurso de captura de entrada é usado para registrar a data e a hora (principalmente externos) de eventos,
que podem ser bordas ascendentes e/ou descendentes.
Sempre que o evento ocorre, o temporizador copia automaticamente seu valor de contagem atual para
um registrador de captura de entrada, onde pode ser lido pelo programa.
•
Ele também define o sinalizador de captura de entrada e pode gerar uma interrupção para notificar a
aplicação de que um evento de captura de entrada ocorreu.
Microcontroladores podem fornecer um ou mais pinos com funcionalidade de captura de entrada.
O recurso de comparação de saída é a contrapartida da captura de entrada. Para o último, o registro de data e
hora é armazenado sempre que algo acontece na linha de entrada. Com a comparação de saída, algo
acontece em uma linha de saída quando um determinado tempo é atingido.
Para implementar esse recurso, o temporizador oferece um registrador de comparação de saída, onde é
possível inserir a hora em que o evento de comparação de saída deve acontecer. Sempre que o valor do
contador atinge esse valor, o evento de comparação de saída é acionado. Ele pode definir ou limpar
automaticamente uma linha de saída ou até mesmo alternar seu estado. Ele também pode não fazer nada e
simplesmente gerar uma interrupção interna.
Atenção
A comparação de saída geralmente vem com uma opção para redefinir automaticamente o contador
quando o valor de comparação for alcançado. Isso permite configurar uma interrupção periódica (ou
sinal de saída) com um mínimo de esforço.
Contador/temporizador nos microcontroladores
No PIC18F4550, existem temporizadores de 8 e 16 bits. O temporizador usa o clock interno como um relógio
de referência, enquanto o contador conta ciclos externos ou pulsos aplicados através dos pinos da porta. O
PIC18F4550 possui quatro temporizadores de hardware: Timer 0, Timer 1, Timer 2, Timer 3. O Timer 2 é de 8
bits, ou seja, conta de 0 a 255 e todos os outros são de 16 bits, contando de 0 a 65535. O PIC16F628A possui
três temporizadores: Timer 0, de 8 bits; Timer 1, de 16 bits; e Timer 2, de 8 bits.
Os microcontroladores ATmega328 da plataforma Arduino possuem 3 temporizadores: Timer 0, Timer 1 e
Timer 2. Timer 0 e Timer 2 são contadores de 8 bits e o Timer 1 é um contador de 16 bits.
Existem funções da IDE do Arduino que usam temporizadores específicos.
Timer 0
O Timer 0 é utilizado pelo Arduino Uno para funções como delay(), millis() e micros(). Então, não se
deve utilizar esse temporizador para evitar comprometer essas funções.
•
Timer 1
No Arduino Uno esse é o temporizador utilizado pela biblioteca de controle de servos. Caso não
esteja utilizando essa biblioteca, esse temporizador está livre para ser utilizado para outros
propósitos.
Timer 2
Esse temporizador é utilizado pela função tone(). Então, caso não precise da função tone(), esse
temporizador está livre para outras aplicações.
Programando temporizadores em microcontroladores
Temporizadores e interrupção no PIC
Os microcontroladores, de forma geral, executam o programa sequencialmente, instrução após instrução.
Uma interrupção é um evento que para a execução do programa e chama uma função para tratar a
parada.
Após o fim dessa função, a execução normal do programa é retomada de onde parou. Os temporizadores
podem ser configurados para, quando atingirem o valor máximo da contagem (overflow), gerarem uma
interrupção e chamarem uma função específica.
Para calcular o tempo entre interrupções com precisão, utiliza-se também um prescaler, a parte que divide a
frequência de oscilação do clock de um microcontrolador. O tempo da interrupção é calculado da seguinte
forma:
Onde o período depende se o contador é de 8 bits (período = 256) ou 16 bits (65536). O ciclo de máquina
depende do microcontrolador. Em geral é de 1/4 do clock.
O programa abaixo pode ser usado na placa 1 do PicSimLab com o PIC16F628A.
c
#include
#fuses XT, MCLR, NOWDT
#use delay(clock=4MHz)
int cont = 0;
#INT_TIMER0
void interrupcao_t0() {
clear_interrupt(INT_TIMER0);
if (cont == 1000) {
output_toggle(PIN_B1);
cont = 0;
}
cont++;
}
void main() {
enable_interrupts(GLOBAL);
enable_interrupts(INT_TIMER0);
setup_timer_0(T0_INTERNAL | T0_DIV_1);
while (true) {
output_toggle(PIN_B0);
delay_ms(1000);
}
}
Observe que existem dois leds piscando. Um, na saída RB0, usa a função delay_ms, já utilizada antes. O outro,
em RB1, está piscando baseado na interrupção do timer 0.
A diretiva #INT_TIMER0 define que a função a seguir (void interrupcao_t0) é chamada no overflow do contador
do timer 0. Ela limpa a interrupção (clear_interrupt(INT_TIMER0)) para permitir que a próxima seja chamada.
Veja que ela usa um contador adicional de 1000 para acender ou apagar o led em RB1.
Na função main temos a habilitação das interrupções e da interrupção do timer 0. A função setup_timer_0
configura o timer 0 com o clock interno e sem prescaler (T0_DIV_1). Esse valor pode dividir o clock interno em
valores de 2, 4, 8, 16, 32, 128 e 256. Como o período é 256, o prescaler é 1 e ciclo de máquina de 1 μs (¼ do
clock de 4 MHz), o intervalo entre interrupções nesse caso é igual a 256us. Com o contador adicional de 1000
utilizado para acender ou apagar o led em RB1, o led piscará em intervalo de 256 μs x 1000, ou seja, 256 ms.
Comentário
O uso das funções, específicas para cada microcontrolador em cada IDE, torna o hardware de baixo nível
ocultado. O acesso aos registradores não é mostrado e muitas vezes usamos funções com
temporizadores sem o conhecimento desses registradores.
Temporizadores e interrupção no Arduino
Conforme foi visto, muitas funções do Arduino usam temporizadores, como as funções de tempo: delay () e
millis (). Não é comum o uso de interrupção por overflow do timer no Arduino. Embora existam algumas
bibliotecas, feitas por terceiros, que podem ajudar na tarefa, em geral, para realizar interrupção por timer, é
necessário acessar os registradores do microcontrolador ATmega328.
O exemplo a seguir mostra esse acesso para piscar o led L da placa Arduino Uno sem usar função de atraso
(delay).
Observe o acesso aos registradores do microcontrolador para realizar a tarefa simples de piscar o led a cada
segundo. Porém, esse código não ocupa a CPU com funções de atraso. Outras funções de monitoração e
controle poderiam ser executadas, o que é uma grande vantagem.
c
#define ledPin 13
void setup()
{
pinMode(ledPin, OUTPUT);
// Configuração do timer1
TCCR1A = 0;//configura timer para operação normal. Pinos OC1A e OC1B desconectados
TCCR1B = 0; //limpa registrador
TCCR1B |= (1B
4
C
33
D
61
E
123
A alternativa D está correta.
Tempo entre chamadas de interrupção = prescaler * período * ciclo de máquina. Logo, Tempo de
interrupção = 1*65536*(0,5*10-6)s = 32,768*10-3s. Com isso, para completar 2 segundos, X deve ser
2/32,768*10-3, ou X aproximadamente 61.
Questão 2
Foi solicitado a você um programa para microcontrolador que verifica o número de pulsos
elétricos de tensão advindos de um detector de radiação a cada segundo, o que corresponde a uma
taxa de radiação. Qual/quais circuito(s) interno(s) ao microcontrolador você deve utilizar para
realizar a tarefa?
A
Contador
B
Temporizador
C
Contador e temporizador
D
Prescaler e temporizador
E
Delay e contador
A alternativa C está correta.
O contador pode ser usado, nesse caso, para contar os pulsos do detector. Mas, para termos a taxa de
radiação, ou seja, o número de pulsos provenientes do detector de radiação por unidade de tempo,
precisamos também de um temporizador que determine esse intervalo de tempo. O temporizador pode,
então, ao final do intervalo de tempo especificado, gerar uma interrupção que chamará uma função para
calcular a taxa. Veja que os dois circuitos podem funcionar de forma independente da CPU.
4. O uso da Modulação por Largura de Pulso (PWM) para o controle de dispositivos externos
Sistema eletrônico
De forma geral, um sistema eletrônico simples consiste em uma entrada, um processo e uma saída, com a
variável de entrada para o sistema e a variável de saída do sistema sendo ambos sinais elétricos. Nele, existe
um processo que transforma um sinal em outro para dar a resposta desejada a ele.
No caso de um sistema eletrônico baseado em processamento por microcontrolador, esses sinais
de entrada e saída podem ser, como vimos, digitais ou analógicos.
Uma saída analógica é necessária para atuar em dispositivos que são acionados por níveis de tensão com
variação contínua. Examinaremos dispositivos que são acionados dessa forma e como um microcontrolador
pode acioná-los.
Motor DC
Podemos exemplificar um sistema eletrônico simples com o acionamento de um motor DC (direct current) em
resposta ao apertar de um botão. O termo "motor DC" é usado para se referir a qualquer máquina elétrica
rotativa que converte energia elétrica de corrente contínua em energia mecânica.
Direct current
Que trabalha com corrente contínua.
Imagem 10: motor DC.
Curiosidade
Eles podem variar em tamanho e potência, desde pequenos motores em brinquedos e eletrodomésticos
até grandes mecanismos que acionam veículos, puxam elevadores e acionam laminadores de aço.
Mas como funcionam os motores DC?
Chave de resposta
Os motores DC incluem dois componentes principais: um estator e uma armadura. O estator é a parte
estacionária de um motor, enquanto a armadura gira. O primeiro componente fornece um campo
magnético giratório que aciona a rotação do segundo.
Um motor DC simples usa um conjunto
estacionário de ímãs no estator e uma bobina
de fio com uma corrente passando por ele para
gerar um campo eletromagnético alinhado com
o centro da bobina. Um ou mais enrolamentos
de fio isolado são enrolados ao redor do núcleo
do motor para concentrar o campo magnético.
Os enrolamentos do fio isolado são conectados
a um comutador (uma chave rotativa elétrica),
que aplica uma corrente elétrica aos
enrolamentos. O comutador permite que cada
bobina da armadura seja energizada por sua
vez, criando uma força de rotação constante
(conhecida como torque).
Quando as bobinas são ligadas e desligadas em sequência, um campo magnético giratório é criado e interage
com os diferentes campos dos ímãs estacionários no estator para criar torque, o que faz com que ele gire.
Esses princípios operacionais fundamentais dos motores DC permitem que eles convertam a energia elétrica
da corrente contínua em energia mecânica por meio do movimento de rotação, que pode então ser usada
para a propulsão de objetos.
Aplicações de motores DC
Graças aos diferentes tipos de motores DC disponíveis, há uma grande variedade de aplicações, conforme
mencionamos anteriormente. Em casa, pequenos motores DC são usados em ferramentas, brinquedos e
diversos eletrodomésticos. No varejo, as aplicações incluem transportadores e plataformas giratórias,
enquanto em um ambiente industrial, grandes motores DC também incluem aplicações de freio e reversão.
A seguir, estão alguns usos mais específicos para motores DC:
Motores DC para ventiladores
Embora tradicionalmente usem motores AC (corrente alternada), há um número
crescente de ventiladores de teto com motor DC chegando ao mercado. Eles
estão ganhando popularidade porque são muito mais econômicos do que seus
equivalentes AC. A única desvantagem real para o ventilador do motor DC é seu
custo, mas a economia de energia pode compensar isso.
Motores DC para bombas
As bombas hidráulicas são ferramentas industriais essenciais, usadas em quase
todas as indústrias, incluindo: construção, mineração, manufatura e aço. Os
motores DC são usados para alimentar essas bombas devido ao seu fácil
controle de velocidade variável e excelente resposta.
Motores DC para brinquedos
Essa é uma escolha popular para fabricantes e amadores, com esses "motores
de brinquedo" frequentemente usados em brinquedos infantis, como carros de
controle remoto e modelos de trens. Pequenos motores DC funcionam bem
nesta configuração, pois são fáceis de usar e extremamente robustos.
Motores DC para carros elétricos
Embora haja uma variedade de tipos de motores diferentes usados em carros
elétricos, os motores DC são amplamente utilizados devido à sua eficiência
energética e durabilidade. Além de fabricantes profissionais, muitos amadores e
fabricantes de kits de carros preferem motores DC grandes para seu torque
inicial mais alto.
Motores DC para robôs
Um robô é qualquer dispositivo eletromecânico projetado para realizar uma
tarefa específica. Nesse caso, os motores DC são usados para "acionar" algo,
como esteiras, braços ou câmeras, sendo particularmente populares nessa área
de robótica por possuírem alto torque e eficiência.
Motores DC para bicicletas
As bicicletas elétricas, populares porque não exigem licença, usam um motor
DC compacto embutido na roda traseira ou dianteira, ou montado no centro da
bicicleta e conectado à roda dentada do pedal. Para garantir os níveis de
potência e o torque necessários, os motores DC sem escovas são normalmente
os usados.
Acionamento de motores DC com PWM
Se um motor DC funciona com corrente contínua e sua velocidade é proporcional a esta, conclui-se que
podemos controlar a velocidadedesse motor usando a saída de um microcontrolador onde seja possível
controlar o nível de tensão contínua. Essa saída é de um conversor digital-analógico (DAC), que é mais raro
em microcontroladores. Uma saída de modulação por largura de pulso (pulse width modulation ou PWM),
porém, é muito comum.
Atenção
PWM é o esquema no qual o ciclo de trabalho (duty cicle) de uma onda quadrada é variado para
fornecer uma saída contínua variável, filtrando a forma de onda de saída real para obter um valor médio.
O modo de modulação por largura de pulso é um caso especial de comparação de saída. Nele, o
temporizador gera um sinal de saída digital periódico com tempo e período configuráveis.
Como é mostrado na imagem abaixo, variando o ciclo de trabalho (percentual do ciclo que é alto ou ON),
varia-se a tensão contínua média da forma de onda. A forma de onda é então usada para controlar
dispositivos analógicos, criando um conversor digital para analógico (DAC).
Imagem 11: Esquema do PWM.
A realização interna do PWM é bastante simples e usa apenas o contador e duas comparações. Nos
compiladores para microcontroladores com pinos de saída PWM, existem funções específicas que permitem
ao programador controlar o percentual de tempo em nível alto, controlando, assim, o valor médio da tensão
contínua nessa saída.
A potência aplicada ao motor pode ser controlada variando a largura desses pulsos aplicados e, assim,
variando a tensão DC média aplicada aos terminais dos motores. Alterando ou modulando o tempo desses
pulsos, a velocidade do motor pode ser controlada, ou seja: quanto mais tempo o pulso estiver “ON”, mais
rápido o motor irá girar e, da mesma forma, quanto mais o pulso estiver “OFF”, mais lento o motor vai girar.
Em outras palavras, quanto maior a largura do pulso, mais tensão média aplicada aos terminais do motor, mais
forte será o fluxo magnético dentro dos enrolamentos da armadura e mais rápido o motor irá girar.
Programando PWM em microcontroladores
Saídas com PWM em microcontroladores da plataforma Arduino
Dos 14 pinos de E/S do Arduino Uno, 6 podem ser usados como saídas PWM. A função analogWrite() é usada
para este fim, controlar o ciclo de trabalho nessas saídas. Essa função recebe dois parâmetros: o primeiro é o
pino a ser controlado e o segundo é a quantidade de tempo que o pino permanecerá no nível alto (ON). A
imagem abaixo mostra exemplos de ciclo ativo (ciclo de trabalho ou duty cycle) que podem ser atribuídas às
saídas PWM dos pinos 3, 5, 6, 9, 10 e 11 do Arduino UNO, com a função analogWrite(). A frequência dos
pulsos é fixa em 490Hz.
Imagem 12: Atuação da função analogWrite() na IDE do Arduino.
Um exemplo de motor DC acionado por pressionar um botão é mostrado na Imagem 13. Na montagem,
realizada no simulador Tinkercad, um motor DC é ligado ao pino 10 e ao terra (GND) de uma placa Arduino
UNO. Um botão de pressão liga o pino 6 ao GND quando acionado.
Imagem 13: Montagem no Tinkercad para acionamento de um motor DC.
O código para processar o acionamento do motor ao se pressionar o botão é mostrado a seguir:
c
void setup() // Executado apenas uma vez
{
pinMode(10, OUTPUT);
pinMode(6, INPUT_PULLUP);
}
void loop()
{
if (digitalRead(6) == LOW){
analogWrite(10, 255);
}
else{
analogWrite(10, 0);
}
}
Atenção
Veja que é necessário colocar o modo do pino de entrada do botão (pino 6) em INPUT_PULLUP para
garantir que, quando o botão não estiver pressionado, o nível lógico será 1 (HIGH).
O código em loop apenas verifica se o pino 6 está ligado ao GND, isto é, se o botão está pressionado (LOW
no pino 6). Caso esteja, a função analogWrite() manda o valor 255 para o pino 10, o que significa enviar um
nível DC constante, ou seja, máxima tensão para o motor DC e máxima velocidade. É um bom exercício criar
uma variação no programa que permita alterar a velocidade entre 0, 25%, 50%, 75% e 100% ao se pressionar
o botão.
Saídas com PWM em microcontroladores PIC
No modelo PIC18F4550, somente o Timer 2 pode ser usado para geração de PWM. Este é um registrador de 8
bits que é utilizado para armazenar a contagem, usado como base de tempo para a modulação PWM.
A frequência de saída pode ser calculada por:
O prescaler do Timer 2 pode ser 1, 4 ou 16.
PR2 é carga do Timer 2, que também é chamado de período, podendo ser de 0 a 255.
Considerando a utilização de um cristal de 4 Mhz, temos que um PR2 de 124 fornece uma frequência de 500
Hz.
Com esses valores, é possível configurar a frequência do PWM com a seguinte função no compilador CCS,
configurando o Timer 2:
c
setup_timer_2(T2_DIV_BY_16, PR2, 1);
Onde o primeiro parâmetro ajusta o prescaler para 16, o segundo passa o valor PR2 (124 para 500 Hz) e o
terceiro é um poscaler, mantido no valor padrão 1.
O ciclo de trabalho ou duty cycle pode ser configurado pela função set_pwm1_duty(DC), onde DC deve ter o
valor:
Onde P é o valor percentual desejado para duty cycle.
O código a seguir pode ser usado na placa 4 do PicSimLab, que possui a ventoinha ligada no pino RC1 do
PIC18F4550, uma das duas saídas que podem ser usadas como PWM nesse microcontrolador. É possível criar
uma variação no programa que permita alterar a velocidade do motor.
c
#include
#fuses XT, MCLR, NOWDT
#use delay(clock=4MHz)
void main() {
unsigned int16 P;
unsigned int16 PR2;
unsigned int16 DC;
PR2 = 124;
P = 50; // 50% de duty cycle ou metade da máxima potência
setup_timer_2(T2_DIV_BY_16, PR2, 1);
setup_ccp1(CCP_PWM);
DC = (unsigned int16)((PR2 + 1) * 4 * (P/100.0));
set_pwm1_duty(DC);
while(true) {
}
}
Os exemplos mostrados nos simuladores para Arduino e PIC indicam um acionamento direto dos motores pelo
pino dos microcontroladores com função PWM. Porém, para a maioria dos motores, o acionamento não
poderá ser feito diretamente devido às limitações no valor de corrente que um microcontrolador possui. Se
quisermos controlar motores DC usando microcontroladores, precisamos de algo conhecido como driver de
motor.
Eles atuam como uma interface entre os motores e os circuitos de controle. O motor, em geral, requer mais
quantidade de corrente do que o microcontrolador pode dispor em seus pinos. Portanto, a função dos drivers
de motor é pegar um sinal de controle de baixa corrente e transformá-lo em um sinal de corrente mais alta
que pode acionar um motor DC. Dessa forma, existem diversos drivers que devem se adequar ao motor e ao
microcontrolador.
Drivers específicos podem ser usados para permitir que se use um microcontrolador para controle de cargas
maiores de outros tipos, como resistências de aquecimento de um forno, motores de passo, servo motores,
acionamento pneumático e diversos outros tipos atuadores.
Simulando o uso de modulação por largura de pulso (PWM)
Assista ao vídeo a seguir e acompanhe uma simulação do uso de modulação por largura de pulso (PWM).
Conteúdo interativo
Acesse a versão digital para assistir ao vídeo.
Verificando o aprendizado
Questão 1
Quais das afirmações a seguir estão corretas com relação a PWM?
I - PWM é um sinal de frequência constante.
II – Ciclo de trabalho é a razão entre o tempo de duração da onda ligada e o período do sinal PWM.
III – Um PWM de frequência menor permite um ciclo de trabalho maior.
A
I e II.
B
I e III.
C
II e III.
D
Somente