Documente Academic
Documente Profesional
Documente Cultură
com
a
n
e
s
o
i
g
r
é
s
o
i
n
ó
t
n
a
microcontroladores
PIC
www.meca ron ca egaragem. ogspo .com
a
n
e
s
o
i
g
r
é
s
o
i
n
ó
t
n
a
microcontroladores
PIC
www.meca ron ca egaragem. ogspo .com
microcontr oladores PIC Índice
Índice de Conteúdos
Arquitectura Interna.................................................................................. 40
Conjunto de Instruções.............................................................................. 42
Uma panorâmica........................................................................................ 44
Funcionalidades e Funções......................................................................... 80
Temporizadores ......................................................................................... 93
Registo OPTION_REG............................................................................ 94
Registo
Registo ADCON0
ADCON1 ..............................................................................................................................165
..............................................................................................................................167
Resumidamente: .................................................................................................................................167
Directiva END
Directiva ORG ...................................................................................................................................229
...................................................................................................................................229
Directiva .............................................................................................................................................$IN-
CLUDE ..............................................................................................................................................230
Directivas CBLOCK e ENDC ...........................................................................................................230
Directivas IF, ENDIF e ELSE ............................................................................................................231
Directiva BANKSEL .........................................................................................................................232
Em 1969, uma equipa de engenheiros Japoneses da BUSICOM, foi para os EUA com o pedido de desenhar
alguns circuitos integrados para calculadoras. O pedido foi enviado para a INTEL, e Marcian Hoff estava en-
carregue do projecto. Tendo experiência em trabalhar com um computador, o PDP8, ele teve a ideia de sugerir
soluções diferentes, ao invés dos designs sugeridos pelos Japoneses. A ideia dele presumia que o funcionamento
do circuito integrado, era determinado pelo programa armazenado dentro do chip. Significava que a configura-
ção era mais simples, mas iria requerer muito mais memória que o projecto dos engenheiros Japoneses.
Após um certo tempo, apesar de os Japoneses estarem ainda a tentar encontrar uma solução mais simples, a
ideia de Marcian venceu, e o primeiro microprocessador nasceu. Federico Faggin foi uma grande ajuda em
tornar a ideia num produto acabado. E, nove meses após ter sido contratado, a INTEL tinha acabado de de-
senvolver um produto desde a ideia srcinal.
Em 1971, a INTEL obteve os direitos de venda deste circuito integrado, e antes disso já tinha comprado a
licença da BUSICOM. Durante esse ano, um microprocessador chamado 4004 foi lançado no mercado. Esse
foi o primeiro processador de 4 bits, com a velocidade de 6000 instruções por segundo.
Não muito tempo depois, uma empresa Americana chamada CTC pediu à INTEL e TEXAS Instruments,
para fabricarem um microprocessador de 8 bits, para ser aplicado nos seus terminais. Embora a CTC tenha
desistido do projecto, a INTEL e a TEXAS continuaram o trabalho e, em Abril de 1972, o primeiro micro-
processador de 8 bits, chamado de 8008, foi lançado no mercado. Podia endereçar 16Kb de memória, tinha 45
instruções e uma velocidade de 300.000 instruções por segundo. Esse microprocessador foi o predecessor de
Outra empresa Americana chamada MOTOROLA, depressa se apercebeu do potencial, e então lançaram o
microprocessador de 8 bit, 6800. O engenheiro chefe era Chuck Peddle. Aparte do microprocessador, a MO-
TOROLA também fabricava periféricos como o 6820 e 6850.
Nessa altura muitas empresas reconheciam a importância dos microprocessadores, e iniciaram o seu próprio
desenvolvimento. Chuck Peddle deixou a MOTOROLA, juntou-se à MOS Technology, e continuou o traba-
lho intensivo no desenvolvimento em microprocessadores.
Na exposição WESCON, nos EUA em 1975, um evento crucial na história dos microprocessadores aconte-
ceu. A MOS Technology anunciou que estava a vender os processadores 6501 e 6502 a $25 cada, que os inte-
ressados podiam comprar na hora. Foi tamanha a sensação, que muita gente pensava em fraude, considerando
que a concorrência vendia o 8080 e 6800, a $179 cada.
Devido ao seu baixo preço, o 6502 tornou-se muito popular, e então foi instalado em computadores como o
KIM-1, Apple I, Apple II, Atari, Commodore, Acorn, Oric, Galeb, Orao, Ultra e muitos outros.
Em breve, muitas empresas começaram a fabricar o 6502 (Rockwell, Sznertek, GTE, NCR, Ricoh, Commo-
dore assumiram a MOS Technology).
No ano da sua prosperidade, 1982, este processador estava a ser vendido à taxa de 15 milhões de unidades por
ano.
Outras empresas não desistiram. Frederico Faggin deixou a INTEL, e abriu a sua própria empresa chamada
ZILOG INC. Em 1976 a ZILOG anunciou o Z80. Quando desenhou este processador, Faggin tomou uma
decisão crucial. O 8080 já tinha sido desenvolvido, e ele apercebeu-se que muitos iriam continuar fieis a esse
processador, devido aos grandes gastos em reescrever todos os programas. Então, ele decidiu que este novo
processador teria de ser compativel com o 8080, ou seja, teria de poder correr todos os programas escritos para
o 8080.
Aparte desta decisão, muitas outras funcionalidades foram acrescentadas, para que o Z80 fosse o micropro-
cessador mais poderoso da altura. Podia endereçar directamente 64Kb de memória, tinha 176 instruções, um
grande número de registos, uma opção interna para fazer o refrescamento da RAM, só uma fonte de alimenta-
ção, maior velocidade, entre outros. O Z80 foi um grande sucesso, e toda a gente substituiu o 8080 pelo Z80.
Além da ZILOG, outros fabricantes como Mostek, NEC, SHARP e SGS apareceram logo a seguir. O Z80
era o coração de muitos computadores, tais como: Spectrum, Partner, TRS703, Z-3 and Galaxy.
Em 1976 a INTEL lançou uma versão melhorada do microprocessador de 8 bits, chamado de 8085. No en-
tanto, o Z80 era muito melhor, e a INTEL perdeu a batalha.
Mesmo após outros microprocessadores terem aparecido no mercado, 6809, 2650, SC/MP, etc, não havia
grandes melhoramentos que justificasse aos fabricantes mudarem de processador, por isso o 6502, o Z80 e o
6800 continuaram os microprocessadores dominantes, e durante muito tempo.
A primeira, e mais importante, é a sua funcionalidade. Para que um microprocessador possa ser usado, outros
componentes tais como memória, têem que ser ligados ao chip. Mesmo sendo os microprocessador considera-
dos potentes máquinas matemáticas, o seu ponto fraco é a sua parca possibilidade de comunicar com periféri-
cos.
Então, de maneira a que possa comunicar com periféricos, o microprocessador tem que usar circuitos especiais,
como chips externos.
Resumindo, os microprocessadores são o coração dos computadores. Era assim no início, e ainda nos dias de
hoje se mantêm.
Por outro lado, o microcontrolador está desenhado para ser um “tudo-em-um”. Não são necessários componen-
tes externos, para as suas aplicações, porque todos os circuitos, que pertencem aos periféricos, já estão dentro
do chip. Poupa tempo e espaço necessários, aquando do design de um sistema.
Conceitos Básicos
Um mundo de números
O universo por ser descrito com apenas 10 digitos. Mas, precisamos apenas de 10 digitos? Claro que não, é
apenas uma questão de hábito.
Por exemplo, o número 764 o que significa?: quatro unidades, seis dezenas e sete centenas, ou 4 + 60 + 700,
ou 4*1 + 6*10 + 7*100!
Podemos representar o número de uma maneira mais científica? a resposta é positiva: 4*10^0 + 6*10^1 +
7*10^2. Mas porquê? Simplesmente porque usamos um sistema de numeração de base 10, ou seja, um sistema
de numeração décimal.
De maneira a que possamos aprender isto, devemos seguir a mesma lógica do exemplo anterior, mas em ordem
inversa. Não esquecer que se trata de matemática com apenas dois digitos, ou seja, um sistema de numeração
binário.
É o mesmo número, representado de duas formas distintas. A única diferença reside no número de dígitos
necessários para escrever um número. Um dígito (2) é usado para escrever o número 2 em décimal, onde dois
dígitos (1 e 0), são usados para escrever esse número em sistema binário.
É chamado de nível lógico zero (0) e nível lógico um (1), com os quais a electrónica perfeita e simplesmente
trabalha as operações complexas matemáticas. É a electrónica que aplica a matemática, onde todos os números
são representados por apenas dois dígitos, e onde só importa saber se há tensão eléctrica, ou não. Estamos a
falar de electrónica digital.
No início do desenvolvimento dos computadores, percebeu-se que as pessoas tinham muitas dificuldades em
trabalhar com numeração binária. Devido a isto, um novo sistema de numeração foi desenvolvido, e usando 16
digitos distintos. Os primeiros dez dígitos são os tradicionais (0, 1, 2,... 9), mas existem mais seis. Por forma a
não inventar novos símbolos, convencionou-se usar as seis primeiras letras do alfabeto: A, B, C, D, E e F.
Um sistema hexadecimal de numeração, consistindo nos dígitos: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E e F foi
estabelecido.
O maior número que pode ser representado por 4 dígitos binários é 1111. E corresponde ao número 15 no
sistema decimal. Esse número no sistema hexadecimal, é representado pelo dígito F. É o maior número de um
dígito no sistema hexadecimal. O número da figura escrito com oito dígitos, é ao mesmo tempo o número he-
xadecimal de dois dígitos. Não esquecer que os computadores usam números binários de 8 dígitos.
O código BCD
O código BCD é um código binário apenas para números decimais. É usado para fazer comunicar os circuitos
electrónicos com os periféricos, e num sistema binário dentro do seu próprio mundo. Consiste em números
binários de quatro dígitos, que representam os primeiros dez dígitos décimais (0, 1, 2,... 9). Embora quatro
digitos nos dêem 16 combinações possiveis, apenas as primeiras 10 são usadas.
Os digitos de um número binário têem diferentes valores, dependendo da posição onde se encontram. Adi-
cionalmente, cada posição pode ter 1 ou 0, e o seu valor facilmente determinado através da sua posição desde
a direita. Para executar a conversão, é necessário multiplicar valores pelos dígitos correspondentes, e somar os
resultados.
Por forma a se fazer a conversão de um número hexadecimal para decimal, cada digito hexadecimal deve ser
multiplicado por 16, levantado ao expoente da sua posição. Por exemplo:
Não é necessário nenhum cálculo, de maneira a converter números hexadecimais para binario. Os dígitos hexa-
cedimais são simplesmente substituidos pelos seus congéneres 4 dígitos binários. Por exemplo:
Esta tabela comparativa, tem os valores dos números de 0 a 255, em três sistemas de numeração distintos:
Bit
Um bit é um dígito binário. De igual forma que o sistema de numeração decimal, no qual os dígitos de um nú-
mero não têem o mesmo valor, o significado do bit depende da sua posição no número binário. Então, não faz
sentido falar de unidades, dezenas, etc. Deve-se, sim, falar do bit zero, bit um, bit dois, etc. Sempre a contar do
lado direito. E, como o sistema binário usa apenas dois dígitos, 0 e 1, o valor de um bit só pode ser 0 ou 1.
Não nos devemos confundir, se o bit tiver valor de 4, 16 ou 32. Isso significa que os valores dos bits estão repre-
sentado em sistema decimal. Será correcto dizer que: o valor do quinto bit de um número binário, é equivalente
ao decimal 32.
Byte
Um byte consiste em oito bits agrupados. À semelhança dos digitos de outro qualquer sistema de numeração,
os dígitos dos bytes não têem o mesmo significado. O maior valor tem o bit mais à esquerda chamado de Bit
Mais Significativo (MSB - Most Significant Bit). O bit mais à direita tem o menor valor, e é chamado de Bit
Menos Significativo (LSB - Least Significant Bit). Como um byte pode ter 256 combinações possiveis de bits,
o maior número decimal possível de representar é o 255, pois há uma combinação que representa zero.
Um nibble é representado como meio byte. Dependendo de que metade do byte estamos a falar, há nibbles
“altos” ou “baixos”.
Circuitos Lógicos
A porta lógica AND tem duas ou mais entradas, e uma saída. A saída terá um 1 lógico, se as as suas entradas
A e B estiverem a nivel lógico 1.
A tabela mostra dependência entre entradas e saída. Qualquer outra combinação nas entradas, dará um nivel
lógico 0 na saída.
Quando usada num programa, a operação lógica AND é feita por instruções, que serão discutidas mais à fren-
te. Por agora, é importante referir que AND num programa, faz correspondência aos bits de dois registos.
Porta lógica OR
A porta lógica OR tem duas ou mais entradas, e uma saída. A saída terá um 1 lógico, se qualquer das suas en-
tradas A ou B estiverem a nivel lógico 1.
Num programa, a operação lógica OR é feita entre os bits correspondentes dos registos. À semelhança da ope-
ração lógica AND.
A porta lógica NOT tem apenas uma entrada, e uma saída. Quando um 0 lógico está presente na entrada, a
Se for executada num programa, a operação NOT é feita num byte. O resultado é esse byte com todos os bits inver-
tidos. Se o byte for considerado um número, o valor invertido é na realidade o complemento desse número. Isto é, o
complemento de um número é o que é necessário adicionar-lhe, para que o mesmo atinja o máximo valor de 8 bits
(255).
Esta porta é uma combinação das atrás referidas. A saída apresenta um 1 lógico, apenas quando as suas entradas
apresentam niveis lógicos diferentes.
Em um programa, esta operação também é usada para comparar dois bytes, para inverter quaisquer bits de um byte
ou para subtrair. E não há o perigo de subtrair um número grande, de um menor.
Registo
Registo
Como acrescento aos registos que não têem qualquer função predeterminada, todos os microcontroladores
têem alguns registos em que a sua função está predeterminada pelo fabricante. Os seus bits estão interligados
fisicamente aos circuitos internos, tais como temporizadores, conversores A/D, osciladores, portas série e ou-
tros, o que significa que são responsaveis pelo funcionamento do microcontrolador. Como um byte tem oito
bits, é como se fossem oito interruptores que comandam outros pequenos circuitos dentro do chip. Os SFR
têem essa exacta função.
De maneira a tornar o microcontrolador de alguma utilidade, o mesmo tem que estar ligado a electrónica adi-
cional no seu exterior, tais como periféricos. Cada micro tem um ou mais registos, chamados de Portas, ligados
aos pinos do mesmo.
O porquê de I/O, deve-se a que o utilizador pode alterar a função a seu belo prazer, e conforme a aplicação a
dar-lhes. Como exemplo, vamos supor que queremos comandar três LEDs, e simultaneamente controlar o es-
tado lógico de cinco botões: algumas portas têem de ser configuradas para que haja três saídas e cinco entradas.
Esta configuração é simples e confortavelmente feita por software, o que significa, também, que a função pode
ser alterada durante a operação (on-the-fly).
Uma das mais importantes especificações dos pinos I/O, é a corrente máxima que os mesmos podem suportar.
Para a maioria dos microcontroladores, a corrente possível de tirar de um pino é a suficiente para activar um
LED, ou outro dispositivo similar de baixa corrente (5-25mA). Se o microcontrolador tiver muitos pinos I/O,
então a máxima corrente de um só pino é menor. Resumidamente, não é possível que todos os pinos suportem
a máxima corrente, se houver mais de 80 pinos em total no microcontrolador. A corrente máxima descrita nas
especificações, é partilhada entre todos os portos I/O.
Outra importante função, é a de que podem ter resistências de “pull-up” (polarização positiva). Estas resistên-
cias ligam os pinos à alimentação positiva, e o seu efeito é visivel quando o pino está configurado como entrada.
As novas versões de microcontroladores já têem estas resistências configuraveis por software.
Normalmente, cada porto I/O é controlado por um SFR, o que significa que, cada bit desse registo, determina
o estado do pino correspondente do microcontrolador. Como exemplo, escrevendo 1 lógico no bit desse SFR,
o pino da porta correspondente é automaticamente configurado como entrada. De outra maneira, escrevendo
0 lógico no SFR, o pino da porta correspondente é configurado como saída. A tensão deste pino, 0v ou 5v, cor-
responde ao estado do correspondente bit do registo da Porta.
Se escrevermos 0 em um bit de registo da Porta, esse pino apresentará 0v. Se, inversamente, escrevermos 1 no
mesmo bit, o pino já vai apresentar 5v.
Unidade de memória
ROM - Read Only Memory: Apenas de Leitura, é usada para permanentemente gravar o programa a execu-
tar.
OTP ROM - One Time Programmable ROM: ROM onde só se pode escrever o programa na memória ape-
nas uma vez. Se houver necessidade de alterar o mesmo, terá de se fazer a gravação em um novo chip.
FLASH - Este tipo de memória foi inventada pela Intel nos anos 80. O seu conteúdo pode ser escrito/apaga-
do quase que infinitamente. Os microcontroladores com memória Flash são muito uteis para aprendizagem,
investigação e desenvolvimento, bem como para pequenas séries. Devido à sua popularidade, a maioria dos
microcontroladores são fabricados com este tipo de memória.
RAM - Random Access Memory: Este tipo de memória é volátil, o que significa que quando se desliga a ali-
mentação do chip, a sua informação desaparece. É usada para o armazenamento temporário de dados, criados
e usados durante a operação do microcontrolador. Como exemplo, se o programa faz uma adição, é necessário
haver um registo que tenha o valor da soma. Para esse fim, um dos registos da RAM é chamado de “soma” e
usado para armazenar o resultado da adição.
EEPROM - Electrically Erasable Programmable ROM: ROM programavel, que se pode apagar electricamen-
te. O conteúdo desta memória pode ser mudado durante a operação, mas o seu conteúdo não é perdido quando
se desliga a alimentação do microcontrolador. Este tipo de memória é usada para guardar valores, criados du-
rante a operação, que devem ser permanente armazenados.
Interrupções
A maioria dos programas usa interrupções durante a execução normal dos mesmos. O fim de um microcon-
trolador é o de reagir consoante os estímulos exteriores. Posto por outras palavras, quando algo acontece, o
microcontrolador faz qualquer coisa. Como exemplo, quando se pressiona um botão de um controlo remoto, o
microcontrolador vai registar o acto, e responder à ordem aumentando/baixando o volume, mudando de canal,
etc.
Se o microcontrolador dispendesse o teu tempo indefinidademente, a ler alguns botões durante horas ou dias,
simplesmente seria impraticavel. Em vez de o fazer, o microcontrolador delega este trabalho ao “especialista”,
que vai apenas reagir quando houver necessidade de atenção.
O sinal que informa o processador central deste tipo de eventos, é chamado de Interrupção.
Como o seu nome sugere, esta é a unidade que monitoriza e controla todos os processos dentro do microcon-
trolador. Consiste em variadas subunidades, em que as mais importantes são:
Descodificador de Instruções: é a parte electrónica que reconhece as instruções de programa, e faz funcionar
o outros circuitos com base nisso. O conjunto de instruções que é diferente para cada familia de microcontro-
ladores, mostra as capacidades deste circuito.
ALU: Unidade Lógica e Aritmética: responsavel por todas as operações lógicas e matemáticas.
Acumulador: é um registo SFR responsavel pela operação da ALU. É como um registo de trabalho, usado para
armazenar todos os dados que são usados para executar uma operação, e que também armazena os resultados
prontos para serem usados para a continuação do processamento. Um dos SFR, chamado de Status, contém
bastante informação sobre o estado dos dados armazenados no Acumulador (o número é maior ou menor que
zero, etc).
Barramento
Fisicamente, o barramento é constituido por 8, 16 ou mais condutores. Existem dois tipos de barramento: o de
endereçamento e o de dados. O barramento de endereçamento consiste no número de linhas necessárias para
poder endereçar a memória. É usado para transmitir o endereço da CPU para a Memória. O barramento de
dados é tão largo quanto os dados que vão ser trabalhados, e no caso deste manual é de 8 bits ou largura de fios.
É usado para ligar todos os circuitos dentro do microcontrolador.
Comunicações Série
Ligações paralelas entre microcontroladores e periféricos, através de portas I/O, são a solução ideal para curtas
distâncias - poucos metros. No entanto, e em outros casos em que há necessidade de estabelecer comunicações
entre dois dispositivos em maiores distâncias, não é possível utilizar comunicações paralelas. Nestas situações,
a comunicação série é a melhor solução.
Hoje em dia, a maior parte dos microcontroladores têem dentro, já de fábrica, variados sistemas para comuni-
cações série. Quais destes são usados, depende de muitos factores, os quais mais importantes são:
O termo Baud Rate é normalmente usado para especificar o número de bits transferidos por segundo (bps).
Dever-se-á ter em atenção que se referem bits, e não bytes. É, normalmente, requisito do protocolo, que cada
byte seja transferido em conjunto com vários bits de controlo, o que pode significar que um byte da trama de
dados série, consista em 11 bits. Como exemplo, se o Baud Rate é de 300 bps, então, um máximo de 37 e um
mínimo de 27 bytes podem ser transferidos por segundo, ambos dependentes do tipo de ligação e protocolo
usado.
I2C ( Inter Integrated Circuit) é um sistema usado quando a distância entre microcontroladores e periféricos
é curta (normalmente o emissor e o receptor estão na mesma placa de circuito impresso). A ligação é feita com
dois condutores: um para transferência de dados, e o outro para o sinal de relógio (sincronização). Como se
pode ver na figura, um dos dispositivos é sempre o Mestre. Faz o endereçamento de um chip Escravo, antes da
comunicação se iniciar. Desta maneira, um microcontrolador pode comunicar com 112 dispositivos diferentes.
O Baud Rate é normalmente de 100 Kbit/s no modo normal, ou de 10 Kb/s em modo lento. A distância má-
xima, sem ajudas, entre dispositivos que se comunicam por I2C, está limitada a poucos metros.
Comunicação I2C
SPI (Serial Peripheral Interface Bus) é um sistema de comunicação série, que usa até 4 condutores: um para
receber dados, outro para enviar dados, um para sinal de relógio, e em alternativa outro para escolher com qual
dos dispositivos o Mestre vai comunicar. É uma ligação Full-Duplex, o que significa que o envio e a recepção
podem ser feitas simultaneamente. O Baud Rate máximo é superior a uma ligação I2C.
Comunicação SPI
UART (Universal Asynchronous Receiver/Transmitter)é uma ligação assíncrona, o que significa que o sinal
de relógio não é usado. Como há apenas uma linha de comunicação, ambos o receptor e emissor trabalham a
um Baud Rate pré-determinado, de maneira a manter a sua sincronização. Esta é uma maneira muito simples
de transferir informação, pois representa a conversão de dados 8-bit em formato paralelos, para formato série.
O Baud Rate faz-se abaixo de 1 Mbit/s.
Oscilador
Pulsos dados pelo oscilador, possibilitam a operação síncrona de todos os circuitos do microcontrolador. O
módulo oscilador é normalmente configurado para usar um cristal de quartzo, ou um ressoador cerâmico, para
ter a sua oscilação estabilizada. Se não houver, por parte da aplicação, necessidade de estabilidade da oscilação,
então pode usar-se um oscilador RC (resistência/condensador).
É importante sublinhar que, as instruções, não são executas ao ritmo imposto pelo oscilador, mas algumas vezes
mais lento. Isto acontece porque cada instrução é executada em vários passos. Em alguns microcontroladores, o
mesmo número de ciclos é necessário para qualquer instrução, enquanto que em outros, o tempo de execução
não é o mesmo para todas as instruções. Se o sistema usa um cristal de 20 MHz, o tempo de execuçaõ de uma
instrução não é de 50ns, mas 200ns, 400 ou 800ns, dependendo do tipo de microcontrolador usado.
Oscilador
Circuito de Alimentação
Pino Reset, normalmente marcado como MCLR (Master Clear Reset), e serve para fazer o Reset externo do
microcontrolador, aplicando nível lógico 0 ou 1, dependendo do tipo de microcontrolador usado. No caso de o
chip não ter circuito de Brown-Out, um simples circuito externo de Brown-Out pode ser ligado a este pino.
Temporizadores e Contadores
O microcontrolador usa, normalmente, cristal de quartzo para funcionar. Mesmo que não seja a solução mais
simples, há muitas razões para o fazer. Nomeadamente, a frequência do oscilador é precisamente definida e
muito estavel, os pulsos srcinados têem sempre a mesma largura, o que os faz ideais para medições de tempo.
Estes osciladores são usados em relógios de quartzo.
Temporizadores / Contadores
Se é necessário medir o tempo entre dois eventos, é suficiente contar os pulsos enviados pelo oscilador. Isto é
exactamente o que o Temporizador faz.
Muitos programas usam estes cronómetros miniatura, que são SFR de 8 ou 16 bits, e o seu conteudo é automa-
ticamente incrementado a cada pulso recebido. Quando um registo chegar ao fim da contagem (255 ou 65535),
uma Interrupção é gerada.
Se os temporizadores usam um oscilador interno de quartzo, então é possível medir o tempo entre dois eventos
(se o valor do registo é T1 no momento inicial, e T2 no momento final, então o tempo passado é igual ao resul-
tado da subtração T2-T1). Se os temporizadores usam pulsos externos, então o temporizador é transformado
em contador.
Na prática, os pulsos que chegam do oscilador de quartzo a cada ciclo de máquina, ou através o divisor, vão
incrementar (somar uma unidade) o valor do registo do temporizador. Se uma instrução (um ciclo de máqui-
na) durar por quatro periodos do oscilador de quartzo, então, o número vai mudar um milhão de vezes por
segundo, ou a cada microsegundo (us).
Funcionamento do Temporizador
É simples medir curtos intervalos de tempo (até 256us), pelo método descrito acima, porque é o maior número
que um registo pode ter. Esta óbvia desvantagem pode ser facilmente contornavel de diversas maneiras, como
usando um oscilador mais lento, registos com mais bits, um divisor ou interrupções. Como as duas primeiras
soluções são menos simples de resolver, é preferivel enveredar pelas duas últimas.
Um divisor é um dispositivo electrónico usado para reduzir a frequência, por um factor pré-determinado. O
que significa que, para gerar um pulso na sua saída, é necessário fazer chegar 1, 2, 4, 8 ou mais pulsos à sua
entrada. Este circuito é parte integrante do microcontrolador, e o seu factor de divisão pode ser alterado pelo
software. É usado quando é necessário medir períodos de tempo longos.
Este divisor é normalmente partilhado pelo Temporizador e pelo Watchdog, o que faz com que não possa ser
usado por ambos em simultâneo.
Se o registo do temporizador for de 8 bits, o maior número que lhe poderá ser escrito é de 255 (ou de 65535
se o registo for de 16 bits). Se este número for excedido, o temporizador vai automaticamente limpar-se (auto
reset), e a contagem vai iniciar-se do 0. Esta condição é chamada de Overflow. Se for habilitado pelo software,
esse overflow pode gerar uma interrupção, o que nos trás imensas novas possibilidades.
Como exemplo, o estado dos registos de um relógio, segundos-minutos-horas, podem ser alterados dentro da
rotina de interrupção.
Todo o processo, excepto a rotina de interrupção, é executado em “background”, o que possibilita que o circuito
principal do microcontrolador execute outras operações.
Atrasos de diferente duração, com mínima interferência do programa principal, podem facilmente ser obtidos
atribuindo o divisor ao temporizador.
Contadores
Se o temporizador estiver a ser carregado com pulsos do exterior, então o mesmo torna-se num Contador. O
circuito não mudou, mantém-se o mesmo.
A única diferença é que, neste caso, os pulsos a contar chegam através das portas, e a sua duração nunca é defi-
nida. Esta é a razão pela qual não podem ser usados para medição de tempo, embora os seus fins sejam imensos.
Desde a contagem de peças numa linha de montagem, quantidade de passos que o motor andou, número de
passageiros numa fila, etc. As possibilidades são vastas, e são dependentes dos sensores usados.
Temporizador Watchdog
Se o watchdog estiver ligado, escolha que apenas pode ser feita durante a programação física, cada vez que
chega ao fim da sua contagem, ocorre um reset do microcontrolador, e a execução do programa volta à primeira
instrução. O objectivo é fazer com que isto não aconteça, pelo uso de uma instrução específica.
Assim, se algo se descontrolar na execução do programa, o microcontrolador poderá reiniciar-se, não correndo
o risco de ficar empatado num círculo infinito.
Se as instruções que fazem o reset do watchdog, forem colocadas em sítios específicos do programa, então, o
funcionamento do watchdog não vai interferir com o programa principal. Se, por alguma razão, normalmente
por ruidos na linha eléctrica, o programa ficar bloqueado em alguma posição da qual não consegue sair, não vai
ser feito o reset do watchdog e, quando este chegar ao fim da contagem, o reset do microcontrolador acontece,
iniciando o programa desde o início.
Temporizador Watchdog
Conversores Analógico/Digital
Os sinais externos são, normalmente, diferentes dos que o microcontrolador compreende (1’s e 0’s). Devido a
isto, os sinais têem que ser convertidos para linguagem compatível. Um conversor de Analógico para Digital, é
um circuito que converte sinais contínuos, para números digitais. Este circuito é, então, usado para converter
um valor analógico, para um número binário, e enviá-lo ao CPU para processamento. Posto por outras pala-
vras, este módulo é usado para medir tensões presentes no pino. O resultado da medida é um número de valor
Conversor A/D
Arquitectura Interna
Todos os microcontroladores modernos usam uma de duas arquitecturas: Harvard ou von-Neumann. Em
suma, são duas formas distintas de trocar a informação entre o CPU e a Memória.
Arquitectura von-Neumann
Arquitectura Harvard
Os microcontroladores que usam esta arquitectura, dispõem de dois barramentos de dados distintos. Um é de
8 bits e liga o CPU à RAM. O outro tem várias linhas (12, 14 ou 16) e liga o CPU à ROM.
Assim, o CPU pode ler uma instrução, ao mesmo tempo que faz um acesso à memória de dados. Como todos
os registos RAM são de 8 bits, todos os dados trocados dentro do microcontrolador estão no mesmo formato.
Adicionalmente, durante a escrita do software, apenas 8 bits de dados são considerados. Por outras palavras, só
se pode trabalhar com 8 bits de dados, no máximo.
Um programa escrito para estes microcontroladores, depois de compilado, vai ser guardado na ROM interna.
No entanto, estas posições de memória não têem apenas 8 bits, mas sim 12, 14 ou 16. Os restantes 4, 6 ou 8
bits representam a própria instrução, especificando ao CPU o que fazer com os dados de 8 bits.
Arq. Harvard
• Todos os dados são de 8 bits. Como o barramento usado para a leitura do programa tem 12, 14 ou 16
linhas, ambos as instruções e dados pode ser lidos simultaneamente. Assim, todas as instruções são execu-
tadas em apenas um ciclo. A única excepção são as instruções de salto, que são executadas em dois ciclos.
• Como a ROM e RAM são separadas, o CPU pode executar duas instruções simultaneamente. Enquanto a
leitura/escrita da RAM está a ser feita, a próxima instrução está a ser lida pelo outro barramento.
• Nesta arquitectura, o barramento de programa é maior que um byte, o que possibilita que cada linha de
programa seja feita de instrução + dados. Por outras palavras: uma linha de programa - uma instrução.
Conjunto de Instruções
Quando se define muito bem os requisitos do projecto, a larga oferta é naturalmente filtrada, e é muito mais
simples fazer a escolha adequada.
Por último, fazer a escolha consoante o número de unidades do produto, e o preço por unidade.
Microcontroladores PIC
Estes microcontroladores, fabricados pela Microchip, são provavelmente a melhor aposta para iniciados. O
verdadeito nome deste microcontroladores é PICmicro, mas são mais conhecidos por PIC.
O primeiro modelo foi desenhado em 1975 pela General Instruments. Chamava-se PIC1650, e foi idealizado
para fins totalmente diferentes.
Após 10 anos, e juntando memória EEPROM, este circuito transforma-se num verdadeiro microcontrolador
PIC.
Microcontrolador PIC16F887
Uma panorâmica
O PIC16F887 é um dos mais recentes produtos da Microchip. Tem todos os componentes que um moderno
microcontrolador tem e, pelo baixo custo, amplo campo de aplicações, alta qualidade e facilidade de adquirir, é a
solução ideal para aplicações como: controlo de processo industrial, controlo de máquinas, medição de valores,
entre outros.
• 35 pinos de I/O
• alta corrente para polarizar LEDs directamente
• resistências individuais de polarização positiva, programaveis por software
• interrupção quando há mudança no estado lógico dos pinos de entrada
• Conversor A/D
• 14 canais
• 10 bits de resolução
• 3 Temporizadores/Contadores independentes
• Temporizador Watch-dog
Como se pode ver na figura acima, quase todos os pinos são multi-funcionais. Como exemplo, o pino 33, com
a designação RB0/AN12/INT, tem as seguintes funções:
Este modo de dar funcionalidade extra aos pinos, faz o microcontrolador mais compacto, sem perder a sua fun-
cionalidade. Estas funcionalidades não podem ser usadas em simultâneo, mas podem ser alteradas a qualquer
momento pelo software.
Atribuição de Pinos
Atribuição de Pinos
Atribuição de Pinos
CPU
Não vamos falar do funcionamento da CPU por enquanto. Mas é importante frisar que a CPU é desenhada
com tecnologia RISC, o que é um importante factor a ter em conta, aquando da decisão de que microcontro-
lador usar.
A CPU e a Memória
Memória
Este microcontrolador tem três tipos de memória: ROM, RAM e EEPROM. Todas elas vão ser separada-
mente discutidas, pois cada uma delas têm funcionalidade e organização especificas.
Memória ROM
A memória ROM é usada para permanentemente guardar o programa a executar, e esta é a razão pela qual é
chamada de memória de programa. O PIC16F887 tem 8Kb de ROM, num total de 8192 posições. Como esta
ROM é feita com tecnologia FLASH, o seu conteúdo pode ser mudado electricamente, com o auxílio de um
programador externo.
Memória EEPROM
Com parecenças à memória de programa, o conteúdo da EEPROM é permanentemente gravado, mesmo que a
energia seja desligada. No entanto, ao contrário da ROM, o conteúdo da EEPROM pode ser alterado durante
a execução do programa. E esta é a razão, pela qual esta memória é perfeita para guardar resultados criados, e
usados, durante a operação.
Memória RAM
Esta é a mais complexa memória do microcontrolador. Neste caso, consiste em dois módulos: os registos-de-
função-geral (GPR), e os registos-de-função-especial.
Embora ambos os módulos de registos sejam limpos quando a alimentação desliga, e sejam fabricados da
mesma maneira, as suas funções são completamente díspares.
Os GPR são usados para armazenar temporariamente os dados, e resultados, criados durante a execução do
programa. Se o programa está a executar uma contagem, é necessário que haja um registo que sirva de “soma-
dor” ou contador. Como o microcontrolador tem que ser configurado para trabalhar como o utilizador deseja,
Então, o microcontrolador pode executar o programa, porque “sabe” o quê, e onde está a “soma” que deve ser
incrementada. Por analogia, a cada variavel do programa deve ser atribuido um GPR.
Os SFR também são locais na RAM, mas contrariamente aos GPR, o seu fim é predeterminado no processo
Como os seus bits estão fisicamente ligados a circuitos internos do chip (módulo de comunicações série, con-
microcontrolador, ou alguns dos seus circuitos. Como exemplo, mudando o registo TRISB, a função de cada
pino da porta B pode ser alterada, para que seja ou entrada ou saída.
Outra particularidade dos SFR’s, é a de que estes têem nomes, tanto o registo como os seus bits, o que torna
a escrita do programa mais facilitada. Como a programação em linguagens de alto-nível pode usar a lista de
todos os registos, com o seu endereço exacto, é apenas necessário especificar o nome do registo, de maneira a
escrever/lêr o seu conteudo.
Bancos de Memória
A memória de dados está particionada em quatro bancos. Antes de aceder a algum registo, durante a escrita do
programa para escrever/lêr, é necessário seleccionar o banco que contém esse mesmo registo. Dois bits no reg-
isto STATUS são usados para a selecção dos bancos. De forma a facilitar esta operação, os SFR mais comuns
têm o mesmo endereço em todos os bancos, o que possibilita que possam ser facilmente acedidos.
Bancos de Memória
SFR - Banco 0
SFR - Banco 1
SFR - Banco 2
SFR - Banco 3
A parte da RAM destinada à Stack, consiste em oito registos de 13 bits. Antes do microcontrolador executar
uma subrotina (instrução CALL), ou quando surge uma interrupção, o endereço da próxima instrução é em-
purrado para dentro de um registo da stack.
Dessa maneira, aquando da conclusão da subrotina ou interrupção, o microcontrolador sabe de onde deve con-
tinuar a execução normal do programa. Este endereço, na stack, é limpo depois do retorno ao programa princi-
pal, pois não há necessidade de o conservar, e essa posição fica automaticamente disponivel para ser usada.
É importante compreender que a stack funciona em círculo, ou seja, quando a stack já foi carregada oito vezes,
a nona carga vai ser sobrepôr-se ao valor que está guardado na primeira posição. A décima carga vai sobrepôr
a segunda posição, e por aí em diante. Os dados que foram sobrepostos desta maneira, não têem qualquer ma-
neira de serem recuperados. Ainda, o programador não tem acesso a estes registos para escrever/ler, e não há
nenhum bit no registo STATUS que indique que houve “stack overflow” ou “stack underflow”. Devido a isto,
deve ter-se em consideração esta particularidade aquando da programação.
Sistema de interrupção
A primeira situação que o microcontrolador faz quando acontece uma interrupção, é executar a actual instrução
e parar a execução do programa.
Imediatamente depois disso, o endereço da memória do programa é automaticamente empurrado para a stack,
e o endereço predefinido é carregado para o contador de programa. Essa localização de onde o programa con-
tinua, chama-se de Vector de Interrupção. Para o PIC em causa, o vector é 0x0004.
Como se pode ver na figura abaixo, o endereço que tem o vector de interrupção é saltado durante a execução
normal do programa.
Parte do programa que é activado quando acontece uma interrupção, é chamado de Rotina de Interrupção. A
sua primeira instrução está localizada no vector de interrupção. Quão longa a subrotina vai ser, e como vai ser,
depende apenas do programador, bem como do tipo de interrupção.
Alguns microcontroladores têem mais vectores de interrupção (cada interrupção têm um vector associado),
mas no caso deste PIC, existe apenas um vector. Consequentemente, a primeira parte da rotina de interrupção,
consiste no reconhecimento da fonte da mesma, ou onde foi srcinada.
Por último, quando a srcem da interrupção foi encontrada, e a rotina de interrupção é executada, o micro-
controlador chega à instrução RETFIE, puxa o endereço da stack, e continua a execução do programa de onde
tinha saído.
O programador adquire o microcontrolador, já com uma ideia bem definida do que vai fazer com o mesmo. Há
uma lista longa de SFR’s, com os seus bits. Cada um deles controla um qualquer processo. Num todo, é tudo
como uma grande tabela de controlo, com muitos instrumentos e interruptores.
Os microcontroladores oferecem muitos produtos a baixo preço, que cabe ao programador tomar a decisão.
Assim, este deve escolher a área que mais o agrada, e estudar apenas aquilo que necessita de saber.
Depois, quando compreender por completo o funcionamento completo do hardware, deve estudar os SFR’s
que o controlam.
E não esquecer!, que durante a escrita do programa, aquando do trabalho com registos e seus bits, deve ser
lembrado mudar para o banco apropriado. As tabelas acima são perfeitamente explanatórias.
Características e Funções
• SFR do CPU, que controlam e monitorizam os processos no processador central. Mesmo havendo poucos,
a operação de todo o microcoltrolador depende do seu conteúdo.
• SFR periféricos, que controlam a operação dos periféricos (conversor A/D, módulo de comunicações série,
etc). Cada um destes registos é normalmente usado para um circuito, e por esta razão, será explicado mais
à frente o seu funcionamento junto com o do periférico.
Os SFR do CPU do PIC, serão descritos neste capítulo. Visto que os seus bits controlam vários circuitos den-
tro do chip, não é possivel classificá-los por grupos. Estes bits são descritos juntamente com o processo que vão
controlar.
Registo STATUS
O registo de STATUS contém: o estado aritmético do registo W, o estado do RESET e os bits de selecção do
banco de memória.
O programador deve ser cauteloso, quando escreve valores para este registo porque, se o fizer erradamente, os
resultados podem ser diferentes do esperado. Por exemplo, se se tentar apagar todos os bits, usando a instrução
“CLRF STATUS”, o resultado no registo será 000xx1xx, em vez do esperado 00000000.
Tais erros acontecem, porque alguns bits deste registos são comandados pelo hardware, e não podem ser altera-
dos pelo programa. E, também, os bits 3 e 4 são apenas de leitura.
Por estas razões, se é necessário alterar o seu conteúdo, é recomendado usar instruções que não alterem os bits
TO - bit de Time-out
1 - A seguir ao Power-on, ou depois de executar a instrução CLRWDT, que limpa o temporizador do watch-
dog, ou da instrução SLEEP, que põe o microcontrolador em modo adormecido.
0 - A seguir a ter ocorrido um time-out do temporizador watchdog.
PD - bit de Power-down
1 - Depois do Power-on, ou depois de executar a instrução CLRWDT, que limpa o temporizador watchdog.
0 - Depois de de executar a instrução SLEEP, que coloca o microcontrolador em modo adormecido e baixo
consumo.
Z - bit Zero
1 - O resultado da operação lógica ou aritmética é zero
DC - bit de transporte de digito, é mudado durante a soma ou subtracção, se houver “overflow” ou um “borrow”
do resultado
1 - Houve transporte do 4º bit do resultado.
0 - Não houve transporte do 4º bit do resultado.
C - bit de Transporte, é mudado durante a soma ou subtracção, se houver “overflow” ou um “borrow” do resul-
tado: se o resultado é maior que 255 ou menor que 0
1 - Houve transporte do bit mais significativo do resultado
0 - Não houve transporte do bit mais significativo do resultado
Registo OPTION_REG
O registo OPTION_REG tem vários bits de controlo, para configurar: divisor do TMR0/WDT, temporiza-
dor TMR0, Interrupção externa e Pull-ups da Porta B.
A magnitude de divisão, do divisor interno, é configurada por estes três bits, descritos na tabela abaixo. A mag-
nitude depende de se o divisor está atribuido ao TMR0, ou ao Watchdog.
De maneira a conseguir uma divisão de 1:1, quando o temporizador TMR0 é usado, o divisor deverá estar atri-
buido ao Watchdog. Como resultado, o temporizador TMR0 não usa o divisor, e conta directamente os pulsos
que lhe são chegados pelo oscilador interno, ou por via externa no pino RA4/T0CKI.
Quando um pedido de interrupção chega ao microcontrolador, não significa que a interrupção seja automatica-
mente atendida pois, a mesma, terá de estar habilitada pelo programador. Devido a isto, há bits seleccionados
para ligar/desligar as interrupções.
É simples reconhecer estes bits, porque o seu nome tem a sigla “IE” (Interrupt Enable, ou Habilitação da Inter-
rupção). Além disto, cada interrupção está associada com outro bit chamado de Flag (sinalizador), que indica
que o pedido de interrupção chegou ao microcontrolador, independentemente se a interrupção está habilitada,
ou não. Também são facilmente reconhecidos pelas últimas letras “IF” (Interrup Flag, ou Sinalizador de Inter-
rupção).
Como já foi descrito, o princípio é baseado numa ideia simples e eficiente. Quando um pedido de interrupção
chega, o bit de flag é também automatica e autonomamente ligado em primeiro lugar.
Se o bit respectivo IE não está activado, este evento será completamente ignorado pelo microcontrolador. De
outra forma, a interrupção será trabalhada pelo CPU.
Se várias fontes de interrupção estão activadas, então é necessário detectar as que estão activas, antes de iniciar
a execução da interrupção. A detecção é feita, analisando quais os bits de flags que estão activos.
É importante compreender que os bits de flag não são automaticamente limpos, depois da interrupção ser ex-
ecutada. Sim, devem ser apagados pelo programador, dentro do software de execução da interrupção.
Se este pormenor não fôr tomado em conta, outra interrupção irá disparar quando se voltar para o programa
principal, mesmo que não haja mais pedidos para a sua execução. Resumindo, o bit de flag e o bit IE continu-
arão activados.
Todas as fontes de interrupção do microcontrolador PIC16F887, poderão ser visualisadas na imagem abaixo.
De notar os seguintes pontos:
Para habilitar as interrupções causadas pela mudança de estado na Porta B, é necessário activar cada bit sepa-
radamente. Neste caso, os bits do registo IOCB têem essa função em particular.
Registo INTCON
O registo INTCON contém vários bits de activação, e flag, para o TMR0, Porta B e pino INT.
INTE - Habilita interrupção externa em RB0/INT, causada pela mudança de estado no pino
1 - Activa interrupção do RB0/INT
0 - Desactiva interrupção do RB0/INT
RBIE - Habilita interrupção da Porta B, da mudança de estado nos pinos. Quando configurados como entra-
das, os pinos da Porta B podem causar interrupção, se mudarem de estado lógico. Seja com flanco ascendente,
seja descendente. Interessa apenas que houve mudança.
1 - Activa interrupção por mudança de estado da Porta B
0 - Deactiva interrupção por mudança de estado da Porta B
1 - Pelo meno um dos pinos da Porta B mudou de estado lógico. Após a leitura da Porta B, a flag RBIF deverá
ser limpa pelo software.
0 - Nenhum dos pinos da Porta B mudou de estado lógico.
Registo PIE1
SSPIE - Habilita a interrupção da Porta Série Síncrona (MSSP), a cada transferência efectuada
1 - Liga a interrupção MSSP
0 - Desliga a interrupção MSSP
Registo PIE2
O registo PIE2 também contém bits que habilitam as interrupções dos periféricos.
Registo PIR1
Registo PIR2
Registo PCON
O registo PCON contém apenas duas flags, para diferenciar entre: Reset de Power-on, Reset de Brown-out,
Reset de Watchdog ou Reset externo.
acontecer.
Registos P CL e P CLATH
O tamanho da memória de programa do PIC16F887 é de 8k. Então, tem 8192 posições para armazenar o pro-
grama. Por esta razão, o contador de programa tem de ter 13 bits (2^13 = 8192). Por forma a que o conteúdo
de qualquer posição seja alterada por software durante a operação, o seu endereço deverá ser acessível através
de algum SFR. Como os SFR’s são todos de 8 bits, este registo é “artificialmente” criado, dividindo os seus 13
bits por dois registos independentes: PCLATH e o PCL.
Se a execução do programa não interferir com o contador de programa, o valor deste registo é automatica e
constantemente incrementado +1, +1, +1, +1 ... Desta forma, o programa é executado como está escrito - in-
strução a instrução, seguindo um constante incremento de endereço de memória de programa.
Se o contador de programa é alterado pelo software, então há alguns pontos a ter consideração, para evitar
problemas:
• Os oito bits menos significativos são provenientes do registo PCL, que é legível e escrevível, quando os
cinco bits mais significativos provêem do registo PCLATH que é apenas escrevível.
• Em linguagem assembler, o valor do contador de programa é marcado como PCL, mas obviamente apenas
se refere aos 8 bits menos significativos. O programador deverá ter em atenção quando usar a instrução
“ADDWF PCL”. O resultado é um salto na posição de memória, através da soma de um número ao actual
endereço. É bastante usado quando de saltos para tabelas de conversão (look-up). Um problema surge
quando esta soma se arrasta para mais dos 8 bits do registo PCL. Não esquecer que, acima destes 8 bits,
já se trata do registo PCLATH.
• Executando qualquer instrução para o registo PCL, simultaneamente causa os bits do contador de pro-
grama serem substituidos pelo conteudo do registo PCLATH. No entanto, o PCL tem acesso a apenas
8 bits do resultado da instrução, e o salto consequente será totalmente erróneo. O problema é resolvido
colocando essas instruções em endereços terminando por 0xXX00. Isto possibilita o programa saltar até
255 posições. Se saltos maiores são executados por esta instrução, o PCLATH deverá ser incrementado
em uma unidade para cada excesso do PCL (255 para 0).
• Aquando da chamada, ou salto, para subrotinas (instruções CALL e GOTO), o microcontrolador dispõe
apenas de 11 bits para endereçar. Por esta razão, como a RAM que também é dividida em bancos, a ROM
está dividida em “páginas” de 2k cada. Tais instruções são executadas dentro destas páginas, sem quais-
quer problemas. Simplesmente, como o processador tem 11 bits de endereço do programa, pode endereçar
qualquer posição dentro dos 2KB. A figura abaixo explica em mais detalhe esta situação, como um salto
• No entanto, se a subrotina, ou endereço de salto, não está dentro da mesma página da srcem do mesmo, os
dois bits superiores em falta devem ser escritos no PCLATH. Esta operação está descrita na figura abaixo,
como um salto para o endereço da subrotina PP2.
Registos do PCLATH
Em ambos os casos, quando a subrotina encontra as instruções RETURN, RETLW ou RETFIE (para voltar
ao programa principal), o microcontrolador vai simplesmente continuar a execução do programa de onde tinha
deixado, pois o endereço de retorno foi armazenado na stack que, como mencionado, consiste de registos de
13 bits.
Endereçamento Indirecto
Juntamente com o endereçamento indirecto, o qual é lógico por si só, este microcontrolador é capaz de fazer
endereçamento indirecto através dos registos INDF e FSR. E, por vezes, simplifica em muito a escrita do pro-
grama. Todo o procedimento é possível porque o registo INDF não é um verdadeiro registo (fisicamente não
existe), mas apenas especifica o registo que é dado pelo valor que está no FSR. Devido a isto, escrever ou ler
do INDF, significa que se está a ler ou a escrever no registo que é dado pelo valor que está no FSR. Por outras
palavras, os endereços dos registos são especificados pelo FSR, e o conteúdo dos registos está armazenado no
INDF.
A diferença entre endereçamento directo e indirecto, é exemplificado na figura abaixo.
Como se pode ver, o problema dos “bits de endereços não existentes”, é solucionado por “pedi-los emprestado”
de outro registo. Desta vez, é o sétimo bit chamado IRP, do registo STATUS.
Uma das mais importantes funcionalidades do microcontrolador, é o número de pinos I/O usados para ligação
aos periféricos externos. Neste caso do PIC16F887, há um total de 35 pinos I/O de uso geral.
De maneira a que o funcionamento dos pinos I/O coincida com a organização a 8 bits, todos eles estão, simi-
larmente aos registos, agrupados em Portas denominadas A, B, C, D e E.
Todas têem características em comum:
• Por razões práticas, a maioria dos pinos I/O têm várias funções. Se um pino é usado para uma qualquer
função, não pode ser usado como I/O;
• Cada porta tem um par, isto é, o correspondente registo TRIS: TRISA, TRISB,TRISC, TRISD e TRISE,
que determina o funcionamento, mas não o conteúdo.
Limpando os bits do TRIS (bit=0), o correspondente pino da Porta é configurado como Saída.
De igual forma, activando os bits do TRIS (bit=1), o correspondente pino da Porta é configurado como En-
trada.
A Porta A é um registo de 8 bits bidireccionais. Os bits do TRISA e ANSEL controlam os pinos da PORTA.
Todos os pinos da PORTA funcionam como I/O digital, e cinco deles ainda podem trabalhar como entradas
analógicas (descritas a AN):
Similarmente aos bits do TRISA, que determinam quais dos pinos vão ser configurados como entrada ou
saída, os bits respectivos do ANSEL determinam quais os pinos que vão ser usados como entradas analógicas
ou I/O digitais.
Cada bit desta porta tem uma funcção adicional, relacionada com algum periférico interno. Estas funções
adicionais vão ser discutidas mais à frente.
Unidade ULPWU
O microcontrolador é normalmente usado em dispositivos que têem que funcionar periodicamente e, comple-
tamente independentemente, usando energia de baterias. Nestes casos, o consumo de energia deverá ser o mais
reduzido possível e prioritário. Exemplos típicos dessas são: termómetro, sensores de detecção de incêndio e
produtos de baixo consumo similares. Também é sabido que, uma redução na frequência de relógio reduz o
consumo energético, então, uma das mais convenientes soluções para esta situação é reduzir o relógio (usar um
cristal de 32KHz em vez de 4MHz ou 20MHz).
A solução ideal será a de, o microcontrolador, acordar sózinho periódicamente, o que é perfeitamente possível.
O circuito que o permite fazer, é mostrado aqui.
Um pino é configurado como saída, e é activado a nível lógico 1. Isso causa o condensador ser carregado.
Imediatamente depois, o mesmo pino é configurado como entrada. A mudança de estado lógico, habilita uma
interrupção, e o microcontrolador é posto em modo Sleep.
Seguidamente não há nada a fazer, excepto aguardar que o condensador se descarregue, através da corrente
de fuga que flui pelo pino de entrada. Quando isso ocorre, uma interrupção é gerada e o microcontrolador
continua a execução do programa em modo normal. A sequência é outra vez repetida.
Teoricamente, esta é uma solução perfeita. O problema é que, todos os pinos possíveis de gerar uma interrup-
ção, são digitais, e têem uma corrente de fuga excessivamente grande, quando a sua voltagem não está próxima
dos limites de Vdd ou Vss. Neste caso, o condensador é descarregado rapidamente, pois a corrente de descarga
é de várias centenas de microamperes. Esta é a razão pela qual o circuito ULPWU foi desenhado para ter lentas
quedas de tensão, e muito baixo consumo. A sua saída gera uma interrupção, enquanto que a entrada é ligada
a um dos pinos do microcontrolador. Está no pino RA0. Vendo a figura abaixo, com R=200ohms e C=1nF,
descarrega em aproximadamente 30ms, enquanto que o consumo total do microcontrolador reduz-se em 1000
vezes (algumas centenas de nanoamperes).
Unidade ULPWU
A Porta B é um registo de 8 bits bidireccionais. Os bits do registo TRISB determinam a função dos seus
pinos.
Similarmente à Porta A, um 1 lógico no registo TRISB, configura o pino respectivo como entrada, e vice-versa.
Seis pinos desta porta podem ser configurados como entrada analógica (AN). Os bits do registo ANSELH
determinam quais destes pinos vão trabalhar como entradas analógicas ou I/O digitais.
Cada bit desta porta tem uma função adicional, relacionada com algum periférico interno. Estas funções adi-
cionais vão ser discutidas mais à frente.
• Todos os pinos desta porta têem resistências pull-ups internas, o que faz deles ideais para ligar botões-
de-pressão, interruptores, foto-acopladores, entre outros. De forma a ligar estas resistências às portas dos
microcontroladores, o bit apropriado do registo WPUB deve ser activado.
Além dos bits do WPUB, há outro bit que afecta a operação das resistências pull-up: o bit RBPU do registo
OPTION_REG. É um bit de uso geral, porque afecta a instalação global destas resistências.
Sendo de alta impedância, estes resistências virtuais não afectam os pinos configurados como saídas, mas
servem de extraordinária ajuda para as entradas. Assim, estão ligadas às entradas dos circuitos lógicos CMOS.
De outra maneira, comportar-se-iam como se estivessem a flutuar, devido ao estado de alta impedância.
Resistências de Pull-up
• Se habilitado, cada pino da Porta B configurado como entrada, pode causar uma interrupção, mudando o
seu estado lógico. De maneira a habilitar os pinos que podem gerar a interrução, o bit respectivo no registo
IOCB deverá ser activado.
Devido a estas particularidades, os pinos da Porta B são normalmente usados para ligar botões-de-pressão, ou
teclados, pois não há necessidade de perder ciclos de programa a fazer o “varrimento” destas entradas.
Exemplo de Teclado
Quando os pinos X, Y e Z estão configuradas como saídas activadas ao estado lógico 1, é apenas necessário
esperar por um pedido de interrupção, que chega quando qualquer botão é premido. Fazendo, então, o var-
rimento das teclas, pode encontrar-se qual a que está a ser premida.
Pino RB0/INT
O pino RB0/INT é uma fonte verdadeira de interrupção externa. Pode ser configurado para reagir a um flanco
ascendente ou descentence. O bit INTEDG do registo OPTION_REG selecciona qual o sinal.
O leitor já deve ter notado que o microcontrolador PIC não tem quaisquer pinos especiais para a programação
(escrever para a memória de programa). Os pinos I/O normalmente usados para o funcionamento normal, são
usados para este fim (RB6 para o clock e RB7 para dados). Também, é necessário alimentar o chip com 5V em
Vdd e 0V em Vss, como também a tensão de programação Vpp da FLASH (12-14V). Durante a programa-
ção, a tensão Vpp é aplicada no pino de Reset (MCLR).
Apesar destas ligações serem necessárias, o microcontrolador pode ser gravado mesmo estando já montado
no sistema final. Normalmente, um programa já gravado pode ser alterado pelo mesmo processo. Esta função
chama-se ICSP (In-Circuit Serial Programming - Programação Série Dentro do Circuito).
É necessário planear o sistema, se se pretende usar esta funcionalidade.
Não é nada de complicado, basta instalar um conector de 5 pinos no sistema a gravar, para que as tensões do
hardware programador possam aceder ao microcontrolador. De maneira a que estas tensões não interfiram
com a restante electrónica, deverá ser pensado um circuito para travar as mesmas, usando resistências, díodos
ou jumpers.
Ligação ICSP
A Porta C é um registo de 8 bits bidireccionais. Os bits do registo TRISC determinam a função dos seus pinos.
Todas as funções adicionais desta porta, serão explicadas mais à frente.
A Porta D é um registo de 8 bits bidireccionais. Os bits do registo TRISD determinam a função dos seus
pinos.
A Porta E é um registo de 8 bits bidireccionais. Os bits do registo TRISE determinam a função dos seus pinos.
A única excepção é o pino RE3, que apenas serve de entrada, e o seu bit TRIS lê sempre “1”.
Similarmente às Portas A e B, três pinos podem ser configurados como entradas analógicas. Os bits do registo
ANSELH determinam se o pino vai funcionar como entrada analógica (AN), ou se como I/O digital :
Ambos estes registos são usados para configurar os pinos como analógico, ou I/O digital.
Como fazê-lo:
Para configurar um pino como entrada analógica, o bit respectivo do ANSEL, ou ANSELH, deverá ser acti-
vado a 1. Para configurar o pino como I/O digital, o bit respectivo deverá ser desactivado (0).
O estado dos bits ANSEL, não tem qualquer efeito nas funções de saída digitais. O resultado de qualquer
• Quando se projecta um sistema, escolher a porta através da qual o microcontrolador vai comunicar com os
periféricos circundantes. Se se pretender usar apenas I/O digitais, pode escolher-se qualquer das portas. Se
se pretender usar algumas das entradas analógicas, deverá escolher-se as portas apropriadas que suportam
essa configuração, AN0-AN13;
• Qualquer pino pode ser configurado como entrada ou saída, excepto o RE3 apenas como entrada. Os bits
dos TRISA, TRISB, TRISC, TRISD e TRISE, determinam como os respectivos pinos das PORTA,
PORTB, PORTC, PORTD e PORTE se vão comportar;
• Se se usarem quaisquer entradas analógicas, activar o bit respectivo no ANSEL e ANSELH, no início do
programa;
• Se se usarem interruptores ou botões-de-pressão, deverão ser ligados à Porta B, porque esta têm resistências
de pull-up. O uso destas resistências é habilitado pelo bit RBPU no OPTION_REG, e onde a activação
de resistências individualmente é possivel nos bits do WPUB; e
• É normalmente necessário reagir, assim que os pinos de entrada mudam de estado lógico. No entanto, não é
necessário escrever um programa para mudar o estado lógico dos pinos. É mais simples ligar estas entradas
aos pinos da PORTB, e habilitar a interrupção a cada mudança de estado lógico. Os bits dos registos
IOCOB e INTCON servem para tal.
Temporizadores
Os temporizadores deste PIC, podem ser descritos sucintamente. Há apenas três temporizadores/contadores
totalmente independentes, mas dados como TMR0, TMR1 e TMR2. Mas não tão simples quanto isso.
Temporizador TMR0
O temporizador TMR0 permite uma panóplia de aplicações práticas. É bastante conveniente, e simples, de
usar, para gerar pulsos de duração arbitrária, medição do tempo, ou para contar pulsos externos. Isto tudo
quase sem limitações.
• Temporizador/contador de 8 bit;
• Divisor de 8 bit, partilhado com o Watchdog;
• Fonte de relógio interna, ou externa, programavel;
• Interrupção por fim de contagem (255 -> 0);
• Selecção do flanco do relógio externo.
A figura abaixo representa o TMR0 com todos os bits que determinam a sua operação. Estes bits são armaze-
nados no registo OPTION_REG.
Temporizador TMR0
Registo OPTION_REG
Como se vê, o estado lógico do bit PSA determina qual a atribuição do divisor: se para o TMR0, se para o
Watchdog.
• Quando o divisor é atribuido ao TMR0, qualquer escrita no mesmo vai também limpar o divisor;
• Quando o divisor é atribuido ao Watchdog, a instrução CLRWDT vai limpar ambos o divisor e o WDT;
• Escrever para o registo TMR0, usado como temporizador, não dá o início de qualquer contagem, mas sim
após dois ciclos de relógio. Então é necessário ajustar o valor escrito no registo TMR0;
• Quando o microcontrolador é posto em modo Sleep, o oscilador é desligado. O overflow (fim de contagem,
255->0) não pode acontecer, pois não há pulsos para contar. É por esta razão que, a interrupção por over-
flow do TMR0, não pode “acordar” o microcontrolador;
• Quando usado como contador de pulsos externos, sem divisor, a duração mínima do pulso, ou pausa,
deverá ser de 2 Tosc + 20ns. Tosc é o periodo do oscilador interno;
• Quando usado como contador de pulsos externos, com divisor, a duração mínima do pulso, ou pausa,
deverá ser de 10ns;
• O registo, do divisor de 8 bits, não está disponivel ao programador, o que significa que não pode ser directa-
mente lido/escrito;
• Aquando da mudança da atribuição do divisor, do TMR0 para o Watchdog, a seguinte sequência de in-
struções deverá ser feita, de maneira a evitar um Reset:
BANKSEL TMR0
CLRWDT ;CLEAR WDT
CLRF TMR0 ;CLEAR TMR0 AND PRESCALER
BANKSEL OPTION_REG
BSF OPTION_REG,PSA ;PRESCALER IS ASSIGNED TO THE WDT
• Da mesma forma, aquando da mudança da atribuição do divisor, do Watchdog para o TMR0, a seguinte
sequência de instruções deverá ser feita:
BANKSEL TMR0
Seleccionar o modo:
• O tempo decorrido (em microsegundos, quando se usa um cristal de 4MHz) é medido lendo o TMR0; e
• A flag TMR0IF do registo INTCON, é automativamente activada, a cada vez que há um overflow do
TMR0. Se activada, é gerada uma interrupção.
• A polaridade dos pulsos a contar no pino Ra4, é seleccionada pelo bit T0SE do OPTION_REG: 0=flanco
ascendente, 1=flanco descendente; e
• O número de pulsos pode ser lido do registo TMR0. O divisor, e interrupção, são usados da mesma ma-
neira do medidor de tempo.
Temporizador TMR1
O módulo TMR1 é um temporizador/contador de 16 bit, o que significa que tem dois registos, TMR1L e
TMR1H. Pode contar até 65535 pulsos num só ciclo, ou seja, antes do contador retornar a zero (overflow).
Temporizador TMR1
Similarmente ao TMR0, estes registos podem ser lidos/escritos a qualquer momento. Em caso de overflow,
uma interrupção é gerada.
O TMR1 pode funcionar em um de dois modos básicos: como temporizador, ou como contador. No entanto,
ao contrário do TMR0, cada um destes módulos tem funçoes adicionais.
Divisor do TMR1
O TMR1 tem um divisor separado, o que permite divisões por 1, 2, 4 ou 8, da entrada de relógio. Não se pode
ler/escrever directamente o divisor. No entanto, o contador do divisor é automaticamente limpo aquando de
uma escrita nos registos TMR1H ou TMR1L.
Oscilador do TMR1
Os pinos RC0/T1OSO e RC1/T1OSI são usados para registar os pulsos dos periféricos externos, mas tam-
bém têem uma funcionalidade acrescida. Como se pode ver pela figura abaixo, são simultaneamente configura-
dos como entradas, pino RC1, e como saída, pino RC0, do oscilador adicional de baixa potência de quartzo.
Este circuito adicional, é principalmente desenhado para funcionar a baixas frequências (até 200KHz), mais
precisamente, para ser usado com cristais de quartzo de 32.768 KHz. Estes cristais são usados nos relógios de
quartzo, pois é simples de obter pulsos de um segundo, simplesmente dividindo a frequência.
Como este oscilador não depende do relógio interno, pode funcionar quando no modo de Sleep. É activado
pelo bit T1OSCEN do registo T1CON. O programador deve certificar-se que aguarda alguns milisegundos,
para garantir um bom arranque deste oscilador.
Oscillator Frequency C1 C2
LP 32kHz 33pF 33pF
LP 100kHz 15pF 15pF
LP 200kHz 15pF 15pF
Oscilador do TMR1
Gate do TMR1
A srcem da gate do TMR1 (interruptor que liga ou desliga), é controlado por software para ser o pino TG1
ou a saída do comparador C2. Esta gate permite ao TMR1 contar eventos de estado lógico no pino TG1, ou
eventos analógicos usando a saída do comparador C2. Ver figura a baixo. De maneira a medir a duração de um
sinal, é suficiente ligar esta gate, e contar os pulsos que vão passando pela mesma.
De maneira a seleccionar este modo, é necessário limpar o bit TMR1CS. Depois disto, o registo de 16 bits vai
ser incrementado a cada pulso que chegar do oscilador interno. Se um cristal de 4MHz estiver a ser usado, vai
haver uma incrementação a casa microsegundo.
Neste modo, o bit T1SYNC não afecta o temporizador, porque o mesmo está a contar pulsos do relógio
interno. Como toda a electrónica usa estes pulsos, não há necessidade de sincronização.
O relógio oscilador do microcontrolador não funciona durante o modo Sleep. Devido a isto, o Overflow do
TMR1 não causa nenhuma interrupção.
Oscilador do TMR1
O consumo energético do microcontrolador é reduzido, ao seu nível mínimo, quando no modo Sleep. O objec-
tivo é parar o oscilador.
De qualquer forma, é simples colocar o TMR1 neste modo - escrevendo uma instrução de SLEEP no pro-
grama. Surge o problema de como acordar o microcontrolador, porque apenas uma interrupção o pode fazer.
Como o microcontrolador “dorme”, uma interrupção tem que ser gerada por electrónica externa.
Oscilador do TMR1
De modo a resolver esta situação, um oscilador de baixo consumo a quartzo, que funciona quando no modo
Sleep, foi desenhado dentro do PIC. Aquilo que dantes era externo ao microcontrolador, está agora embutido
no silício e destinado ao TMR1.
O oscilador é ligado, activando o bit T1OSCEN do registo T1CON. Seguidamente, o bit TMR1CS é usado
para indicar que o TMR1 usa pulsos desse oscilador.
• O sinal deste oscilador de quartzo é sincronizado, com o relógio do microcontrolador, desactivando o bit
T1SYNC. Neste caso, o TMR1 não pode trabalhar no modo Sleep. Simplesmente porque o circuito de
sincronização usa o relógio do microcontrolador; e
• A interrupção por Overflow do TMR1 pode ser habilitada. Estas interrupções vão ocorrer no modo de
Sleep.
O TMR1 inicía o seu funcionamento como contador, activando o bit TMR1CS. Significa que, o TMR1, é
incrementado a cada flanco ascendente do pino T1CKI. Se o bit de controlo T1SYNC estiver desactivado, os
pulsos externos vão ser sincronizados. Por outras palavras, o TMR1 é sincronizado com o relógio de sistema
do microcontrolador, o que o torna um Contador Síncrono.
Quando o microcontrolador, funcionando desta maneira, é posto em Sleep, os registos TMR1H e TMR1L
não são incrementados, mesmo havendo pulsos externos na entrada T1CKI. Como o relógio do sistema não
funciona quando em Sleep, não há relógio para sincronização. No entanto, o divisor mantém o seu funciona-
mento, pois é apenas um divisor de frequência.
Registo T1CON
T1GINV - Bit de inversão da Gate do TMR1, serve de inversão do estado lógico do pino T1G ou da saída
do comparador C2 (C2OUT). Permite que o TMR1 incrementa, tanto quando recebe pulsos de flanco ascen-
dente, como de flanco descendente.
1 - TMR1 incrementa a cada flanco ascendente; e
0 - TMR1 incrementa a cada flanco descendente.
TMR1GE - Bit que habilita a Gate do TMR1, que determina se a gate do pino T1G, ou a saída do compara-
dor C2, vai estar activa, ou não. Este bit só é funcional, se o bit TMR1ON estiver activo. De outra maneira, o
TMR1GE é ignorado.
1 - TMR1 está ligado, apenas se a Gate estiver desligada; e
0 - A gate não afecta o funcionamento do TMR1
11 01 1:4
1:8
T1SYNC - Bit de sincronização do relógio externo do TMR1, habilita a sincronização dos pulsos de entrada
no T1CKI ou pelo oscilador de baixa potência. Quando conta pulsos do oscilador interno (TMR1CS=0), este
bit é ignorado.
1 - Não sincroniza a entrada externa de relógio; e
0 - Sincroniza a entrada externa de relógio.
• Como não é possivel desligar o divisor, a sua taxa de divisão é ajustada pelos bits T1CKPS1 e T1CKPS0,
do registo T1CON;
• O modo deverá ser escolhido pelo bit TMR1CS: 0=clock interno, 1=pulsos externos;
• Activando o bit T1OSCEN, o TMR1 é ligado, e os registos TMR1H e TMR1L são incrementados a cada
pulso do cristal externo. A contagem pára quando este bit é desactivado;
• O divisor é limpo, quando se limpa ou escreve nos registos contadores TMR1H e TMR1L; e
• Quando os registos TMR1H e TMR1L excedem o seu valor, a flag TMR1IF é activada, e a contagem
começa do zero.
Temporizador TMR2
O temporizador TMR2 é um módulo temporizador que funciona de uma maneira específica, e é controlado
por bits do registo T2CON.
Temporizador TMR2
Os pulsos do oscilador interno, passam primeiro pelo divisor, em que a taxa pode ser alterada pelos bits
T2CKPS1 e T2CKPS0. A saída do divisor é então usada para incrementar o registo do TMR2, começando
de 0x00.
Os valores do TMR2 e PR2, são constantemente comparados, e o TMR2 é constantemente incrementado
até que o seu valor coincida com o de PR2. Quando ambos coincidem, o TMR2 é automaticamente posto a
0x00. O pós-divisor é incrementando, e a sua saída é usada para gerar uma interrupção, se a mesma estiver
habilitada.
Ambos os registos TMR2 e PR2 são possiveis de ler e escrever. A contagem é interrompida a qualquer mo-
mento, desactivando o bit TMR2ON, o que contribui para a poupança de energia.
Como opção extra, o momento do Reset do TMR2 pode, também, ser usado para determinar a velocidade de
comunicações síncronas série.
Registo T2CON
00 11 01 10 1:6
1:7
0 1 1 1 1:8
1 0 0 0 1:9
1 0 0 1 1:10
1 0 1 0 1:11
1 0 1 1 1:12
1 1 0 0 1:13
1 1 0 1 1:14
1 1 1 0 1:15
1 1 1 1 1:16
Quando se usa o TMR2, não deverão ser esquecidos alguns detalhes que têem a ver com os seus registos:
Módulos CCP
Capture/Compare/PWM - Captura/Compara/PWM
O módulo CCP é um periférico que permite, ao programador, controlar e medir o tempo de diversos eventos.
Modo de Captura - permite a medição do tempo de duração de um evento. Este circuito monitoriza o estado
do TMR1, que constantemente muda de valor.
Modo de Comparação - compara valores entre os registos do TMR1 e CCPR. Também permite, ao pro-
gramador, gerar um sinal quando um determinado tempo já expirou.
Modo de PWM - Pulse Width Modulation = Modulação por Largura de Impulsos - gera sinais de frequência
e Duty-Cycle variaveis.
Ambos são idênticos nas suas funções, com a excepção das funcionalidades avançadas do CCP1.
Módulo CCP1
Uma parte importante deste circuito, é o registo CCPR1 de 16 bits, que consiste nos registos CCPR1L e
CCPR1H. É usado para capturar, ou comparar com o TMR1 (TMR1H and TMR1L).
Módulo CCP1
No modo de comparação, se habilitado por software, o Reset do temporizador TMR1 pode ocorrer com
coincidência de valores. Além disto, o módulo CCP1 pode gerar sinais PWM, de frequência e duty-cycle
variaveis.
A combinação dos quatro bits (CCP1M3 - CCP1M0) do registo de controlo, determina destas situações quais
vão disparar a transferência dos 16 bits. Também, o pino RC2/CCP1 deverá estar configurado como entrada,
e o TMR1 deverá funcionar como temporizador ou contador síncrono.
A flag CCP1IF é activada quando a captura é feita. Se tal acontecer, e se o bit PIE estiver activado, então uma
interrupção é gerada.
Quando o modo de captura é mudado, interrupções de captura não desejaveis poderão ser geradas. De maneira
a evitar esta situação, ambos os bits CCP1IE e CCP1IF deverão ser desactivados, antes de fazer qualquer
mudança.
Interrupções não desejaveis também poderão ser geradas, ao mudar de um divisor de captura para outro. Para
evitar esta situação, o módulo CCP1 deve ser temporáriamente desligado, antes de mudar de divisor.
BANKSEL CCP1CON
CLRF CCP1CON ;CONTROL REGISTER IS CLEARED
;CCP1 MODULE IS OFF
MOVLW XX ;NEW PRESCALER MODE IS SELECTED
Neste modo, o valor do CCP1 é constantemente comparado com o valor do TMR1. Quando os valores co-
incidem, o estado lógico da saída RC2/CCP1 pode alterar, o que vai depender do estado dos bits CCP1M3
- CCP1M0. A flag CCP1IF é, também, simultaneamente activada.
Para configurar o módulo CCP1 para funcionar deste modo, duas condições devem ser verdadeiras:
Sinais com frequência e duty-cycle variavel, têem uma grande aplicação em automação. Um exemplo típico é
um circuito de controlo de potência, que está na figura abaixo. Se um estado lógico 0 representa o interruptor-
desligado, e um estado lógico 1 representa o interruptor-ligado, a energia que a carga consome, é directamente
proporcional à duração do pulso. Esta relação é chamada de Duty-Cycle, ou ciclo-activo.
Outro exemplo muito comum, é o uso de sinais PWM para gerar sinais ou formas de onda arbitrárias, como
por exemplo uma onda sinusoidal.
Dispositivos que funcionam desta maneira, são frequentemente usados como reguladores comutados, que con-
trolam o funcionamento de motores: velocidade, aceleração, desaceleração, etc.
Módulo PWM
A figura acima, mostra o diagrama de blocos do módulo CCP1 configurado no modo de PWM. De maneira
a gerar pulsos de forma arbitrária no pino de saída, é necessário determinar dois valores: a frequência do pulso
e a sua duração.
Modo PWM
Periodo do PWM
O periodo (T) do pulso de saída é especificado pelo registo PR2 do TMR2. O periodo do PWM pode ser
calculado pela seguinte equação:
Se o periodo do PWM fôr conhecido, é facil de calcular a frequência, pois esta é o inverso do periodo -> F =
1 / T.
Duty-Cycle do PWM
O Duty-Cycle do PWM é configurado usando 10 bits: oito MSb’s (bits mais significativos) do registo CCP1RL
e dois adicionais LSb’s (bits menos significativos) do registo CCP1CON (DC1B1 e DC1B0). O resultado é
um número de 10 bits, presente na fórmula:
A tabela seguinte, mostra como gerar sinais PWM de frequência variavel, se se usar um cristal quartzo de
20MHz (Tosc=50ns)
A lembrar:
• O pino de saída será constantemente activado, caso a Largura do Pulso seja maior que o periodo do
PWM;
• Nesta aplicação, o pós-divisor do TMR2 não pode ser usado para gerar periodos maiores de PWM.
Resolução do PWM
Um sinal de PWM não é mais que uma sequência de pulsos, com largura do pulso variavel. Para uma de-
terminada frequência (número de pulsos por segundo), há um número limitado de combinações de larguras
de impulso. Este número é chamado de resolução, e medido em bits. Por exemplo, uma resolução de 10 bits,
resulta em 1024 larguras de impulso, onde uma resolução de 8 bits, resulta em 256 larguras de impulso.
Relativamente a este microcontrolador, a resolução é especificada pelo PR2. O valor máximo é obtido escre-
vendo 0xFF.
Registos CCP1CON
P1M1, P1M0 - bits de configuração da saída de PWM - em todos os modos, excepto no PWM, o pino P1A
é a entrada do módulo de Captura/Comparação. Os pinos P1B, P1C e P1D são I/O da Porta D. No modo de
PWM, estes bits afectam o módulo CCP1, como mostra a tabela abaixo:
DC1B1, DC1B0 - M Sb’s do Duty-Cycle do PWM - são apenas usados no modo de PWM, em que represen-
tam os dois bits menos significativos de um número de 10 bit. Este número determina a Largura de Impulso
do sinal PWM. Os restantes 8 bits, estão armazenados no registo CCP1RL.
Módulo CCP2
Excluindo a diferença de nomes de registos e bits, este módulo é uma boa cópia do CCP1, em modo normal.
Há apenas uma diferença entre ambos, quando o CCP2 opera no modo de Comparação.
Essa diferença centra-se no sinal de Reset do TMR1. Nomeadamente, se o conversor A/D está ligado, no
momento em que os valores de TMR1 e CCPR2 coincidem, o sinal de Reset do TMR1 vai automaticamente
iniciar uma conversão A/D.
Módulo CCP2
Similarmente ao módulo anterior, este circuito é controlador pelos bits do registo CCP2CON.
Registo CCP2CON
DC2B1, DC2B0 - M Sb’s do Duty-Cycle do PWM - são apenas usados no modo de PWM, em que represen-
tam os dois bits menos significativos de um número de 10 bit. Este número determina a Largura de Impulso
do sinal PWM. Os restantes 8 bits, estão armazenados no registo CCP2RL.
Contém todos os geradores de relógio, “shift-registers” e registos de dados necessários para fazer uma emissão,
ou recepção, de dados série, independentemente da execução do programa principal. Como o seu nome indica,
aparte do uso do relógio para sincronização, este módulo também pode estabelecer comunicações assíncronas,
o que o torna insubstituivel em algumas aplicações.
De maneira a possibilitar a transmissão de dados com o módulo EUSART, é necessário configurá-lo para
trabalhar como transmissor. Ou seja, é necessário definir o estado dos seguintes bits:
TXEN = 1 - O transmissor da EUSART está ligado, activando este bit no registo TXSTA;
SYNC = 0 - A EUSART está configurada para funcionar em modo assíncrono, desactivando este bit do
registo TXSTA;
SPEN = 1 - Activando este bit do registo RCSTA, a EUSART é activada e o pino TX/CK é automaticamente
configurado como saída. Se este bit é simultaneamente usado para alguma função analógica, esta deve ser
desactivada, limpando o bit correspondente no registo ANSEL.
O cerne do transmissor EUSART, é o “shift-register” TSR, que não é directamente acessivel pelo utilizador. De
maneira a iniciar a transmissão, o módulo deve estar ligado, activando o bit TXEN. Os dados a enviar, devem
ser escritos no registo TXREG, o que vai causar a seguinte sequência de eventos:
• A electrónica “empurra” os dados para o pino TX, ao mesmo ritmo do relógio interno: START bit ... dados
... STOP bit;
• Quando o último bit abandona o TSR, o bit TRMT do registo TXSTA é automaticamente activado;
• Se, entretanto, o TXREG recebeu um novo caracter, todo o procedimento é repetido imediatamente ao
STOP bit do caracter anteriormente transmitido.
O envio de dados de 9 bits, é habilitado activando o bit TX9 do TXSTA. O bit TX9D do TXSTA é o nono
MSB. Quando da transferência, o TX9D deverá ser escrito, antes de escrever para o TXREG. Todos os noves
bits de dados serão transmitidos, assim que a escrita no TXREG estiver completa.
SYNC = 0 - A EUSART está configurada para funcionar em modo assíncrono, desactivando este bit do
registo TXSTA;
SPEN = 1 - Activando este bit do registo RCSTA, a EUSART é activada e o pino TX/CK é automaticamente
configurado como saída. Se este bit é simultaneamente usado para alguma função analógica, esta deve ser
desactivada, limpando o bit correspondente no registo ANSEL.
Quando estes passos forem concluidos, e o START bit detectado, os dados são transferidos para o shift-regis-
ter RSR pelo pino RX. Quando o STOP bit fôr recebido, a seguinte ocorre:
flow OERR vai ser activado. Neste caso, os dados que chegaram são perdidos, e o bit OERR deverá ser
limpo pelo software. Tal é feito desactivando e activando o bit CREN. NOTA: não é possivel receber novos
dados, enquanto o bit OERR estiver activo;
• Se o STOP bit for zero, o bit FERR do RCSTA é activado, indicando erro na recepção;
• Para receber dados com 9 bits, é necessário activar o bit RX9 no RCSTA.
Há dois tipos de erros que o microcontrolador pode detectar automaticamente. O primeiro é chamado de erro
de Framing, e ocorre quando o receptor não detecta o STOP bit no tempo certo. Este erro é indicado pelo bit
FERR do RCSTA.
Se este bit estiver activado, significa que a última recepção de dados pode estar incorrecta.
É importante lembrar:
Outro tipo de erro, é chamado de “Overrun”. A memória de receoção pode conter dois caracteres. Um erro
overrun vai ser gerado se o terceiro caracter é recebido. Simplesmente não há espaço para outro byte, e um
error é inevitavel. Quando esta situação acontece, o bit OERR do RCSTA é activado. As consequências são as
seguintes:
Além de receber dados de 8 bits, o sistema EUSART suporta recepção de dados com 9 bits.
No lado transmissor, o nono bit está “agarrado” ao byte srcinal, mesmo antes do STOP bit. No lado receptor,
quando o bit RX9 do RCSTA está activo, o nono bit vai ser automaticamente escrito no bit RX9D, do mesmo
registo.
Quando este byte é recebido, o programador deve ter em atenção em como o vai ler. O nono bit deverá ser lido
antes de ler os restantes 8 bits, pois se não o fizer, o nono bit será automaticamente limpo.
Detecção de endereços
Quando o bit ADDEN do registo RCSTA está activo, o módulo EUSART está habilitado a receber dados
de 9 bits, onde todos os dados de 8 bits serão ignorados. Embora pareça uma restrição, este modo permite a
comunicação série entre vários microcontroladores.
O principio de operação é simples. O Mestre envia 9 bits, que representa o endereço de um microcontrolador.
Todos os microcontroladores Escravos que partilham a linha de transmissão, recebem estes dados. Todos os
escravos deverão ter o bit ADDEN activado, para permitir a detecção de endereço.
Depois da recepção, cada Escravo verifica se esse endereço é o seu. O software, depois de confirmar o endereço,
deverá desactivar a detecção de endereço, limpando o bit ADDEN. O dispositivo Mestre continua o envio de
dados de 8 bits. Todos os dados passando pela linha de transmissão, vão ser recebidos e reconhecidos apenas
pelo Escravo já correctamente endereçado. Após receber o último byte, o Escravo deverá activar o bit AD-
DEN.
de maneira a poder detectar outra vez os endereços.
Registo TXSTA
SENDB - Bit de envio de caracter de “break”. Apenas usado em modo assíncrono, e apenas no caso de desco-
brir o standard do barramento LIN
1 - O envio do caracter Break activado
0 - O envio do caracter Break terminou
BRGH - Bit de selecção de High Baud Rate (alta velocidade de relógio) no modo assíncrono. Não afecta a
EUSART no modo síncrono.
TX9D - Nono bit de dados transmitidos. Pode ser usado para endereço ou para bit de paridade.
Registo RCSTA
SREN - Bit de activação de Recepção singular. Usado apenas em modo síncrono, quando o microcontrolador
funciona como Mestre
1 - Recepção singular activada
0 - Recepção singular desactivada
RX9D - O nono bit dos dados recebidos, pode ser usado com endereço, ou bit de paridade
Um número escrito para estes dois registos, determina o Baud Rate - Velocidade da porta Série. Além do mais,
ambos o bit BRGH do TXSTA e o bit BRGH16 do BAUDCTL, influenciam a frequência de relógio.
A fórmula usada para calcular o Baud Rate, é dada pela tabela abaixo:
Bits
BRG / EUSART Mode Baud Rate Formula
SYNC BRG1G BRGH
0 0 0 8-bitassíncrono
/ Fosc[64
/ (n+1)]
0 0 1 8-bitassíncrono
/ Fosc[16
/ (n+1)]
0 1 0 16-bitassíncrono
/ Fosc[16
/ (n+1)]
0 1 1 16-bitassíncrono
/ Fosc[4
/(n+1)]
1 0 x 16-bitassíncrono
/ Fosc[4
/(n+1)]
1 1 x 16-bitassíncrono
/ Fosc[4
/(n+1)]
As tabelas seguintes, contêem valores que devem ser escritos no registo SPBRG, e nos bits SYNC, BRGH e
BRGH16, de maneira a obter Baud Rates padronizadas.
Registo BAUDCTL
ABDOVF - Flag de Overflow da detecção de Auto-Baud-Rate, é apenas usado no modo assíncrono, durante
a detecção do baud rate
1 - Temporizador Auto Baud Rate chegou ao fim
0 - Temporizador Auto Baud Rate não chegou ao fim
ABDEN - Bit de habilitação de Detecção Automática do Baud Rate, apenas em modo assíncrono
1 - Modo de detecção automática do baud rate está ligado. Este bit é automaticamente limpo aquando da
detecção do baud rate
0 - Modo de detecção automática do baud rate está desligado
Resumidamente:
• O baud rate deverá ser ajustado, pelos bits BRGH do registo TXSTA, e BRG16 do registo BAUDCTL,
e pelos registos SPBRGH eSPBRG;
• O bit SYNC do TXSTA deverá ser limpo, e o bit SPEN do RCSTA deverá ser activado, de maneira a
ligar a porta série;
• Na transmissão de 9 bits, o bit TX9 do TXSTA deverá ser activado;
• A transmissão de dados é habilitada, activando o bit TXEN do TXSTA. O bit TXIF do PIR1 é automati-
camente activado;
• Se for necessário haver um interrupção, o bit TXIE do PIE1, e os GIE e PEIE do INTCON deverão ser
activados;
• Na transmissão de 9 bits, o valor do nono bit deverá ser escrito no bit TX9D do TXSTA;
• A transmissão inicia quando se escreve no registo TXREG;
• O baud rate deverá ser ajustado, pelos bits BRGH do registo TXSTA, e BRG16 do registo BAUDCTL,
e pelos registos SPBRGH eSPBRG;
• O bit SYNC do TXSTA deverá ser limpo, e o bit SPEN do RCSTA deverá ser activado, de maneira a
ligar a porta série;
• Se for necessário haver uma interrupção, o bit RCIE do PIE1, e os GIE e PEIE do INTCON deverão ser
activados;
• Na recepção de 9 bits, o bit RX9 do RCSTA deverá ser activado;
• A recepção de dados deverá ser habilitada, activando o bit CREN do RXSTA;
• O registo RCSTA deverá ser lido, para tirar a informação de possiveis erros que ocorreram durante a
transmisssão. Na recepção a 9 bits, o nono bit estará armazenado neste registo;
• O byte recebido e armazenado no registo RCREG, deverá ser lido.
• O baud rate deverá ser ajustado, pelos bits BRGH do registo TXSTA, e BRG16 do registo BAUDCTL,
e pelos registos SPBRGH e SPBRG;
• O bit SYNC do TXSTA deverá ser limpo, e o bit SPEN do RCSTA deverá ser activado, de maneira a
ligar a porta série;
• Se for necessário haver uma interrupção, o bit RCIE do PIE1, e os GIE e PEIE do INTCON deverão ser
activados;
• O bit RX9 do RCSTA deverá ser activado;
• O bit ADDEN do RCSTA deverá ser activado, o que habilita que um caracter recebido, seja interpretado
como endereço;
• A recepção de dados deverá ser habilitada, activando o bit CREN do RXSTA;
• Imediatamente após os 9 bits serem recebidos, o bit RCIF do PIR1 é automaticamente activado. Se habil-
itada, uma interrupção é gerada;
• O registo RCSTA deverá ser lido, para tirar a informação de possiveis erros que ocorreram durante a
transmisssão. Na recepção a 9 bits, o nono bit estará armazenado neste registo;
• Os 8 bits recebidos e armazenados no registo RCREG, deverão ser lidos. Agora deve ser feita a verificação
do endereço. Se coincidirem, é necessário limpar o bit ADDEN do RCSTA, o que possibilita a continui-
dade da recepção em 8 bits.
O módulo MSSP - Master Sínchronous Serial Port, Porta Série Síncrona Mestre, é bastante útil, porque é ao
mesmo tempo um dos mais complexos circuitos dentro do microcontrolador. Ele permite comunicações de alta
velocidade entre o microcontrolador e periféricos externos, usando algumas linhas de I/O. É comum usá-lo
para ligar a ecrãns LCD, conversores A/D, EEPROM’s série, shift-registers, entre outros.
A principal funcionalidade deste tipo de comunicações é a de ser síncrona, e óptimo para sistemas onde há
um só Mestre, e um ou mais Escravos. O dispositivo Mestre tem os circuitos necessários para a geração do
Baud Rate, e fornece o Relógio para todos os dispositivos do sistema. Os dispositivos Escravos, podem dessa
maneira, eliminar o gerador de Relógio interno.
Módulo MSSP
Como se pode ver na figura, um módulo MSSP representa metade do hardware necessário para estabelecer
uma comunicação série, enquanto que a outra metade está presente no dispositivo com que se vai trocar a
informação. Apesar dos módulos serem iguais em ambos os lados, os seus modos são essencialmente diferentes,
dependendo se operam como Mestre ou Escravo:
• Se o microcontrolador a ser programado, controla outros dispositivos, então vai funcionar como Mestre.
Um módulo definido como tal, vai gerar o relógio quando necessário, e apenas quando informação é en-
viada/recebida.
• Depende do Mestre, se a ligação é estabelecida, ou não.
• Se o microcontrolador a ser programado, é parte de um sistema periférico, então vai funcionar como dis-
positivo Escravo. Então, terá sempre de aguardar os pedidos por parte do Mestre.
Modo SPI
O modo de SPI permite o envio/recepção simultânea, de dados de 8 bits, usando 3 linhas I/O;
Em conjunto com esta linha, se o microcontrolador trocar informação com vários periféricos, a quarta linha,
SS, também pode ser usada. Ver figura abaixo.
SS - Selecção de Escravo - um pino adicional usado para selecção de dispositivo. Está apenas activo se o micro-
controlador está em modo Escravo.
Os primeiros três registos são possiveis de escrever/ler, e podem ser alterado a qualquer momento, enquanto
que o quarto registo, como não está disponivel, é usado para converter os dados para formato série.
Modo SPI
Como pode ser visto na figura abaixo, o cerne do módulo SPI consiste em, dois registos ligados aos pinos para
receber, transmitir e sincronizar.
Modo SPI
O Shift Register, SSPRS, é directamente ligado aos pinos do microcontrolador, e usado para transmissão de
dados em formato série. O SSPRS tem a sua entrada e saída, e desloca os dados para dentro/fora do disposi-
tivo. Por outras palavras, cada bit que aparece na entrada (linha de recepção) simultaneamente empurra outro
bit para a saída (linha de transmissão).
O registo SSPBUF, é um bloco de memória para temporariamente armazenar a informação escrita no SSPRS,
até que os dados recebidos estejam prontos. Após a recepção dos 8 bits de dados, esse byte é deslocado para o
SSPBUF.
Esta dupla memória dos dados recebidos, SSPBUF, permite ao próximo byte ser recebido, antes de ler os dados
acabados de receber. Qualquer escrita no SSPBUF durante a transmissão/recepção de dados, é ignorada.
Nomeadamente, se as configurações do modo forem esquecidas, a transferência de dados SPI significa que
apenas se escreve e lê deste registo. Enquanto que o funcionamento do módulo em si, é automaticamente feito
por hardware.
Resumidamente:
Passo 1
Passo 2
Passo 3
Passo 4
Passo 5
Modo I2C
O modo I2C é especialmente útil quando, o microcontrolador e um circuito integrado com o qual o micro
deverá trocar informação, estiverem montados no mesmo sistema. Esta forma de transmissão de dados é co-
mum a outros microcontroladores, ou circuitos integrados especializados, tais como memórias, sensores de
temperatura, expansores de porta, relógios em tempo-real, etc.
Similarmente ao SPI, a transferência de dados por I2C é síncrona e bidireccional. Desta vez, apenas dois pinos
são usados para a transferência de dados. Estes são o SDA, dados série, e o SCL, relógio série. O programador
deve configurar estes pinos como entradas/saídas, através dos bits do TRISC.
Provavelmente não é directamente perceptivel, mas observando regras particulares (protocolos), este modo
possibilita que 122 dispositivos diferentes estajam simultaneamente ligados, usando apenas dois pinos I/O.
Funciona da seguinte maneira; o relógio necessário para sincronizar a operação de ambos os dispositivos, é
sempre gerado pelo Mestre. A frequência de relógio mais habitual é de 100KHz, mas não há limite no caso de
frequência mínima.
Quando o Mestre e Escravo estão sincronizados com o relógio, toda a troca de dados é sempre iniciada pelo
Mestre. Assim que o módulo MSSP está activo, fica a aguardar uma condição de Start.
Primeiro, o Mestre envia o bit de Start, depois o endereço de 7 bits do Escravo, e finalmente o bit que especifica
se vai ler ou escrever no Escravo. A seguir ao bit de Start, os oito bits são enviados para o registo SSPSR.
Todos os Escravos partilham a linha de transmissão, e vão simultaneamente receber o primeiro byte, mas
apenas um deles tem o endereço coincidente.
Depois do primeiro byte ter sido enviado, o Mestre entra em modo de recepção, e aguarda o ACK - Acknowl-
edge (confirmação) do Escravo com o endereço coindicente. Se o Escravo envia um ACK lógico 1, a transferên-
cia vai continuar até o Mestre enviar o bit de Stop.
Esta é uma simples explicação de como dois dispositivos comunicam. Se necessário, este microcontrolador é
capaz de controlar situações mais complicadas, onde 1024 dispositivos diferentes, partilhados por diferentes
Transferência de Dados
Registo S SPSTAT
R/W - Bit de Escrita/Leitura, usado em I2C apenas. Este bit guarda a informação R/W a seguir ao endereço.
Só é válido desde a coincidência de endereço, até ao próximo bit de Start, Stop ou não-ACK.
I2C Escravo:
1 - Ler dados;
0 - Escrever dados.
I2C Mestre:
1 - Transmissão em progresso;
0 - Transmissão parada.
Registo SSPCON
SSPEN - Bit que habilita a porta série síncrona, e inicializa o módulo MSSP:
No modo SPI:
1 - Liga módulo MSSP e configura os pinos SCK, SDO, SDI e SS, para a porta série;
0 - Desliga módulo MSSP e configura estes pinos como portas I/O.
No modo I2C:
1 - Liga módulo MSSP e configura os pinos SDA e SCL, para a porta série;
0 - Desliga módulo MSSP e configura estes pinos como portas I/O.
1 - Habilita o relógio;
0 - Mantém o relógio a estado lógico 0, para dar mais tempo à estabilização dos dados.
SSPM3-SSPM0 - Bits de selecção da porta série Síncrona. O modo é definido por estes três bits:
0 0 0 0 SPIMestre,
clock=Fosc/4
0 0 0 1 SPIMestre,
clock=Fosc/16
0 0 1 0 SPIMestre,
clock=Fosc/64
0 0 1 1 SPIMestre,clock=(saídaTMR)/2
0 1 0 0 SPIEscravo,pinoSSdecontrololigado
SPI Escravo, pino SS de controlo desligado, SS pode ser
0101
usado como pino I/O
0 1 1 0 I²CEscravo,endereçode7-bitusado
0 1 1 1 I²CEscravo,endereçode10-bitusado
1 0 0 0 I²CMestre,clock=Fosc/[4(SSPAD+1)]
1 0 0 1 MáscarausadanomodoI²CEscravo
1 0 1 0 usado
Não
1 0 1 1 ModocontroladoI²CMestre
1 1 0 0 usado
Não
1 1 0 1 usado
Não
I²C Escravo, endereço de 7-bit usado, bits START e STOP
1110
activam a interrupção
I²C Escravo, endereço de 10-bit usado, bits START e STOP
1111
activam a interrupção
Registo SSPCON2
O caso mais comum é quando o microcontrolador funciona como Mestre, e os periféricos como Escravos. Esta
é a razão de apenas se falar aqui deste modo. Também se vai considerar que o endereço é de 7 bits, e o sistema
electrónico só tem um microcontrolador, ou um só mestre.
Depois destes passo feitos, e do módulo ter sido ligado pelo bit SSPEN do SSPCON, deverá esperar-se pela
electrónica interna indicar que está pronta para transmissão: bit SSPIF do registo PIR1 activado.
Este bit deverá ser limpo por software, e seguidamente o microcontrolador está pronto a iniciar uma comuni-
cação com os periféricos.
Cada condição de relógio no pino SDA, é iniciado com estado lógico 0, que aparece após ligar o bit SEN do
SSPCON2. Mesmo depois de ligar, o microcontrolador aguarda um momento antes de iniciar a comunicação.
É a chamada Condição de Start, durante a qual há estabilização interna da electrónica. Se todas as condições
satisfazerem, o bit SSPIF do PIR1 é activado, e a transferência de dados é iniciada, assim que o registo SSP-
BUF for carregado com um byte.
A preparação para a recepção de dados, é similar à de transmissão de dados, com a excepção de que, o último bit
do byte de endereço, é lógico 1. Especifica que o Mestre espera receber informação do Escravo endereçado.
O seguinte vai ocorrer:
Depois da preparação interna terminar e do bit START ser activado, o Escravo dá início ao envio de um byte
de cada vez. Estes bytes são armazenados no registo SSPSR. Cada byte é carregado para o SSPBUF, de onde
pode ser lido. Ao ler este registo, o bit ACK é automaticamente enviado, significando que o Mestre está pronto
para receber novo byte.
De maneira a sincronizar as comunicações, todos os eventos no pino SDA devem ser síncronizados com o
relógio gerado no Mestre. Este relógio é gerado por um simples oscilador, em que a frequência depende do
oscilador principal do microcontrolador, do valor escrito no registo SSPADD e do modo corrente de SPI e
I2C.
A frequência de relógio dos modos descritos neste manual, dependem do cristal de quartzo e do registo
SSPADD. A fórmula usada para a calcular está na figura abaixo:
Quando o microcontrolador comunica com os periféricos, pode acontecer que a transferência de dados falha
por alguma razão. Neste caso, é recomendada a verificação do estado de alguns bit, que podem ajudar a clari-
ficar o problema. Na prática, o estado destes bits é verificado através da execução de uma subrotina, depois da
transmissão/recepção de um byte.
WCOL - SPCON,7 - Se se tentar escrever um novo byte para o SSPBUF, enquanto estiver em progresso uma
transmissão/recepção, o bit WCOL vai ser activado e o conteúdo do SSPBUF mantém-se inalterado. A escrita
não ocorre e, depois disto, o WCOL deverá ser limpo por software.
BF - SSPSTAT,0- No modo de transmissão, este bit é activado quando o CPU escreve para o SSPBUF, e
mantém-se activo enquanto o byte é deslocado para fora do registo SSPSR. No modo de recepção, este bit é
activado quando um byte é carregado para o SSPBUF. É limpo quando o SSPBUF é lido.
SSPOC - SSPCON,6 - No modo de recepção, este bit é activado quando um novo byte é recebido pelo
SSPSR, quando o byte anterior ainda não foi lido do SSPBUF.
Pinos SDA e SCL - Quando o módulo SSP está activo, estes pinos transformam-se em saídas Open Drain
(Dreno Comum). Significa que, estes pinos, devem ser ligados a resistências de Pull-Up (entre o pino e o
terminal positivo da alimentação).
Resumidamente:
De maneira a estabelecer uma comunicação série no modo I2C, o seguinte tem que ser tomado em conta:
• O valor que determina o Baud Rate, deve ser escrito para o registo SSPADD
• Slew Rate - Controlo de interferências, deve ser desligado, limpando o bit SMP do registo SSPSTAT
• De modo a escolher modo Mestre, o valor binário 1000 deverá ser escrito nos bits SSPM3-SSPM0 do
registo SSPCON
• O bit SEN do registo SSPCON2 deverá ser activado - Condição START
• O bit SSPIF é automaticamente activado no fim do START, quando o módulo está pronto a funcionar.
Deverá ser limpo por software
• O endereço do Escravo deverá ser escrito para o SSPBUF
• Quando o byte é enviado, o bit SSPIF é automaticamente activado quando o ACK é recebido do Escravo.
Transmissão de dados:
Recepção de dados:
• De maneira a ligar a recepção de dados, o bit RSEN do SSPCON2 deverá ser activado
• O bit SSPIF assinala a recepção de um byte. Quando o byte é lido do SSPBUF, o bit ACKEN do SSP-
CON2 deverá ser activado, de maneira a enviar o bit de ACK
• De maneira a informar o Escravo que a transmissão está completa, uma condição de STOP deverá ser
iniciada, activando o bit PEN no SSCON.
Módulos Analógicos
Além de uma variedade de linhas digitais de I/O, este PIC tem ainda várias entradas analógicas. Estas, pos-
sibilitam ao microcontrolador reconhecer, não só os estados lógicos 0 e 1, bem como fazer a medição precisa da
sua tensão e converte-la para um valor digital. Todo o procedimento acontece no módulo conversor A/D, que
tem as seguintes características:
• O conversor gera um resultado binário de 10 bits, usando o método de aproximação sucessiva (SAR), e
armazena o resultado nos registos ADRESL e ADRESH;
• Disponibiliza 14 entradas analógicas;
• O conversor possibilita a conversão de um sinal analógico, para um número binário de 10 bits;
• Escolhendo tensões diferentes para o Vref- e Vref+, a resolução mínima, ou qualidade de conversão, pode
ser ajustada à necessidade do projecto.
Apesar do uso de um ADC parecer deveras complicado, na prática é bastante simples. Mais simples do que
usar temporizadores e comunicações série.
Quando se converte um sinal analógico, o resultado dos 10 bits vai ser guardado em dois registos. De maneira
a lidar com este valor mais facilmente, o mesmo pode aparecer em dois formatos: justificado à esquerda, ou
justificado à direita. O bit ADFM do registo ADCON1 determina o formato de conversão.
No caso de o ADC não ser usado, estes registos podem ser usado para quaisquer fins.
Periodo do AD C
O tempo necessário para completar a conversão de um-bit, é definido como TAD. O TAD necessário é de pelo
menos 1.6 microsegundos. Uma conversão completa de 10 bits demora cerca de 11 TAD. No entanto, como
ambos o relógio e a fonte de conversão são configurados por software, uma das combinações disponiveis dos bits
ADCS1 e ADCS0, deverá ser escolhida antes da medição analógica. Estes bits estão no registo ADCON0.
Qualquer mudança na frequência de relógio do sistema, vai afectar o relógio do ADC, o que poderá afectar o
resultado do ADC. Os valores nas células com fundo cinza, estão fora do recomendando.
De maneira a possibilitar o ADC a funcionar sem problemas, bem como a evitar resultados inesperados, é
necessário considerar o seguinte:
• O ADC não distingue entre tensões analógicas ou digitais. De maneira a evitar erros na medição, ou es-
tragos no chip, os pinos devem ser configurados como entradas analógicas, antes de iniciar a conversão. Os
bits usados para este fim, estão nos registos TRIS e ANSEL.
• Quando a porta com entradas analógicas CH0-CH13 é lida, os bits correspondentes vão estar a lógico 0
• A medição de tensão no conversor, é baseada na comparação da tensão de entrada, com uma escala interna
que tem 1024 posições. O nível mais baixo da escala é o Vref-, e o nível mais alto é o Vref+. A figura abaixo
mostra os níveis possiveis para cada um deles.
Registo ADCON0
ADCS1-ADCS0 - Bits de selecção do Relógio de Conversão do ADC, usado para sincronização interna do
ADC. Também afecta a duração da conversão.
11 01 * Fosc/32
RC
* Relógio gerado por oscilador interno no microcontrolador
CHS3-CHS0 - Bits de selecção do Canal analógico, escolhem qual o canal analógico a converter.
00 11 00 1 0 5 4 RA5/AN4
RE0/AN5
0 1 1 0 6 RE1/AN6
0 1 1 1 7 RE2/AN7
1 0 0 0 8 RB2/AN8
1 0 0 1 9 RB3/AN9
1 0 1 0 10 RB1/AN10
1 0 1 1 11 RB4/AN11
1 1 0 0 12 RB0/AN12
1 1 0 1 13 RB5/AN13
1 1 1 0 CVref
1 1 1 1 0.6V
=Vref
Bits de escolha do Canal Analógico
Registo ADCON1
VCFG1 - Bit da Tensão de Referência, escolhe a fonte de tensão para o pino Vref-
1 - Tensão externa é aplicada no pino Vref-
0 - Tensão de alimentação interna, Vss, é usada como Vref-
VCFG0 - Bit da Tensão de Referência, escolhe a fonte de tensão para o pino Vref+
1 - Tensão externa é aplicada no pino Vref+
0 - Tensão de alimentação interna, Vdd, é usada como Vref+
Resumidamente:
De forma a medir uma tensão com o ADC, o seguinte deverá ser feito:
• Configurar a porta
• escrever lógico 1 no bit correspondente do registo TRIS, para configurar como entrada
• escrever lógico 1 no bit correspondente do registo ANSEL, para configurar como entrada analógica
Comparador Analógico
Em conjunto com o ADC, existe outro módulo que só recentemente começou a ser introduzido dentro de mi-
crocontroladores. Como é natural encontrar-se estes componenetes em quaisquer circuitos electrónicos, dois
comparadores de alta qualidade, com electrónica adicional, estão integrados no microcontrolador, e ligados aos
seus pinos.
Como funciona o comparador? Basicamente, o comparador analógico é um amplificador que compara a mag-
nitude de tensões às suas duas entradas. Observando as suas funcionalidades físicas, tem duas entradas e uma
saída. Dependendo de qual entrada tem uma tensão maior (valor analógico), um sinal lógico 0 ou 1 (valor
digital) irá estar na sua saída:
Comparador Analógico
• Quando a tensão no Vin- é maior que a tensão em Vin+, a saída do comparador está ao lógico 0;
• Quando a tensão no Vin+ é maior que a tensão em Vin-, a saída do comparador está ao lógico 1.
Este microcontrolador tem dois destes comparadores, em que as entradas estão ligadas aos pinos I/O RA0-
RA3, e onde as saídas estão ligadas aos pinos RA4 e RA5. Também está disponivel um referencial de tensão
Para gerar esta tensão de referência, fontes externas ou interna podem ser usadas. Após escolher a fonte da
tensão, o Vref é derivado desta, por intermédio de uma rede por escada, baseada em 16 resistência que formam
um divisor de tensão. A fonte de tensão é escolhida para ambas as pontas deste divisor, pelo bit VRSS do
registo VRCON.
A tensão a tirar do divisor de tensão resistivo, é escolhida pelos bits VR0-VR3, e usada como tensão de refer-
ência. Ver figura abaixo.
A referência de tensão do comparador tem duas gamas, com 16 níveis em cada. A escolha da gama é controlada
pelo bit VRR do registo VRCON. E a tensão de referência pode ser disponibilizada na saída do pino RA2/
AN2.
O bit flag CMIF do registo PIR, é activada a cada mudança de estado lógico da saída do comparador. As
mesmas mudanças também podem gerar uma interrupção, se os seguintes bits estiverem activos:
Se a interrupção estiver habilitada, qualquer mudança na saída do comparador, vai “acordar” o microcontrola-
dor do modo de Sleep, se estiver nesse modo.
Registo CM1CON0
Os bits deste registo, são os que controlam o Comparador C1. Afectam principalmente a configuração das
entradas. Para entender melhor, observar a figura abaixo, que mostra apenas uma parte da electrónica afectada
pelos bits deste registo.
C1POL - Bit de selecção da Polaridade da saída do Comparador C1, permite a inversão do estado da saída
1 - A saída do comparador C1 é invertida
0 - A saída do comparador C1 é não-invertida
Registo CM2CON0
Os bits deste registo, são os que controlam o Comparador C2. Similarmente ao caso anterior, a figura abaixo
mostra um esquema simplificado do circuito afectado por estes bits.
C2POL - Bit de selecção da Polaridade da saída do Comparador C2, permite a inversão do estado da saída
1 - A saída do comparador C2 é invertida
0 - A saída do comparador C2 é não-invertida
Registo CM2CON1
Registo VRCON
Em resumo :
De forma a convenientemente usar os Comparadores internos, é necessário o seguinte:
1 - Configurar o módulo:
De modo a escolher o modo apropriado, os bits dos registos CM1CON0 e CM2CON0 devem ser configura-
dos. A interrupção de ser desligada, quando da mudança de modos.
2 - Configurar a tensão de referência interna Vref (se usada). No registo VRCON é necessário:
• Escolher uma das duas gamas de tensão, pelo bit VRR
• Configurar a tensão de referência Vref, pelos bits VR3-VR0
• Activar o bit VROE se necessário
• Activar a tensão de referência Vref, activando o bit VREN
3 - O arranque:
• Activar interrupção, activando os bits CMIE (registo PIE), PEIE e GIE (no registo INTCON)
• Ler os bits C1OUT e C2OUT do registo CMCON
• Ler a Flag CMIF do registo PIR. Depois de activada, deverá ser limpa por software.
Como se pode ver pela figura abaixo, o relógio pode ser gerado por um de dois osciladores internos:
Um Oscilador Externo é instalado na proximidade do microcontrolador, e ligado aos pinos OSC1 e OSC2.
É chamado de externo, porque consiste em electrónica externa que gera o sinal de relógio e a estabilização de
frequência, tal como um cristal de quartzo, ressoador cerâmico ou resistência-condensador.
O modo do oscilador é escolhido por bits que são enviados durante a programação física, numa chamada
Palavra de Configuração, ou Fusíveis.
O LFINTOSC é um oscilador interno de baixa-frequência, que funciona a 31KHz. O seu relógio é usado
para o Watch-dog e temporizadores Power-up, mas pode também ser usado como fonte de relógio para todo
o microcontrolador.
O relógio do sistema pode ser escolhido entre externo e interno, através do bit SCS - System Clock Select, do
registo OSCCON.
Registo OSCCON
O registo OSCCON controla o relógio de sistema, e as opções de selecção da frequência. Contém os seguintes
bit:
IRCF2-IRCF0 - Bits de selecção da Frequência do Oscilador Interno. A combinação destes bits determina a
taxa de divisão. A frequência de relógio do oscilador interno é também determinada desta forma.
OSTS - Bits de estado do Start-up Time-out do Oscilador. Indica que fonte de relógio está, no momento, em
uso. É apenas de leitura.
1 - Oscilador externo em uso
0 - Um dos osciladores internos está em uso (HFINTOSC ou LFINTOSC)
HTS - bit de estado do HFINTOSC (125KHz - 8MHz). Indica se o oscilador de alta-frequência está a
funcionar com estabilidade
LTS - bit de estado do LFINTOSC (31KHz). Indica se o oscilador de baixa-frequência está a funcionar com
estabilidade
1 - LFINTOSC está estavel
0 - LFINTOSC está instavel
SCS - Bit de selecção do Relógio do Sistema. Determina qual o oscilador a usar como fonte de relógio
1 - O oscilador interno é usado como fonte de relógio do sistema
O modo do oscilador é escolhido por bits que são enviados durante a programação física, numa chamada
Palavra de Configuração, ou Fusíveis.
A selecção do modo pode ser incluida junto com o software, no momento da escrita, ou então pode ser ajustada
no software de programação no PC.
Durante a programação, os bytes da Palavra de Configuração - Fusiveis, são escritos na memória ROM do
microcontrolador, e guardados em registos especiais, que não estão disponiveis para o o programador. É com
base nestes bits, que o microcontrolador sabe o que fazer.
O modo de relógio externo, EC, usa o relógio do sistema configurado para oscilador externo. A frequência
deste relógio é ilimitada (0-20MHz).
• A fonte de relógio externo é ligada ao pino OSC1, e o pino OSC2 está disponivel para I/O geral
• É possivel sincronizar o funcionamento do microcontrolador, com o resto da electrónica
• Neste modo, o microcontrolador arranca o funcionamento assim que o sistema é energizado
• Se se parar o relógio externo temporariamente, o microcontrolador congela o funcionamento, deixando
todos os dados intactos. Assim que se restabelecer o relógio, o microcontrolador resume o funcionamento,
do ponto de onde parou, como se nada tivesse acontecido
Os modos LP, XT e HS, suportam o uso do oscilador interno, para configurar a fonte de relógio. A frequên-
cia desta fonte é determinada por cristais de quartzo, ou ressoadores cerâmicos, ligados aos pinos OSC1 e
OSC2.
Modo LP (Low Power - Baixa Potência) - é usado apenas para cristais de quartzo de baixa-frequência. Este
modo foi desenhado para acolher cristais de 32.768KHz, normalmente usados para relógios de quartzo. São
simples de reconhecer, pela sua forma cilíndrica, e o consumo de corrente é a mais baixa de todos os modos.
Modo XT - é usado para cristais de quartzo de frequências até os 8MHz. O consumo de corrente é mediano.
Modo HS (High Speed - Alta Velocidade) - é usado para cristais quartzo de frequências acima dos 8MHz. O
consumo de corrente é o mais elevado.
Ressoador cerâmico
Os ressoador cerâmicos têem características bastante similares aos cristais de quartzo. Por isso são ligados da
mesma maneira. Mas têem a vantagem de serem muito menos onerosos, não tendo tão boa estabilidade de
frequência como os cristais. São usados para frequências de relógio entre os 100KHz e os 20MHz.
Há certamente muitas vantagens em usar elementos para estabilização de frequência. Mas, por vezes, são per-
feitamente desnecessários.
É suficiente que o oscilador funcione a uma frequência não definida, e a solução mais simples e menos onerosa,
é usar uma resistência-condensador para fazer o oscilador funcionar.
Há dois modos:
Modo RC:
Modo RCIO:
f = Frequência [Hertz]
T = R*C = constante de tempo [segundos]
R = Resistência [Ohm]
C = Capacidade [Farad]
• O oscilador HFINTOSC é calibrado de fábrica, e oscila a 8MHz. Esta frequência pode ser ajustada pelo
programador, usado bits do registo OSCTUNE.
• O oscilador LFINTOSC não é calibrado de fábrica, e oscila a 31KHz.
Da mesma forma que o oscilador externo, o interno também pode funcionar em vários modos. O modo é selec-
cionado da mesma maneira que o oscilador externo - pelos bits da Palavra de Configuração - Fusiveis.
1.
O oscilador interno de alta-frequência HFINTOSC, está ligado a um divisor de frequência. É calibrado de
fábrica, e funciona a 8MHz. Usando o divisor, este oscilador pode ter na sua saída, uma de sete frequências, que
podem ser escolhidas pelos bits IRCF2-IRCF0 do registo OSCCON.
O HFINTOSC é ligado, escolhendo uma de sete frequências (entre 125KHz e 8MHz), e activando o bit
SCS do OSCCON. Como se pode ver pela figura abaixo, toda a configuração é realizada pelos bits do registo
OSCCON.
2.
O oscilador interno de baixa-frequência LFINTOSC, funciona a 31KHz e não vem calibrado de fábrica. É
activado, escolhendo esta frequências (bits no OSCCON), e activando o bit SCS do mesmo registo.
Quando configurado no modo LP, XT ou HS, o oscilador externo vai estar desligado quando em Sleep, de
maneira a reduzir o consumo médio energético do microcontrolador.
Quando as condições para “acordar” estão reunidas, o microcontrolador não vai retomar o serviço automatica-
mente, porque tem que aguardar que o sinal de relógio fique estavel. Este atraso é de exactamente 1024 pulsos.
Depois destes, o microcontrolador procede com a execução do programa.
O problema é que, quase sempre, são apenas umas poucas instruções executadas, antes de o microcontrolador
entrar em Sleep. Significa que, na maior parte do tempo, a energia é desperdiçada.
Este problema é solucionado, usando o oscilador interno para a execução do programa, enquanto os 1024
pulsos são contados. Seguidamente, e assim que o oscilador externo ficar estável, vai automaticamente tomar o
lugar principal. Todo o processo é habilitado, activando o bit IESO nos Fusiveis.
O FSCM detecta a falha do oscilador, comparando as fontes de relógio Interna e Externa. Caso o oscilador
esterno demore mais de 2 milisegundos a chegar aos pinos do microcontrolador, a fonte de relógio é mudada
automaticamente para o oscilador interno, que continua a operação, controlado pelos bits do OSCCON.
Quando o bit OSFIE do registo PIE2 estiver activo, uma interrupção é gerada.
O relógio de sistema continuará a ser o interno, até que o oscilador externo retome o funcionamento. A tran-
sição é feita automaticamente.
Este módulo é activado, pela configuração do bit FCMEN nos Fusiveis, aquando da programação física do
microcontrolador.
Registo OSCTUNE
Quaisquer modificações no registo OSCTUNE, afectam a frequência HFINTOSC, mas não a LFINTOSC.
Também, não há indicação durante a operação, de que houve mudança.
TUN4-TUN0 - Bits de Sintonização da Frequência. Pela combinação destes cinco bit, a frequência do oscila-
dor de 8MHz varia. Desta maneira, as frequências obtidas pelo divisor, também mudam.
Memória EEPROM
A EEPROM não pertence, nem à memória do programa (ROM FLASH), nem à memória de dados (RAM),
mas sim a um grupo especial. Mesmo estas posições de memória não sendo facil e rapidamente acessiveis como
os outros registos, são de grande importância pois, os dados da EEPROM, são permanentemente gravados. Os
dados da EEPROM podem ser alterados a qualquer momento. Devido a estas excepcionais qualidades, cada
byte de EEPROM é valioso.
O PIC estudado neste manual tem 256 posições de EEPROM, controlados pelos bits dos seguintes registos:
No entanto, o EECON2 não é um registo verdadeiro, pois não existe fisicamente. É apenas usado na sequência
de escrita.
Os registos EEDATH e EEADRH, pertencem ao mesmo grupo de registos usados durante a escrita/leitura
da EEPROM. Ambos são udados, também, para escrita/leitura da memória do programa (ROM FLASH).
Como esta é considerada uma zona de risco, pois não queremos inadvertidamente apagar o programa do mi-
crocontrolador, fica o aviso.
Registo EECON1
RD
- Bit de controlo da Leitura
1 - Dá início à leitura da EEPROM
0 - Leitura da EEPROM desactivada
Leitura da EEPROM
BSF STATUS,RP1 ;
BCF STATUS,RP0 ; Access bank 2
MOVF ADDRESS,W ; Move address to the W register
MOVWF EEADR ; Write address
BSF STATUS,RP0 ; Access bank 3
BCF EECON1,EEPGD ; Select EEPROM
BSF EECON1,RD ; Read data
BCF STATUS,RP0 ; Access bank 2
MOVF EEDATA,W ; Data is stored in the W register
Escrita da EEPROM
De modo a escrever na EEPROM, deve escrever-se o endereço no registo EEADR, e depois o byte de dados
no registo EEDAT. Seguidamente é necessário fazer uma sequência de segurança, para iniciar a escrita de cada
byte. As interrupções devem ser desligadas durante esta sequência.
BSF STATUS,RP1
BSF STATUS,RP0
BTFSC EECON,WR1 ; Wait for the previous write to complete
GOTO $-1 ;
BCF STATUS,RP0 ; Bank 2
MOVF ADDRESS,W ; Move address to W
MOVWF EEADR ; Write address
MOVF DATA,W ; Move data to W
MOVWF EEDATA ; Write data
BSF STATUS,RP0 ; Bank 3
BCF EECON1,EEPGD ; Select EEPROM
BSF EECON1,WREN ; Write to EEPROM enabled
BCF INCON,GIE ; All interrupts disabled
MOVLW 55h ; Required sequence start
MOVWF EECON2
MOVLW AAh
MOVWF EECON2 ; Required sequence end
BSF EECON1,WR
BSF INTCON,GIE ; Interrupts enabled
BCF EECON1,WREN ; Write to EEPROM disabled
O sinal de Reset pode ser gerado externamente a qualquer momento, pelo nivel lógizo 0 no pino MCLR. Se
necessário, também pode ser gerado pela electrónica interna. O Power-on gera sempre um Reset. Nomeada-
mente, devido a vários eventos que acontecem quando a fonte de alimentação está ligada (maus contactos de
interruptores, arcos eléctricos, tensão a subir vagarosamente, estabilização gradual da frequência de relógio,
etc), é necessário forçar um atraso de tempo, antes do microcontrolador iniciar o funcionamento.
Dois temporizadores internos - PWRT e OST, estão encarregados deste serviço. O primeiro pode ser ligado/
desligado durante a execução do programa.
Há, ainda, mais dois Resets, que podem ocorrer durante o funcionamento, bem como no momento em que a
energia é desligada.
Ruidos
Ruídos
Pino de MCLR
Um nível lógico 0 no pino MCLR, faz um Reset imediato. É recomendado que seja ligado como mostra a
figura abaixo. A função dos componentes adicionais, é a de conseguir suster um estado lógico 1 puro, durante
o funcionamento normal.
Conjunto de Instruções
Já dissemos que um microcontrolador não é como qualquer outro circuito integrado. Quando saem da cadeia
de produção, a maioria dos circuitos integrados, estão prontos para serem introduzidos nos dispositivos, o que
não é o caso dos microcontroladores.
Para que um microcontrolador cumpra a sua tarefa, nós temos que lhe dizer exactamente o que fazer. Por
outras palavras, nós temos que escrever o programa que o microcontrolador vai executar. Neste capítulo iremos
descrever as instruções que constituem o assembler, ou seja, a linguagem de baixo nível para os microcontrola-
dores PIC.
*1 - Se o porto de entrada/saída for o operando srcem, é lido o estado dos pinos do microcontrolador.
*2 - Se esta instrução for executada no registo TMR0 e se d=1, o divisor atribuído a esse temporizador é
automaticamente limpo.
*3 - Se o PC for modificado, ou se resultado do teste for verdadeiro, a instrução é executada em dois ciclos
Transferência de dados
A transferência de dados num microcontrolador, ocorre entre o registo de trabalho “W” e um registo “f ” que
representa um qualquer local de memória na RAM interna (quer se trate de um registo especial ou de um
registo de uso genérico).
As primeiras três instruções (observar a tabela anterior), referem-se à escrita de uma constante no registo W
(MOVLW é uma abreviatura para “MOVa Literal para W”), à cópia de um dado do registo W para o registo
“f ”, e à cópia de um dado de um registo ‘f ’ para o registo W (ou nele próprio, caso em que apenas a flag do zero
é afectada).
A instrução CLRF, escreve a constante 0 no registo “f ”, e CLRW escreve a constante 0 no registo W.
A instrução SWAPF troca o nibble (conjunto de 4 bits) mais significativo, com o nibble menos significativo de
um registo, passando o primeiro a ser o menos significativo, e o outro o mais significativo do registo.
Lógicas e aritméticas
De todas as operações aritméticas possíveis, os microcontroladores PIC, tal como a grande maioria dos outros
microcontroladores, apenas suportam a subtracção e a adição. Os bits ou flags C, DC e Z, são afectados con-
forme o resultado da adição ou da subtracção, com uma única excepção: uma vez que a subtracção é executada
como uma adição com um número negativo, a flag C (Carry), comporta-se inversamente no que diz respeito
à subtracção. Por outras palavras, é posta a “1” se a operação é possível, e posta a “0” se um número maior tiver
que ser subtraído de outro mais pequeno.
A lógica dentro do PIC tem a capacidade de executar as operações AND, OR, EX-OR, complemento (COMF)
e rotações (RLF e RRF).
Estas duas últimas instruções, rodam o conteúdo do registo, através desse registo e da flag C, em uma casa
para a esquerda (na direcção do bit 7), ou para a direita (na direcção do bit 0). O bit que sai do registo é escrito
na flag C e o conteúdo anterior desta flag, é escrito no bit situado do lado oposto no registo. Ver imagem com
exemplo.
As instruções BCF e BSF, põem a “0” ou a “1” qualquer bit de qualquer local da memória. Apesar de parecer
uma operação simples, ela é executada do seguinte modo, o CPU primeiro lê o byte completo, altera o valor de
um bit e, a seguir, escreve o byte completo no mesmo sítio.
As instruções GOTO, CALL e RETURN são executadas do mesmo modo que em todos os outros microcon-
troladores. A diferença é que a pilha (stack) é independente da RAM interna, e é limitada a oito níveis.
A instrução “RETLW k” é idêntica à instrução RETURN, excepto que, ao regressar de uma subrotina, é escrita
no registo W uma constante definida pelo operando “k” da instrução. Esta instrução, permite implementar
facilmente listagens (também chamadas tabelas de “look-up”).
Esta tabela pode apresentar-se como um subprograma, que consiste numa série de instruções “RETLW k”,
onde as constantes “k” são membros da tabela.
1. Escreve-se a posição de um membro da nossa tabela no registo W e, usando a instrução CALL, chama-se
o subprograma que contém a tabela.
2. A primeira linha do subprograma, “ ADDWF PCL,f”, adiciona a posição na tabela (que está escrita em
W) ao endereço do início da tabela (que está no registo PCL), assim, obtém-se o endereço real do dado da
tabela na memória de programa.
3. Quando se regressa do subprograma, ter-se-á no registo W, o conteúdo do membro da tabela endereçado.
4. No exemplo anterior, a constante “k2” estará no registo W, após o retorno do subprograma.
RETFIE (RETurn From Interrupt – Interrupt Enable, ou regresso da rotina de interrupção com as inter-
rupções habilitadas) é um regresso da rotina de interrupção, e difere de RETURN apenas em que, automatica-
mente, põe a “1” o bit GIE (Global Interrupt Enable - habilitação global das interrupções).
Quando a interrupção começa, este bit é automaticamente reposto a “0”. Também, quando a interrupção tem
início, somente o valor do contador de programa é posto no cimo da pilha.
O PIC não tem capacidade automática de armazenamento dos registos de estado. Ou seja, os registos de
trabalho do microcontrolador devem ser guardados assim que se entra na rotina de interrupção, para que mais
tarde, mesmo antes de saír, se reponham estes registos de trabalho.
Os saltos condicionais estão sintetizados em duas instruções: BTFSC e BTFSS. Consoante o estado lógico do
bit do registo “f ” que está a ser testado, a instrução seguinte no programa é, ou não, executada.
Todas as instruções são executadas num único ciclo, excepto as instruções de ramificação condicional se a
condição for verdadeira, ou se o conteúdo do contador de programa for alterado pela instrução. Nestes casos,
a execução requer dois ciclos de instrução, e o segundo ciclo é executado como sendo um NOP (Nenhuma
Operação).
Quatro oscilações de clock, perfazem um ciclo de instrução. Se estivermos a usar um oscilador com 4MHz de
frequência, o tempo normal de execução de uma instrução será de 1 microsegundo e, no caso de uma ramifica-
ção condicional, de 2 microsegundos.
Número deciclos:
Númerode palavras: 11
Exemplo1: MOVLW0x5A
Depois da instrução: W= 0x5A
Exemplo2: MOVLW REGISTAR
Antes da instrução: W = 0x10 e REGISTAR = 0x40
Depois da instrução: W = 0x40
Operação:
Operando: W ->)(kf<=127
0<=
Flag: -
Númerodepalavras: 1
Númerodeciclos: 1
Exemplo1: MOVWF OPTION_REG
Antes da instrução: OPTION_REG = 0x20
W = 0x40
Depois da instrução: OPTION_REG = 0x40
W = 0x40
Exemplo2: MOVWFINDF
Antes da instrução: W = 0x17
FSR = 0xC2
Conteúdo
Depois da do endereço 0xC2
instrução: = 0x00
W = 0x17
FSR = 0xC2
Conteúdo do endereço 0xC2 = 0x17
CLRW Escrever 0 em W
Sintaxe: [rótulo]CLRW
Descrição: O conteúdo do registo W passa para 0 e a flag Z do registo STATUS toma o
valor 1.
Operação: 0->(W)
Operando: -
Flag: Z
Númerodepalavras: 1
Númerodeciclos: 1
Exemplo: CLRW
Antes da instrução: W = 0x55
Depois da instrução: W = 0x00
Z=1
CLRF Escrever 0 em f
Sintaxe: [rótulo]CLRF
f
Descrição: Oconteúdodoregisto‘f ’passapara0eaflagZdo
registo STATUS toma o valor 1.
Operação: f->0
Operando: <=
0k127
<=
Flag: Z
Númerodepalavras: 1
Númerode
ciclos: 1
Exemplo
1: CLRFSTATUS
Antes da instrução: STATUS = 0xC2
Depois da instrução: STATUS = 0x00
Z=1
Exemplo
2: CLRFINDF
Antes da instrução: FSR = 0xC2
conteúdo do endereço 0xC2 = 0x33
Depois da instrução: FSR = 0xC2
conteúdo do endereço 0xC2 = 0x00
Z=1
SWAPF Copiar o conteúdo de f para d, trocando a posição dos 4 primeiros bits com a dos 4 últimos
Sintaxe: [rótulo]SWAPFf,d
Descrição: Os 4 bits + significativos e os 4 bits – significativos de f, trocam de
posições.
Se d = 0, o resultado é guardado no registo W
Se d = 1, o resultado é guardado no registo f
Operação: f<0:3>-> d<4:7>,f<4:7>-> d<0:3>,
Operando: 0<=k<=127,dE[0,1]
Flag: -
Númerodepalavras: 1
Númerodeciclos: 1
Exemplo1: SWAPFREG,0
Antes da instrução: REG = 0xF3
Depois da instrução: REG = 0xF3
W = 0x3F
Exemplo2: SWAPFREG,1
Antes da instrução: REG = 0xF3
Depois da instrução: REG = 0x3F
Sintaxe: [rótulo]ADDLWk
Descrição: O conteúdo do registo W, é adicionado à constante de 8-bits k e o resul-
tado é guardado no registo W.
Operação: W
( )+k->W
Operando: 0<=k<=255
Flag: DC,
C,Z
Númerodepalavras: 1
Númerodeciclos: 1
Exemplo1: ADDLW0x15
Antes da instrução: W= 0x10
Depois da instrução: W= 0x25
Exemplo2: ADDLWREG
Antes da instrução: W = 0x10
REG = 0x37
Depois da instrução: W = 0x47
ADDWF Adicionar W a f
Sintaxe: [rótulo]ADDWFf,d
Descrição: AdicionarosconteúdosdosregistosWef
Se d=0, o resultado é guardado no registo W
Operação: Se
(W)d=1,
+(f)->o d,
resultado
dE[0,1] é guardado no registo f
Operando: 0<=k<=127
Flag: DC,
C,Z
Númerodepalavras: 1
Númerodeciclos: 1
Exemplo1: ADDWFFSR,0
Antes da instrução: W = 0x17
FSR = 0xC2
Depois da instrução: W = 0xD9
FSR = 0xC2
Exemplo2: ADDWFINDF,0
Antes da instrução: W = 0x17
FSR = 0xC2
conteúdo do endereço 0xC2 = 0x20
Depois da instrução: W = 0x37
FSR = 0xC2
Conteúdo do endereço 0xC2 = 0x20
Sintaxe: [rótulo]SUBLWk
Descrição: O conteúdo do registo W, é subtraído à constante k e, o resultado, é guar-
dado no registo W.
Operação: kW
(- )->W
Operando: 0<=k<=255
Flag: C,
DC,
Z
Númerodepalavras: 1
Númerodeciclos: 1
Exemplo1: SUBLW0x03
Antes da instrução: W= 0x01, C = x, Z = x
Depois da instrução: W= 0x02, C = 1, Z = 0 Resultado > 0
Antes da instrução: W= 0x03, C = x, Z = x
Depois da instrução: W= 0x00, C = 1, Z = 1 Resultado = 0
Antes da instrução: W= 0x04, C = x, Z = x
Depois da instrução: W= 0xFF, C = 0, Z = 0 Resultado < 0
Exemplo2: SUBLWREG
Antes da instrução: W = 0x10
REG = 0x37
Depois da instrução: W = 0x27
C=1 Resultado > 0
SUBWF Subtrair W a f
Sintaxe: [rótulo]SUBWFf,d
Descrição: O conteúdo do registo W é subtraído ao conteúdo do registo f
Se d=0, o resultado é guardado no registo W
Se d=1, o resultado é guardado no registo f
Operação: (f)-(W)->d
Operando:
Flag: 0<=
Z k<=127,dE[0,1]
DC,
C,
Númerodepalavras: 1
Númerodeciclos: 1
Exemplo: SUBWFREG,1
Antes da instrução: REG= 3, W= 2, C = x, Z = x
Depois da instrução: REG= 1, W= 2, C = 1, Z = 0 Resultado
>0
Antes da instrução: REG= 2, W= 2, C = x, Z = x
Depois da instrução: REG=0, W= 2, C = 1, Z = 1 Resultado
=0
Antes da instrução: REG=1, W= 2, C = x, Z = x
Depois da instrução: REG= 0xFF, W=2, C = 0, Z = 0 Resultado
<0
Sintaxe: [rótulo]ANDLWk
Descrição: É executado o“E”lógico do conteúdo do registo W, com a constante k
O resultado é guardado no registo W.
Operação: (W).AND.k->W
Operando: 0<=k<=255
Flag: Z
Númerodepalavras: 1
Númerodeciclos: 1
Exemplo1: ANDLW0x5F
Antes da instrução: W= 0xA3 ; 0101 1111 (0x5F)
;1010 0011 (0xA3)
Depois da instrução: W= 0x03; 0000 0011 (0x03)
Exemplo2: ANDLWREG
Antes da instrução: W = 0xA3 ; 1010 0011 (0xA3)
REG = 0x37 ; 0011 0111 (0x37)
Depois da instrução: W = 0x23 ; 0010 0011 (0x23)
Sintaxe: [rótulo]ANDWFf,d
Descrição: Fazo“E”lógicodos conteúdosdos registosWef
Se d=0, o resultado é guardado no registo W
Se d=1, o resultado é guardado no registo f
Operação: (W).AND.(f)->d
Operando: 0<=k<=127,dE[0,1]
Flag: Z
Númerodepalavras: 1
Númerodeciclos: 1
Exemplo1: ANDWFFSR,1
Antes da instrução: W= 0x17, FSR= 0xC2; 0001 1111 (0x17)
; 1100 0010 (0xC2)
Sintaxe: [rótulo]IORLWk
Descrição: É executado o“OU” lógico do conteúdo do registo W, com a constante de
8 bits k, o resultado é guardado no registo W.
Operação: (W).OR.k->W
Operando:
Flag: 0Z<=k<=255
Númerodepalavras: 1
Númerodeciclos: 1
Exemplo1: IORLW0x35
Antes da instrução: W= 0x9A
Depois da instrução: W= 0xBF
Z= 0
Exemplo2: IORLWREG
Antes da instrução: W = 0x9A
conteúdo de REG = 0x37
Depois
Z = 0 da instrução: W = 0x9F
Sintaxe: [rótulo]IORWFf,d
Descrição: Faz o“OU”lógico dos conteúdos dos registosW ef
Se d=0, o resultado é guardado no registo W
Se d=1, o resultado é guardado no registo f
Operação: (W).OR.(f)->d
Operando: 0<=k<=127,dE[0,1]
Flag: Z
Número deciclos:
Númerode palavras: 11
Exemplo1: IORWFREG,0
Antes da instrução: REG= 0x13, W= 0x91
Depois da instrução: REG= 0x13, W= 0x93
Z= 0
Exemplo2: IORWFREG,1
Antes da instrução: REG= 0x13, W= 0x91
Depois da instrução: REG= 0x93, W= 0x91
Z= 0
Sintaxe: [rótulo]XORLWk
Descrição: É executada a operação“OU-Exclusivo” do conteúdo do registo W, com a
constante k. O resultado é guardado no registo W.
Operação: (W).XOR.k->W
Operando: 0<=k<=255
Flag: Z
Númerodepalavras: 1
Númerodeciclos: 1
Exemplo1: XORLW0xAF
Antes da instrução: W= 0xB5 ; 1010 1111 (0xAF)
;
1011 0101 (0xB5)
Depois da instrução: W= 0x1A; 0001 1010 (0x1A)
Exemplo2: XORLWREG
Antes da instrução:
REG =W = 0xAF
0x37 ; ; 0111
0011 1010 1111
(0x37) (0xAF)
Depois da instrução: W = 0x98 ; 1001 1000 (0x98)
Z=0
Sintaxe: [rótulo]XORWFf,d
Descrição: Faz o“OU-EXCLUSIVO”dos conteúdos dos registos W e f
Se d=0, o resultado é guardado no registo W
Se d=1, o resultado é guardado no registo f
Operação: (W).XOR.(f)->d
Operando:
Flag: 0Z<=k<=127,dE[0,1]
Númerodepalavras: 1
Númerodeciclos: 1
Exemplo1: XORWFREG,1
Antes da instrução: REG= 0xAF, W= 0xB5 ; 1010 1111
(0xAF)
; 1011 0101 (0xB5)
Depois da instrução: REG= 0x1A, W= 0xB5 001 1010
(0x1A)
Exemplo2: XORWFREG,0
Antes da instrução: REG= 0xAF, W= 0xB5; 1010 1111
(0xAF)
; 1011 0101 (0xB5)
Depois da instrução: REG= 0xAF, W= 0x1A ; 0001 1010
(0x1A)
INCF Incrementar f
Sintaxe: [rótulo]INCFf,d
Descrição: Incrementar de uma unidade,o conteúdo do registo f.
Se d=0, o resultado é guardado no registo W
Se d=1, o resultado é guardado no registo f
Operação: +
)f(1->d
Operando:
Flag: 0<=k<=127,dE[0,1]
Z
Númerodepalavras: 1
Númerodeciclos: 1
Exemplo1: INCFREG,1
Antes da instrução: REG = 0xFF
Z=0
Depois da instrução: REG = 0x00
Z=1
Exemplo2: INCFREG,0
Antes da instrução: REG = 0x10
W=x
Z=0
Depois da instrução: REG = 0x10
W = 0x11
Z=0
DECF Decrementar f
Sintaxe: [rótulo]DECFf,d
Descrição: Decrementar de uma unidade,o conteúdo do registo f.
Se d=0, o resultado é guardado no registo W
Se d=1, o resultado é guardado no registo f
Operação: 1-)f(->d
Operando: 0<=k<=127,dE[0,1]
Flag:
Númerodepalavras: 1Z
Númerodeciclos: 1
Exemplo1: DECFREG,1
Antes da instrução: REG = 0x01
Z=0
Depois da instrução: REG = 0x00
Z=1
Exemplo2: DECFREG,0
Antes da instrução: REG = 0x13
W
Z ==0x
Depois da instrução: REG = 0x13
W = 0x12
Z=0
Sintaxe: [rótulo]RLFf,d
Descrição: O conteúdo do registo f é rodado um espaço para a esquerda, através de
C (flag do Carry).
Se d=0, o resultado é guardado no registo W
Se d=1, o resultado é guardado no registo f
Operação: (f<n>)- > d<n+1>,f<7>->C,C->d<0>;
Operando: 0<=k<=127,dE[0,1]
Flag: C
Númerodepalavras: 1
Númerodeciclos: 1
Exemplo1: RLFREG,0
Antes da instrução: REG = 1110 0110
C=0
Depois da instrução: REG = 1110 0110
W = 1100 1100
C=1
Exemplo2: RLFREG,1
Antes da instrução: REG = 1110 0110
C=0
Depois da instrução: REG = 1100 1100
C=1
Sintaxe: [rótulo]RRFf,d
Descrição: O conteúdo do registo f é rodado um espaço para a direita, através de C
(flag do Carry).
Se d=0, o resultado é guardado no registo W
Se d=1, o resultado é guardado no registo f
Operação: (f<n>)- >d <n-1>,f<0>->C,C->d<7>;
Operando: 0<=k<=127,dE[0,1]
Flag: C
Númerodepalavras: 1
Númerodeciclos: 1
Exemplo1: RRFREG,0
Antes da instrução: REG = 1110 0110
W=x
C=0
Depois da instrução: REG = 1110 0110
W = 0111 0011
C=0
Exemplo2: RRFREG,1
Antes da instrução: REG = 1110 0110
C=0
Depois da instrução: REG = 0111 0011
C=0
COMF Complementar f
Sintaxe: [rótulo]COMFf,d
Descrição: Oconteúdodoregistof écomplementado.
Se d=0, o resultado é guardado no registo W
Se d=1, o resultado é guardado no registo f
Operação: ()->d
Operando: 0<=k<=127,dE[0,1]
Flag: Z
Númerodepalavras: 1
Númerodeciclos: 1
Exemplo1: COMFREG,0
Antes da instrução: REG= 0x13 ; 0001 0011 (0x13)
Depois da instrução: REG= 0x13 ; complementar
W = 0xEC ; 1110 1100 (0xEC)
Exemplo2: COMFINDF,1
Antes da instrução: FSR= 0xC2
conteúdo de FSR = (FSR) = 0xAA
Depois dade
conteúdo instrução: FSR=
FSR = (FSR) 0xC2
= 0x55
Sintaxe: [rótulo]BCFf,b
Descrição: Limpar(pôra‘0’),obitbdoregistof
Operação: 0->f<b>
Operando: 0<=k<=127,0<=b<=7
Flag: -
Númerodepalavras: 1
Númerodeciclos: 1
Sintaxe: [rótulo]BSFf,b
Descrição: Pôra‘1’,obitbdoregistof
Operação: 1->f<b>
Operando: 0<=k<=127,0<=b<=7
Flag: -
Númerodepalavras: 1
Númerodeciclos: 1
Exemplo1: BSFREG,7
Antes da instrução: REG = 0x07 ; 0000 0111 (0x07)
Depois da instrução: REG = 0x17 ; 1000 0111 (0x87)
Exemplo2: BSFINDF,3
Antes da instrução: W = 0x17
FSR = 0xC2
conteúdo
Depois dado endereço em
instrução: WFSR (FSR) = 0x2F
= 0x17
FSR = 0xC2
conteúdo do endereço em FSR (FSR) = 0x28
Sintaxe: [rótulo]BTFSCf,b
Descrição: Se o bit b do registo f for igual a zero, ignorar instrução seguinte. Se este
bit b for zero, então, durante a execução da instrução actual, a execução
da instrução seguinte não se concretiza e é executada, em vez desta, uma
instrução NOP, fazendo com que a instrução actual, demore dois ciclos
de instrução a ser executada.
Operação: Ignorarainstruçãoseguintese(f<b>)=0
Operando: 0<=k<=127,0<=b<=7
Flag: -
Númerodepalavras: 1
Número de ciclos: 1 ou 2 dependendo do valor lógico do bit b
Exemplo: LAB_01 BTFSC REG,1;Testarobit1doregistoREG
LAB_02 ........... ; Ignorar esta linha se for 0
LAB_03 ........... ; Executar esta linha depois da anterior, se for 1
Antes da instrução, o contador de programa contém o endereço LAB_01.
Depois desta instrução, se o bit 1 do registo REG for zero, o contador de
programa contém o endereço LAB_03. Se o bit 1 do registo REG for u‘ m’,
o contador de programa contém o endereço LAB_02.
Sintaxe: [rótulo]BTFSSf,b
Descrição: Se o bit b do registo f for igual a um, ignorar instrução seguinte. Se du-
rante a execução desta instrução este bit b for um, então, a execução da
instrução seguinte não se concretiza e é executada, em vez desta, uma
instrução NOP, assim, a instrução actual demora dois ciclos de instrução
a ser executada.
Operação: Ignorarainstruçãoseguintese(f<b>)=1
Operando: 0<=k<=127,0<=b<=7
Flag: -
Númerodepalavras: 1
Número de ciclos: 1 ou 2 dependendo do valor lógico do bit b
Exemplo: LAB_01 BTFSS REG,1;Testarobit1doregistoREG
LAB_02 ........... ; Ignorar esta linha se for 1
LAB_03 ........... ; Executar esta linha depois da anterior, se for 0
Antes da instrução, o contador de programa contém o endereço LAB_01.
Depois desta instrução, se o bit 1 do registo REG for ‘um’, o contador de
programa contém o endereço LAB_03. Se o bit 1 do registo REG for
zero, o contador de programa contém o endereço LAB_02.
Sintaxe: [rótulo]INCFSZf,d
Descrição: Descrição: O conteúdo do registo f é incrementado de uma unidade.
Se d = 0, o resultado é guardado no registo W.
Se d = 1, o resultado é guardado no registo f.
Se o resultado do incremento for = 0, a instrução seguinte é substituída
por uma instrução NOP, fazendo com que a instrução actual, demore dois
ciclos de instrução a ser executada.
Operação: (f )+1->d
Operando: 0<=k<=127,dE[0,1]
Flag: -
Númerodepalavras: 1
Número de ciclos: 1 ou 2 dependendo do resultado
Sintaxe: [rótulo]DECFSZf,d
Descrição: O conteúdo do registo f é decrementado uma unidade.
Se d = 0, o resultado é guardado no registo W.
Se d = 1, o resultado é guardado no registo f.
Se o resultado do decremento for = 0, a instrução seguinte é substituída
por uma instrução NOP, fazendo assim com que a instrução actual, de-
more dois ciclos de instrução a ser executada.
Operação: (f 1-)->d
Operando: 0<=k<=127,dE[0,1]
Flag: -
Númerodepalavras: 1
Número de ciclos: 1 ou 2 dependendo do resultado
Exemplo: LAB_01 DECFSZ R EG,1; Decrementar o conteúdo de REG de uma
unidade
LAB_02 ........... ; Ignorar esta linha se resultado = 0
LAB_03 ........... ; Executar esta linha depois da anterior, se der
0
Conteúdo do contador de programa antes da instrução, PC = endereço
LAB_01. Se o conteúdo do registo REG depois de a operação REG
= REG – 1 ter sido executada, for REG = 0, o contador de programa
aponta para o rótulo de endereço LAB_03. Caso contrário, o contador de
programa contém o endereço da instrução seguinte, ou seja, LAB_02.
Sintaxe: [rótulo]GOTOk
Descrição: Saltoincondicionalparaoendereçok.
Operação: k- >PC<10:0>,(PCLATH<4:3>)->PC<12:11>
Operando: 0<=k<=2048
Flag: -
Número deciclos:
Númerode palavras: 21
Exemplo: LAB_00 GOTOLAB_01;SaltarparaLAB_01
:
LAB_01 ............
Antes da instrução: PC = endereço LAB_00
Depois da instrução: PC = endereço LAB_01
Sintaxe: [rótulo]CALLk
Descrição: Esta instrução, chama um subprograma. Primeiro, o endereço de retorno
(PC+1) é guardado na pilha, a seguir, o operando k de 11 bits, corre-
spondente ao endereço de início do subprograma, vai para o contador de
programa (PC).
Operação: PC+1 - >Topodapilha(TOS–TopOf Stack)
Operando: 0<=k<=2048
Flag: -
Númerodepalavras: 1
Númerodeciclos: 2
Exemplo: LAB_00 CALLLAB_02 ;ChamarasubrotinaLAB_02
LAB_01 :
:
Sintaxe: [rótulo]RETURN
Descrição: O conteúdo do topo da pilha é guardado no contador de programa.
Operação: TOS ->ContadordeprogramaPC
Operando: -
Flag: -
Número deciclos:
Númerode palavras: 21
Exemplo: RETURN
Antes da instrução: PC = x
TOS = x
Depois da instrução: PC = TOS
TOS = TOS - 1
Sintaxe: [rótulo]RETLWk
Descrição: Aconstantekde8bits,éguardadanoregistoW.
Operação:
Operando: (k)
0<=-> W;
k<= TOS->PC
255
Flag: -
Númerodepalavras: 1
Númerodeciclos: 2
Exemplo: RETLW0x43
Antes da instrução: W = x
PC = x
TOS = x
Depois da instrução: W = 0x43
PC = TOS
TOS = TOS – 1
Sintaxe: [rótulo]RETLWk
Descrição: Retorno de uma subrotina de atendimento de interrupção. O conteúdo do
topo de pilha (TOS), é transferido para o contador de programa (PC). Ao
mesmo tempo, as interrupções são habilitadas, pois o bit GIE de habilita-
ção global das interrupções, é posto a ‘1’.
Operação: TOS->PC;1->GIE
Operando: -
Flag: -
Númerodepalavras: 1
Númerodeciclos: 2
Exemplo: RETFIE
Antes da instrução: PC = x
GIE = 0
Depois da instrução: PC = TOS
GIE = 1
Sintaxe: [rótulo]NOP
Descrição: Nenhuma operação é executada, nem qualquer flag é afectada.
Operação: -
Operando: -
Flag: -
Númerodepalavras: 1
Númerodeciclos: 1
Exemplo: NOP
Sintaxe: [rótulo]CLRWDT
Descrição: O temporizador do watchdog é reposto a zero. O prescaler do temporiza-
dor de Watchdog é também reposto a 0 e, também, os bits do registo de
estado e são postos a u‘ m’.
Operação: 0->WDT
0 -> prescaler de WDT
Operando: -
Flag:
Númerodepalavras: 1
Númerodeciclos: 1
Exemplo: CLRWDT
Antes da instrução: Contador de WDT = x
Prescaler de WDT = 1:128
Depois
Prescaledadoinstrução:
WDT = 0 Contador do WDT = 0x00
Sintaxe: [rótulo]SLEEP
Descrição: O processador entra no modo de baixo consumo. O oscilador pára. O bit
(Power Down) do registo Status é reposto a ‘0’. O bit (Timer Out) é posto
a ‘1’. O temporizador de WDT (Watchdog) e o respectivo prescaler são
repostos a ‘0’.
Operação: 0->WDT
0 -> prescaler do WDT
1 -> TO
0 -> PD
Operando: -
Flag:
Númerodepalavras: 1
Númerodeciclos: 1
Exemplo1: SLEEP
Antes da instrução: Contador do WDT = x
Prescaler do WDT = x
Depois da instrução: Contador do WDT = 0x00
Prescaler do WDT = 0
A capacidade de comunicar, é da maior importância nesta área. Contudo, isso só é possível se ambas as partes
usarem a mesma linguagem, ou seja, se seguirem as mesmas regras para comunicarem. Isto mesmo se aplica à
comunicação entre os microcontroladores e o homem.
A linguagem que o microcontrolador, e o homem, usam para comunicar entre si é designada por “linguagem
assembly”. O próprio título não tem um significado profundo, trata-se de apenas um nome como por exemplo
inglês ou francês. Mais precisamente, “linguagem assembly” é apenas uma solução transitória. Os programas
escritos em linguagem assembly, devem ser traduzidos para uma “linguagem de zeros e uns”, de modo a que um
microcontrolador a possa receber.
A primeira, representa um conjunto de regras usadas para escrever um programa para um microcontrolador,
e, a outra, é um programa que corre num computador pessoal que traduz a linguagem assembly para uma
linguagem de zeros e uns.
Um programa escrito em “zeros” e “uns” diz-se que está escrito em “linguagem máquina”, ou “código máquina”.
Fisicamente, “Programa” representa um ficheiro num disco de computador (ou na memória se estivermos a ler
de um microcontrolador), e é escrito de acordo com as regras do assembly, ou qualquer outra linguagem de
programação de microcontroladores.
O homem pode entender a linguagem assembly, já que ela é constituída por símbolos alfabéticos e palavras. Ao
escrever um programa, certas regras devem ser seguidas para alcançar o efeito desejado. Um Tradutor (compi-
lador) interpreta cada instrução escrita em linguagem assembly como uma série de zeros e uns com significado
para a lógica interna do microcontrolador.
Consideremos, por exemplo, a instrução “RETURN” que um microcontrolador utilizada para regressar de uma
subrotina.
Quando o assembler a traduz, nós obtemos uma série de uns e zeros, correspondentes a 14 bits, que o micro-
controlador sabe como interpretar.
O resultado desta tradução da linguagem assembly, é designado por um ficheiro de “execução”. Muitas vezes
encontramos o nome de ficheiro “HEX”. Este nome provém de uma representação hexadecimal desse ficheiro,
bem como o sufixo “hex” no título, por exemplo “correr.hex”. Uma vez produzido, o ficheiro de execução é
inserido no microcontrolador através de um programador físico.
Linguagem Assembly
Um programa, em Linguagem Assembly, é escrito por intermédio de um processador de texto (editor), e é ca-
paz de produzir um ficheiro ASCII no disco de um computador, ou em ambientes próprios como o MPLAB.
Um Label (etiqueta/rótulo) é uma designação textual (geralmente de fácil leitura) de uma linha num programa
ou de uma secção de um programa para onde um microcontrolador deve saltar ou, ainda, o início de um con-
junto de linhas de um programa. Também pode ser usado para executar uma ramificação de um programa (tal
como Goto....), o programa pode ainda conter uma condição que deve ser satisfeita, para que uma instrução
Goto seja executada.
É importante que uma etiqueta seja iniciada com uma letra do alfabeto, ou com um traço baixo “_” (under-
score). O comprimento de uma label pode ir até 32 caracteres. É também importante que a label comece na
primeira coluna.
Instruções
As instruções são específicas para cada microcontrolador, assim, se quisermos utilizar a linguagem assembly
temos que estudar as instruções desse microcontrolador.
O modo como se escreve uma instrução é designado por “sintaxe”. No exemplo que se segue, é possível recon-
hecer erros de escrita, dado que as instruções movlp e gotto não existem no microcontrolador PIC.
Operandos
Operandos são os elementos da instrução necessários, para que a instrução possa ser executada. Normalmente
são registos, variáveis e constantes. As constantes são designadas por “literais”. A palavra literal significa “núme-
ro”.
Comentários
O comentário é um texto que o programador escreve no programa, afim de o tornar mais claro e legível. É
colocado logo a seguir a uma instrução, e deve começar com um ponto-e-vírgula “;”.
Directivas
Uma directiva é parecida com uma instrução mas, ao contrário desta, é independente do tipo de microcontro-
lador e é uma característica inerente à própria linguagem assembly.
As directivas servem-se de variáveis, ou registos, para satisfazer determinados propósitos. Por exemplo, NIVEL,
pode ser uma designação para uma variável localizada no endereço 0x0D da memória RAM. Deste modo, a
variável que reside nesse endereço, pode ser acedida pela palavra NIVEL. É muito mais fácil a um programador
recordar a palavra NIVEL, que lembrar-se que o endereço 0x0D contém informação sobre o nível.
Directiva PROCESSOR
Esta directiva deve ser escrita no início de todos os programas. Define o tipo de microcontrolador, para o qual
o programa vai ser/está escrito. Como exemplo:
Processor 16f887
Directiva EQU
Esta directiva é usada para substituir um valor numérico, por um símbolo. Desta forma, a uma posição especí-
fica de memória RAM é atríbuido um nome. Como exemplo:
Isto significa que, à posição de memória 0x25, é atribuido o nome “MAXIMUM”. A cada uso da label “MAXI-
MUM” no programa, esta vai ser interpretada pelo assembler como endereço 0x25 (“MAXIMUM” = 0x25).
Os símbolos podem ser especificados desta forma, e apenas uma vez no programa. Esta directiva é usada es-
sencialmente no ínicio do mesmo.
Directiva ORG
Esta directiva especifica uma posição na memória do programa, onde as instruções a seguir à directiva vão ser
colocadas. Como exemplo:
ORG 0x100
START ... ...
...
ORG 0x1000
TABLE ...
...
Directiva END
Cada programa tem, obrigatoriamente, que ser terminado por esta directiva. Onde o compilador encontrar esta
directiva, imediatamente deixa de compilar. Como exemplo:
...
END ;Fim de programa
Directiva $INCLUDE
O nome desta directiva, expressa bem o seu propósito. Durante a compilação do assembler, possibilita o pro-
grama a usar outro ficheiro que está no disco do computador. Como exemplo:
...
#include <p16f887.inc>
Todas as variaveis (nomes e endereços) que vão ser usados no programa, têem que ser definidos no início do
programa. Devido a esta funcionalidade, não é necessário especificar o endereço de cada variavel, mais tarde
no programa. Em vez disso, é apenas necessário escrever o endereço da primeira variavel, usando a directiva
CBLOCK, e listar todas as outras variaveis a seguir. O compilador automaticamente atribui, a estas variaveis,
os correspondentes endereços, pela ordem como são escritas. Por fim, a directiva ENDC indica o fim da lista
de variaveis.
CBLOCK 0x20
START ; endereço 0x20
RELE ; endereço 0x21
STOP ; endereço 0x22
LEFT ; endereço 0x23
RIGHT ; endereço 0x24
ENDC
...
Estas directivas são usadas, para criar os chamados blocos condicionais de um programa. Cada um destes
blocos começa com uma directiva IF, e termina com a directiva ENDIF ou ELSE. Uma declaração, ou símbolo,
(em parênteses), a seguir à directiva IF, representa uma condição que determina qual parte do programa a ser
compilada.
Se a declaração estiver correcta, ou se o valor de um símbolo é igual a 1, o programa compila todas as instruções
antes da directiva ELSE ou ENDIF.
Se a declaração não estiver correcta, ou o valor de um símbolo é igual a zero, apenas as instruções escritas
depois das directivas ELSE ou ENDIF, são para compilar.
Exemplo 1:
IF (VERSION>3)
CALL Table_2
CALL Extension
ENDIF
Se o programa é lançado depois da versão 3 (declaração correcta), então, as subrotinas “Table 2” e “Extension”
são executadas. Se a declaração em parênteses é falsa, (VERSION<3), as duas instruções que chamas as sub-
rotinas são ignoradas, e não vão ser compiladas.
Exemplo 2:
Se o valor do símbolo “Model” é igual a 1, então as duas instruções depois da directiva IF são compiladas, bem
como as instruções depois da directiva ENDIF (todas as instruções entre ELSE e ENDIF são ignoradas).
De outro forma, se “Model” é igual a 0, então as instruções entre IF e ELSE são ignoradas, onde as instruções
depois de ELSE são compiladas.
IF (Model)
MOVFW BUFFER
MOVWF MAXIMUM
ELSE
MOVFW BUFFER1
MOVWF MAXIMUM
ENDIF
...
Directiva BANKSEL
De maneira a aceder a um registo SFR, é necessário escolher o banco da memória RAM apropriado, usando
os bits RP0 e RP1 do registo STATUS. Esta directiva é usada neste caso. Como o ficheiro de dados “.inc”
contém já a lista de todos os registos, bem como o seu endereço de memória, o compilador sabe a que banco
corresponde este registo. Depois de encontrar esta directiva, o compilador escolhe os bits RP0 e RP1 para o
registo especificado, de forma automática. Como exemplo:
...
BANKSEL TRISB
CLRF TRISB
MOVLW B’01001101’
BANKSEL PORTB
MOVWF PORTB
...
O exemplo que se segue, ilustra como um programa escrito em linguagem assembly se apresenta:
Quando se escreve um programa, além das regras fundamentais, existem princípios que, embora não ob-
rigatórios, é conveniente serem seguidos. Um deles, é escrever no seu início, o nome do programa, aquilo que
o programa faz, a versão deste, a data em que foi escrito, tipo de microcontrolador para o qual foi escrito e o
nome do programador.
Uma vez que estes dados não interessam ao tradutor de assembly, são escritos na forma de comentários. Deve
ter-se em atenção que um comentário começa sempre com ponto e vírgula, e pode ser colocado na linha seguinte,
ou logo a seguir à instrução. Depois deste comentário inicial ter sido escrito, devem incluir-se as directivas. Isto
mostra-se no exemplo de cima.
Para que o seu funcionamento seja correcto, é preciso definir vários parâmetros para o microcontrolador, tais
como:
• Tipo de oscilador;
• Se o temporizador do watchdog está ligado; e
• Se o circuito interno de reset está habilitado.
Logo que todos os elementos que precisamos tenham sido definidos, podemos começar a escrever o pro-
grama.
Primeiro, é necessário definir o endereço para que o microcontrolador deve ir quando se liga a alimentação. É
esta a finalidade de (org 0x00).
O endereço para onde um programa salta se ocorrer uma interrupção, é (org 0x04).
Como este é um programa simples, é suficiente dirigir o microcontrolador para o início de um programa com
uma instrução “goto Main” (Main = programa principal).
As instruções encontradas em Main, seleccionam o banco 1 (BANK1) de modo a poder aceder-se ao registo
TRISB, afim de que o porto B seja definido como uma saída (banksel TRISB).
O próximo passo é seleccionar o banco de memória 0, e colocar os bits do porto B no estado lógico ‘1’ e, assim,
o programa principal fica terminado ( movlw 0xFF, movwf PORTB).
É preciso, no entanto, um outro ciclo (loop), onde o microcontrolador possa permanecer sem que ocorram er-
ros. Trata-se de um ‘loop’ infinito, que é executado continuamente, enquanto a alimentação não for desligada.
Finalmente, é necessário colocar a palavra “end” no fim de cada programa, de modo a informar o compilador
de que o programa não contém mais instruções.
O primeiro ficheiro contém o programa traduzido, e que vai ser introduzido no microcontrolador quando
este é programado. O conteúdo deste ficheiro não dá grande informação ao programador, por isso, não vai ser
discutido.
O segundo ficheiro contém erros possíveis, que foram cometidos no processo de escrita e que foram notificados
pelo compilador durante a tradução. Estes erros também são mencionados no ficheiro de listagem “list”. No en-
tanto, é preferível utilizar este ficheiro de erros “err”, em casos em que o ficheiro “lst” é muito grande e, portanto,
difícil de consultar.
O terceiro ficheiro é o mais útil para o programador. Contém muita informação, tal como o posicionamento das
instruções e variáveis na memória e a sinalização dos erros.
No início de cada página, encontra-se informação acerca do nome do ficheiro, data em que foi criado e número
de página.
A primeira coluna, contém o endereço da memória de programa, onde a instrução mencionada nessa linha,
é colocada. A segunda coluna, contém os valores de quaisquer símbolos definidos com as directivas: SET,
EQU, VARIABLE, CONSTANT ou CBLOCK. A terceira coluna, tem, o código da instrução que o PIC
irá executar. A quarta coluna contém instruções assembler e comentários do programador. Possíveis erros são
mencionados entre as linhas, a seguir à linha em que o erro ocorreu.
MPLAB
O MPLAB, é um pacote de programas que correm no Windows e que tornam mais fácil escrever ou desen-
volver um programa. Pode descrever-se ainda melhor, como sendo um ambiente de desenvolvimento para uma
linguagem de programação normalizada, e destinado a correr num computador pessoal (PC). Anteriormente,
as operações incidiam sobre uma linha de instrução e contemplavam um grande número de parâmetros, até
que se introduziu o IDE “Integrated Development Environment” (Ambiente Integrado de Desenvolvimento)
e as operações tornaram-se mais fáceis, usando o MPLAB. Mesmo agora, as preferências das pessoas divergem
e alguns programadores preferem ainda os editores standard e os intérpretes linha a linha. Em qualquer dos
casos, o programa escrito é legível e uma ajuda bem documentada está disponível.
• Agrupamento de todos os ficheiros do mesmo projecto, num único projecto (Gestor de Projecto)
• Escrever e processar um programa (Editor de Texto)
• Simular o funcionamento no microcontrolador do programa que se acabou de escrever (Simulador)
Além destes, existem sistemas de suporte para os produtos da Microchip, tais como o PICSTART Plus, ICD2
(In Circuit Debugger - Detecção de erros com o microcontrolador a funcionar) e o Pickit2.
Antes de iniciarmos o MPLAB, temos primeiro que o instalar. A instalação é o processo de copiar os ficheiros
do MPLAB para o disco duro do computador, a partir do ficheiro de instalção disponivel do CD, ou da página
internet do fabricante. Existe uma opção em cada nova janela que permite regressar à anterior. Assim, os erros
não constituem problema e, o trabalho de instalação, torna-se mais fácil. Este modo de instalação é comum
à maioria dos programas Windows. Primeiro, aparece uma janela de boas vindas, a seguir pode-se escolher
entre as opções indicadas e, no fim do processo, obtém-se uma mensagem que informa de que o programa está
Como pode ver-se, o aspecto do MPLAB é o mesmo da maioria dos programas Windows. Perto da área de
trabalho existe um “menu” (faixa azul em cima, com as opções File, Edit, etc.), “toolbar” (barra com figuras que
preenchem pequenos quadrados), e a linha de status no fundo da janela. Assim, pretende-se seguir uma regra
no Windows, que é tornar também acessíveis por baixo do menu, as opções usadas mais frequentemente no
programa. Deste modo, é possível acedê-las de um modo mais fácil, e tornar o nosso trabalho mais rápido. Ou
seja, aquilo que está disponível na barra de ferramentas, também está disponível no menu.
A implementação de um PROJECTO
1. Criar um Projecto
2. Escrever o Programa
3. Compilar
De maneira a criar o Projecto, é necessário clicar na opção “PROJECT”, e depois “PROJECT WIZARD”.
Uma janela de boas vindas aparece.
No fim, é atribuido um nome ao projecto, que normalmente indica o objectivo, e conteúdo, do programa es-
crito. O projecto deverá ser movido para a pasta pretendida.
Documentos contidos no Projecto, não têem necessáriamente que ter sido escritos no MPLAB. Documentos
Clicar “FINISH” para completar o projecto. A janela em si, já contém parâmetros do Projecto.
Quando um projecto é criado, uma janela como a da figura abaixo, deverá aparecer:
Gravar o documento na pasta do projecto, usando os comandos FILE > SAVE, e dar-lhe o nome pretendido.
Depois de “XPTO.asm” ter sido criado, deverá ser incluido no projecto, fazendo clique direito na opção
“SOURCE FILES”, na janela “xxxx.MCW”. A seguir, uma pequena janela dará duas opções, das quais será
seleccionada “ADD FILES”.
Clicando nessa opção, abre outra janela que contém as pastas dos disco rígido. Escolher a pasta do projecto, e
o ficheiro “XPTO.asm”. Ver figura abaixo.
O primeiro programa
A escrita do programa não pode ser iniciada, antes destas operações anteriores terem sido realizadas.
O programa abaixo é um exemplo de como se faz:
PROCESSOR 16f887
#include “p16f887.inc”
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
End
O programa deve ser escrito na janela “xxxx.ASM”. Quando completada a escrita, o programa deverá ser com-
pilado para um ficheiro executavel de formato HEX, usando a opção PROJECT > BUILD ALL, e uma nova
janela vai aparecer. A última frase é a mais importante, porque diz se a compilação foi bem sucedida, ou não. Se
houver dúvidas, a mensagem “BUILD SUCCEEDED” significa que não houve nenhum erro.
Em caso de ocorrência de erro, é necessário fazer duplo clique em cima da linha de erro, na janela “Output”, que
automaticamente é mudada a janela, e o cursor será posicionado na linha do programa que contém o erro.
Simulador
O simulador faz parte do ambiente do MPLAB, e que dá uma maior perspectiva do funcionamento do micro-
controlador. Uma simulação é uma tentativa de imitar uma hipotética situação da vida real, para que possa ser
estudada e compreender como funcionar.
É, também, através do simulador que se faz a monitorização das variaveis, registos e estado dos pinos das
portas. Em programas complexos que usam Temporizadores, diferentes condições e pedidos, especialmente
matemáticas, o simulador pode ser de grande ajuda.
Tal como o microcontrolador, o simulador executa as instruções uma-a-uma, linha-por-linha, e faz o refres-
camento constante do estado de todos os registos. Desta maneira, o programador simplesmente monitoriza a
execução do programa.
O simulador é activado clicando em DEBUGGER > SELECT TOOL > MPLAB SIM, como ilustra a figura.
Como resultado, vários ícones do simulador aparecem. O seu significado é o seguinte:
Este ícone tem a mesma função do anterior, excepto que dá a possibilidade de saltar as sub-
rotinas.
Como no ambiente real, a primeira coisa a ser feita é o RESET ao microcontrolador, usando a opção DEBUG-
GER > RESET, ou clicando no ícone respectivo. Como consequência, uma linha verde é posicionada no início
do programa, e o Contador de Programa PCL é limpo para zero. Ver imagem abaixo com os SFR’s.
Aparte dos SFR’s, também se pode ver os Registos normais. Clicando em VIEW > FILE REGISTERS, uma
janela onde estes estão, vai aparecer.
Se o programa tem variaveis próprias, é também bom poder ver o seu valor. Clicando em VIEW > WATCH,
aparece uma janela onde podem ser acrescentadas estas variaveis.
Após todas as variaveis e registos de interesse estarem disponiveis, na área do simulador, o processo é simples.
A próxima instrução pode ser passo-a-passo, ou outro tipo. As instruções passo-a-passo podem ser executa-
das, também, através da tecla <F7> no teclado. Normalmente, todas as funções importantes, têem já teclas
atribuidas.
Bibliografia
Microchip: PIC16F886. www.microchip.com
www.microchipc.com
Microchip. PICmicro - Introduction to Programming in Assembler for PIC16 Products, 701 PIC. Mi-
crochip Masters, 2003
MikroElektronika: http://www.mikroe.com/en/
CONTACTOS
info@senaeng.com
+351.967033209
+351.236215256 (fax)
www.senaen
antónio g.com
sérgio ::
sena
soluções em electrónica
+351.967033209
www.senaeng .com :: soluções em electrónica e microcontroladores
+351.967033209 2 54