apostila pic 16f877a

123
Exsto Tecnologia Kit de Microcontroladores PIC Apostila de microcontroladores PIC16 Exsto Tecnologia Ltda. R. Vereador José Eduardo da Costa, 169 Santa Rita do Sapucaí – MG CEP: 37540-000 +55 35 3471 6898 www.exsto.com.br

Upload: geraldo-dias

Post on 02-Jan-2016

223 views

Category:

Documents


15 download

TRANSCRIPT

Page 1: Apostila PIC 16f877a

Exsto

Tecnologia

Kit de Microcontroladores PIC

Apostila de microcontroladores PIC16

Exsto Tecnologia Ltda.

R. Vereador José Eduardo da Costa, 169 Santa Rita do Sapucaí – MG

CEP: 37540-000 +55 35 3471 6898

www.exsto.com.br

Page 2: Apostila PIC 16f877a

Exsto Tecnologia

2 Microcontroladores PIC16F877A

Revisão Principais Autores Descrição da Versão Data de Término

1 José Domingos Adriano Revisão inicial para a nova versão do kit

© Copyright 2008 por Exsto Tecnologia Ltda.

Todos os direitos reservados

“Desenvolvido e produzido com orgulho no Brasil”

Exsto Tecnologia Ltda

R. Vereador José Eduardo da Costa, 169 Santa Rita do Sapucaí – MG

CEP: 37540-000 +55 35 3471 6898

www.exsto.com.br

Page 3: Apostila PIC 16f877a

Exsto Tecnologia

3 Microcontroladores PIC16F877A

ÍÍÍÍNDICE NDICE NDICE NDICE PPPPÁGINAÁGINAÁGINAÁGINA

Introdução .............................................................................................................................................. 6

1 CONCEITOS BÁSICOS ................................................................................................................ 7

1.1 Sistema Computacional .......................................................................................................... 7 1.1.1 Memórias........................................................................................................................... 8

1.1.2 Memória de programa ...................................................................................................... 8

1.1.3 Memória de Dados ............................................................................................................ 9

1.1.4 Barramentos ...................................................................................................................... 9

1.1.5 Dispositivos de entrada e saída ....................................................................................... 10

1.1.6 Periféricos ........................................................................................................................ 13

1.1.7 CPU .................................................................................................................................. 14

1.2 Arquitetura Computacional ................................................................................................... 17 1.2.1 Arquitetura von-Neumann .............................................................................................. 17

1.2.2 Arquitetura Harvard ........................................................................................................ 18

2 O MICROCONTROLADOR PIC16F877A ................................................................................. 20

2.1 A Microchip .......................................................................................................................... 20

2.2 Microcontroladores PIC ........................................................................................................ 20

2.3 A Arquitetura do PIC16F877A ............................................................................................. 21

2.4 Geração de clock ................................................................................................................... 22 2.4.1 Modos LP,XT e HS ............................................................................................................ 23

2.4.2 Modos RC......................................................................................................................... 25

2.4.3 Modo INTOSC .................................................................................................................. 26

2.4.4 Comparação entre os modos de oscilador ...................................................................... 26

2.4.5 Clock e execução das instruções ..................................................................................... 26

2.5 Memórias .............................................................................................................................. 27 2.5.1 Memória de programa .................................................................................................... 27

2.5.2 Memória de dados .......................................................................................................... 28

2.6 RESET .................................................................................................................................. 31 2.6.1 POR – Power-On Reset .................................................................................................... 31

2.6.2 PWRT – Power-up Timer ................................................................................................. 31

2.6.3 OST – Oscillator Start-up Timer ....................................................................................... 31

2.6.4 BOR – Brown-out Reset ................................................................................................... 31

2.6.5 Seqüência de inicialização ............................................................................................... 32

2.6.6 Identificação de Reset pelo Software .............................................................................. 32

2.7 Watch-Dog Timer ................................................................................................................. 33

2.8 Modo de baixo consumo – Modo SLEEP............................................................................. 33

Page 4: Apostila PIC 16f877a

Exsto Tecnologia

4 Microcontroladores PIC16F877A

2.9 Características especiais ....................................................................................................... 34 2.9.1 Proteção de Código (Code Protect) ................................................................................. 34

2.9.2 Locais de Identificação (ID Locations) ............................................................................. 34

2.9.3 Pinagem e Hardware Básico ............................................................................................ 34

2.10 Gravação ............................................................................................................................... 36

2.11 O conjunto de instruções do PIC16F877A ........................................................................... 37 2.11.1 Manipulação de Byte .................................................................................................. 39

2.11.2 Manipulação de bit ..................................................................................................... 40

2.11.3 Matemáticas ............................................................................................................... 41

2.11.4 Lógicas ......................................................................................................................... 44

2.11.5 Testes .......................................................................................................................... 48

2.11.6 Chamadas e desvio ...................................................................................................... 49

2.11.7 Controle ....................................................................................................................... 51

2.12 Programando em assembly ................................................................................................... 52

2.13 Estrutura do Programa .......................................................................................................... 53

2.14 Programação estruturada ....................................................................................................... 56

3 PROGRAMANDO O PIC16F877A ............................................................................................. 58

3.1 Diretivas ................................................................................................................................ 58

3.2 Variáveis ............................................................................................................................... 61

3.3 Sub-rotinas ............................................................................................................................ 62 3.3.1 Passagem de Parâmetros ................................................................................................ 63

3.3.2 Chamada X Desvio (CALL X GOTO) .................................................................................. 64

3.4 Atribuição ............................................................................................................................. 66

3.5 Entrada e Saída ..................................................................................................................... 67

3.6 Estruturas de Decisão ............................................................................................................ 68

3.7 Condições ............................................................................................................................. 69

3.8 Se .......................................................................................................................................... 71

3.9 Se senão ................................................................................................................................ 72

3.10 Se senão se ............................................................................................................................ 73

3.11 Caso ...................................................................................................................................... 75

3.12 Estruturas de repetição .......................................................................................................... 77 3.12.1 Faça-Enquanto ............................................................................................................ 78

3.12.2 Enquanto ..................................................................................................................... 78

3.12.3 Para ............................................................................................................................. 79

3.13 Temporização por software – Rotinas de atraso ................................................................... 80

4 RECURSOS AVANÇADOS ......................................................................................................... 84

4.1 Display de cristal Líquido ..................................................................................................... 84

4.2 Teclado ................................................................................................................................. 87

Page 5: Apostila PIC 16f877a

Exsto Tecnologia

5 Microcontroladores PIC16F877A

4.3 Interrupções .......................................................................................................................... 89 4.3.1 Utilização das Interrupções ............................................................................................. 92

4.3.2 Interrupção externa em RB0 ........................................................................................... 96

4.3.3 Interrupção por mudança no portal B ............................................................................. 96

5 PERIFÉRICOS DO PIC16F877A .............................................................................................. 98

5.1 Timers ................................................................................................................................... 98 5.1.1 Timer 1 ............................................................................................................................. 98

5.1.2 Oscilador do timer 1 ...................................................................................................... 101

5.1.3 Interrupção .................................................................................................................... 101

5.2 Módulo CCP ....................................................................................................................... 101 5.2.1 Modo captura ................................................................................................................ 102

5.2.2 Modo comparação ........................................................................................................ 103

5.2.3 Modo PWM ................................................................................................................... 103

5.2.4 Interrupção .................................................................................................................... 106

5.3 Comunicação Serial ............................................................................................................ 106 5.3.1 Comunicação Paralela ................................................................................................... 106

5.3.2 Comunicação serial ........................................................................................................ 107

5.3.3 EIA-232C ........................................................................................................................ 109

5.3.4 A USART do PIC16F877A................................................................................................ 110

5.3.5 Transmissão ................................................................................................................... 112

5.3.6 Recepção ....................................................................................................................... 113

5.4 Conversor Analógico para digital – ADC ........................................................................... 114 5.4.1 Configuração e uso ........................................................................................................ 116

5.5 Memórias EEPROM e Flash ............................................................................................... 118 5.5.1 Memória EEPROM ......................................................................................................... 118

5.5.2 Rotinas de acesso a EEPROM ........................................................................................ 119

5.5.3 Memória FLASH de programa ....................................................................................... 120

5.5.4 Rotinas de acesso a FLASH. ........................................................................................... 120

Apêndices ............................................................................................................................................ 122

Apêndice A – Conjunto de Instruções do PIC16 ............................................................................. 122

Apêndice B – Mapeamento de memória de dados ........................................................................... 123

Page 6: Apostila PIC 16f877a

Exsto Tecnologia

6 Microcontroladores PIC16F877A

Introdução Está apostila tem o objetivo de servir como livro texto para um curso de microcontroladores PIC16.

Esse conteúdo foi preparado para ser usado em disciplinas de microcontrolador/microprocessadores

em cursos técnicos ou superiores na área de tecnologia.

Os pré-requisitos para o bom aproveitamento do curso são conhecimentos básicos de informática,

eletrônica básica, eletrônica digital básica (principalmente memórias, contadores, portas lógicas e

flip-flops ). Também é recomendável para o bom andamento do curso que os alunos já tenham

freqüentada alguma matéria de programação (seja qual for a linguagem estudada).

O curso é estruturado em 5 capítulos que abordam o funcionamento do PIC16F877A, partindo de

conceitos mais gerais e especializando a cada passo, até tratar vários dos periféricos.

O capítulo inicial com os conceitos básicos sobre microcontroladores e sistemas computacionais, e

tem o objetivo de equalizar os pré-requisitos sobre o assunto. Este capítulo pode ser omitido, sem

qualquer prejuízo no andamento do curso, caso esses conceitos já tenham sido estudados em outras

disciplinas.

O capítulo 2 apresenta os microcontroladores PIC16 , tratando tanto de hardware como de

software, além de trazer os fundamentos de programação em linguagem assembly. São discutidos

organização de memória e funcionamento da CPU, além das principais características destes

microcontroladores.

De posse dos conhecimentos do Capítulo 2 é feito um estudo mais aprofundado de técnicas de

programação segundo os preceitos da programação estruturada e engenharia de software. Vale

ressaltar a importância dessa unidade, visto que ela visa formar as bases da lógica de programação e

que o desenvolvimento com microcontroladores é basicamente um desenvolvimento de software.

O capítulo 4 apresenta algumas aplicações avançadas de programação, com displays LCD, teclados

matriciais e, principalmente, interrupções.

No último capítulo são apresentados alguns dos principais periféricos do PIC16F877A, também

encontrados em outros microcontroladores da família PIC16. Destes, são fundamentais os timers e

comunicação serial. Os demais poderão ser sacrificadas ou resumidas, caso a carga horária não

suporte a totalidade do conteúdo, apesar de ser recomendado dar uma maior atenção ao conversor

analógico para digital.

Page 7: Apostila PIC 16f877a

Exsto Tecnologia

7 Microcontroladores PIC16F877A

1 CONCEITOS BÁSICOS Inicialmente será apresentado o conceito de microcontroladores de forma genérica, que

posteriormente será estendido ao PIC16F877A e pode ser aplicado a qualquer outro

microcontrolador.

É importante este embasamento teórico não somente para garantir um melhor aproveitamento no

estudo do PIC 16F877A como também para tornar o leitor apto a entender o funcionamento de

outros microcontroladores, tanto da linha PIC como de outros fabricantes. Esses conhecimentos

também são importantes na escolha do microcontrolador a ser utilizado em um projeto, pois permite

estabelecer as bases conceituais para a comparação de suas características.

1.1 Sistema Computacional Inicialmente devemos conceituar o que vem a ser um sistema computacional. Os sistemas

computacionais são compostos por sistemas combinacionais e seqüenciais. O que caracteriza um

sistema computacional é a possibilidade de ser programado.

Um sistema computacional é composto por hardware (parte física) e software (programa). O

hardware dos sistemas computacionais, ao contrário do que ocorre com sistema combinacionais e

seqüenciais, não possui uma aplicação específica. É necessário que exista um software para ser

executado. Em contrapartida, um mesmo hardware pode executar uma infinidade de funções

diferentes, simplesmente alterando o seu software.

Uma boa analogia é imaginar o hardware como um instrumento musical e o software como uma

partitura. Um piano por si só não faz nada, é necessária uma música que possa ser executada a fim

de se obter algum resultado. Da mesma forma que a música contida na partitura, um programa será

composto por um conjunto limitado de símbolos (no caso da partitura são as notas musicais e no

caso do programa são as instruções) que podem ser organizados de diversas formas diferentes,

obtendo-se diferentes resultados.

Como exemplo de sistema computacional, o primeiro que nos vem em mente é o computador

pessoal (PC), hoje tão difundido. Contudo, existem vários equipamentos, tão ou mais comuns que os

PC´s, que são sistemas computacionais. Por exemplo, os vídeo-games, os mini-games, as

calculadoras, palm-top´s, etc. Além disso, temos os microcontroladores, que são o objetivo desse

nosso estudo, que estão presentes nas mais diversas aplicações.

A estrutura de um sistema computacional é como a apresentada no diagrama em blocos abaixo

(Figura 1.1).

Page 8: Apostila PIC 16f877a

Exsto Tecnologia

8 Microcontroladores PIC16F877A

Figura 1.1 – Diagrama em blocos genérico de um sistema computacional

1.1.1 Memórias Memórias são dispositivos que armazenam informações. No caso de um sistema computacional, essa

informação, assim como a memória, pode ser dividida em dois tipos: de programa e de dados.

Existem também Registros (bytes de memória) com funções especiais que trabalham junto ao

processador (CPU).

1.1.2 Memória de programa Sua função é armazenar o software (programa) a ser executado no sistema. Também é utilizada para

guardar tabelas de constantes

Existem endereços de memória de programa existem alguns com finalidade específica, chamados

vetores, que são endereços para onde o programa desvia quando ocorrem determinados eventos.

Temos o vetor de reset, que é o endereço pelo qual o programa começa a ser executado e o vetor de

interrupções, que é para onde o programa desvia quando ocorreu um pedido de interrupção

(trataremos desse conceito mais adiante).

De uma forma geral, a memória de programa é uma memória não volátil. O tipo dessa memória pode

ser:

• ROM (Read Only Memory): somente de leitura. Geralmente chamada de masked-ROM

(masked = mascarado), é gravada pelo fabricante do componente, o que em quantidades

muito grandes reduz custos.

• OTP (Only Time programming): programável somente uma vez, utilizada em produção.

• EPROM (Erasable Progrmable Read Only Memory) : apagável através de luz ultra-

violeta. Utilizada no processo de desenvolvimento e algumas vezes no produto acabado,

quando há a necessidade de se poder alterar o software.

Controle

(CPU)

Dados

Memória

Programa

Dispositivos de

Entrada e saída e

periféricos

“Mundo

Externo”

Barramento de Dados

Page 9: Apostila PIC 16f877a

Exsto Tecnologia

9 Microcontroladores PIC16F877A

• Flash: é uma memória eletricamente apagável (EEPROM – Electricaly Eresable Read Only

Memory) com tempos de acesso para leitura rápido. Oferece uma grande flexibilidade,

pois geralmente é possível reprogramar um equipamento sem troca de componentes.

Praticamente todos os microcontroladores já possuem internamente algum desses tipos de memória

de programa. Atualmente quase todos os microcontroladores possuem versões em memória Flash,

pois a mesma apresenta muitas vantagens a um custo dos mais baixos.

1.1.3 Memória de Dados É a memória onde são armazenados os dados a serem processados pelo computador (as variáveis

dos programas e outras informações.). Como esses dados são constantemente alterados, a memória

utilizada para armazena-los é do tipo RAM. Como se trata de uma memória volátil, quando a

alimentação é cortada esses dados são perdidos.

Alguns microcontroladores disponibilizam também memórias EEPROM para armazenar dados que

não devem ser perdidos com a falta de energia.

1.1.4 Barramentos As várias partes de um sistema computacional (CPU, memórias, dispositivos de entrada e saída) são

ligadas entre si através de barramentos, ou vias, que são ligações físicas de comunicação paralela

entre os componentes. São eles:

• Barramento de dados: pelo qual os dispositivos de I/O e memórias trocam dados com o

processador

• Barramento de endereços: permite ao processador “endereçar” qual dispositivo será

acessado

• Barramento de controle: indica se o acesso é de leitura ou escrita, se é feito a posição de

memória ou a I/O.

• Barramento de programa: por onde o processador recebe as instruções que compõe o

programa.

O tamanho do barramento de dados limita o tamanho de dados que trafegam pelo sistema. Por isso

é comum classificar os sistemas computacionais pelo tamanho de seu barramento; temos então

sistemas de 8 bits, 16 bits, 32bits, etc. Os microcontroladores são em sua maioria de 8 bits, apesar de

existirem alguns modelos de 16 bits.

Já o tamanho do barramento de endereços nos informa qual a quantidade máxima de endereços de

memória ou dispositivos de I/O e periféricos podem ser acessados. Por exemplo, um barramento de

endereços de 10 bits permite acessar 210 = 1024 endereços.

Todos os dispositivos de um sistema computacional fazem uso do barramento de dados para trafegar

informações. Para que o sistema funcione corretamente podemos apresentar o processo de forma

simplificada assim: o processador (que coordena o processo) escreve no barramento de endereços o

endereço do dispositivo a ser acessado. Através do barramento de controle ele informa ao

dispositivo se o acesso é de leitura ou escrita (a definição de leitura ou escrita de dispositivos sempre

é feita pelo ponto de vista do processador). No caso de um aceso de leitura o dispositivo escreve no

Page 10: Apostila PIC 16f877a

Exsto Tecnologia

10 Microcontroladores PIC16F877A

barramento de dados e a informação é lida pelo processador. No caso de um acesso de escrita, o

processador envia dados para o barramento de dados que são lidos pelo dispositivo acessado.

Como dispositivos de um sistema computacional usam o mesmo barramento de dados para trafegar

informações é preciso que, quando um dispositivo estiver escrevendo no barramento (portanto

aplicando níveis de tensão ao barramento) os demais dispositivos não causem conflito de dados. De

fato, todos os dispositivos presentes em um sistema computacional são capazes de ficar em estado

de “alta impedância” enquanto não forem acessados para leitura.

1.1.5 Dispositivos de entrada e saída São responsáveis por realizar a interface do processador com o “mundo externo”. É através deles

que um sistema computacional adquire dados externos e aciona processos. São comumente

chamados de dispositivos de I/O (Input/Output – Entrada/Saída), portais de I/O (no inglês, ports) ou

simplesmente portais.

A função dos portais de saída é transferir ao “mundo externo” um dado que esteja presente no

barramento de dados. Para isso são utilizados latches, pois permitem o “carregar” dados somente

quando são acionados, retendo esses dados independente de haverem alterações em suas entradas.

Os portais de entrada devem permitir a transferência de dados do “mundo externo” para o

barramento de dados quando acionados e em alta impedância no restante do tempo. Para tanto, são

tradicionalmente utilizados buffers com saída tri-state para essa função.

A seleção dos dispositivos de I/O a partir do barramento de endereços é feita por decodificadores

ligados ao barramento de endereços e seu acionamento é feita através do barramento de controle.

Exemplo 1.1

A figura 1.2, abaixo, mostra um exemplo de utilização de buffers e latches como portais de entrada e

saída, respectivamente.

Ambos os portais estão ligados ao barramento de dados. Cada portal possui um decodificador (DEC),

que apresenta nível alto na saída quando o valor do barramento de endereços é o endereço do portal.

Os sinais RD (read – ler), WR (write – escrever) e IORQ (I/O request – requisição de I/O) constituem o

barramento de controle.

Para a operação de leitura, o endereço do portal é colocado no barramento de dados.O decodificador

decodifica o endereço do portal de leitura e coloca em sua saída nível lógico 0. Em seguida, os sinais

IORQ e RD são acionados. Assim temos ‘1’ no terminal de habilitação de saída do buffer e o valor em

sua entrada é transferido para o barramento de dados, podendo ser armazenado pela CPU.

Page 11: Apostila PIC 16f877a

Exsto Tecnologia

11 Microcontroladores PIC16F877A

Figura 1.2 – Portais de entrada e saída

Para realizar uma operação de escrita do portal , o processador inicialmente coloca os dados a serem

escritos no barramento de dados e o endereço do portal no barramento de endereço.O decodificador

decodifica o endereço do portal de escrita e coloca em sua saída nível lógico 0. Então são acionados

os sinais WR e IORQ. Nesse instante temos ‘1’ nas três entradas da porta AND que aciona o terminal E

do latch, que faz com ele carregue os dados presentes no barramento na saída.

Figura 1.2 – Portais de entrada e saída

A função do microcontrolador, como o próprio nome diz, é controlar processos e circuitos. Para

otimizar essa função, seus portais de entrada e saída são tratados como registros de funções

especiais, ou seja, são lidos e escritos como se fossem simples bytes de memória. Em sistemas como

microprocessadores geralmente o tratamento é diferente, havendo instruções específicas para

acesso aos portais e outras implicações, que diminuem a eficiência do código gerado quando se

trabalha intensamente com entrada e saída.

Page 12: Apostila PIC 16f877a

Exsto Tecnologia

12 Microcontroladores PIC16F877A

Para maior flexibilidade do sistema, geralmente os microcontroladores utilizam um sistema de

portais mais complexo que o apresentado acima, que permite que um mesmo terminal do

microcontrolador seja configurado como entrada ou saída. Para que isso seja possível é utilizado um

registro de portal (PORT) e um registro de direção de dados (DDR – Data Direction Register). Esse

último permite selecionar a direção de cada bit de um portal de saída, individualmente. A figura 1.3a

e 1.3b abaixo mostram o esquema genérico de um bit de portal do PIC16F877A. Outros

microcontroladores utilizam configurações semelhantes.

Figura 1.3a – Esquema típico de um pino de I/O

OPERAÇÃO DE ESCRITA OU SAÍDA DE DADOS: ao acionar o controle WR PORT, o latch de saída (Data

Latch) armazena a informação complementar do barramento de dados em sua saída complementar

Q “barra”. Vamos admitir que o registro de direção de dados (TRIS Latch) foi carregado inicialmente

com o valor ‘0’. O registro de direção de dados é habilitado através do controle WR TRIS e a

informação de direção fica armazenada em sua saída. Para Q=0 e Q ”barra”=1 na saída do registro de

direção, o pino I/O estará configurado como saída e tem-se a transferência da informação Q ”barra”

do latch de saída para o driver do pino I/O conforme o arranjo das portas lógicas. Se este último Q

”barra” =0 o transistor “N” será cortado e “P” será ativado permitindo que a tensão Vdd apareça no

pino I/O como nível lógico 1 que era a informação original do barramento de dados. Se Q “barra” =1

o transistor “P” será cortado e “N” estará ativo. A tensão no pino I/O cai para o nível Vss indicando

nível lógico 0.

Page 13: Apostila PIC 16f877a

Exsto Tecnologia

13 Microcontroladores PIC16F877A

Figura 1.3b – Esquema típico de um pino de I/O

OPERAÇÃO DE LEITURA OU ENTRADA DE DADOS: novamente admitamos que o registro de direção

foi carregado inicialmente com o valor ‘1’ em sua saída. Agora, o arranjo das portas lógicas permite

o corte simultâneo dos dois transistores do driver configurando o pino I/O como entrada de dados.

Assim, o controle RD PORT habilita o latch de entrada e o buffer tri-state, o que possibilita que a

informação do pino de I/O trafegue pelo barramento de dados. No restante do tempo o buffer fica

em alta impedância.

Caso seja feita uma operação de escrita em um terminal configurado como entrada, o dado escrito

será armazenado no latch de dados, mas não será transferido para o terminal, pois o driver está

desativado. Por outro lado, se for realizada uma operação de leitura em um terminal configurado

como saída, o valor lido será o dado presente no terminal, que é o mesmo escrito no latch de dados

anteriormente.

1.1.6 Periféricos Além dos portais de I/O e as memórias, podemos ter muitos outros tipos de dispositivos ligados ao

barramento de dados. Esses dispositivos nada mais são do que circuitos destinados a realizar funções

especiais. Esses dispositivos periféricos são particularmente importantes nos microcontroladores.

Como periféricos mais comuns podemos citar os temporizadores e contadores (Timers), os módulos

de comunicação serial, conversores AD e DA, módulos de CCP (Captura, comparação e PWM), drivers

de LCD, comparadores analógicos, etc.

Page 14: Apostila PIC 16f877a

Exsto Tecnologia

14 Microcontroladores PIC16F877A

O modo de acesso aos periféricos é semelhante ao de acesso aos portais de I/O. Eles muitas vezes

possuem vários registros de parâmetros que podem ser configurados, e um ou mais registros de

entrada e saída de dados.

Quando estivermos tratando dos periféricos do PIC16F877A mostraremos como trabalhar com eles

e, apesar de cada microcontrolador apresentar um conjunto de periféricos diferentes, seu

funcionamento é muito semelhante.

1.1.7 CPU A CPU (Central Processing Unit – Unidade Central de Processamento) ou processador é parte

principal de um sistema computacional. É comum se referir à CPU dos microcontroladores como core

(núcleo). Sua função é executar as instruções do programa e processar dados. Para tanto ela controla

todas as demais partes do sistema e envia ou recebe dados dessas partes. Ela também é capaz de

interpretar e colocar em execução as instruções que compõe o programa e realizar operações lógicas

e aritméticas.

Genericamente um processador é organizado conforme o diagrama em blocos da figura 1.4.

Figura 1.4 – Diagrama em blocos de uma CPU

Os nomes de cada bloco estão em inglês no diagrama para facilitar a identificação desses blocos nos

manuais de microcontroladores e microprocessadores, que comumente são escritos nessa língua. Os

blocos pontilhados podem ou não estar presentes. As vias em amarelo representam o barramento de

dados interno do processador, que é ligado ao barramento de dados do sistema. As vias em verde

são outras vias de dados e sinais de controle.

Page 15: Apostila PIC 16f877a

Exsto Tecnologia

15 Microcontroladores PIC16F877A

O principal bloco de um processador é o decodificador de instruções (Instructiuon Decoder).

Voltando a analogia entre um sistema computacional e um instrumento musical, o decodificador de

instruções pode ser comparado ao músico, que age sobre o instrumento (hardware) executando a

música (software).

Esse bloco é composto por um decodificador e um contador. Tal decodificador pode ser visto como

um livro de receitas culinárias. No livro, cada página contém uma receita e dentro de cada receita há

os passos para sua execução. De modo análogo, cada instrução do processador é como o endereço

de uma “página” onde está a seqüências de acionamento dos sinais de controles (internos e externos

ao processador) que permitem a execução da instrução. O contador existente é responsável por

fazer com que os passos para a execução de uma instrução sejam executados em seqüência. Cada

modelo de processador possui um conjunto, ou set, de instruções que pode executar.

O barramento de controle interno (Internal Control) permite ao decodificador de instruções

controlar os blocos internos do processador, enquanto o barramento de controle externo (External

Control) já foi discutido e tem a função de indicar se o acesso é de leitura ou escrita, se é em

memória ou dispositivos de I/O.

O programa armazenado na memória é uma seqüência de instruções. Podemos então supor que

para endereçar corretamente essas instruções deveria haver um contador. Ele existe e é chamado

Contador de Programa ou PC (Program Counter). A cada instrução iniciada o PC é incrementado.

Portanto ele aponta a próxima instrução, isto é, contém o endereço da próxima instrução a ser

executada. A saída desse contador é ligada a um registro (Program Addressing) que é carregado ao

final de cada instrução com o endereço da próxima instrução. A saída do registro Program Addressing

está ligada ao barramento de endereços da memória de programa.

Quando a CPU é resetada, o PC é automaticamente carregado com o valor do vetor de reset. Durante

a execução do programa, um valor pode ser carregado no PC. Isso ocorre para desviar o fluxo do

programa. Existem instruções que realizam essa alteração de fluxo, que pode ser de dois tipos:

desvio ou chamada.

Quando ocorre um desvio o conteúdo do PC é alterado para que ele passe a executar o programa a

partir de outro ponto.

Na execução de uma chamada o fluxo do programa também é desviado para um determinado ponto

para executar um trecho do programa, mas nesse caso ele deve retornar ao ponto do programa onde

ocorreu o desvio (mais precisamente à primeira instrução após a instrução de chamada). Isso

permite executar uma sub-rotina, conceito que será discutido quando tratarmos do software.

Em uma chamada o endereço de retorno deve ser armazenado em algum lugar, caso contrário não

seria possível retornar ao ponto onde a chamada ocorreu. Esse lugar é chamado de pilha (stack). O

nome pilha se deve a seu funcionamento, que é semelhante a uma pilha de pratos: como pode haver

várias chamadas consecutivas sem que haja retorno, os endereços de retorno são armazenados “uns

sobre os outros”. Quando ocorre uma instrução de retorno (que é o que faz o programa retornar da

chamada), o programa volta para o último endereço guardado, e assim sucessivamente até que a

pilha esteja vazia. A pilha é então uma porção de memória onde podem ser armazenados os

endereços de retorno.

Page 16: Apostila PIC 16f877a

Exsto Tecnologia

16 Microcontroladores PIC16F877A

Para indicar a próxima posição livre na pilha existe um registro (na verdade um contador) chamado

ponteiro da pilha (Stack Pointer) que aponta o topo. Esse registro é incrementado cada vez que um

novo endereço de retorno é armazenado na pilha e decrementado quando ocorre um retorno.

Uma vez determinado o endereço, seu conteúdo é lido e armazenado em um registro chamado

registro de instrução (Instruction Register). Desse registro, parte da instrução vai para o

decodificador de instruções e parte pode ir para a ALU e/ou parte para o registro de endereçamento

de dados (Data Addressing). Para entender o porque disso, devemos ter em mente que uma

instrução nada mais é que uma palavra binária. Parte dela, que é efetivamente a instrução, indica ao

decodificador de instruções qual a seqüência de ações deve ser executada (qual a “página” do

decodificador de instruções). O restante constitui os operandos da instrução, ou seja, os dados a

serem processados. Esses dados podem ser constantes ou endereços de dados variáveis na memória

RAM. Conforme sua natureza e a instrução a ser executada eles tem um destino ou outro.

A unidade lógico-aritmética ou ALU (Aritmetic and Lógic Unit) é o circuito responsável pelos cálculos

em um processador. Como próprio nome diz, ela é responsável pela realização de operações lógicas,

(E, OU, OU-exclusivo, deslocamentos, rotações, complemento), e aritméticas (incremento,

decremento, adição, subtração, multiplicação, e divisão). Os processos de divisão e multiplicação são

feitos com a ALU utilizando seqüências somas e subtrações, o que efetivamente o que a ALU é capaz

de fazer.

A ALU trabalha juntamente com dois registros especiais: o Acumulador (Accumulator) e o registro de

estado de operações aritméticas (Status). É comum se referir ao acumulador simplesmente como

Acc ou, no caso dos PICs, como W (Worker – Trabalhador ). O acumulador quase sempre está

envolvido nas operações realizadas pela ALU. Ele pode ser um dos operandos, pode ser onde se

armazena o resultado ou pode ser as duas coisas. Há também microcontroladores onde qualquer

transferência de dados entre dois endereços da RAM passa pelo acumulador.

Quanto ao registro de status, sua função é indicar resultados notáveis das operações matemáticas.

Esses resultados são indicados por flags, que são bits desse registro. Através da análise dos flags é

possível saber, dentre outras coisas, se uma operação resultou em zero; se houve estouro da

capacidade de armazenamento (overflow), que acontece quando um resultado é maior que o

máximo valor possível de ser representado pelo sistema; se o resultado de uma operação aritimética

é negativo ou positivo. Existe uma interação do registro status com o decodificador de instruções,

pois através da análise de seus flags é possível realizar instruções de testes.

Para acessar a memória de dados e os periféricos existe um registro, que em nosso sistema é

chamado de endereçamento de dados (Data Addressing) que pode receber valores de duas formas.

A primeira é diretamente de parte da instrução. Nesse caso se está fazendo referência a endereços

da RAM conhecidos e fixos, pois são carregados valores constantes existentes no programa. Esse

modo é chamado endereçamento direto.

Em muitos casos é necessário fazer referências a endereços variáveis. Isso é feito carregando o

registro de endereçamento com dados provenientes de um outro registro, o registro de

endereçamento indireto (Indirect Addressig). Como qualquer outro registro, ele pode ser carregado

com um valor, constante ou proveniente de uma variável, pode ser incrementado, decrementado ou

participar que qualquer operação lógico-aritmética. Sua função é semelhante a dos ponteiros em

linguagens de alto nível.

Page 17: Apostila PIC 16f877a

Exsto Tecnologia

17 Microcontroladores PIC16F877A

Todo o sistema computacional trabalha sincronizado com um mesmo sinal de clock. Devemos

lembrar que esse clock é o que faz o decodificador de instruções passar de uma instrução para a

outra, e tudo o mais deve estar sincronizado com ele, senão haveria o caos. Para gerar esse sinal de

clock é necessário um oscilador. Nos microcontroladores esse oscilador já faz parte do componente

Independente da forma como o clock é gerado, esse sinal é aplicado a CPU e aos periféricos. É

comum que a freqüência do clock dos periféricos seja menor que a da CPU. Para tanto são utilizados

divisores de freqüência

Outro ponto importante é o reset. Além do reset que ocorre quando o sistema é ligado, chamado de

Power-on reset, os microcontroladores apresentam várias outras fontes de reset. Esses resets são

proteções do sistema.

Síntese genérica de operação de uma CPU:

1) O iniciar um programa, o contador de programa aponta para o primeiro endereço na memória de programa.

2) Neste endereço começa o programa. 3) O registrador de instrução armazena o dado guardado neste endereço. Este dado é

composto da instrução e do operando. O operando pode ser proveniente da memória de programa ou da memória RAM ( memória de dados ).

4) O decodificador de instrução recebe a instrução do registrador de instrução. 5) A instrução corresponde a uma seqüência de passos programados em uma ROM, o chamado

microcódigo. 6) Um contador dentro do decodificador de instrução varre essa seqüência de passos. 7) O decodificador de instrução começa então a acionar os dispositivos dentro ou fora da CPU

através dos barramentos de dados, controle e endereço. 8) A partir desse ponto os dispositivos podem ser acionados nas mais diversas seqüências de

operação dependendo da necesidade de processamento imposta pelo código, por exemplo:

• O contador de programa aponta para o próximo endereço de memória de programa onde pode estar o valor de uma instrução com operando. A memória de programa é habilitada e esse valor é passado do para a ALU através do registro de instrução.

• O contador de programa aponta para o próximo endereço na memória de dados. A memória de dados é habilitada e o valor armazenado nesse endereço passa para o acumulador.

• A ALU opera aritmeticamente esses dois dados, sinaliza para o registrador de estados qual foi e estado da operação e disponibiza o resultado em sua saída.

• Uma memória ou um dispositivo de saída pode ser habilitado e o resultado será armazenado em um desses dispositivos.

Em resumo sempre ocorre um processo de BUSCA e EXECUÇÃO da instrução. A busca se

refere a localização das instruções e dos operandos na memória e a execução se refere ao

acionamento de dispositivos em seqüência para conseguir o resultado desejado.

1.2 Arquitetura Computacional

1.2.1 Arquitetura von-Neumann Na arquitetura von-Neumann, as memórias tanto de dados quanto de programa, são acessadas

usando-se o mesmo barramento de dados; os portais de I/O também fazem uso do barramento de

dados. Ou seja, a memória e os dispositivos de I/O compartilham o mesmo barramento em

momentos distintos.

Page 18: Apostila PIC 16f877a

Exsto Tecnologia

18 Microcontroladores PIC16F877A

Vale lembrar aqui que uma instrução é como uma operação matemática, isto é, composta de

operadores, que indicam o que será feito, e operandos, que são os parâmetros envolvidos na

operação.Desta forma, o processo de execução de cada instrução é dividido em dois momentos: a

leitura da instrução e a leitura dos operandos (fetch) e a execução da instrução propriamente dita.

Nota-se que dessa forma o processador está parte do tempo ocupado com a leitura da memória de

programa e, conseqüentemente não fica executando o firmware o tempo todo. Outra característica

da arquitetura von-Neumann é que, visto que os operandos das instruções são geralmente do

mesmo tamanho do barramento de dados, quanto mais complexa a instrução maior será a

quantidade de endereços ocupados por ela na memória. Isto quer dizer que por exemplo, para um

barramento de 8 vias, uma instrução de 16 bits é buscada e executada em duas partes de 8 bits. Por

outro lado, como a complexidade da instrução não tem limite a não ser o espaço ocupado, podemos

ter um set de instruções tão complexo quanto se queira.

Podemos concluir que arquitetura von-Neumann consome muito tempo de processamento com a

leitura da instrução e dos operandos. Conclui-se também que instruções diferentes ocupam

quantidades diferentes de memória e são executadas em tempos diferentes.

Figura 1.5 – Arquitetura von-Neumann

Os sistemas de arquitetura von-Neumann geralmente têm conjuntos de instruções complexos, o que

equivale a dizer que possuem um grande número de instruções e cada instrução realiza uma grande

seqüência de ações. Processadores desse tipo são chamados CISC (Complex Instruction Set CPU –

CPU com Set de Instruções Complexo).

1.2.2 Arquitetura Harvard Já a arquitetura chamada de arquitetura Harvard, que é utilizada nos microcontroladores PIC, tem

como principal característica acessar a memória de dados separadamente da memória de programa.

A principal vantagem dessa arquitetura é que a leitura de instruções e de alguns tipos de operandos

pode ser feita ao mesmo tempo em que a execução das instruções (tempo Tcy). Isso significa que o

sistema fica todo o tempo executando instruções, o que acarreta um significativo ganho de

velocidade. Enquanto uma instrução está sendo executada, a seguinte está sendo lida. Esse processo

é conhecido como pipelining (canalização) e é ilustrado pela figura 1.6 abaixo.

Memória

CPU

I/O

Programa

Dados

Barramento de

Dados

Page 19: Apostila PIC 16f877a

Exsto Tecnologia

19 Microcontroladores PIC16F877A

CPU

I/O

Memória de

Dados

Memória de

Programa

Barramento de

Programa Barramento de

Dados

Figura 1.6 – Pipeline

O barramento de programa não necessariamente tem o mesmo tamanho do barramento de dados.

Dessa forma, em uma única palavra da memória de programa pode conter operando e operadores, o

que nos permite carregar toda a instrução em um único ciclo de leitura da memória.

Figura 1.7 – Arquitetura Harvard

Pode-se notar então que os tempos de execução e de leitura estão atrelados e são os menores

possíveis. Isso acarreta em as instruções não poderem executar uma grande seqüência de ações, ou

seja, não existem instruções complexas. Por isso, os PIC´s são considerados processadores RISC

(Reduced Instruction Set CPU – CPU com Set de Instruções Reduzido). O número de instruções é

reduzido, o que não significa que não se possa executar programas complexos, mas sim que

seqüências complexas de ações devem ser construídas por seqüências de instruções básicas.

Page 20: Apostila PIC 16f877a

Exsto Tecnologia

20 Microcontroladores PIC16F877A

2 O MICROCONTROLADOR PIC16F877A

2.1 A Microchip O fabricante dos microcontroladores PIC é a empresa americana Microchip. Atualmente ela é um dos

maiores fabricante mundiais de microcontroladores de 8, 16 e 32 bits, além de possuir uma ampla

linha de memórias e componentes analógicos.

A Microchip trabalha com uma política de suporte ao cliente muito eficiente, que provavelmente é

uma das causas de seu sucesso. Em seu site (www.microchip.com) existe uma grande quantidade de

informação disponível. Além dos manuais dos componentes, existem muitas notas de aplicação

(Application Notes) e projetos de referência, que são de grande ajuda para a formação da base de

conhecimentos do estudante de microcontroladores PIC.

2.2 Microcontroladores PIC Os PICs são divididos em famílias. Cada família, ou plaforma, tem vários componentes, com

tamanhos e recursos diferentes; no entanto o código desenvolvido para um componente de uma

determinada família é compatível com os demais componentes da mesma família, exceto por umas

poucas alterações, que ser referem principalmente aos periféricos. Cada família tem seu próprio set

(conjunto) de instruções. Essas instruções são comandos em linguagem de programação assembly

que compõe os softwares gravados nos microcontroladores, com as quais o aluno entrará em

contato mais adiante. Dessa forma, ao se estudar um componente específico de uma família, se está

adquirindo conhecimento para trabalhar com microcontroladores de toda a família.

As famílias são se dividem ainda conforme o tamanho do barramento de bits, havendo

microcontroladores de 8, 16 e 32 bits.

As famílias de microcontroladores PIC são:

• 8 bits o Família PIC10 o Família PIC12 o Família PIC14 e PIC17 o Família PIC16 o Família PIC18

• 16 bits: o Famílias PIC24F e PIC24H o Familias dsPIC30F e dsPIC33F

• 32 bits

Page 21: Apostila PIC 16f877a

Exsto Tecnologia

21 Microcontroladores PIC16F877A

o PIC32 o

Os componentes diferem entre si basicamente em:

• Quantidade de memória RAM

• Quantidade de memória EEPROM de dados (alguns não têm nada)

• Quantidade de memória Flash de programa

• Número de pinos (8,14,18,28,40, ...)

• Freqüência máxima de clock

• Periféricos Nesse curso abordaremos o PIC16F877A, que é um dos componentes mais completos da família

PIC16. Conforme foi dito anteriormente, ao se estudar um membro de uma família o estudante

torna-se apto a trabalhar com toda a família.

2.3 A Arquitetura do PIC16F877A A figura 1.1 apresenta o diagrama em blocos do PIC16F877A.

Trata-se de um microcontrolador de 8 bits de arquitetura Harvard. Seu barramento de programa é de

14 bits. A estrutura do PIC16F877A é semelhante ao sistema genérico estudado na aula 1. Seu

funcionamento e análise também são semelhantes à aquele sistema genérico consistindo nas etapas

de busca de instrução com habilitação e leitura de memória de programa e, execução da instrução

com decodificação da instrução e acionamento de dispositivos em seqüência para o processamento

da atividade programada. Podem ser observados os barramentos de dados e de programa. Além

disso, nota-se como operandos da ALU e de endereçamento da memória de dados vem diretamente

da memória de programa.

Também são dignos de nota os periféricos, localizados na parte inferior do diagrama, que estão

ligados ao barramento de dados.

Page 22: Apostila PIC 16f877a

Exsto Tecnologia

22 Microcontroladores PIC16F877A

Figura 2.1 – Diagrama em blocos do PIC16F877A

2.4 Geração de clock

Os microcontroladores PIC possuem um circuito de oscilação interna, isto é, são capazes de gerar seu

próprio clock (ou sinal de relógio) com acréscimo de poucos (ou nenhum) componentes externos.

Existem sete modos diferentes de clock, e cada componente da família utiliza alguns deles. O modo

de clock para cada aplicação é selecionado no momento da gravação do microcontrolador e não

pode ser alterado pelo programa. São eles:

• LP: Cristal/Ressonador de baixa freqüência e baixo consumo (Low Frequency (Power)

Crystal)

• XT: Cristal/Ressonador (Crystal/Resonator);

• HS: Cristal/Ressonador de Alta Freqüência (High Speed Crystal/Resonator);

• RC: Oscilador RC Externo (External Resistor/Capacitor);

o Com saída de clock

o Sem saída de clock

• INTOSC (INTRC): Oscilador RC Interno de 4MHz (Internal Resistor/Capacitor) Esse modo

não está presente no PIC16F877A, mas existe em outros componentes da família PIC16;

Page 23: Apostila PIC 16f877a

Exsto Tecnologia

23 Microcontroladores PIC16F877A

o Com saída de clock

o Sem saída de clock

Obs.: resistores, indutores, capacitores e cristais podem ser combinados formando circuitos

osciladores em freqüências determinadas. Mais detalhes sobre os conceitos, funcionamento e

projeto desse tipo de circuito podem ser encontrados em livros de eletrônica com capítulos sobre

osciladores.

2.4.1 Modos LP,XT e HS

Os modos LP, XT e HS utilizam um cristal ou ressonador cerâmico para estabilizar o clock. A diferença

está na faixa de freqüência de cada modo e no consumo de energia associado a cada freqüência.

O consumo de energia em sistemas computacionais está diretamente relacionado com o a

freqüência de operação do sistema porque a dissipação de potência (transformação de energia

elétrica em energia térmica) nos transistores que compõem os circuitos integrador digitais se dá nos

momentos de transição de baixo para auto e de auto para baixo. Assim, quanto mais transições por

unidade de tempo (ou seja, quanto maior a freqüência) maior a dissipação de energia e, portanto,

maior o consumo.

O modo LP refere-se a cristal/ressonador cerâmico de baixa freqüência. Esse modo trabalha com

freqüências de oscilação de até 200 kHz e nele conseguimos o menor consumo dos três modos em

questão.

O modo XT abrange as freqüências de 200 kHz até 4 MHz e apresenta um consumo médio.

O modo HS é para freqüências de 4 a 20 MHz e tem o mais alto consumo.

Cada faixa de freqüência possui um ganho do circuito oscilador, que é ajustado de forma diferente

para cada modo. É recomendado que se use o modo adequado para cada freqüência, caso contrário

pode ocorrer mau funcionamento do oscilador.

Além do cristal ou do ressonador, nos modos LP, XT e HS, devem existir capacitores ligados dos

terminais do cristal terra, conforme mostra a figura 2.2.

Os valores desses capacitores C1 e C2 são os indicados nas tabelas Capacitor Selection for Crystal

Oscillator que se encontra nos manuais de cada PIC na seção que trata de configurações do oscilador.

Para o PIC16F877A os valores são os apresentados na tabela 2.2. O valor de RF representa o ajuste

interno do oscilador para cada modo (XT, LP e HS). O resistor RS pode ser necessário para alguns

tipos de corte de cristal, mas geralmente não é usado. O Comando SLEEP desativa o oscilador no

modo de baixo consumo, do qual trataremos mais adiante.

Page 24: Apostila PIC 16f877a

Exsto Tecnologia

24 Microcontroladores PIC16F877A

Figura 2.2 – Circuito do Oscilador a Cristal/Ressonador

Modo de Oscilador Freqüência do Cristal Capacitores C1 e C2

LP 32 kHz 33 pF

200 kHz 15 pF

XT

100 kHz 47 a 68 pF

1 MHz 15 pF

4 MHz 15 pF

HS

4 MHz 15 pF

8 MHz 15 a 33 pF

20 MHz 15 a 33 pF

Tabela 2.1 – Seleção de capacitores para oscilador a cristal

Capacitores maiores aumentam a estabilidade do oscilador, mas também aumenta o tempo de

partida.O tempo de partida do oscilador é o tempo necessário para que o oscilador se estabilize,

pois a oscilação não ocorre de forma imediata assim que o circuito é alimentado,conforme mostra a

figura2.3. Esse tempo depende de uma série de fatores, além dos capacitores, com temperatura,

tensão de alimentação e até capacitâncias parasitas do lay-out da placa. Esse tempo deve ser

considerado pois o programa só será iniciado (ou reiniciado, no caso do modo de baixo consumo)

quando o oscilador se estabilizar.

Page 25: Apostila PIC 16f877a

Exsto Tecnologia

25 Microcontroladores PIC16F877A

Figura 2.3 – Partida do oscilador

Também é possível aplicar sinais de clock gerados externamente, bastando para isso selecionar o

modo relativo a faixa de sinal utilizado. Nesse caso o sinal deve ser aplicado ao pino OSC1/CLKIN e o

pino OSC2/CLKOUT deve permanecer em aberto.

2.4.2 Modos RC Também é possível trabalhar com osciladores RC (Resistor/Capacitor). Para isso é utilizada a

montagem da figura 2.4 e selecionado o modo de oscilador como RC.

Figura 2.4 – Circuito do oscilador no modo RC.

O modo RC apresenta algumas limitações: a freqüência de trabalho é dependente de vários fatores

(valores de resistor e de capacitor, tensão de alimentação, temperatura) e apresenta pouca

estabilidade (tolerância dos resistores e capacitores, variação na tensão de alimentação, variações de

temperatura). Por exemplo, em uma produção em quantidade de produtos utilizando PIC´s no modo

RC, a freqüência de cada produto pode variar em função da tolerância dos resistores utilizados. Não

é possível garantir precisão em nada que se baseie em tempo no programa. Assim esse modo só é

recomendado para aplicações nas quais a freqüência não é um fator crítico. Essa situação é que

justifica a utilização do modo, pois um oscilador RC tem custo menor que um a cristal.

O resistor REXT deve estar entre 3kΩ e 100kΩ e o capacitor CEXT deve ser superior a 20pF. O circuito

pode funcionar sem capacitor CEXT, mas nessa situação ele se torna muito suscetível a variações

drásticas de freqüência devido a capacitâncias externas (do próprio lay-out, por exemplo). Além

disso, a variação da freqüência é maior para resistores maiores e capacitores menores.

Page 26: Apostila PIC 16f877a

Exsto Tecnologia

26 Microcontroladores PIC16F877A

No modo RC com saída de clock o terminal OSC2/CLKOUT apresenta a freqüência do oscilador divida

por quatro, que pode ser utilizado como fonte de clock para outros pontos do circuito. Já no modo

sem saída de clock, esse terminal pode ser utilizado como I/O.

2.4.3 Modo INTOSC Esse modo de oscilador não está disponível no PIC16F877A, mas pode ser encontrado em outros

modelos de microcontroladores. No modo INTOSC (ou INTRC) não se necessita de nenhum outro

componente externo. Portanto, além da redução de custos, ele libera terminais do microcontrolador

para serem utilizados como I/O.

Nesse modo, o sinal de clock é obtido de forma semelhante ao funcionamento do modo RC, porém o

“resistor” e “capacitor” são implementados na própria pastilha do componente. Devido a isso temos

geralmente uma ou duas freqüências de clock fixas.

Tipicamente o oscilador interno é menos preciso que o oscilador a cristal é mais preciso que o

oscilador RC, com tolerâncias entre +/- 1 e 10 %.

2.4.4 Comparação entre os modos de oscilador Na tabela 2.2 é feita uma comparação entre os diferentes modos de oscilador.

Quesito Tipo de Oscilador

Cristal (HS, XT e HS) RC Externo RC Interno Precisão Preciso Impreciso Pouco preciso Estabilidade Estável Instável Pouco Estável Variedade de freqüências Pequena Grande Nenhuma Custo Alto Baixo Nenhum

Tabela 2.2 – Seleção de capacitores para oscilador a cristal

2.4.5 Clock e execução das instruções Cada instrução executado pelos microcontroladores PIC16 gasta 4 ciclos de clock, chamados “ciclos

Q”. Esses 4 ciclos compõem um ciclo de instrução (TCY) que dura 4 vezes mais que um ciclo Q ,

portanto um ciclo de instrução tem ¼ da freqüência do oscilador e o sinal desse ciclo maior é

chamado de clock de instrução ou clock de periféricos. Ou seja, o tempo de execução de cada

instrução e de 4 períodos de clock.

Em cada um dos ciclos Q é realizada uma etapa da instrução, conforme mostrado na tabela 2.2.

Graficamente esse processo é apresentado na figura 2.5.

Ciclo Ação

Q1 Ciclo de decodificação da instrução Q2 Ciclo de leitura de dados Q3 Ciclo de processamento Q4 Ciclo de escrita de dados

Tabela 1.2 – Ciclos de execução das instruções

Page 27: Apostila PIC 16f877a

Exsto Tecnologia

27 Microcontroladores PIC16F877A

Figura 2.5 – Ciclos de instrução

Alguns periféricos e algumas funções do PIC não são sincronizados nem com o clock do oscilador

nem com o clock de periféricos, mas com os ciclos Q.

2.5 Memórias

2.5.1 Memória de programa O PIC16F877A possui 8K-palavras de memória de programa. Já que se trata de um processador RISC,

o tamanho das palavras da memória de programa é maior que o barramento de dados. Assim, apesar

de ser um microcontrolador de 8 bits, a memória de programa é composta por palavras de 14 bits.

Cada palavra, isto é, cada endereço de memória de programa guarda uma instrução. Dessa forma,

um programa de 500 instruções ocupará 500 bytes.

O vetor de reset é o endereço 0000h. Como vimos, isso significa que o programa deve ser escrito a

partir desse endereço. O vetor de interrupção, para todas as interrupções é o 0004h.

A memória é do tipo FLASH, suportando um grande número de reescritas. É possível, através de

rotinas que trataremos em outro ponto do curso, realizar escrita na memória e programa.

Na estrutura das instruções de chamada e desvio da família 16F o espaço reservado para endereço é

de 11 bits. Portanto é possível endereçar diretamente 2048 endereços de memória. Sendo que o

PIC16F877A tem 8k endereços de memória de programa, essa memória é dividida em unidades que

chamaremos de páginas. Dentro de uma mesma página é possível realizar saltos e desvios para

qualquer ponto. Mas se um salto ou desvio vai de uma página para outra é necessário fazer um

ajuste prévio dos dois bits mais significativos do SFR PCLATH, conforme mostrado na tabela abaixo.

Página PCLATH

Bit 4 Bit 3 0 0 0 1 0 1 2 1 0 3 1 1

Tabela 2.3 – Páginas de memória de programa

A figura 2.6 apresenta o mapemamento de memória de programa.

Page 28: Apostila PIC 16f877a

Exsto Tecnologia

28 Microcontroladores PIC16F877A

0000h Vetor de reset

0001h 0002h Uso geral 0003h

0004h Vetor de interrupção

0005h Página 0 . . Uso geral . 07FFh

0800h . . Uso geral Página 1 . 0FFFh

1000h . . Uso geral Página 2 . 17FFh

1800h . . Uso geral Página 3 . 1FFFh

Figura 1.6 – Mapeamento de memória do PIC16F877A

Os demais microcontroladores da família PIC16F seguem esse mesmo mapeamento de memória,

contudo nem todos os modelos têm 8k-words, isto é, alguns não tem todas as páginas

implementadas. Por exemplo, o PIC16F874A tem as páginas 0 e 1 mas não as 2 e 3, portanto tem 4k-

words; já o 16F628A tem 2k-words, ou seja, somente a página 0.

2.5.2 Memória de dados O core (núcleo ou processador do microcontrolador) da família PIC16 existem 9 vias de

endereçamento o que permite um acesso a 512 endereços diferentes (29 = 512). Contudo, nem

sempre temos memória RAM implementada para todos os endereços. A quantidade e a disposição

da RAM de dados varia de microcontrolador para microcontrolador.

No PIC16F877A existem 368 bytes de memória RAM de dados. Ela é composta por registros de

funções especiais (SFR – Special Function Registers) e a RAM de uso geral (GPR – General Purpose

RAM). Os SFR são responsáveis pelo controle da CPU e dos periféricos, além de conterem os registros

dos portais. Na RAM de uso geral é onde o programa armazenará suas variáveis.

A memória RAM pode ser acessada de duas formas: por acesso direto e por acesso indireto. Acesso

direto ocorre quando o endereço acessado faz parte da própria instrução (é um dos operandos). Já o

acesso indireto é feito através de duas variáveis, uma contendo o endereço a ser acessado e a outra

Page 29: Apostila PIC 16f877a

Exsto Tecnologia

29 Microcontroladores PIC16F877A

se comportando como o byte acessado. Este último modo de endereçamento pode ser muito útil em

algumas situações e será estudado mais adiante.

Para acesso direto, a RAM é dividida em 4 bancos. Isso ocorre porque a capacidade de máxima de

acesso de memória dos microcontroladores PIC é de 512 bytes. Portanto, são necessários 9 bits para

compor os endereços. Como cada instrução tem apenas 14 bits, e esses bits devem ser divididos

entre operadores e operandos, não há espaço para um endereço de 9 bits. Na verdade, as instruções

armazenam apenas 7 bits do endereço a ser acessado. Os dois bits restantes fazem parte do registro

de função especial STATUS e são chamados RP1 e RP0. Já que dois bits podem gerar 4 combinações,

existe essa divisão em 4 bancos. Para acessar um registro em um banco diferente do banco atual, é

necessário ajustar previamente RP1 e RP0. Na prática utilizamos o máximo possível endereços do

banco 0, e mudamos para os demais bancos quando necessário, retornando novamente ao banco 0.

A divisão de bancos é feita conforme a tabela 1.3.

Banco RP1 RP0 Endereços

0 0 0 00h ~ 7Fh 1 0 1 80h ~ FFh 2 1 0 100h ~ 17Fh 3 1 1 180h ~ 1FFh

Tabela 1.4 - Seleção de bancos de RAM

No caso do endereçamento indireto, o endereço é armazenado em um registro de função especial

chamado FSR. Como trata-se de um registro de 8 bits, falta 1 bit, que se chama IRP e faz parte do

STATUS. Quando IRP é ‘0’ são acessados os bancos 0 e 1, quando é ‘1’, são acessados os bancos 2 e 3.

Os registros de funções especiais têm seus nomes e os nomes de seus bits já definidos em um

arquivo. Existe um arquivo desses para cada PIC e a forma de incluí-lo no programa será mostrado

mais adiante. Podemos então tratar os SFR pelo seus nomes, não havendo a preocupação com o

endereço que eles ocupam. Também não é necessário saber qual bit de um registro tem

determinada função, apenas o nome do mesmo. Na apresentação desses registros será seguida a

convenção abaixo, que a mesma utilizada no manual dos componentes.

Os bits são numerados de 0 a 7, da direita para a esquerda. O nome do registro aparece em baixo.

Sobre cada bit temos algumas informações: se ele pode ser lido (R) escrito (W), se não é

implementado. Também contém sua situação após o reset, podendo ser ‘0’, ‘1’ ou desconhecida (x).

Por exemplo, sobre o bit RP0 está escrito R/W-0, que significa que pode ser lido ou escrito e seu valor

no reset é 0.

No anexo B encontra-se o mapa de memória do PIC16F628A. Pode-se observar os nomes dos SFR e

as regiões de uso geral. Note que apesar de ser possível acessar 512 bytes, foram implementados

apenas 224 bytes. As posições não implementadas estão em cinza na figura. Note ainda que os

últimos 16 endereços de todos os bancos acessam os mesmos bytes no banco 0.

R/W – 0 R/W – 0 R/W – 0 R – 1 R/W – x R– 1 R/W – x R/W – x

Bit 7 Bit 0

IRP RP1 RP0 NOT_TO NOT_PD Z DC C

STATUS

Page 30: Apostila PIC 16f877a

Exsto Tecnologia

30 Microcontroladores PIC16F877A

A figura 1.7 trás o mapeamento de memória RAM do PIC16F877A com os nomes dos registros de

função especial e as áreas de uso geral (GPR). As regiões em cinza correspondem a endereços para os

quais não há memória implementada. No manual do PIC16F877A existe um detalhamento maior dos

bits que compõe os SPR´s. A função de vários desses registros será explicada no decorrer do curso.

Tabela 1.7 - Mapeamento de memória RAM de dados

Page 31: Apostila PIC 16f877a

Exsto Tecnologia

31 Microcontroladores PIC16F877A

2.6 RESET O PIC possui várias fontes de reset (reinicialização), que são:

• Reset ao ligar (POR – Power-on Reset);

• Reset por MCLR durante operação normal;

• Reset por MCLR no modo SLEEP (que será tratado adiante);

• Reset por Watch-Dog durante operação normal;

• Reset por Watch-Dog no modo SLEEP;

• Reset por queda de alimentação (BOR – Brown-Out Reset).

O reset por MCLR é acionado quando ao terminal MCLR (pino 4) é aplicado nível lógico baixo. MCLR é

o terminal de Reset do componente, sendo um terminal baixo ativo, isto é, o reset ocorre em ‘0’.

Além disso, o terminal de MCLR possui internamente um filtro para evitar que ruídos possam causar

reset acidental.

O modo como os registros se comportam em cada reset é variado. Para saber quais são os “valores

iniciais” de cada registro, deve ser consultada a tabela de situações iniciais dos registros, presente no

manual de cada PIC.

A seguir são detalhadas algumas fontes e funcionalidades associadas ao reset.

2.6.1 POR – Power-On Reset Essa funcionalidade detecta quando o circuito é ligado, percebendo a subida da tensão de

alimentação, e realiza o reset do microcontrolador. Dessa forma podemos dispensar o resistor e

capacitor tradicionalmente ligados ao terminal de reset para gerar um nível lógico baixo quando o

sistema é ligado, garantido assim o reset inicial. O terminal MCLR pode ser ligado diretamente ao

nível lógico alto sendo recomendado utilizar um resistor de 10 kΩ ligando-o à VDD.

2.6.2 PWRT – Power-up Timer Trata-se de um timer de aproximadamente 72ms que mantém o microcontrolador em condição de

reset durante esse tempo. É útil, pois permite ao sistema ter tempo de se estabilizar (tensão, reset

dos demais componentes, etc.) antes do programa começar a ser executado.

2.6.3 OST – Oscillator Start-up Timer Este timer “conta” 1024 ciclos válidos de clock antes de sair da condição de reset, permitindo assim

que o oscilador se estabilize, conforme trato no tópico “Modos LP, XT e HS”. Essa funcionalidade é

habilitada somente nos modos LP, XT e HS.

2.6.4 BOR – Brown-out Reset Essa funcionalidade visa reiniciar o sistema se houver uma queda na tensão de alimentação.

O BOR ocorre quando a alimentação atinge aproximadamente 4V por mais de 100µs (quedas por

tempo intervalos menores que esse são ignorados pois podem se tratar de ruídos na alimentação),

em situações como as mostradas na figura2.8.

Page 32: Apostila PIC 16f877a

Exsto Tecnologia

32 Microcontroladores PIC16F877A

Figura 2.7 – Situações de Brown-out

2.6.5 Seqüência de inicialização 1. O circuito é ligado: a tensão de alimentação começa a subir; 2. É detectada a subida da tensão: ocorre POR; 3. O sistema aguarda o tempo de PWRT (aprox. 72 ms); 4. O oscilador começa a funcionar: 1024 ciclos são contados (OST); 5. O programa começa a ser efetivamente executado.

2.6.6 Identificação de Reset pelo Software Apesar de existirem várias fontes de Reset, é possível determinar qual reset ocorreu. Para isso

existem 4 bits: NOT_TD e NOT_PD do registro STATUS e NOT_BOR e NOT_POR do registro PCON

(Banco 1). As condições desses bits para cada reset podem ser vistas na tabela 2.4.

Condição NOT_POR NOT_BOR NOT_TO NOT_PD

Reset por Power-on 0 X 1 1 Impossível 0 X 0 X Impossível 0 X x 0 Reset por Brown-out 1 0 1 1 Reset pelo Watchdog 1 1 0 1 Dispertar pelo Watchdog 1 1 0 0 Reset pelo MCLR em operação normal 1 1 U U Reset pelo MCLR no modo SLEEP 1 1 1 0

Tabela 2.4 – Bits de status e seus significados

Essa informação pode ser útil, permitindo que providências sejam tomadas em situações específicas

de problema.

O esquema da figura 1.8 mostra como é a lógica de reset.

Page 33: Apostila PIC 16f877a

Exsto Tecnologia

33 Microcontroladores PIC16F877A

Figura 2.8 – Lógica de reset

2.7 Watch-Dog Timer Esse timer de 8 bits, que é baseado em um oscilador RC interno próprio, independente de qualquer

outra coisa, gera um reset quando “estoura”. Ele é importante em situações em que, por qualquer

motivo, o microcontrolador “trava”. Quando habilitado ele deve ser zerado a intervalos regulares

menores que seu tempo máximo pela instrução CLRWDT. Se o programa “para” e o Watch-Dog não é

zerado, tendo sido habilitada essa função na gravação, ocorre o reset. Ao timer de 8 bits pode ser

atribuído um pré-escala, como será visto mais adiante.

Essa funcionalidade é muito útil, pois, na grande maioria das situações práticas, é melhor que o

sistema reinicie do que fique inoperante. Desenvolvendo o código adequadamente é possível fazer

com que o reset sequer tenha efeitos perceptíveis para o sistema.

O período do watchdog é de 18 ms (típico). Com pré-escala máxima pode chegar a 2,3s.

2.8 Modo de baixo consumo – Modo SLEEP O modo de baixo consumo (Power-dowm Mode), também chamado de modo SLEEP (sono, em

inglês), é a situação de menor consumo do microcontrolador. Ele é ativado pela execução da

instrução SLEEP. Nesse modo o oscilador é desligado, fazendo com que o microcontrolador pare

completamente a execução do programa. Dessa forma conseguimos reduzir drasticamente o

consumo do sistema, o que é importante sobretudo em sistemas alimentados por bateria.

O microcontrolador pode ser “acordado” por qualquer um dos eventos abaixo:

• Qualquer reset;

• Estouro do Watch-Dog (se este estiver habilitado);

• Qualquer periférico que estiver com sua respectiva interrupção habilitada (incluso INT e interrupção por mudança no Portal B).

Page 34: Apostila PIC 16f877a

Exsto Tecnologia

34 Microcontroladores PIC16F877A

Quando da ocorrência de algum reset, o programa recomeça sua execução no vetor de reset

(0000h). Se, porém, ocorrer um estouro do Watch-Dog ou a chamada de alguma interrupção o

programa continua sua execução a partir do endereço imediatamente posterior a instrução SLEEP

que ativou o modo de baixo consumo. E ainda, se o controle geral de interrupções estiver habilitado,

o programa recomeça pelo vetor de interrupções (0004h) se desperto por interrupção. Assim, se

desejamos que uma interrupção simplesmente “acorde” o microcontrolador, devemos desabilitar

globalmente as interrupções.

Deve-se ter atenção ao fato de que no modo SLEEP o oscilador está desligado. Dessa forma não

podem ser utilizadas interrupções dos timer’s para a saída do modo, se estes timer’s utilizarem como

fonte de clock o oscilador interno, nem demais periféricos cujo funcionamento se baseie no oscilador

principal do sistema.

2.9 Características especiais

2.9.1 Proteção de Código (Code Protect) O programa gravado em um PIC pode ser protegido, isto é, pode ser impedida a sua leitura. Essa

funcionalidade é muito importante, sobretudo quando se trata de produção industrial, visto que

assim se podem preservar os direitos autorais do autor do firmware e dificultar a cópia de produtos.

2.9.2 Locais de Identificação (ID Locations) Existem 4 endereços não acessáveis pelo microcontrolador que podem ser utilizados para

identificação do componente (por exemplo, o número de série do produto ou a versão do firmware).

2.9.3 Pinagem e Hardware Básico Como já foi comentado anteriormente, o PIC16F877A é um componente de 40 pinos, em seu

encapsulamento PDIP (Plastic Dual In-line Package – Encapsulamento plástico em linha dupla). Esses

pinos podem ser divididos em terminais de alimentação, de reset, de conexão com o oscilador e os

terminais de portais e periféricos. Como se trata de um componente com diversas características e

um pequeno número de terminais, muitos terminais possuem mais de uma função. Dessa forma,

temos terminais de entrada e saída dos portais multiplexados com terminais dos periféricos, com

terminais do oscilador e terminais de reset. De uma forma geral, quando usamos um determinado

periférico, o terminal é associado a ele serve ao periférico e sua função de entrada e saída fica

desativada. Quando o periférico não é utilizado, o terminal trabalha como I/O.

A figura abaixo apresenta a pinagem do PIC 16F877A. Para facilitar a escrita, toda documentação da

Microchip quando se refere a um terminal não utiliza a notação bit N do portal X, e sim RX N. Por

exemplo, o bit 2 do portal A é representado por RA2, o bit 7 do portal C por RC7, e assim por diante.

Page 35: Apostila PIC 16f877a

Exsto Tecnologia

35 Microcontroladores PIC16F877A

Figura 2.1 – Pinagem do PIC 16F877A

As principais características do PIC são apresentadas na tabela abaixo.

Característica Valor Unidade

Frequência de Operação 0 ~ 20 MHz MHz Resets POR, BOR - Memória de Programa (FLASH) 8k palavras de 14 bits Memória de Dados (RAM) 368 bytes Memória de Dados Não Volátil (EEPROM) 256 bytes Interrupções 15 Timers 3 Módulo CCP 2 Módulo SSP (SPI e I2C) 1 Comparador analógico 2 Comunicação Paralela PSP Módulo ADC de 10-bits 8 canais Set de Instruções 35 instruções

A tabela seguinte contém as características elétricas do PIC 16F877A.

Característica Min Max Unidade

Temperatura de Trabalho -55 125 ºC Vdd ( em relação à Vss) 4 5,5 V Máxima Corrente de saída em Vss - 300 mA Máxima Corrente de entrada em Vdd - 250 mA Máxima Corrente drenada por I/O - 25 mA Máxima Corrente de saída po I/O - 25 mA Máxima Corrente drenada por PORTA + PORTB + PORTE - 200 mA Máxima Corrente fornecida por PORTA + PORTB + PORTE - 200 mA Máxima Corrente drenada por PORTC + PORTD - 200 mA Máxima Corrente fornecida por PORTC + PORTD - 200 mA

Page 36: Apostila PIC 16f877a

Exsto Tecnologia

36 Microcontroladores PIC16F877A

Os níveis de tensão de entrada e saída para o PIC são apresentados na tabela abaixo. Os valores são

considerndo que a alimentação é de 5,0 V. O buffer de entrada de cada pino pode ser do tipo TTL

simples ou Schmitt Trigger. Para saber qual o tipo de buffer deve-se consultar a parte do manual de

cada componente relativo aos portais de I/O.

Parâmetro Tipo de buffer Min Max Unid

VIH TTL Vss 0,8 V

Schmitt Trigger Vss 1,0 V

VIH TTL 2,0 VDD V

Schmitt Trigger 4,0 VDD V

VOL - 0,6 V

VOH 4,3 - V

Como já foi discutido, um microcontrolador possui todos os componentes básicos de um sistema

computacional em um único chip. Assim o circuito básico necessário para um PIC funcionar é

bastante reduzido. É necessário somente :

• A alimentação de +5V, bem regulada;

• Como em todo circuito digital, um capacitor de desacoplamento de 100nF bem próximo aos terminais de Vdd e Vss;

• O terminal /MCLR é o terminal de reset do PIC e é baixo ativo. Por isso ele deve ser mantido em

nível lógico alto. Recomenda-se a liga-lo a Vdd por um resistor (10kΩ). Não é necessário o circuito RC de reset.

• Definir-se um esquema de clock conforme já tratado.

Um cuidado que deve ser tomado, independente do tipo de oscilador escolhido, é fazer com que os

componentes externos do circuito oscilador fiquem bem próximo uns dos outros e todos bem

próximos ao microcontrolador. Além disso, quando for confeccionada uma placa de circuito impresso

deve-se minimizar as indutâncias e capacitâncias parasitas. Isso é feito aumentando a espessura das

trilhas, diminuindo seu comprimento e posicionando trilhas excessivamente próximas umas das

outras. Esses cuidados são fundamentais quando se trabalha com freqüências altas.

2.10 Gravação A gravação do microcontrolador PIC pode ser realizada sem que o componente seja retirado da placa

(gravação in-circuit). Essa gravação é feita de forma serial utilizando somente dois pinos: PB7/PGD

para envio de dados e RB6/PGC para clock.

Além dos pinos RB7 e RB6 é necessário que o pino MCLR/VPP receba uma tensão de 13VDC +/- 0,5V

durante o processo de gravação. Também é necessário que o microcontrolador esteja devidamente

alimentado, portanto VDD e VSS devem estar devidamente conectados.

Page 37: Apostila PIC 16f877a

Exsto Tecnologia

37 Microcontroladores PIC16F877A

2.11 O conjunto de instruções do PIC16F877A O set de instruções de um microcontrolador é o conjunto de todas as instruções que o processador

pode interpretar e executar. Voltando a analogia com um instrumento musical, são como as notas

musicais que o compositor usa para escrever uma partitura. Cada processador (ou core) possui seu

próprio conjunto de instruções (ou set de instruções). Isso significa que todos os microcontroladores

da linha PIC16 são capazes de executar o mesmo código, ou seja, falam a mesma língua. Significa

também que microcontroladores de outras famílias ou fabricantes não são compatíveis com o código

gerado para PIC16 ou para outro conjunto de instruções (não falam a mesma lingua).

Cada instrução na verdade é um código numérico (chamado Opcode) que o decodificador de

instruções é capaz de interpretar e disparar uma seqüência de ações pré-definida. Por exemplo, uma

instrução de soma inicia um processo interno do microcontrolador que realiza movimento de bytes,

ajusta e realiza operações na unidade lógico-aritmética, carrega resultados em endereços de

memória. Fazendo uma analogia com um livro de culinária, o opcode indica a página onde estão os

passos para a realização de uma receita.

Como criar uma lógica complexa de programação usando apenas códigos numéricos seria um

trabalho muito desgastante e o resultado muito confuso foi criada uma linguagem simbólica

que associa nomes, denominados mnemônicos, aos opcodes; por conveniência esses nomes

fazem referência a ação realiza, como poderá ser observado brevemente.

Para assembler é o programa responsável por “traduzir” o código mnemônico (entendido pelo ser

humano) para um código numérico composto de opcodes (entendido pelo core do

microcontrolador).

Antes de estudar as instruções deve-se definir alguns termos que serão utilizados na descrição das

instruções e na apresentação de sua sintaxe:

f Registro da RAM (0x00~0x7F)

W Acumulador (Working register)

b Bit em um byte

k Constante de 8 bits

x Irrelevante

d destino: 0 => Acumulador (W)

1=> registro

PC Program Counter

NOT_TO Bit de time-out

NOT_PD Bit de Power Down

TOS Topo da pilha (Top Of Stack)

O acumulador, chamado no PIC de Working Register ou simplesmente W, é um registro interno do

microcontrolador, não mapeado em RAM, que está envolvido na maioria das instruções. Como será

visto, ele participa das instruções de movimentação e é um dos operandos ou o destino do resultado

nas operações lógico e matemáticas.

Para maior compreensão do funcionamento das instruções se faz necessário comentar o

funcionamento do registro de STATUS. Os bits desse registro nos apresentam a situação do

Page 38: Apostila PIC 16f877a

Exsto Tecnologia

38 Microcontroladores PIC16F877A

microcontrolador a cada instrução. Esses bits são tipicamente chamados de flags (Bandeiras).

Através deles podemos saber de resultados de operações da ALU (se uma subtração resultou em

zero, se uma soma causou “overflow”, etc), a situação do RESET, além do controle bancos de

memória.

• IRP :bit de seleção de banco, usado para endereçamento indireto.

o 1 = Bancos 2 e 3 (100h - 1FFh) o 0 = Bancos 0 e 1 (00h - FFh)

• RP1~RP0 : bit de seleção de banco, usado para endereçamento direto. o 11 = Banco 3 (180h - 1FFh ) o 10 = Banco 2 (100h - 17Fh ) o 01 = Banco 1 (80h - FFh ) o 00 = Banco 0 (00h - 7Fh )

• NOT_TO: Bit indicador de Time-out o 1 = após todos os Resets, exceto time-out do WDT o 0 = ocorreu um time-out do WDT

• NOT_PD: Bit indicador de Power-down o 1 = quando é ligado ou após a instrução CLRWDT o 0 = pela execução de uma instrução SLEEP

• Z: Bit indicador de zero o 1 = se o resultado de uma operação da ALU é zero o 0 = se o resultado de uma operação da ALU é diferente de zero

• DC: Carry/Borrow de dígito. Para borrow o sinal é inverso o 1 = houve transporte do 4o. para o 5o. bit o 0 = não houve transporte do 4o. para o 5o. bit

• C: Carry/Borrow . Para borrow o sinal é inverso o 1 = houve transporte do 8o. bit o 0 = não houve transporte do 8o. bit

O conjunto de instruções do core PIC16 é composto de 35 instruções, apresentadas a seguir. O

campo “Sintaxe” mostra a forma de se escrever a instrução. O campo “Operadores” indica quais os

operadores envolvidos e quais seus domínios. “Operação” apresenta a operação realizada pela

instrução. O campo “Flags Afetados” mostra quais flags de STATUS são afetados pela execução da

operação; essas alterações são comentadas abaixo dos quadros. No campo “Ciclos” está o número

de ciclos de máquina gastos para a execução da instrução. Finalmente, o campo “Exemplo”

apresenta um exemplo simples de utilização da instrução.

As instruções são divididas, conforme sua função, nos seguintes tipos:

• Manipulação de byte

• Manipulação e bit

• Matemáticas

• Lógicas

R/W – 0 R/W – 0 R/W – 0 R – 1 R/W – x R/– 1 R/W – x R/W – x

Bit 7 Bit 0

IRP RP1 RP0 NOT_TO NOT_PD Z DC C

STATUS

Page 39: Apostila PIC 16f877a

Exsto Tecnologia

39 Microcontroladores PIC16F877A

• Testes e desvios condicionais

• Chamadas e desvio (controle de fluxo)

• Controle (da CPU)

No anexo A existe uma tabela resumo de todas as instruções. Recomenda-se tirar uma cópia desta

pagina e tela sempre à mão para consulta rápida.

2.11.1 Manipulação de Byte As instruções de manipulação de byte permitem atribuir valores a endereços da RAM e ao registro

W. É importante ressaltar que apesar de normalmente o mnemônico dessas instruções trazer a

palavra move (mover) o valor do registro é na verdade copiado, isto é, o registro de destino recebe o

valor do registro de origem, mas o valor da origem não é alterado.

CLRW

"Zera" o registro W. O bit Z do registro STATUS é setado.

Sintaxe CLRW

Operadores Nenhum Operação (W) 00h Flags Afetados Z Ciclos 1 Exemplo CLRW

Alterações nas Flags: Como a instrução resultou em um registro se tornar 0, o bit Z é setado

indicando esse evento.

CLRF

"Zera" o registro indicado por f. O bit Z do registro STATUS é setado.

Sintaxe CLRF f

Operadores 0 ≤ f ≤ 127 Operação (f) 00h Flags Afetados Z Ciclos 1 Exemplo CLRF TEST

Alterações nas Flags: Como a instrução resultou em um registro se tornar 0, o bit Z é setado

indicando esse evento.

MOVLW

Move a constante k para W.

Sintaxe MOVLW k

Operadores 0 ≤ k ≤ 255 Operação (W) k Flags Afetados Nenhum Ciclos 1 Exemplo MOVLW 35h

Page 40: Apostila PIC 16f877a

Exsto Tecnologia

40 Microcontroladores PIC16F877A

MOVF

Move o valor do registro (f) para o destino. Se d é 0 destino é W; se d é 1 o destino é o próprio

registro (f). Mover o valor do registro para ele mesmo é útil para testarmos se o valor é 0, uma vez

que essa instrução afeta o bit Z do registro STATUS.

Sintaxe MOVF f, d

Operadores 0 ≤ f ≤ 127 d = 0 : W d = 1 : registro f

Operação (d) (f) Flags Afetados Z Ciclos 1 Exemplo MOVF TEST,0

Alterações nas Flags:

Z = 0: o valor movido, é diferente de zero.

Z = 1: o valor movido, é 0.

MOVWF

Move o conteúdo de W para o registro f.

Sintaxe MOVWF f

Operadores 0 ≤ f ≤ 127 Operação (f) W Flags Afetados Nenhum Ciclos 1 Exemplo MOVWF TEST

2.11.2 Manipulação de bit As operações de manipulação de bit são uma particularidade dos microcontroladores e dificilmente

são encontradas em outros sistema computacionais. Sua função é permitir alterar o valor de um

único bit de um determinado registro, sem qualquer influência nos demais bits.

BCF

"Zera" o bit b do registro f.

Sintaxe BCF f, b

Operadores 0 ≤ f ≤ 127

0 ≤ b ≤ 7 Operação f[b] 0 Flags Afetados Nenhum Ciclos 1 Exemplo BCF CONTROLE,5

Page 41: Apostila PIC 16f877a

Exsto Tecnologia

41 Microcontroladores PIC16F877A

BSF

"Seta" o bit b do registro f.

Sintaxe BSF f, b

Operadores 0 ≤ f ≤ 127

0 ≤ b ≤ 7 Operação f[b] 1 Flags Afetados Nenhum Ciclos 1 Exemplo BSF CONTROLE,7

2.11.3 Matemáticas As instruções matemáticas são capazes de realizar operações matemáticas básicas através da

operação da ALU do microcontrolador. Como trata-se de um microcontrolador de 8 bits essas

operações tem operadores e resultados de 8 bits. Para cálculos com valores maiores de 8 bits deve-

se desenvolver rotinas fazendo uso das instruções básicas. Da mesma forma, operações mais

complexas podem ser construídas a partir das rotinas básicas. Essa raciocínio se aplica para

operações de multiplicação e divisão, que não suportadas pela ALU do PIC16.

ADDLW

Realiza a adição do valor contido em W com a constante k. O resultado é armazenado em W.

Sintaxe ADDLW k

Operadores 0 ≤ k ≤ 255 Operação (W) (W) + k Flags Afetados C, DC, Z Ciclos 1 Exemplo ADDLW 35h

Alterações nas Flags:

C = 1: o resultado da adição é maior que 255.

C = 0: o resultado da adição é menor ou igual a que 255.

DC = 1: o resultado da adição causou o transporte de 4o para o 5o bit

DC = 0: o resultado da adição não causou o transporte de 4o para o 5o bit

Z = 0: o resultado da adição é diferente de zero.

Z = 1: o resultado da adição é 0. Pode ocorrer com 128 + 128 = 256: C=1 e o resultado da adição é

igual a 0.

ADDWF

Realiza a adição do valor contido em W com o valor do registro f. O resultado é armazenado no

destino: d=0 para W ou d=1 para o registro f.

Page 42: Apostila PIC 16f877a

Exsto Tecnologia

42 Microcontroladores PIC16F877A

Sintaxe ADDWF f, d

Operadores 0 ≤ f ≤ 127 d = 0 : W d = 1 : registro f

Operação (d) (W) + (f) Flags Afetados C, DC,Z Ciclos 1 Exemplo ADDWF TEST,0

Alterações nas Flags:

C = 1: o resultado da adição é maior que 255.

C = 0: o resultado da adição é menor ou igual a que 255.

DC = 1: o resultado da adição causou o transporte de 4o para o 5o bit

DC = 0: o resultado da adição não causou o transporte de 4o para o 5o bit

Z = 0: o resultado da adição é diferente de 0.

Z = 1: o resultado da adição é 0. Pode ocorre com 128 + 128 = 256: C=1 e o resultado da adição é

igual a 0.

DECF

Decrementa o valor contido no registro f. O resultado é armazenado no destino: d=0 para W ou d=1

para o registro designado por f.

Sintaxe DECF f,d

Operadores 0 ≤ f ≤ 127 d = 0 : W d = 1 : registro f

Operação (d) (f) – 1 Flags Afetados Z Ciclos 1 Exemplo DECF COUNT,0

Alterações nas Flags:

Z = 0: o resultado do decremento é diferente de zero.

Z = 1: o resultado do decremento é 0 (quando o valor original for igual a 1).

INCF

Incrementa o valor contido no registro f. O resultado é armazenado no destino: d=0 para W ou d=1

para o registro designado por f.

Sintaxe INCF f,d

Operadores 0 ≤ f ≤ 127 d = 0 : W d = 1 : registro f

Operação (d) (f) + 1 Flags Afetados Z Ciclos 1 Exemplo INCF COUNT,0

Page 43: Apostila PIC 16f877a

Exsto Tecnologia

43 Microcontroladores PIC16F877A

Alterações nos Flags:

Z = 0: o resultado do incremento é diferente de zero.

Z = 1: o resultado do incremento é igual a 0 (quando o valor original for igual a 255).

SUBLW

O valor contido em W é subtraído, pelo método do complemento 2, da constante de oito bits k. O

Resultado é armazenado em W.

Sintaxe SUBLW k

Operadores 0 ≤ k ≤ 255 Operação (W) k - (W) Flags Afetados C, DC, Z Ciclos 1 Exemplo SUBLW 23h

Alterações nas Flags:

ATENÇÃO: nessa operação os bits C e DC tem significado inverso ao que seria esperado, isto é,

quando ocorre um borrow ("estouro para menos"), os bits C e DC ficam em zero, ao contrário que

quando ocorre um Carry ("estouro para mais"), quando C e DC ficam em 1.

C = 1: o resultado da subtração é maior ou igual a 0.

C = 0: o resultado da subtração é menor a 0.

DC = 1: o resultado da subtração não causou o transporte de 5o para o 4o bit

DC = 0: o resultado da subtração causou o transporte de 4o para o 5o bit

Z = 0: o resultado da subtração é diferente de zero.

Z = 1: o resultado da subtração é igual a 0.

SUBWF

O valor contido em W é subtraído, pelo método do complemento 2, do valor contido no registro f. O

resultado é armazenado no destino: d=0 para W ou d=1 para o registro designado por f.

Sintaxe SUBWF f,d

Operadores 0 ≤ f ≤ 127 d = 0 : W d = 1 : registro f

Operação (W) (f) - (W) Flags Afetados C, DC, Z Ciclos 1 Exemplo SUBWF TEST,0

Alterações nas Flags:

ATENÇÃO: nessa operação os bits C e DC têm significado inverso ao que seria esperado, isto é,

quando ocorre um borrow ("estouro para menos"), os bits C e DC ficam em zero, ao contrário que

quando ocorre um Carry ("estouro para mais"), quando C e DC ficam em 1.

Page 44: Apostila PIC 16f877a

Exsto Tecnologia

44 Microcontroladores PIC16F877A

C = 1: o resultado da subtração é maior ou igual a 0.

C = 0: o resultado da subtração é menor a 0.

DC = 1: o resultado da subtração não causou o transporte de 5o para o 4o bit.

DC = 0: o resultado da subtração causou o transporte de 4o para o 5o bit.

Z = 0: o resultado da subtração é diferente de zero.

Z = 1: o resultado da subtração é igual a 0.

2.11.4 Lógicas Assim como as instruções matemáticas, as instruções lógicas realizam operações lógicas básicas

fazendo uso da ALU.

ANDLW

Realiza uma operação lógica "E" entre o valor contido em W e a constante k. O resultado é

armazenado em W.

Sintaxe ANDLW k

Operadores 0 ≤ k ≤ 255 Operação (W) (W) E k Flags Afetados Z Ciclos 1 Exemplo ANDLW 0Fh

Alterações nas Flags:

Z = 0: o resultado da operação "E" é diferente de zero.

Z = 1: o resultado da operação "E" é igual a 0.

ANDWF

Realiza a operação "E" entre o valor contido em W o valor contido no registro f. O resultado é

armazenado no destino: 0 para W ou 1 para o registro designado por f.

Sintaxe ANDWF f, d

Operadores 0 ≤ f ≤ 127 d = 0 : W d = 1 : registro f

Operação (d) (W) E (f) Flags Afetados Z Ciclos 1 Exemplo ANDWF TEST,1

Alterações nas Flags:

Z = 0: o resultado da operação "E" é diferente de zero.

Z = 1: o resultado da operação "E" é igual a 0.

Page 45: Apostila PIC 16f877a

Exsto Tecnologia

45 Microcontroladores PIC16F877A

COMF

Complementa o valor contido no registro f. O resultado é armazenado no destino: d=0 para W ou

d=1 para o registro designado por f.

Sintaxe COMF f,d

Operadores 0 ≤ f ≤ 127 d = 0 : W d = 1 :registro f

Operação (d) complemento de (f) Flags Afetados Z Ciclos 1 Exemplo COMF TESTE,1

Alterações nas Flags:

Z = 0: o resultado do complemento é diferente de zero.

Z = 1: o resultado do complemento é 0. O complemento de 255 (11111111b) é 0 (00000000b).

IORLW

Realiza uma operação "OU" bit a bit entre o valor contido em W e a constante k. O resultado é

armazenado em W.

Sintaxe IORLW k

Operadores 0 ≤ k ≤ 255 Operação (W) (W) OU (f) Flags Afetados Z Ciclos 1 Exemplo IORLW TEST

Alterações nas Flags:

Z = 0 o resultado da operação "OU" é diferente de zero.

Z = 1 o resultado da operação "OU" é igual a 0 (0 OU 0 é igual a zero)

IORWF

Realiza a operação "OU" bit a bit entre o valor contido em W com o valor do registro indicado por f.

O resultado é armazenado no destino: d=0 para W ou d=1 para o registro designado por f.

Sintaxe [label] IORWF f, d

Operadores 0 ≤ f ≤ 127 d = 0 : W d = 1 : registro f

Operação (d) (W) OU (f) Flags Afetados Z Ciclos 1 Exemplo IORWF TEST,1

Alterações nas Flags:

Z = 0 o resultado da operação "OU" é diferente de zero.

Z = 1 o resultado da operação "OU" é igual a 0 (0 OU 0 é igual a zero).

Page 46: Apostila PIC 16f877a

Exsto Tecnologia

46 Microcontroladores PIC16F877A

RLF

O valor contido em f é rotacionado para a esquerda através do bit de Carry (bit C do registro

STATUS). O resultado é armazenado no destino: d=0 para W ou d=1 para o registro designado por f. A

operação de rotação a esquerda consiste no deslocamento sucessivo de bits de sua posição inicial

para a posição consecutiva de modo que o último bit do registro f vá para C e o bit que estava em C

vá para o primeiro bit do registro f.

Sintaxe RLF f,d

Operadores 0 ≤ f ≤ 127 d = 0 : W d = 1 : registro f

Operação veja a figura abaixo Flags Afetados C Ciclos 1 Exemplo RLF TEST,1

Alterações nas Flags:

C passa conter o valor (0 ou 1) do 8 bit do registro f.

RRF

O valor contido em f é rotacionado para a direita através do bit de Carry (bit C do registro STATUS). O

resultado é armazenado no destino: 0 para W ou 1 para o registro designado por f. A operação de

rotação a direita consiste no deslocamento sucessivo de bits de sua posição inicial para a posição

consecutiva de modo que o primeiro bit do registro f vá para C e o bit que estava em C vá para o

último bit do registro f.

Sintaxe RRF f,d

Operadores 0 ≤ f ≤ 127 d = 0 : W d = 1 : registro f

Operação veja a figura abaixo Flags Afetados C Ciclos 1 Exemplo RRF TEST,1

Alterações nas Flags:

C passa a conter o valor (0 ou 1) do registro f.

C Registro f

C Registro f

Page 47: Apostila PIC 16f877a

Exsto Tecnologia

47 Microcontroladores PIC16F877A

SWAPF

O nibble (conjuntos de 4 bits) mais significativo e o menos significativo do registro f são trocados. Ou

seja, os bits de 7 a 4 vão para as posições de 3 a 0 e os bits de 3 a 0 vão para as posições de 7 a 4. A

figura abaixo ilustra esse processo. O resultado é armazenado no destino: d=0 para W ou d=1 para o

registro designado por f.

Sintaxe SWAPF f,d

Operadores 0 ≤ f ≤ 127 d = 0 : W d = 1 : registro f

Operação Destino [7:4] f [3:0] Destino [3:0] f [7:4]

Flags Afetados Nenhum Ciclos 1 Exemplo SWAPF TEST,1

XORLW

Realiza uma operação "OU exclusivo" entre o valor contido em W e a constante de oito bits k. O

resultado é armazenado em W.

Sintaxe XORLW k

Operadores 0 ≤ k ≤ 255 Operação (W) (W) XOU (f) Flags Afetados Z Ciclos 1 Exemplo XORLW OFh

Alterações nas Flags:

Z = 0: o resultado da operação "OU exclusivo" é diferente de zero.

Z = 1: o resultado da operação "OU exclusivo" é 0 (um valor "OU-exclusivo" consigo mesmo é igual a

zero).

XORWF

Realiza a operação "OU exclusivo" entre o valor contido em W com o valor do registro indicado por f.

O resultado é armazenado no destino: d=0 para W ou d=1 para o registro designado por f.

Sintaxe XORWF f, d

Operadores 0 ≤ f ≤ 127

d= 0 → W

Page 48: Apostila PIC 16f877a

Exsto Tecnologia

48 Microcontroladores PIC16F877A

d=1 → registro f

Operação (d) ← (W) XOU (f) Flags Afetados Z Ciclos 1 Exemplo XORWF TEST,0

Alterações nas Flags:

Z = 0: o resultado da operação "OU exclusivo" é diferente de zero.

Z = 1: o resultado da operação "OU exclusivo" é 0 (um valor "OU-exclusivo" consigo mesmo é igual a

zero).

2.11.5 Testes BTFSC

Testa o bit b do registro f : se o bit for '1' a próxima instrução é executada; se o bit for '0' a próxima

instrução não é executada, em seu lugar é executada uma instrução NOP, seguindo o programa na

segunda instrução após a BTFSC.

Sintaxe BTFSC f, b

Operadores 0 ≤ f ≤ 127 0 ≤ b ≤ 7

Operação se f[b]=0 salta a próxima instrução Flags Afetados nenhum

Ciclos se o bit não estiver em 1; se o bit estiver em 1.

Exemplo BTFSC STATUS,Z GOTO ZERO

BTFSS

Testa o bit b do registro f : se o bit for '0' a próxima instrução é executada; se o bit for '1' a próxima

instrução não é executada, em seu lugar é executada uma instrução NOP, seguindo o programa na

segunda instrução após a BTFSS.

Sintaxe BTFSS f, b

Operadores 0 ≤ f ≤ 127 0 ≤ b ≤ 7

Operação se f[b]=1 salta a próxima instrução Flags Afetados Nenhum

Ciclos se o bit não estiver em 1; se o bit estiver em 1.

Exemplo BTFSS STATUS,Z GOTO NO_ZERO

DECFSZ

Decrementa o valor contido no registro f. O resultado é armazenado no destino: d=0 para W ou d=1

para o registro designado por f. Se o resultado for diferente de 0 a próxima instrução é executada; se

o resultado for 0 a próxima instrução não é executada, em seu lugar é executada uma instrução NOP,

seguindo o programa na segunda instrução após a DECFSZ.

Page 49: Apostila PIC 16f877a

Exsto Tecnologia

49 Microcontroladores PIC16F877A

Sintaxe DECFSZ f,d

Operadores 0 ≤ f ≤ 127

d = 0 → W

d = 1 → registro f

Operação (d) (f) - 1 se f[b] = 1 salta a próxima instrução

Flags Afetados Nenhum Ciclos 1 Exemplo DECFSZ COUNT,1

INCFSZ

Incrementa o valor contido no registro f. O resultado é armazenado no destino: d=0 para W ou d=1

para o registro designado por f. Se o resultado for diferente de 0 a próxima instrução é executada; se

o resultado for 0 a próxima não é executada, em seu lugar é executada uma instrução NOP e o

seguindo o programa na segunda instrução após a INCFSZ.

Sintaxe INCFSZ f,d

Operadores

0 ≤ f ≤ 127

d= 0 → W

d=1 → registro f

Operação (d) ← (f)+1 se f[b]=1 salta a próxima instrução

Flags Afetados Nenhum Ciclos 1 Exemplo INCFSZ COUNT,1

2.11.6 Chamadas e desvio CALL

Chamada de sub-rotina. O endereço de retorno (próxima instrução) é guardado no topo da pilha

(TOS) e um valor de 11 bits é carregado nos bits menos significativos do PC (PC[10:0]), fazendo a

seqüência do programa ser transferida para o endereço indicado por k. Os bits superiores do PC

(PC[12:11]) são carregados a partir de PCLATH. Ver tópico "Desvio X Chamada" para maiores

informações.

Sintaxe CALL k

Operadores 0 ≤ k ≤ 2047

Operação TOS PC+1 PC[10:0] k PC[12:11] (PCLATCH[4:3])

Flags Afetados Nenhum Ciclos 2 Exemplo CALL TX_SERIAL

Page 50: Apostila PIC 16f877a

Exsto Tecnologia

50 Microcontroladores PIC16F877A

GOTO

Realiza um desvio incondicional para endereço k. O endereço de 11 bits é carregado no PC, fazendo a

seqüência do programa ser transferida para o endereço indicado por k. Os bits superiores do PC são

carregados de PCLATH. Ver tópico "Desvio X Chamada" para mais informações.

Sintaxe GOTO k

Operadores 0 ≤ k ≤ 2047

Operação PC[10:0] k PC[12:11] (PCLATCH[4:3])

Flags Afetados Nenhum Ciclos 2 Exemplo GOTO INICIO

RETURN

Retorno de sub-rotina. O endereço de retorno salvo na pilha quando da ocorrência da interrupção é

carregado no PC. Ver tópico "Desvio X Chamada" para mais informações.

Sintaxe RETURN

Operadores Nenhum Operação PC TOS Flags Afetados Nenhum Ciclos 2 Exemplo RETURN

RETLW

Realiza o retorno de uma sub-rotina com o W contendo a constante de oito bits k . W passa a conter

k e o endereço de retorno salvo na pilha quando da ocorrência da interrupção é carregado no PC.

Sintaxe RETLW k

Operadores 0 ≤k ≤ 255

Operação PC TOS (W) k

Flags Afetados nenhum Ciclos 2 Exemplo RETLW 69h

Page 51: Apostila PIC 16f877a

Exsto Tecnologia

51 Microcontroladores PIC16F877A

RETFIE

Retorno de interrupção. O endereço de retorno salvo na pilha quando da ocorrência da interrupção é

carregado no PC. O bit GIE do registro INTCON é setado (as interrupções são reativadas).\

Sintaxe RETFIE

Operadores nenhum

Operação PC TOS GIE 1

Flags Afetados nenhum Ciclos 2 Exemplo RETFIE

2.11.7 Controle NOP

Um ciclo de instrução ocorre sem que nenhuma ação seja realizada.

Sintaxe NOP

Operadores Nenhum Operação Nenhuma Flags Afetados Nenhum Ciclos 1 Exemplo NOP

CLRWDT

Reseta o timer do Watchdog. O prescaler do Watchdog também é resetado. O bits NOT_TO e

NOT_PD são setados.

Sintaxe CLRWDT

Operadores nenhum

Operação

WDT 00h WDT prescaler 0 NOT_TO 1 NOT_PD 1

Flags Afetados NOT_TO, NOT_PD Ciclos 1 Exemplo CLRWDT

Alterações nos Flags:

NOT_PD = 1: indica que não houve queda de energia.

NOT_TO = 1: indica que não houve time-out.

Page 52: Apostila PIC 16f877a

Exsto Tecnologia

52 Microcontroladores PIC16F877A

SLEEP

O Processador entra no modo SLEEP, desativando oscilador. O bit NOT_PD é zerado; O bit NOT_TO é

setado. O timer do Watchdog e seu prescaler são zerados.

Sintaxe SLEEP

Operadores nenhum

Operação

WDT 00h WDT prescaler 0 NOT_TO 1 NOT_PD 0

Flags Afetados NOT_TO, NOT_PD Ciclos 1 Exemplo SLEEP

Alterações nos Flags:

NOT_PD=0 e NOT_TO=1 indicam que o microcontrolador está em modo SLEEP.

2.12 Programando em assembly

Como já foi visto, a principal característica de um sistema computacional é permitir que um mesmo

hardware execute diferentes funções pela mudança de seu software.

Então, para programar um sistema computacional deve-se criar uma seqüência lógica de comandos

que possam ser traduzidos em uma determinada linguagem de programação, para que o sistema

possa entender o que deve ser feito. Linguagem de programação é uma forma de escrever um

programa. Cada linguagem possui sua sintaxe, suas regras de escritas, suas instruções. Exemplos de

linguagem de programação são Assembly, C/C++, Pascal, Basic, Cobol. A seqüência lógica de ações é

o que chamamos de algoritmo.

Dessa forma, é importante notar que o algoritmo é independente da linguagem de programação. Um

mesmo algoritmo pode ser implementado por qualquer linguagem de programação: o que muda é

como podemos escrever-lo numa linguagem. E ainda, um algoritmo não necessariamente precisa ser

implementado em um computador.

Na execução de um projeto, antes de se começar a programar é importante se ter bem claro os

objetivos a serem alcançados e o modo de alcançá-los, pois em fazer o algoritmo é que está a

verdadeira “arte” da programação, e não saber essa ou aquela linguagem. De fato, simplesmente

conhecer as instruções de uma linguagem está tão distante de se saber programar quanto saber

várias palavras está longe de se saber escrever.

A apresentação de um algoritmo pode ser feita de forma escrita, o que é chamado português

estruturado ou “portugol”, ou de forma gráfica, utilizando fluxogramas. O fluxograma, por se tratar

de uma ferramenta gráfica, deixa bem clara a seqüência de ações realizadas pelo programa. Contudo

não apresenta muitos detalhes de implementação.

O fluxograma consiste em um diagrama em blocos (cada tipo de bloco representa um tipo de

estrutura) ligados por setas que indicam qual o fluxo seguido pelo programa. Como não existe uma

Page 53: Apostila PIC 16f877a

Exsto Tecnologia

53 Microcontroladores PIC16F877A

interpretação universal de fluxograma, foi desenvolvido um conjunto específico para trabalho com

programação de microcontroladores para esse curso. Suas principais características são possuir

símbolos diferentes para entrada e saída de dados e possuir um símbolo de Atraso, devido à

importância desse conceito para sistemas microcontrolados.

Quanto às linguagens de programação, elas são classificadas em “níveis”, sendo as de nível mais alto

as próximas da linguagem humana e as de baixo nível as próximas à linguagem de máquina, que o

que o microcontrolador/processador efetivamente entende. O Assembly do PIC é uma linguagem de

baixo nível.

2.13 Estrutura do Programa Abaixo temos a estrutura básica de um programa em assembly. O símbolo ‘ ; ’ (ponto e vírgula) indica

comentário e os textos que vêm a direita eles são ignorados pelo montador.

Page 54: Apostila PIC 16f877a

Exsto Tecnologia

54 Microcontroladores PIC16F877A

;================================================== =========== ; <Nome da empresa> ; <Nome do projeto/programa> ;================================================== =========== ; Versão: ; <numero> <descrição da versão> ; <descrição da finalidade e operação do programa> ; Cristal <freqüência> - Ti = <tempo de instrução> ; ; <autor > ; <e-mail do autor> ;================================================== =========== #include<P16F877A.INC> ; microcontrolador a ser uti lizado __CONFIG <opções> ; configurações do programa ; *** Variáveis CBLOCK 20h <variáveis> ENDC ; *** Definições de Hardware ; *** Software org 0000H ; vetor de reset GOTO INICIO ; inicio do programa principal ; *** Tratamento de interrupção org 0004H ; vetor de interrupção ; <aqui deve estar o salvamento de contexto> ; <aqui devem ser inseridas as rotinas de tratament o ; de interrupções, quando houverem > ; <aqui deve estar o retorno de contexto> RETFIE ; *** Rotina principal INICIO: < aqui fica a inicialização> PRINCIPAL: ; < a rotina principal fica aqui > GOTO PRINCIPAL ; loop principal ; *** Sub-Rotinas ; < as sub-rotinas podem ser inseridas aqui > <nome da subrotina>: ; Descrição da função da sub-rotina (1) ; Entrada: < parâmetros de entrada> (2) ; Saída: < parâmetros de saída > (3) ; <aqui vem o código da sub-rotina> RETURN END ; FIM DO CÓDIGO

Ro

tin

a

Pri

nci

pa

l S

ub

-ro

tin

as

Ca

be

çalh

o

Co

nfi

gu

raçõ

eD

efi

niç

õe

s d

e

ha

rdw

are

e

So

ftw

are

Iníc

io d

o

Pro

gra

ma

T

rata

me

nto

de

Inte

rru

pçã

o

Page 55: Apostila PIC 16f877a

Exsto Tecnologia

55 Microcontroladores PIC16F877A

Como pude ser observado, várias partes da estrutura do programa não constituem código executável

propriamente dito, mas comentários e outras informações. Isso é feito visando documentar

adequadamente o projeto, permitindo realizar melhor o entendimento e a manutenção do software,

além de seu desenvolvimento.

Cabeçalho

O cabeçalho contém informações sobre o programa, como objetivo, autor, revisões e seus motivos,

dentre outras. Sua finalidade e documentar um resumo do programa, quem é o responsável pela sua

implementação e outras observações que permitam estabelecer a finalidade e o contexto para os

quais aquele código foi desenvolvido.

Assim como no cabeçalho, em muitas outras partes do texto são feitos comentário e explicações

sobre o que está sendo realizado. Esse procedimento é extremamente recomendado, pois, como

logo será percebido, o código em Assembly muitas vezes não deixa claro o que está sendo feito. É

comum que um programador, ao retomar um programa com o qual não trabalhou por algumas

semanas, não se lembre mais do motivo de ter feito certas partes do código. Quando é necessária

alguma manutenção em um programa, por pessoas que não o desenvolveram, e não há comentários,

o trabalho se torna virtualmente impossível.

Configurações

Nesse ponto do programa é incluído o arquivo de definições do microcontrolador a ser utilizado e

são realizadas as configurações dos bits de configuração.

Definições de Hardware e Software

Aqui são realizadas as declarações de variáveis, as definições de constantes e as definições de

hardware.

Podemos fazer definições de hardware utilizando a diretiva #DEFINE para tornar o programa mais

claro. A idéia é atribuir nomes aos pinos e/ou aos portais, segundo sua função. Dessa forma, na

escrita do programa, não é necessário lembrar qual função está associada a cada pino, apenas a

função. Por exemplo, suponhamos que existe um LED no pino RB2, isto é, no bit 2 do PORTB. É mais

cômodo nos referirmos a ele simplesmente por LED, não sendo preciso lembrar onde realmente está

o LED. Além disso, se por algum motivo for preciso mudar o LED para o pino RB6, basta alterar

somente a definição, e não todo local onde se faça referências ao LED.

O trecho de código abaixo exemplificar o que discutimos acima.

... CBLOCK 20h ENTRADA ; ARMAZENA OS VALORES DE ENTRADA CONT ; CONTADOR PARA TEMPORIZAÇÃO ... ENDC ...

#DEFINE LED PORTB,2 ; o LED está em RB2 ...

Page 56: Apostila PIC 16f877a

Exsto Tecnologia

56 Microcontroladores PIC16F877A

BSF LED ;é o mesmo que BSF PORTB,2 -> acende o LED ...

Início do programa

É aqui que o programa que vai ser gravado no microcontrolador realmente começa. A diretiva ORG

indica que o programa vai ser escrito a partir do vetor de reset (0000h). Como logo em seguida

temos o vetor de interrupção, caso esta esteja sendo utilizada, é necessário fazer um desvio para a

rotina principal do programa.

Tratamento de interrupção

A partir do vetor de interrupção (0004h) é colocado o código para tratar das interrupções, quando

estas forem utilizadas, conforme será discutido no futuro.

Rotina principal

É o corpo principal do programa. Na quase totalidade de programas para microcontroladores essa

rotina é constituída por uma seqüência de inicialização e um loop, que será repetido

indefinidamente. Não existe uma ordem obrigatória da posição onde deve estar essa rotina, mas é

comum que ele seja a primeira, ou a última, rotina do programa, para facilitar sua localização.

Na inicialização do microcontrolador serão realizadas todas as configurações do componente para

que o programa opere conforme o desejado.

Sub-rotinas

As sub-rotinas devem ser devidamente identificadas com seus cabeçalhos, informando sua função e

seus parâmetros de entrada e saída. Ao utilizar sub-rotinas bem feitas e documentadas reduzimos o

tempo de desenvolvimento, pois passamos a simplesmente organizar a rotinas já desenvolvidas, cujo

funcionamento é totalmente descrito pelo cabeçalho, não sendo necessário refazer a rotina nem

mesmo perder tempo estudando-a.

2.14 Programação estruturada

Programar de forma estruturada é seguir uma série de regras que fazem com que o software final

tenha uma estrutura que facilite seu desenvolvimento, compreensão e manutenção.

O problema a ser resolvido, que geralmente é um problema complexo, deve ser dividido em blocos

de problemas mais simples, e assim sucessivamente até que os sub-problemas atinjam uma

simplicidade tal que possam ser resolvidos com o uso de estruturas básicas. Para resolver qualquer

tipo de problema, independente de sua complexidade, existe apenas três tipos de estruturas: a

atribuição de valores, as estrutura de decisão e as estruturas de repetição.

É importante que um programa estruturado seja modular. Isto quer dizer que deve ser composto por

partes independentes do todo, que resolvam problemas específicos. Essas partes são chamadas sub-

rotinas. Harmoniosamente organizadas, as sub-rotinas nos permitem solucionar o problema, que é o

objetivo do software.

A divisão do programa em módulos acarreta uma série de vantagens. Como cada função trata de um

problema específico, fica fácil identificar onde está ocorrendo algum problema e também soluciona-

Page 57: Apostila PIC 16f877a

Exsto Tecnologia

57 Microcontroladores PIC16F877A

lo. Além disso, uma função pode facilmente ser “levada” para outro programa onde a mesma

solução se faça necessária, reduzindo assim o tempo de desenvolvimento. E ainda, um programa

modular é mais facilmente compreendido quando lido.

Page 58: Apostila PIC 16f877a

Exsto Tecnologia

58 Microcontroladores PIC16F877A

3 PROGRAMANDO O PIC16F877A

3.1 Diretivas Diretivas podem ser vistas como instruções dadas ao montador, e não ao microcontrolador. Elas são

reconhecidas ou interpretadas pelo processador e realizam várias funções na criação do programa.

Trataremos aqui de algumas diretivas principais, que serão utilizadas na grande maioria dos

programas.

ORG e END

Sintaxe ORG <endereço>

Exemplo

org 0000h ; inicio do programa INICIO: CALL INIT GOTO PRINCIPAL

A diretiva ORG indica ao compilador que o código que se segue será alojado a partir da posição de

memória indicada por <endereço>. Sempre é necessária uma diretiva ORG para indicar o começo do

programa, conforme mostrado no exemplo.

Sintaxe END

Exemplo

org 0000h ; inicio do programa INICIO: ... ; corpo do programa end ; fim do programa

A diretiva END indica o fim do programa. Todo código escrito deve ser finalizado com END. Qualquer

código escrito após END será ignorado pelo compilador.

#INCLUDE

Sintaxe #include <nome_do_arquivo>

Exemplo #include <PIC16F628A.inc> ;definições do 16F628A #include <MINHAS_MACROS.inc>; biblioteca de macros

Page 59: Apostila PIC 16f877a

Exsto Tecnologia

59 Microcontroladores PIC16F877A

A diretiva #INCLUDE permite incluir arquivos no código fonte principal. Esses arquivos podem ser

arquivos de definições dos microcontroladores (cada microcontrolador tem seu arquivo de

definições, que deve ser incluído no início do programa) ou “bibliotecas”, que são conjuntos de

funções e/ou macros já prontas. No exemplo dado, temos esses dois casos

#DEFINE e EQU

Sintaxe #define <nome> <texto>

Exemplo #define SETPOINT 32h #define ENTRADA PORTA #define LED PORTB,5

Sintaxe <nome> EQU <texto>

Exemplo MEDIDA EQU 20h ; variável TESTE EQU 21h ; variável SETPOINT EQU 32h ; constante

Essas duas diretivas têm função semelhante, que é estabelecer uma substituição de texto. Em ambos

os casos, elas informam ao compilador que <nome> deve ser substituído por <texto> quando o

programa for compilado. A diferença fundamental entre elas é que #DEFINE aceita textos compostos

por virgulas, pontos, espaços, etc, enquanto EQU aceita apenas uma seqüência simples de

caracteres.

Ambas as diretivas pode ser utilizadas para declarar variáveis. Como veremos, declarar uma variável

nada mais é que dar um nome a um endereço de memória, que é a mesma coisa que declarar uma

constante. A diferença entre constante e variável está somente no tratamento dado no programa.

Apesar disso, vamos estabelecer o critério de utilizar EQU para definição de variáveis e #DEFINE para

definição de constantes.

Veremos na próxima diretiva que existe um jeito mais eficiente de declarar variáveis.

CBLOCK e ENDC

Sintaxe

CBLOCK <valor_inicial> <nome_1> <nome_2> ... <nome_N> ENDC

Exemplo

CBLOCK 20h ;endereço inicial da RAM geral TESTE MEDIDAS VALOR ... ENDC

A diretiva CBLOCK permite criar um bloco de constantes consecutivas. É especificado um valor inicial,

que será o valor atribuído ao primeiro nome do bloco de constantes, a partir dele, cada nome recebe

Page 60: Apostila PIC 16f877a

Exsto Tecnologia

60 Microcontroladores PIC16F877A

um valor em ordem crescente a partir do valor inicial. No exemplo dado, o valor inicial é 20h, o que

resulta em TESTE = 20h, MEDIDAS = 21h e VALOR = 22h.

O bloco é sempre terminado pela diretiva ENDC.

Essa diretiva é muito útil para a definição de variáveis, pois nos permite estabelecer o endereço onde

começa a RAM de uso geral e simplesmente dar o nomes as variáveis, sem preocupação com o

endereço individual de cada variável. Contudo, deve-se estar atento para que o número de variáveis

não seja tão grande que extrapole os endereços do banco.

BANKSEL

Sintaxe BANKSEL <endereço_de_memória>

Exemplo

MEDIDA EQU 20h ; variável no banco 0 TESTE EQU A0h ; variável no banco 1 ... MOVFW MEDIDA ; banco 0 BANKSEL TESTE ; muda para o banco 1 MOVWF TESTE ; banco 1 BANKSEL MEDIDA ; retorna ao banco 0

Essas duas diretivas são utilizadas quando é necessário realizar mudanças de bancos de RAM de

dados. BANKSEL realiza automaticamente a alteração dos valores de RP0 e RP1 para acessar

<endereço_de_memória> diretamente. BANKISEL realiza a alteração de IRP para realizar acesso

indireto.

A vantagem de se utilizar essas diretivas é que não é preciso saber em qual banco está o registro

acessado, apenas que ele não está no banco corrente. Como elas geram código para alterar os bits

em questão, sua utilização deve ser cuidadosa.

No exemplo acima da diretiva BANKSEL são declaradas duas variáveis, MEDIDA e TESTE, nos

endereços 20h (banco 0) e A0h (banco 1), respectivamente. Considerando a formação de endereços

por 7 bits essas duas variáveis correspondem ao mesmo valor de operando na instrução, no entanto

se encontram em bancos diferentes. Para a manipulação de dados entre elas é necessário o ajuste de

banco, que é feito atribuído os valores corretos a RP0 e RP1. A diretiva BANKSEL realiza essa ação. No

exemplo, o valor contido em MEDIDA é carregado em W, a diretiva BANKSEL realiza o ajuste de

banco para acessar a variável TESTE, ou seja, realiza a mudança de banco para o banco 1, o valor

contido em W é transferido para TESTE e a diretiva BANKSEL é novamente utilizada, agora para fazer

o ajuste para o banco de MEDIDA, isto é, para o banco 0.

__CONFIG

Sintaxe __CONFIG <opções>

Exemplo __CONFIG INTRC_OSC_NOCLKOUT & _WDT_OFF

A diretiva __CONFIG (existem dois ‘_’ (dois caracteres underline) antes de CONFIG) permite

estabelecer a configuração dos “fusíveis” utilizada pelo programa. Fusíveis ou fuses são como são

Page 61: Apostila PIC 16f877a

Exsto Tecnologia

61 Microcontroladores PIC16F877A

chamados os bits de configuração das diversas características especiais, das quais trataremos mais

adiante. As várias opções, que na verdade são constantes, são associadas pelo símbolo &, que realiza

uma operação E entre os valores dessas constantes.

Para cada PIC existem várias opções, que podem ser encontradas no arquivo de definições. A tabela

4.1 contém as opções de configuração para os PIC 16F628 e 16F628A

Opção Descrição Padrão

_BODEN_ON Brown-out Reset habilitado x

_BODEN_OFF Brown-out Reset desabilitado

_CP_ALL Proteção de código total

_CP_OFF Proteção de código desativada x

_CPD_ON Proteção da memória EEPROM habilitada

_CPD_OFF Proteção da memória EEPROM desabilitada x

_PWRTE_OFF Power-up Timer habilitado x

_PWRTE_ON Power-up Timer desabilitado

_WDT_ON Watch-dog ligado x

_WDT_OFF Watch-dog desligado

_LVP_ON Programação em baixa tensão habilitada x

_LVP_OFF Programação em baixa tensão desabilitada

_DEBUG_ON Depurador ativo

_DEBUG_OFF Depurador inativo x

_RC_OSC Oscilador externo (Modo EC) x

_LP_OSC Oscilador a cristal/ressonador – modo LP

_XT_OSC Oscilador a cristal/ressonador – modo XT

_HS_OSC Oscilador a cristal/ressonador – modo HS

_WRT_OFF Proteção de escrita na FLASH desabilitada x

_WRT_256 Proteção de escrita nos primeiros 256 bytes

_WRT_1FOURTH Proteção de escrita no primeiro quarto

_WRT_HALF Proteção de escrita em metade da memória

Tabela 4.1 – Parâmetros da diretiva CONFIG

3.2 Variáveis Os dados a serem manipulados pelo microcontrolador são armazenados na memória RAM de uso

geral. É nessa região da memória onde são declaradas as variáveis do programa. Quando se trabalha

em Assembly no PIC somente dois tipos de variável existem diretamente. O primeiro é o byte, que

pode ser encarado como o tipo caracter (8 bits). Byte aceita valores de 0 a 255 se considerarmos

valores não sinalizados ou de –128 a 127 se considerarmos valores sinalizados (notação

complemento 2).

A outra possibilidade é o tipo lógico. Nesse caso, como a variável pode assumir somente dois valores,

verdadeiro (‘1’ ou true) ou falso (‘0’ ou false), são utilizados individualmente bits de bytes

pertencentes a RAM. É comum se referir a esses bits como flags (bandeiras).

As variáveis a serem usadas em um programa devem ser declaradas, isto é, deve-se informar ao

sistema que elas existem antes de usá-las, para que lhes seja destinado um espaço de memória.

Page 62: Apostila PIC 16f877a

Exsto Tecnologia

62 Microcontroladores PIC16F877A

Declarar bytes é simplesmente atribuir um nome a um determinado endereço de memória.

Para a declaração de bytes utiliza-se a diretiva CBLOCK, conforme já tratado.

Para declarar variáveis de tipo lógico, ou flags, primeiramente declara-se um endereço que irá conter

os flags. Em seguida utiliza-se a diretiva #DEFINE para declarar o flag dentro do byte de flags,

conforme a sintaxe abaixo.

#define <nome_do_flag> <Nome_do_byte_flags> , <bit>

Sendo que o campo <bit> pode conter valores de 0 a 7, sendo 0 o bit menos significativo do byte e 7

o mais significativo. Abaixo pode ser observado um exemplo de declaração de variáveis lógicas.

FLAGS1 EQU 20h ; o byte de flags ocupa o endereço 20h #define F_RECEBEU FLAGS1, 0 #define F_ACABOU FLAGS1, 1 ; . . . #define F_ALARME FLAGS1, 7

Uma boa dica de programação é usar sempre nomes de variáveis e flags que deixem clara sua

função, facilitando a compreensão do código. Pode-se ainda obedecer a regra de sempre iniciar o

nome de variáveis lógicas com “F_”, para indicar que se trata de um flag e não de um byte.

3.3 Sub-rotinas Para a implementação de programas modulares é de fundamental importância o conceito de sub-

rotinas. Uma sub-rotina é definida como um trecho de código que realiza uma ação específica, assim

como uma função matemática. Ela pode ou não ter parâmetros de entrada (operandos de uma

função matemática) e parâmetros de saída (resultados). O conceito de sub-rotina admite ainda que

ela será “chamada” pelo programa, isto é, ela será executada e depois retornará ao ponto onde foi

chamada.

Em Assembly, uma sub-rotina inicia-se no Label (ou rótulo) que dá lhe o nome pelo qual ela será

“chamada” pelo programa e termina sempre com uma instrução RETURN. A instrução RETURN é

necessária para que o programa retorne ao ponto onde a sub-rotina foi chamada. As sub-rotinas

seguirão a forma geral abaixo.

<nome da subrotina>: ; Descrição da função da sub-rotina (1) ; Entrada: < parâmetros de entrada> (2) ; Saída: < parâmetros de saída > (3) ; <aqui vem o código da sub-rotina>

RETURN

Exemplo 4.1

Por exemplo, o código abaixo soma o valor de duas variáveis e salva esse valor em W.

ADD_FUNCTION: ; soma dois números (1) ; entrada: NUMERO_1 (2) ; NUMERO_2 (2)

Page 63: Apostila PIC 16f877a

Exsto Tecnologia

63 Microcontroladores PIC16F877A

; saída: W (3) MOVFW NUMERO_1 ; W NUMERO_1 ADDWF NUMERO_2,W ; W W + NUMERO_2 RETURN

3.3.1 Passagem de Parâmetros A passagem de parâmetros nos algoritmos é feita na própria forma de escrita da sub-rotina. A forma

geral de referência à sub-rotina no português estruturado e em fluxograma será a apresentada

abaixo, sendo que o campo [destino] é opcional, pois a sub-rotina pode não retornar nenhum valor,

e os parâmetros podem ser de qualquer quantidade, inclusive nenhum.

[destino] <Nome da função> ( [Parâmetro1], ..., [ParâmetroN] );

Em um programa em Assembly, porém, esse tipo de construção é impossível. A passagem de

parâmetros é feita então simplesmente atribuindo os valores a serem processados nas variáveis que

serão utilizadas na função. Uma boa técnica é, sempre que existir apenas um valor de entrada e/ou

de saída da função, utilizar o registro W para o transporte de parâmetros. Isso facilita as operações e

reduz o tamanho do código. Outra boa prática de programação é nunca manter valores importantes

em W, pois, como destino de grande parte das operações da ALU, ele pode ser alterado a qualquer

momento.

Exemplo 4.2

Para a implementação da sub-rotina de soma suposta no exemplo anterior podemos utilizar o código

abaixo. Simule-o para observar seu funcionamento.

CBLOCK 20h NUMERO_1 NUMERO_2 SOMA ENDC ORG 0000H MOVLW 32h MOVWF NUMERO_1 ; NUMERO_1 <- 32h MOVLW 04h MOVWF NUMERO_2 ; NUMERO_2 <- AUX CALL ADD_FUNCTION ; chama a função MOVWF SOMA ; SUM <- resultado contido em W GOTO $ ADD_FUNCTION: ; soma dois números (1) ; entrada: NUMERO_1 (2) ; NUMERO_2 (2) ; saída: W (3) MOVFW NUMERO_1 ; W <- NUMERO_1 ADDWF NUMERO_2,W ; W <- W + NUMERO_2

[destino] <Nome da função> ( [Parâmetro1], ..., [Parâmetro N] )

Page 64: Apostila PIC 16f877a

Exsto Tecnologia

64 Microcontroladores PIC16F877A

RETURN ; retorna o resultado em W END

Pode-se notar que abaixo do nome da sub-rotina foram introduzidas algumas linhas de comentários

que especificam (1) o que faz a sub-rotina, (2) quais são os parâmetros de entrada e (3) quais são os

parâmetros de saída. É extremamente recomendado que se siga esse procedimento para garantir

maior facilidade de compreensão e melhor documentação do software.

3.3.2 Chamada X Desvio (CALL X GOTO) Um problema que atinge praticamente a todos quando começam o estudo de uma linguagem de

programação de baixo nível é não ter claro em mente a diferença entre desvio e chamada no fluxo

do programa.

O fluxo do programa em um microcontrolador se dá da seguinte maneira: partindo de um endereço

inicial as instruções são executadas seqüencialmente. É aí que entra a conceito do PC (Program

Counter – Contador de programa). O programa seguindo normalmente, a cada instrução o PC é

incrementado, fazendo com que no próximo ciclo de leitura de instrução o endereço lido seja o

imediatamente seguinte ao atual.

Porém para a grande maioria das aplicações não é de grande utilidade um programa que seja

executado sempre na mesma seqüência. Por isso o programa deve ser capaz de mudar seu próprio

fluxo. Nas chamadas de sub-rotinas e tratamento de interrupções ele deve ser capaz de interromper

sua seqüência normal, executar um código armazenado em outra região da memória e retornar ao

ponto onde a seqüência foi interrompida. Numa estrutura de decisão ele deve ser capaz de executar

o bloco verdadeiro ou o bloco falso. E ainda, numa estrutura de repetição ele deve ser capaz de

realizar a mesma seqüência N vezes, dependendo das condições da estrutura.

Para realizar tudo isso existem dois meios: o desvio e a chamada.

O desvio, que no PIC é realizado pela execução da instrução GOTO, consiste em alterar o valor do PC,

fazendo com ele contenha o endereço onde está o código que se deseja executar. Dessa maneira a

seqüência do código é desviada para aquele endereço e de lá segue seqüencialmente, até encontrar

uma outro desvio ou uma chamada.

A chamada, que no PIC é realizada pela execução da instrução CALL, é semelhante ao desvio, porém

fundamentalmente diferente. A chamada também altera o valor do PC, causando um desvio na

seqüência do programa para um determinado endereço, porém antes de realizar essa alteração ela

“salva” o valor do PC (próximo endereço depois do CALL), que será seu endereço de retorno, numa

região de memória chamada pilha. Isso é feito porque o conceito de chamada é de que uma parte do

código, gravada em uma diferente região da memória, deve ser executada e depois o fluxo retorna o

ponto em que a chamada foi originada. Portanto uma instrução de chamada sempre exigirá uma

instrução de retorno, que no PIC é a instrução RETURN. A chamada em Assembly funciona então

como a chamada de funções numa linguagem de médio ou alto nível, porém temos que nos

preocupar com o retorno dessa função. Uma função em Assembly sempre terminará com uma

instrução de retorno (RETURN ou RETLW). O que o RETURN faz é recuperar o valor salvo na pilha

pela última instrução CALL executada e carrega-lo no PC, fazendo com que o fluxo do programa volte

ao ponto onde foi executada a chamada.

Page 65: Apostila PIC 16f877a

Exsto Tecnologia

65 Microcontroladores PIC16F877A

A pilha do PIC possui somente oito níveis, isto é, pode armazenar somente oito endereços de

retorno. Ela trabalha de forma circular, assim, já tendo 8 endereços armazenados, o nono substitui o

primeiro e assim por diante. Em uma analogia com uma pilha de pratos, o nono prato tomará o lugar

do primeiro que está em baixo. Portanto deve-se tomar cuidado para não se fazer mais de 8

chamadas consecutivas (incluindo a interrupção!), senão perde-se os endereços de retorno das

primeiras chamadas, fazendo com que o programa perca completamente sua seqüência lógica.

A figura 4.1 ilustra o a seqüência do programa dentro da memória, quando temos uma chamada, um

desvio, depois mais uma chamada, o retorno da segunda chamada e o retorno da primeira.

Figura 4.1 – CALL X GOTO

No programa existirão labels com duas finalidades: indicar o início de sub-rotinas e indicar pontos de

desvio. Para desvios curtos (poucas instruções acima ou abaixo do ponto atual) é possível utilizar a

construção:

GOTO $ +/- k

Onde k é um valor constante e $ indica o endereço atual. Sendo assim, para realizar um salto

a 3 instrução abaixo soma-se 3 ao endereço atual. Para saltar para a instrução anterior, subtrai-se 1

do endereço atual. Esses procedimentos são apresentados abaixo.

0000h

CALL A

B

RETURN

C

GOTO B

A

CALL C

RETURN

Page 66: Apostila PIC 16f877a

Exsto Tecnologia

66 Microcontroladores PIC16F877A

GOTO $+3 ; salta para a 3 instrução abaixo ... GOTO $-1 ; volta para a instrução anter ior

3.4 Atribuição A estrutura mais simples existente em algoritmo ou fluxograma é a atribuição, que nada mais é que o

modo pelo qual se atribui valor a uma variável. Em outras palavras, trata-se de mover o valor de uma

origem, sendo essa uma constante ou uma variável, para uma variável de destino. Tanto nos

fluxogramas como no português estruturado essa operação será caracterizada pelo símbolo “”,

sendo que o destino encontra-se na ponta da seta e a origem na extremidade oposta a ponta. Abaixo

são apresentados alguns exemplos.

Português Estruturado Fluxograma

X Soma;

F_ALARME Falso;

No Assembly do PIC a atribuição é feita pelas seguintes instruções:

Orientadas a bytes:

MOVLW k : W k

MOVF f, 1 : f f

MOVF f, 0 : W f (instrução especial MOVFW)

MOVWF f : f W

CLRF f : f 0

CLRW : W 0

RETLW k : W k e realiza o retorno

Orientadas a bit:

BSF f, b : f[b] Verdadeiro

BCF f, b : f[b] Falso

Obs.: f[b] significa bit “b” do registrador “f”

Devido ao reduzido número de instrução no Assembly do PIC não existem instruções que permitam

mover o conteúdo de uma variável diretamente para outra ou uma constante diretamente para uma

variável (exceto quando a constante for zero). Para mover uma constante para uma variável utiliza-se

a seqüência abaixo.

X Soma;

F_ALARME Falso;

Page 67: Apostila PIC 16f877a

Exsto Tecnologia

67 Microcontroladores PIC16F877A

MOVLW k ; W k

MOVWF f ; f W

Para atribuir o valor de uma constante a outra procede-se da seguinte forma.

MOVLW <origem> ; W <origem>

MOVWF <destino> ; f <destino>

3.5 Entrada e Saída Nos modelos básicos de algoritmos e fluxogramas utilizados existem funções de entrada e saída. Elas

permitem a comunicação do software com o “mundo exterior”. O PIC tem a particularidade de não

possuir instruções de entrada e saída de dados, sendo estas funções realizadas pela escrita e leitura

dos registros de cada portal (instruções de atribuição). Esses registros são nomeados como PORTA,

PORTB, PORTC, etc. No caso específico do PIC16F628A existem o PORTA e o PORTB. Assim, comandos

de entrada e saída resumem-se a simples atribuições envolvendo os registros de portais (PORTA,

PORTB). Esta característica ocorre de forma a simplificar o set de instruções, facilitando o

desenvolvimento de software e reduzindo o número de instruções.

Uma instrução de saída é uma atribuição que tem como destino o registro de um portal. Do mesmo

modo, uma instrução de entrada é uma atribuição que tem como origem o registro de um portal.

Exemplos são apresentados abaixo.

MOVFW PORTA ; W <-- PORTA MOVWF RX_DTMF ; RX_DTMF <-- W Entrada ... MOVLW 0AFh ; W <-- 0Afh MOVWF PORTB ; PORTB <-- W Saída

Para saída de dados é possível ainda trabalhar alterando somente um bit de um portal, sendo essa

alteração refletida em um único terminal de saída. Para isso utilizam-se as instruções de atribuição

orientadas a bit (BCF e BSF), como pode ser visto abaixo. Também é possível realizar entradas em

nível de bit, procedimento esse que será tratado mais adiante.

BCF PORTA,3 ; bit 3 do portal A <-- Falso BSF PORTB,0 ; PORTB[0] <-- Verdadeiro

Na figura 4.2 são apresentados os símbolos de entrada (a) e saída (b) para fluxogramas.

Figura 4.2 – Símbolos de (a) entrada e (b) saída em fluxogramas

As representações em português estruturadas são as palavras Escreva para saída de dados e Leia

para a entrada de dados.

(a) (b)

Page 68: Apostila PIC 16f877a

Exsto Tecnologia

68 Microcontroladores PIC16F877A

3.6 Estruturas de Decisão Um programa composto apenas por atribuições teria aplicações bastante limitadas. Além disso, uma

das vantagens do software é que ele pode tomar decisões a partir de informações de entrada.

Estruturas permitem que isso seja feito são chamadas estruturas de decisão.

As estruturas de decisão existentes são:

• Se

• Se-Senão

• Se-Senão-Se

• Caso

No Assembly do PIC, as estruturas de decisão são implementadas através de instruções que realizam

teste e desvios, que são:

BTFSS <registro>, <bit>

Salta a próxima instrução se <bit> de <registro> estiver em ‘1’.

BTFSC <registro>, <bit>

Salta a próxima instrução se <bit> de <registro> estiver em ‘0’.

DECFSZ <registro>, <destino>

Decrementa <registro> e salta a próxima instrução se o resultado for ‘0’.

INCFSZ <registro>, <destino>

Incrementa <registro> e salta a próxima instrução se o resultado for ‘0’ (255 + 1 = 0 e ‘vai um’ para

STATUS,C).

Juntamente com as instruções citadas acima, geralmente se utilizam instruções de desvio para os

endereços do código que tratam de cada situação. O exemplo abaixo mostra como isso acontece:

LOOP: ... DECFSZ CONTADOR,F ; desvia para LOOP se o contador GOTO LOOP ; não vale ‘0’

Os procedimentos acima descritos podem ser utilizados para o teste de bits em portais, realizando

assim decisão e entrada de dados ao mesmo tempo. Dessa forma consegue-se maior agilidade no

software. O exemplo abaixo realiza uma decisão a partir de um bit de entrada; neste caso o bit em

questão foi definido com o nome SENSOR_1.

BTFSC SENSOR_1 ; Se (SENSOR_1 = Verdadeiro)então GOTO DISPARA_ALARME ; dispara o alarme

Page 69: Apostila PIC 16f877a

Exsto Tecnologia

69 Microcontroladores PIC16F877A

3.7 Condições As decisões que devem ser tomadas em um programa muitas vezes são baseadas na comparação

numérica entre dois valores, isso é, se esses valores são iguais ou não, qual é o maior, etc. No set de

instruções da linha PIC 16Xxxx não existe nenhuma instrução de comparação. Então para realizar

comparação se faz necessário utilizar instruções de teste associada a manipulações matemáticas.

Assim, antes de tratar propriamente das estruturas de decisões, deve-se saber como reconhecer

essas condições.

Condições A = B e A != B

Uma forma simples de saber se dois valores são iguais é subtraindo um do outro: se o resultado for

zero os dois valores são iguais; qualquer outro resultado significa que os valores são diferentes. Em

Assembly realiza-se a subtração e estuda-se o bit Z do registro STATUS, conforme pode ser

observado no exemplo abaixo.

Simule esse exemplo, alterando o valor da variável MEDIDA para 25h e outros valores e observado o

que ocorre.

#INCLUDE<P16F877A.INC> ; definições dos registros do PIC CBLOCK 20H MEDIDA ENDC ORG 0000H MOVLW 25h ; W <-- 25h SUBWF MEDIDA,W ; W <-- MEDIDA - W BTFSC STATUS,Z ; Se (Medida = 25h) então GOTO IGUAIS ; desvia para IGUAIS GOTO DIFERENTES ; senão, desvia para diferentes IGUAIS: GOTO $ ; se forem iguais, pa ra aqui DIFERENTES: GOTO $ ; se forem difer entes, para aqui END

E ainda, para testar se uma variável é igual a zero, pode-se utilizar a instrução MOVF, tendo como

destino o próprio registro. Nesse caso o valor da variável é movido para ela mesma, não sofrendo

qualquer alteração. Porém, se a variável for igual a zero o bit Z de STATUS será afetado, assumindo

valor igual a 1.

Condições A > B, A >= B, A < B, A <= B

Pode haver a necessidade de saber qual de dois valores é o maior, sendo eles diferentes entre si.

Para tanto, novamente subtrai-se um valor pelo outro e então analisa-se o bit de Carry (Transporte)

que é o bit C do registro STATUS.

Supondo dois valores , A e B, diferentes e tais que A > B, temos que:

A – B : resultado normal (valor positivo)

Page 70: Apostila PIC 16f877a

Exsto Tecnologia

70 Microcontroladores PIC16F877A

B – A : ocorrência de estouro do acumulador na subtração, chamado de Borrow. (valor negativo)

O Borrow pode ser percebido pela análise do bit C do STATUS. É importante notar que na subtração

esse bit trabalha com lógica inversa à adição. Assim:

C = ‘1’ : resultado normal

C = ‘0’ : ocorrência de borrow

Resultado normal inclui 0. Dessa forma, se fazendo A – B resulta em C = 1 conclui-se que A >= B (ou

que B <= A).

O trecho de código abaixo chama a sub-rotina “AJUSTE” se MEDIDA for maior que MAX. Simule seu

funcionamento para diferentes valores de MEDIDA e MAX.

#INCLUDE<P16F877A.INC> CBLOCK 20H MAX MEDIDA ENDC ORG 0000H REPETE: MOVFW MAX ; W <-- MAX SUBWF MEDIDA,W ; W <-- MEDIDA - W BTFSC STATUS,C ; Se (MEDIDA >= MAX) então CALL AJUSTE ; AJUSTE é chamado GOTO REPETE ; senão desvia para REPETE ; ... AJUSTE: NOP ; \ NOP ; > corpo da sub-rotina NOP ; / RETURN ;retorna para o endereço de chamada END

Finalmente, para testar se um valor é somente menor ou maior que outro, e não igual, testa-se na

mesma operação o bit Z de STATUS. O código abaixo exemplifica essa operação:

#INCLUDE<P16F877A.INC> ; definições dos registros do PIC CBLOCK 20H MEDIDA ENDC ORG 0000H MOVLW 05h ; W <-- 05h SUBWF MEDIDA,W ; W <-- MEDIDA - W BTFSC STATUS,Z ; Se (Medida = 05h) então GOTO IGUAL ; desvia para IGUAIS BTFSC STATUS,C GOTO MAIOR ; se MEDIDA > 05h : C = 1 GOTO MENOR ; se MEDIDA < 05h : C = 0

Page 71: Apostila PIC 16f877a

Exsto Tecnologia

71 Microcontroladores PIC16F877A

IGUAL: GOTO $ ; se MEDIDA == 05h, p ara aqui MENOR: GOTO $ ; se MEDIDA < 05h, pa ra aqui MAIOR: GOTO $ ; se MEDIDA > 05h, pa ra aqui END

Resumo das condições

Em resumo, havendo dois valores, A e B, e sendo realizada a subtração A – B, temos que:

Z C Condição

0 0 A < B 0 1 A > B 1 0 impossível 1 1 A = B

3.8 Se A estrutura de decisão Se funciona da seguinte forma: se a condição for verdadeira, o

Bloco_verdadeiro é executado; senão, programa continua o fluxo normalmente a partir de Fim_Se.

Em outras palavras, o código contido no Bloco_verdadeiro é executado somente se a condição for

verdadeira.

A implementação dessa estrutura pode ser feita com uma instrução de teste e salto seguida por uma

chamada de função. Essa chamada contem o Bloco_verdadeiro. É conveniente a utilização de uma

chamada de função, pois o programa retorna ao ponto onde foi chamado e continua o programa da

próxima linha, isto é, do mesmo ponto de onde continuaria se a condição fosse falsa. Esse

procedimento é exemplificado abaixo.

BTFSS PORTB,2 ; se (PORTB[2] = Verdadeiro) então CALL BL_VERDADE ; executa o bloco verdadeiro e re torna BCF PORTC,0 ; senão, segue o programa . . . BL_VERDADE: ; Bloco verdadeiro MOVLW 0Fh MOVWF PORTB RETURN

Bloco

<Condição>

F

V Se (<condição>) então

[Bloco_verdadeiro]

Fim_Se

Page 72: Apostila PIC 16f877a

Exsto Tecnologia

72 Microcontroladores PIC16F877A

Se (<condição>) então

[Bloco_verdadeiro]

Senão

[Bloco_falso]

Fim_Se

Bloco Verdadeiro

<Condição> F V

Bloco Falso

Se por algum motivo não for interessante a utilização de uma chamada, devemos fazer o teste

inverso, de forma a desviar quando a condição for falsa. Esse desvio deve ser para o ponto que

também será o destino do termino do bloco verdade. O trecho de código abaixo realiza o mesmo

que o código anterior, porém sem a utilização de chamada.

BTFSC PORTB,2 ; se (PORTB[2] != Vedadeiro)então GOTO FIM_SE ; segue para END_IF MOVLW 0Fh ; se (PORTB[2] = Vedadeiro) então MOVWF PORTB ; executa o bloco verdadeiro FIM_SE: BCF PORTC,0 ; em qualquer caso, o programa segue . . .

3.9 Se senão A estrutura Se-Senão é uma derivação da estrutura Se onde, além de um bloco a ser executado

somente quando a condição for verdadeira (o Bloco_verdadeiro), existe um bloco a ser executado

somente quando a condição for falsa (o Bloco_falso). Sua representação é ilustrada abaixo.

Essa estrutura é implementada em Assembly por uma instrução de teste e salto seguida de dois

desvios, conforme o trecho abaixo.

CBLOCK 20H CANAL TST1 ENDC ORG 0000H MOVFW CANAL SUBLW 35h SKPNZ ; instrução especial = BTFSC STATUS,Z GOTO BL_VERDADE ; se (CHANNEL) = 35h GOTO BL_FALSO ; senão BL_VERDADE: ; Bloco Verdadeiro MOVLW 03h MOVWF TST1 GOTO FIM_SE ; vai para o “Fim_Se” BL_FALSO: ; Bloco Falso MOVLW 08h MOVWF TST1 ; vai para o “Fim_Se”

Page 73: Apostila PIC 16f877a

Exsto Tecnologia

73 Microcontroladores PIC16F877A

FIM_SE: ; os dois blocos convergem para cá GOTO $ ; para aqui. END

Um modo mais compacto de se implementar um se-senão é fazendo todos os blocos de forma

seguida no código, dessa forma são economizadas instruções de desvio. Esse modo é apresentado

abaixo.

CBLOCK 20H CANAL TST1 ENDC ORG 0000H MOVFW CANAL SUBLW 35h SKPNZ ; instrução especial = BTFSC STATUS,Z GOTO BL_VERDADE ; se (CHANNEL) = 35h ; Bloco Falso vem aqui MOVLW 08h MOVWF TST1 GOTO FIM_SE ; vai para o “Fim_Se” BL_VERDADE: ; Bloco Verdadeiro MOVLW 03h MOVWF TST1 ; vai para Fim_se FIM_SE: ; os dois blocos convergem para cá GOTO $ ; para aqui. END

A diferença entre esses dois códigos é que no segundo, as instruções do bloco falso vêm logo em

seguida ao desvio BL_VERDADE sem que seja necessário colocar outro desvio para a as instruções a

serem executadas em caso de a condição da estrutura de decisão ser falsa.

3.10 Se senão se Uma outra possibilidade de construção utilizando-se a estrutura Se-Senão é a chamada estrutura Se-

Senão-Se, que é simplesmente a implementação onde o bloco falso de uma estrutura Se-Senão é

composto por outra estrutura Se-Senão. Esta forma pode ser utilizada em cascata, possibilitando a

verificação de quantas possibilidades forem necessárias no programa. Abaixo é apresentada a forma

geral dessa estrutura. Deve-se notar que todos os “FIM_SE” da estrutura levam na verdade a um

mesmo ponto. E ainda, pode haver ou não um Bloco Falso, que será executado caso nenhuma das

condições seja satisfeitas.

Page 74: Apostila PIC 16f877a

Exsto Tecnologia

74 Microcontroladores PIC16F877A

Uma estrutura Se-Senão-Se em Assembly é implementada facilmente utilizando-se as técnicas já

apresentas para a estrutura Se-Senão. Contudo, deve-se dar especial atenção para o fato de o

destino final de todos os blocos é o mesmo, para que não se perca a estruturação do código.

Abaixo é apresentado um exemplo da utilização da estrutura Se-Senão-Se para controle de

temperatura e umidade.

Se (<condição 1>) então [Bloco_verdadeiro 1] Senão Se (<condição 2>) então [Bloco_verdadeiro 2] Senão

Se (<condição 3>) então [Bloco_verdadeiro 3]

Senão . . .

Se (<condição n>) então [Bloco_verdadeiro n] Senão

[Bloco Falso] Fim_Se . . .

Fim_Se Fim_Se Fim_se

Condição 1 V F

Bloco Verdadeiro

Condição 2 V F

Bloco Verdadeiro

Bloco Falso

Condição 3 V F

Bloco Verdadeiro

Page 75: Apostila PIC 16f877a

Exsto Tecnologia

75 Microcontroladores PIC16F877A

CBLOCK 20h TEMP UMIDADE ENDC ORG 0000H TEST_TEMP: ; 1o. teste MOVLW .30 ; W <-- 30 SUBWF TEMP,W ; W <-- TEMP - W SKPC ; Se (TEMP < 30) então GOTO TEST_2 ; vai para o próximo teste ; Se (TEMP > 30) então CALL ESFRIA ; executa a sub-rotina GOTO FIM_SE ; vai para Fim_Se TEST_2: ; 2o. teste MOVLW .80 ; W <-- 80 SUBWF UMIDADE,W ; W <-- UMIDADE - W SKPC ; Se (UMIDADE < 80) então GOTO TEST_3 ; vai para o próximo teste ; Se (UMIDADE > 80) então CALL ALARME ; executa a sub-rotina GOTO FIM_SE ; vai para Fim_Se TEST_3: ; 3o. teste MOVLW .20 ; w <-- 20 SUBLW UMIDADE ; W <-- UMIDADE - W SKPNC ; Se (UMIDADE > 20) então GOTO DEFAULT ; vai para a exceção ; Se (UMIDADE < 20) então CALL MOLHA ; executa a sub-rotina GOTO FIM_SE ; vai para Fim_Se DEFAULT: ; tratamento de exceção CALL VENTILAR FIM_SE: ; todos os blocos convergem para cá GOTO TESTE_TEMP ; repete todos os testes ESFRIA: ; Rotina para esfriar alguma coisa NOP RETURN ALARME: ; Rotina que dispara o alarme NOP RETURN MOLHA: ; Rotina que molha alguma coisa NOP RETURN VENTILAR: ; Rotina que ventila alguma coisa NOP RETURN END

3.11 Caso A estrutura Caso (Case ou Switch) é uma estrutura de admite múltiplas condições de igualdade, com

um bloco verdade para cada condição. Existe também a possibilidade de um bloco de exceção para

tratar os casos que não se enquadram em nenhuma condição. Dessa forma temos:

Page 76: Apostila PIC 16f877a

Exsto Tecnologia

76 Microcontroladores PIC16F877A

Caso <Variável> de

<Opção 1>: [Bloco_1]

<Opção 2>: [Bloco_2]

<Opção 3>: [Bloco_3]

. . .

<Opção n>: [Bloco_n]

Senão: [Bloco_exceção]

Fim_caso

A estrutura Caso apresentada em fluxograma é similar a estrutura Se-Senão-Se, porém as condições

devem ser somente igualdades de uma mesma variável.

Usando essa estrutura em Assembly pode-se construir tabelas, que são de grande utilidade em

muitos casos. Elas são de grande ajuda no trabalho com displays de segmentos e na linearização de

medidas analógicas provenientes de sensores não lineares. Uma tabela de software comporta-se

como uma tabela no papel, onde a partir de um valor de entrada obtemos um valor de saída

associado a ele. Como exemplo podemos implementar uma tabela que retorne uma letra do alfabeto

a partir do valor de sua posição ou uma tabela que retorne o quadrado do valor de entrada.

Para construção de tabelas é utilizada a instrução RETLW (Retorna com uma constante em W).

Primeiramente é feito um desvio por software, somando-se o valor de uma variável ao Registro PCL

(bits menos significativos do PC (Program Counter)). Dessa forma a próxima instrução a ser

executada é a n-ésima instrução após a soma, sendo n o valor contido na variável.

Algumas regras devem ser observadas na construção de tabelas. Primeiramente deve-se estar atento

ao banco onde se encontra a tabela. É recomendado que se faça uma tabela no início de um bloco de

256 endereços (0000h, 0100h, 0200h, etc.), pois caso a operação de soma com o PCL der overflow,

isto é, resultar em um valor maior que 256 o PCLATH não será incrementado automaticamente, o

que limita o tamanho da tabela em 256 valores. Além disso, um overflow em PCL causado por uma

instrução de soma não ocasiona automaticamente o incremento de PCH (bits mais significativos do

PC). Dessa forma não se pode fazer tabelas com comprimento maior que 256 itens sem um

tratamento especial, supondo que nesse caso a tabela comece no primeiro endereço de cada bloco

de 256 endereços.

A linha

ADDWF PCL,F ; (PCL) (PCL) + (W) soma um valor n com o PC, o que resulta em a próxima instrução executada ser n-ésima após a

soma. Ou seja, a instrução a ser executada está no n-ésimo endereço a partir do endereço seguinte a

instrução ADDWF. Esse processo é chamado desvio por software.

Page 77: Apostila PIC 16f877a

Exsto Tecnologia

77 Microcontroladores PIC16F877A

A rotina abaixo, que converte valores em BCD para a palavra de ativação dos respectivos caracteres e

um display de LED´s ligado a um portal. A sub-rotina chamada é SEGMENTOS; dentro dela é feito um

desvio para o label TABLE e o retorno é realizado por uma das instruções RETLW. O endereço de

TABLE é tal que o primeiro valor da tabela ocupa a posição 700h. Admite-se que a variável NUMERO

não contém valores maiores que 9. O registro PCLATH é carregado com 07h porque esse é o valor da

parte mais significativa das linhas tabela (como pode ser observado a direita) e o endereço para onde

se desvia é dado pelo par PCLATH e PCL

SEGMENTOS: MOVFW NUMERO ; move o número a ser convertido par a W GOTO TABELA ; desvia para a tabela ; . . . ORG 06FDH ; o código abaixo começa no endereço 6 FDh TABELA: MOVLW 07H ; ajusta os bits mais significativos ( 06FDh) MOVWF PCLATH ; de PCH (06FEh) ADDWF PCL,F ; (PCL) (PCL) + (W) (06FFh) ; ABCDEFG RETLW 01110111B ;0 1111110 (0700h) RETLW 00000110B ;1 0110000 (0701h) RETLW 10110011B ;2 1101101 (0702h) RETLW 10010111B ;3 1111001 (0703h) RETLW 11000110B ;4 0110011 (0704h) RETLW 11010101B ;5 1011011 (0705h) RETLW 11110101B ;6 1011111 (0706h) RETLW 00000111B ;7 1110000 (0707h) RETLW 11110111B ;8 1111111 (0708h) RETLW 11010111B ;9 1111011 (0709h) RETLW 11100111B ;A 1110111 (070Ah) RETLW 11110100B ;B 0011111 (070Bh) RETLW 01110001B ;C 1001110 (070Ch) RETLW 10110110B ;D 0111101 (070Dh) RETLW 11110001B ;E 1001111 (070Eh) RETLW 11100001B ;F 1000111 (070Fh)

3.12 Estruturas de repetição Estruturas de repetição são estruturas que permitem que trechos do programa sejam repetidos

várias vezes. Elas são implementadas com instruções de decisão associadas a desvios, desvios esses

que levam a execução de blocos e depois retornam ao teste que as originou.

Na grande maioria dos casos, os programas para microcontroladores ficam repetindo a mesma

seqüência de instruções indefinidamente ou, pelo menos, checando entradas indefinidamente.

Como pode ser observado nos programas desenvolvidos até o momento, todo programa tem como

“núcleo” uma estrutura de repetição infinita, chamado normalmente de laço principal, loop principal

ou main loop.

Existem três tipos de estruturas de descisão: Faça-Enquanto, Enquanto e Para. Essa estruturas de

repetição são implementadas em linguagens de médio e alto nível por comando como While, Do-

While e For, respectivamente.

Page 78: Apostila PIC 16f877a

Exsto Tecnologia

78 Microcontroladores PIC16F877A

Faça [Bloco] Enquanto (<Condição>) Cond?

F

V

Bloco

3.12.1 Faça-Enquanto Faça-Enquanto (Do-While): estrutura de repetição que executa um bloco enquanto uma

determinada condição é verdadeira. A apresentação dessa estrutura em português estruturado e

fluxograma segue abaixo.

Abaixo é apresentado um trecho de código implementando uma estrutura Faça-enquanto.

LOOP: ; INCF CONTROL,W ; \ MOVWF PORTB ; > Bloco CALL MEDIDA ; / MOVFW MED SUBLW 40h ; (W) 40h – (W) BTFSC STATUS,C ; se((MED) < 40h) então sai do lo op GOTO LOOP ; senão retorna ao inicio loop ... ; Quando sai do loo p segue a partir daqui

3.12.2 Enquanto Enquanto (While): estrutura de repetição semelhante a condição Faça-Enquanto, porém difere em

um ponto muito importante: enquanto um Faça-Enquanto executa o bloco primeiro e testa a

condição depois a estrutura Enquanto testa a condição primeiro e executa o bloco depois. Essa

diferença pode mudar totalmente a lógica do programa. A apresentação da estrutura abaixo deixa

clara essa diferença.

Enquanto (<Condição>)

[Bloco]

Fim_Enquanto

Cond?

F V

Bloco

Page 79: Apostila PIC 16f877a

Exsto Tecnologia

79 Microcontroladores PIC16F877A

O trecho de código abaixo exemplifica a utilização de uma estrutura Enquanto.

LOOP: CALL MEDIDA ; realiza uma medida SUBLW 40h ; (W) 40h – (W) BTFSS STATUS,C ; só “sai”quando (MED) < 40h GOTO CONTINUA ; sai do loop ; INCF CONTROL,W ; \ MOVWF PORTB ; > Bloco MOVFW MED ; / GOTO LOOP CONTINUA: . . .

3.12.3 Para Para (For): estrutura de repetição que tem uma característica que a torna diferente da estruturas de

repetição até agora estudadas: nas estruturas Enquanto e Faça-Enquanto a condição da estrutura é

uma condição aleatória, isto é, ela não depende da estrutura de repetição; isso significa que o

número de vezes que o bloco é repetido não é conhecido a priori. Na estrutura Para a condição está

intimamente ligada a estrutura e seu estado é alterado por esta. De fato, a estrutura Para serve para

que blocos de código sejam repetidos um número de vezes conhecido, o que implica na existência de

uma variável contadora associada à estrutura.

Deve-se notar então que para essa estrutura a variável contadora não deve ter seu valor alterado

pelo bloco de instruções, somente pela estrutura de repetição em si.

A estrutura funciona da seguinte maneira: (1) primeiramente a variável contadora recebe o valor

inicial. (2) O programa entra no loop propriamente dito, o bloco é executado e (3) a instrução que

dará o passo à contagem das vezes que o loop é executada. (4) Em seguida é testado se a variável

Para <contador> = <valor_inicial> até <valor_final> faça [Bloco] Fim_Para

V F

Bloco

Passo

<contador> <valor inicial>

<contador> = <valor final> ?

Page 80: Apostila PIC 16f877a

Exsto Tecnologia

80 Microcontroladores PIC16F877A

contadora atingiu o valor final. Se o atingiu, o programa sai do loop e segue; senão o processo é

repetido novamente a partir do ponto (2).

O passo é como a variável contadora varia a cada execução do loop. Apesar de poder assumir

qualquer forma (por exemplo, a cada execução do loop o contador pode ser elevado ao quadrado)

normalmente o passo é ou um incremento (contador contador + 1) ou um decremento (contador

contador - 1).

Pelo exposto acima, o bloco contido na estrutura será repetido N vezes, N dado por:

N = <valor final> - <valor inicial> , quando for usado incremento

Ou

N = <valor inicial> - <valor final> , quando for usado decremento.

Para a implementação de uma estrutura Para em Assembly são usadas as instruções DECFSZ e

INCFSZ:

DECFSZ CONT,F ; CONT CONT – 1 ; se (CONT = 0) salta a próxima instrução

INCFSZ CONT,F ; CONT CONT + 1 ; se (CONT = 0) salta a próxima instrução ; obs: saltar a próxima instrução signifi ; ca não executar a instrução seguinte a

; a DECFSZ ou INCFSZ

Para o caso de INCFSZ, o valor do contador será igual a zero quando for somado 1 ao valor 255.

Se INCFSZ for usado, o valor final obrigatoriamente será 256, então o valor inicial deve ser calculado

subtraindo a quantidade de vezes que o loop deve ser executado de 256. Por exemplo, para N = 12, o

valor inicial deve ser 256 - 12 = 244. Quando é usada a instrução DECFSZ o valor final

obrigatoriamente será 0. Dessa forma, o valor inicial será o número de vezes que o bloco deve se

repetir. A contagem nesse caso é regressiva, isto é, o passo é de decremento. O código abaixo

apresenta um loop que será repetido 123 vezes.

. . . MOVLW .123 ; o “.” (ponto) indica que o va lor é decimal MOVWF CONT ; (1) (CONT) 123 LOOP: ; (2) o bloco será executado 123 vezes CALL TX_SERIAL ; bloco a ser repetido DECFSZ CONT,F ;(3)e(4) CONT <-CONT-1, se (CONT=0 ) salta GOTO LOOP ; senão volta para LOOP . . .

3.13 Temporização por software – Rotinas de atraso O microcontrolador executa cada instrução em um determinado tempo. No caso do PIC esse tempo é

quatro vezes o período do clock (existem instruções de 2 ciclos, que demoram o dobro das instruções

normais). Por exemplo, com cristal de 4MHz tem-se um período de 250ns e logo cada instrução

demora 1µs para ser executada.

Page 81: Apostila PIC 16f877a

Exsto Tecnologia

81 Microcontroladores PIC16F877A

Porém muitas vezes não se deseja que uma instrução seja executada imediatamente após outra. Em

muitas situações necessitamos de gerar atrasos na execução normal do programa. Por exemplo, em

muitos casos onde um usuário interage com o microcontrolador, é necessário esperar o usuário; em

muitas situações também é preciso respeitar a temporização de outros componentes, não tão

rápidos quanto o microcontrolador. Esses atrasos são conseguidos com as chamadas sub-rotinas de

atraso, ou de delay (atraso, em inglês), como é mais comum chamá-las.

Existem basicamente dois modos de se conseguir “delay”. Um seria utilizando o Timer incorporado

ao microcontrolador, trabalhando então com temporização por interrupção, a qual será tratada

mais adiante. Outra forma é criando estruturas de repetição nas quais possamos “perder” o tempo

necessário, que é a temporização por software.

Ainda considerando o PIC trabalhando a 1 MIPS (1 Milhão de Instruções Por Segundo) quando é

necessário um atraso de 10µs basta executarmos 10 vezes uma instrução qualquer. Porém, aplicando

o mesmo raciocínio para um atraso de 3s é necessário repetir a mesma instrução 3.000.000 vezes, o

que ocupa 3.000.000 endereços da memória de programa! Como pode ser notada, na maior parte

das vezes não podemos criar delays com a simples seqüência do número de instruções necessário. O

que se faz é a criar estruturas de repetição que executem um ou algumas instruções o número de

vezes necessário para nos dar o atraso desejado. Repetir um bloco de 4 instruções 50 vezes equivale

(do ponto de vista do tempo gasto) a executar 200 instruções. Deve-se tomar cuidado, porém, com o

fato de que a estrutura de repetição também demora um tempo para ser executada. Para atrasos

precisos devemos considerar o tempo de execução das estruturas, principalmente quando temos

laços de repetição dentro de outros laços de repetição.

O núcleo de uma rotina de delay é estrutura de repetição Para responsável por repetir um bloco de

instruções um determinado número de vezes. Observemos o trecho de código abaixo. Os

comentários em cada linha indicam quantos ciclos de máquina são executados em cada instrução

(Devemos lembrar que instruções de desvio e instruções de teste, quanto a condição testada é

verdadeira, gastam 2 ciclos de máquina).

MOVLW n ; 1 MOVWF CONT1 ; 1 LOOP1: NOP ; 1 DECFSZ CONT1,F ; 1 normalmente, 2 quando CONT1 == 0 | Bloco GOTO LOOP1 ; 2

No código acima, “n” será substituído por uma constante que, como veremos mais a seguir, dará o

tempo de execução do código. O “bloco“ é será repetido até que CONT1, que é decrementado a cada

execução, resulte em 0. Ou seja, o bloco será repetido “n” vezes. Como a execução do bloco leva 4

ciclos de máquina, o tempo total gasto na repetição do bloco é 4 x n. Já o tempo total de execução

da rotina do trecho de código deve levar em consideração o tempo gasto para carregar a variável

CONT1, que é de 2 ciclos de máquina. Portanto, podemos concluir que o tempo total de execução

desse trecho de código é dado pela equação (1) , sendo TCY o tempo do ciclo de máquina do

microcontrolador (que estamos considerando como sendo de 1µs):

Page 82: Apostila PIC 16f877a

Exsto Tecnologia

82 Microcontroladores PIC16F877A

CYTnT ×+×= )24( (1)

Supondo que necessitamos desse atraso em mais de um ponto de um ponto do programa,

poderíamos transformar o trecho de código acima em uma sub-rotina. Fazendo isso devemos

considerar o tempo gasto pela instrução CALL que chama a sub-rotina (2 ciclos de máquina) e o

tempo da instrução RETURN que retorna da sub-rotina (2 ciclos de máquina). Assim, temos a sub-

rotina abaixo, cujo tempo de execução é dado pela equação (2).

DELAY: ; rotina de atraso ; entrada: nulo ; saída: nulo MOVLW n ; 1 MOVWF CONT1 ; 1 LOOP1: NOP ; 1 \ DECFSZ CONT1,F ; 1 normalmente, 2 quando CONT1 == 0 | Bloco GOTO LOOP1 ; 2 / RETURN

CYTnT ×+×= )64( (2)

Para determinar o valor da constante “n” basta isolá-la na equação (2) e obtemos a equação (3),

lembrando sempre que “n” é um valor inteiro entre 1 e 255.

−= 625,0

CYTTn (3)

Devemos atentar para duas limitações dessa sub-rotina. A primeira é que não é possível obter um

valor de n inteiro para qualquer valor de T. Por exemplo, para T = 31µs temos n = 6,25. Nesse caso,

se adotarmos n = 6 obtemos um tempo de 30µs. Nessa situações, porém, a diferença entre o valor

desejado e o valor obtido será sempre pequena, e podemos completar o tempo necessário com a

simples adição de um instrução NOP

Outra limitação é que o valor máximo de n é 255, o que nos leva a um tempo máximo de 1,026 ms.

Para obter tempos maiores que esse o procedimento é considerar todo o código da rotina como

sendo um bloco, e inseri-lo dentro de outro loop. Observe como isso é feito na sub-rotina baixo.

DELAY_MAIOR: ; rotina de atraso para tempos maiores que 1 ms ; entrada: nulo ; saída: nulo MOVLW m ; 1 MOVWF CONT2 ; 1 LOOP2: ; --- --- --- --- --- --- --- --- --- --- --- MOVLW n ; 1 MOVWF CONT1 ; 1 LOOP1:

Page 83: Apostila PIC 16f877a

Exsto Tecnologia

83 Microcontroladores PIC16F877A

NOP ; 1 \ DECFSZ CONT1,F ; 1 normalmente, 2 quando CONT1 == 0 | Bloco GOTO LOOP1 ; 2 / ; --- --- --- --- --- --- --- --- --- --- --- DECFSZ CONT2,F ; 1 normalmente, 2 quando CONT2 == 0 GOTO LOOP2 ; 2 RETURN

O tempo total gasto para essa rotina é determinado pela equação (4). A equação (5) permite calcular

o valor de “m” arbitrando-se o valor de “n”.

( )[ ] CYTmnT 654 +×+×= (4)

54

6

+

−=

n

TT

m CY (5)

Com essa rotina é possível se obter tempos de até 261,381 ms. Para tempos ainda maiores, basta

usar o mesmo raciocínio: considerar a sub-rotina um bloco e colocá-la dentro de outro loop.

Page 84: Apostila PIC 16f877a

Exsto Tecnologia

84 Microcontroladores PIC16F877A

4 RECURSOS AVANÇADOS

4.1 Display de cristal Líquido Grande parte das aplicações com microcontroladores necessitam de uma interface homem-máquina,

para que os usuários possam passar informações ao sistema e/ou receber informações dele. Para

que informações do sistema sejam passadas ao usuário pode-se utilizar uma serie de recursos,

porém muitos deles não são nada maleáveis e alguns pouco amigáveis. Por exemplo, um modo

bastante simples de se ter informações do sistema é através de um painel com LED´s, cada um

indicando uma determinada situação. Embora em muitas aplicações só isso seja suficiente, em

muitas outras, principalmente quando a quantidade e variedade de informações são grande, esse

método se torna insuficiente. Outro método também muito utilizado e que, porém, aceita uma

grande variedade e quantidade de informações é o Display de Cristal Líquido (LCD – Liquid Cristal

Display).

Existe uma grande variedade de LCD’s no mercado. Existem displays gráficos e displays que aceitam

somente caracteres, esses últimos chamados displays alfanuméricos. Esses podem ter diferentes

quantidades de linha e colunas. LCD’s alfanuméricos tem uma determinada “inteligência”, isto é,

possuem circuitos que controlam o display propriamente dito, e fazer com que algo seja escrito no

LCD é somente o trabalho de comunica-se com esses circuitos.

Para a comunicação com o display são necessários 8 bits como via de dados (podendo também ser

configurado para trabalhar com 4 bits), um bit EN (Enable - Habilitação) e um bit RS (seleção entre

dados e comandos). O display reconhece dois tipos de informação na via de dados: comandos e

dados. Os comandos, que são reconhecidos quando RS = 0, são instruções para o display (limpar a

tela, ir para a segunda linha, ir para a décima coluna, etc... ); os dados são caracteres a serem escritos

no display, e são indicados por RS = 1. A 4 bits da via de dados são ligados aos bits 4 a 7 do LCD.

Abaixo é apresentada uma tabela resumida de códigos hexadecimais de comandos do LCD.

Page 85: Apostila PIC 16f877a

Exsto Tecnologia

85 Microcontroladores PIC16F877A

Descrição do Comando Modo RS R/W Código do Comando

(Hexadecimal)

Controle do display

Ativo (sem cusor) 0 0 0C Inativo 0 0 0A, 08

Limpeza do Display com retorno do cursor

0 0 01

Retorno do cursor à 1a linha e da mensagem à sua posição inicial

0 0 02

Controle do Cursor Ativo (ligado, fixo) 0 0 0E Inativo 0 0 0C Alternado 0 0 0F Desloc. à esquerda 0 0 10 Desloc. à direita 0 0 14 Retorno 0 0 02 Piscante 0 0 0D

Sentido de deslocamento do cursor na entrada de um novo caracter

Para esquerda 0 0 04

Para direita 0 0 06

Deslocamento da mensagem com a entrada de um novo caracter

Para esquerda 0 0 07

Para direita 0 0 05

Deslocamento da mensagem sem entrada de novos caracteres

Para esquerda 0 0 18

Para direita 0 0 1C

Endereço da primeira posição (à esquerda)

1a Linha 0 0 80

2a Linha 0 0 C0

Tabela 7.1 – Comandos do LCD

Os endereços de cada posição no display são dados pela tabela abaixo. Para que um caracter seja

escrito em uma determinada posição, envia-se o valor dessa posição como comando e em seguida

envia-se o caracter a ser escrito.

80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F

C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF

A figura 7.1 apresenta o circuito básico LCD.

Page 86: Apostila PIC 16f877a

Exsto Tecnologia

86 Microcontroladores PIC16F877A

Figura 7.1 – Esquema Básico do Display

A tabela seguinte apresenta a função de cada um dos pinos do display e em como eles estão ligados

ao PIC.

Pino Símbolo Função Ligação com o PIC

1 Vss GND -

2 Vdd +5V -

3 Vo Controle de contraste -

4 RS Seleção de modo PORTE, 0

5 R/W Leitura/Escrita 0

6 EN Habilitação PORTE, 1

7 D0 PORTD, 0

8 D1 PORTD, 1

9 D2 PORTD, 2

10 D3 Via de PORTD, 3

11 D4 Dados PORTD, 4

12 D5 PORTD, 5

13 D6 PORTD, 6

14 D7 PORTD, 7

Tabela 7.2 – Conexão do LCD

A comunicação com o display é feita conforme os algoritmos descritos baixo,apresentados em forma

de português estruturado:

Comando:

LCD_COMANDO (byte Comando)

RS Falso; // seleciona comando PORTD Comando; // bits mais significativos primeiro Atraso de 50 us; // espera 50 us EN Verdadeiro; Atraso de 50 us; // espera 50 us EN Falso; Atraso de 50 us; // espera 50 us

Page 87: Apostila PIC 16f877a

Exsto Tecnologia

87 Microcontroladores PIC16F877A

Dados:

LCD_DADO (byte Dado)

RS Verdadeiro; // seleciona dado PORTD Comando; // bits mais significativos primeiro Atraso de 50 us; // espera 50 us EN Verdadeiro; Atraso de 50 us; // espera 50 us EN Falso; Atraso de 50 us; // espera 50 us

Deverá ser criada uma função que gere um atraso de aproximadamente 50 µs.

Enquanto EN estiver em ‘0’ (‘Falso’) qualquer mudança em RS ou na via de dados é ignorada pelo

display.

Além dessas duas sub-rotinas básicas, deve-se criar também uma sub-rotina de inicialização do

display, pois esse também necessita ser configurado. Essa sub-rotina será chamada logo após a

inicialização do microcontrolador. Somente para a inicialização deve-se utilizar um atraso de 5ms na

rotina de envio de comando. Uma seqüência de inicialização básica é apresentada abaixo.

• Comando 0x33: Configura o LCD para trabalha no modo 8 bits

• Comando 0x32: Configura o LCD para trabalha no modo 8 bits

• Comando 0x38: Configura o LCD para trabalha no modo 8 bits

• Comando 0x06: Deslocamento de cursor na entrada de novos caracteres será para a direita;

• Comando 0x0C: O display está ativo

• Comando 0x01: Limpa a tela.

4.2 Teclado Uma forma muito comum de usuário de um sistema microcontrolado passar informações ao sistema

é através de teclas. Em muitas aplicações o número teclas existentes pode ser bastante grande.

Nesses casos, a leitura dessas teclas simplesmente conectando-as aos terminais do microcontrolador

incorre na utilização de muitos terminais. Nessa aplicação é apresentado um sistema de varredura

que permite fazer um uso otimizado dos terminais do microcontrolador de foram a reduzir o número

de terminais utilizados.

Para essa experiência será feito uso do teclado do kit. Esse módulo funciona implementando um

sistema de varredura que nos permite realizar a leitura de um número de teclas N utilizando menos

de N entradas. Isso é importante quando existe uma grande quantidade de teclas a serem lidas e não

se dispõe tanta entrada.

Para o caso da placa de teclado existem 16 teclas e seus estados são lidos com apenas 4 saídas e 4

entrada, num total de 8 terminais. A varredura funciona da seguinte maneira: o teclado é organizado

de forma a ter 4 colunas e 4 linhas, conforme a figura abaixo. Cada linha é ligada a uma entrada, e

cada coluna a uma saída. Existem resistores de pull-up nas entradas de forma que enquanto uma

tecla não for pressionada, a entrada ficando em aberto tem nível lógico alto. Começando a

varredura, é forçado “0” na coluna 0 (C0), “1” nas coluna 1 (C1), 2 (C2) e 3 (C3) e são lidas as quatro

linhas (L0, L1, L2 e L3). Em seguida coloca-se “1” em C0 e C2 e “0” em C1 e lêem-se as linhas, e assim

Page 88: Apostila PIC 16f877a

Exsto Tecnologia

88 Microcontroladores PIC16F877A

sucessivamente.. Nos momentos em que é feita a leitura das linhas podemos determinar se uma

tecla está pressionada e qual é essa tecla da seguinte maneira: admitindo que a tecla está ligada a

coluna que está em zero no momento a linha ligada a ela estará em também. As linhas que contém

teclas que não estão pressionadas estarão em “1”, devido aos resistores de pull-up. Seguindo esse

raciocínio podemos gerar a seguinte tabela:

C3 C2 C1 C0 L3 L2 L1 L0 Tecla

1 1 1 0 1 1 1 0 1 1 1 0 1 1 1 1 0 2 1 0 1 1 1 1 1 0 3 0 1 1 1 1 1 1 0 A 1 1 1 0 1 1 0 1 4 1 1 0 1 1 1 0 1 5 1 0 1 1 1 1 0 1 6 0 1 1 1 1 1 0 1 B 1 1 1 0 1 0 1 1 7 1 1 0 1 1 0 1 1 8 1 0 1 1 1 0 1 1 9 0 1 1 1 1 0 1 1 C 1 1 1 0 0 1 1 1 */F 1 1 0 1 0 1 1 1 0 1 0 1 1 0 1 1 1 #/E 0 1 1 1 0 1 1 1 D

Tabela 7.3 – Funcionamento do LCD

O circuito do teclado é apresentado na figura abaixo.

Figura 7.2 - Esquema Simplificado do Teclado

Page 89: Apostila PIC 16f877a

Exsto Tecnologia

89 Microcontroladores PIC16F877A

No programa que utilizar leitura de teclado deve-se ativar os resistores de pull-up do portal B. Caso

contrário, o teclado não funcionará corretamente. Isso é feito zerando o bit NOT_RBPU do registro

OPTION_REG, assim

BCF OPTION_REG, NOT_RBPU

O teclado está ligado ao PIC seguindo a tabela 7.4:

Teclado PIC I/O

C3 PORTB,0 Saída C2 PORTB,1 Saída C1 PORTB,2 Saída C0 PORTB,3 Saída L0 PORTB,4 Entrada L1 PORTB,5 Entrada L2 PORTB,6 Entrada L3 PORTB,7 Entrada

Tabela 7.4 –Conexões do teclado

4.3 Interrupções Interrupções são poderosos recursos presentes nos sistemas computacionais, que permitem

desenvolver códigos mais elaborados e profissionais, garantindo tratamento imediato a eventos de

maior prioridade.

Suponhamos uma situação em que o microcontrolador realize medidas para mostrá-las em um

display. Entre cada processo de leitura de medidas, o microcontrolador aciona uma rotina para ler o

estado de um botão, que quando acionado, seleciona a medida. Se o processo de leitura levar alguns

segundos, corre-se o risco de pressionar o botão durante esse processo de forma que o

microcontrolador não tome conhecimento deste pressionamento. O ideal é que o processo de leitura

fosse contínuo e que pudesse ser interrompido para executar a rotina referente ao acionamento do

botão quando o mesmo fosse pressionado.

Uma interrupção faz exatamente isso: interrompe a execução normal do programa para executar

tarefas de maior prioridade no momento. Ela pode ser chamada por determinados eventos, parando

a execução normal no momento em que ocorre o evento, executando o código armazenado em uma

posição de memória vinculada a interrupção e depois retornam a execução normal do programa. As

interrupções podem ser vistas como chamadas de sub-rotinas realizadas pelo hardware.

Observe que a distância entre o vetor de inicialização (0000h) e o vetor de reset (0004h) é de apenas

4 endereços. Dessa forma quando as interrupções estão desabilitadas o PC passa por 0004h

normalmente durante a execução de um programa. Quando se faz necessário o uso de interrupções,

as rotinas de tratamento de interrupção são colocadas a partir do vetor de reset 0004h. No intervalo

entre o vetor de inicialização e o vetor de reset é colocado um desvio para um endereço após as

rotinas de interrupção a partir do qual o programa realmente começa.

Quando ocorre um pedido de interrupção para a CPU do PIC16F877A, o programa é desviado para

um endereço pré-estabelecido, o vetor de reset (0004h). Desse endereço em diante é feito o

tratamento de interrupção, isto é, são executadas as rotinas que se deseja associar ao evento

causador da interrupção.

Page 90: Apostila PIC 16f877a

Exsto Tecnologia

90 Microcontroladores PIC16F877A

O PIC 16F877A possui 15 fontes de interrupções:

• Interrupção do timer 0;

• Interrupção do timer 1;

• Interrupção do timer 2;

• Interrupção externa (RB0/INT);

• Interrupção por mudança de estado (bits 4 a 7 do portal B);

• Interrupção de transmissão serial;

• Interrupção de recepção serial;

• Interrupção do módulo comparador analógico;

• Interrupção do módulo CCP1;

• Interrupção do módulo CCP2;

• Interrupção da memória EEPROM;

• Interrupção do conversor analógico para digital;

• Interrupção da porta paralela escrava;

• Interrupção da comunicação SPI;

• Interrupção por colisão no barramento I2C.

A cada interrupção são associados dois bits, para seu controle, sendo que um é o bit de habilitação,

alterado somente pelo programa, e o outro é o flag indicador de interrupção, que é setado quando

ocorre a interrupção em questão. Esse último bit pode, porém, ser alterado também pelo programa.

A Figura 2.9 mostra a lógica como se relacionam as interrupções. Existem mais dois bits envolvidos

no trabalho com interrupção, PEIE e GIE. PEIE habilita as interrupções dos periféricos. GIE, por sua

vez, realiza a habilitação global. Como pode ser notado, se GIE estiver em ‘0’ todas interrupções

estão desabilitadas; se GIE estiver em ‘1’ as interrupções que estiverem habilitadas gerarão pedidos

de interrupção à CPU.

Figura 8.1 – Lógica de Interrupções

Page 91: Apostila PIC 16f877a

Exsto Tecnologia

91 Microcontroladores PIC16F877A

Atenção: Os flags das interrupções são setados quando ocorre um evento que geraria a interrupção,

mesmo que essa interrupção não esteja habilitada.

As interrupções externas, isto é, que são causadas diretamente por eventos externos ao

microcontrolador, são a interrupção INT em RB0 e a interrupção por mudança de estado do portal B.

As demais interrupções são internas, ou seja, causadas pelos periféricos para indicar determinados

eventos (chegada de dado pelo portal serial, "estouro" de timer, etc).

Quando ocorre uma interrupção o endereço chamado é (sempre) o vetor de interrupção (0004h).

Conseqüentemente, a rotina de tratamento de interrupção deve obrigatoriamente começar nesse

endereço.

Para a determinar qual interrupção ocorreu testa-se os bits de flags de todas as interrupções ativas.

Pela ordem em que esses bits são testados pode-se atribuir a prioridade à interrupção, sendo que as

interrupções testadas em primeiro lugar têm prioridade maior.

Ao contrário de alguns microcontroladores, quando ocorre uma interrupção nenhum registro é

automaticamente salvo. Assim é importante salvar os registros W e STATUS antes que seja realizado

qualquer tratamento de interrupção, bem como qualquer outro SFR que for usado dentro e fora das

rotinas de interrupção. Esse processo é chamado salvamento de contexto. Também é recomendável

que o registro STATUS seja zerado. É necessário então que existam variáveis criadas para salvar esses

registros. Outra prática recomendada é de nunca usar dentro de uma rotina de tratamento de

interrupção registros que são utilizados em outras partes do programa. Todo esse cuidado é

necessário por que uma interrupção pode ocorrer a qualquer momento. Portanto, se durante a

execução de um trecho do programa um determinado endereço de memória (variável do programa

ou SFR) é usado, e exatamente quando esse trecho é execuatdo ocorre o pedido de interrupção que

altera o valor do registro em questão, quando retornar a execução do programa normal o valor do

registro terá sido alterado.

Um outro cuidado que deve ser tomado quando se trabalha com interrupções é não executar

rotinas muito grandes. Isso porque o tratamento de interrupção deve tomar medidas emergenciais.

Nada que não seja estritamente necessário deve ser trabalhado na interrupção, e isso principalmente

porque podem ocorrer várias interrupções em seguida, e só se pode tratar uma por vez. Quando

uma interrupção é chamada, a habilitação das demais fica desativada, e só é reativada após a

execução do RETFIE. Se outra interrupção ocorrer nesse intervalo de tempo, ela é tratada após

RETFIE. Deve-se notar que o que ativa a chamada de interrupção é a existência de um flag setado de

uma interrupção habilitada. Assim, depois de tratar uma determinada interrupção deve-se zerar o

flag associado a ela. Caso contrário, o programa fica travado, pois cada vez que há o retorno de

interrupção (instrução RETFIE), a interrupção é chamada novamente.

Finalmente, é necessário considerar que na realidade o tratamento de interrupção não ocorre no

exato momento em que a interrupção acontece. Primeiramente, a checagem dos eventos que

causam a interrupção obedece a uma varredura interna. E depois de detectado o evento, algumas

ações devem ser realizadas, como o desvio para o endereço 0004h, por exemplo. O tempo decorrido

entre a ocorrência real do evento que causa interrupção e início de seu tratamento efetivo é

chamado de latência da interrupção. Assim, após a real ocorrência de uma interrupção ela só vai

começar a ser tratada 3 ciclos de máquina após sua ocorrência, se for uma interrupção interna, e de

Page 92: Apostila PIC 16f877a

Exsto Tecnologia

92 Microcontroladores PIC16F877A

3 a 3,75 ciclos de máquina se for uma interrupção externa. Esses tempos devem ser considerados

em aplicações onde a precisão de tempo é importante.

4.3.1 Utilização das Interrupções Para trabalhar com uma interrupção deve-se primeiramente configurar o periférico associado a ela, o

que é feito normalmente uma única vez, na inicialização programa. Nada impede, porém que um

periférico seja configurado, ou re-configurado, em qualquer ponto programa.

O próximo passo é habilitar as interrupções a serem utilizadas, e isso pode ser feito em dois

momentos. Pode-se determinar que uma interrupção esteja ativa durante toda a execução do

programa, e nesse caso sua habilitação deve ser feita na inicialização. Por outro lado, em algumas

situações deseja-se que a interrupção seja ativada somente a partir de um dado momento ou ainda

que seja ativada e posteriormente desativada. Nessa situação basta habilitar, ou desabilitar, a

interrupção no momento oportuno.

É importante lembrar que as interrupções habilitadas somente causam chamadas de interrupção se

o bit de habilitação global (GIE) estiver habilitado.

Finalmente, deve-se fazer o “tratamento” de interrupção, isto é, construir as Rotinas de Tratamento

de Interrupção (RTI) que serão chamadas quando ocorrerem as interrupções habilitadas. Essas

rotinas deverão seguir as recomendações dadas acima e deve-se salvar os registros de interesse

conforme exposto.

Como para cada interrupção existe um flag que indica sua ocorrência, para se determinar qual

interrupção basta testar os flags das interrupções habilitadas e tratar a que ocorreu. Somente uma

interrupção pode ser tratada por vez e enquanto uma interrupção é tratada (intervalo que vai desde

sua chamada até o retorno realizado pela interrupção RETFIE) não ocorre outra chamada. Isso

porque quando uma interrupção é chamada, automaticamente GIE é zerado, só sendo setado

novamente pela instrução RETFIE. Os pedidos de interrupção que porventura ocorram nesse

intervalo não são descartados, visto que quando GIE volta a ‘1’ e existe algum flag de interrupção

habilitada também em ‘1’ imediatamente o processo de tratamento de interrupção recomeça e será

repetido até que todas as interrupções pendentes sejam tratadas.

Os bits de habilitação das interrupções e respectivos flags, além de GIE e PEIE encontram-se em

quatro registros, apresentados abaixo.

INTCON (presente em todos os bancos)

Contém o controle das interrupções do timer 0, mudança de estado do portal B e a interrupção

externa INT, o controle de interrupção de periféricos e o controle geral de interrupções. Os flags

indicadores de interrupção devem ser zerados por software. Pode ser lido ou escrito.

GIE: Habilitação global das interrupções o 1 = interrupções habilitadas

R/W – 0 R/W – 0 R/W– 0 R/W – 0 R/W – x R/W – 0 R/W – 0 R/W – 0

Bit 7 Bit 0

GIE PEIE T0IE INTE RBIE T0IF INTF RBIF

INTCON

Page 93: Apostila PIC 16f877a

Exsto Tecnologia

93 Microcontroladores PIC16F877A

o 0 = interrupções desabilitadas PEIE: Habilitação das interrupções de periféricos

o 1 = interrupções de periféricos habilitadas o 0 = interrupções de periféricos desabilitadas

T0IE: Interrupção do timer 0 (por overflow) o 1 = interrupção habilitada o 0 = interrupção desabilitada

INTE: Interrupção RB0/INT o 1 = interrupção habilitada o 0 = interrupção desabilitada

RBIE: Interrupção por mudança de estado no portal B o 1 = interrupção habilitada o 0 = interrupção desabilitada

T0IF: flag da interrupção do timer 0 o 1 = ocorreu overflow de timer 0 o 0 = não ocorreu overflow de timer 0

INTF: flag da interrupção INT o 1 = ocorreu interrupção externa o 0 = não ocorreu interrupção externa

RBIF: flag da interrupção por mudança de estado no portal B o 1 = pelo menos um dos bits RB4~RB7 mudou o 0 = nenhum dos bits RB4~RB7 mudou

PIE1 (Banco 1)

Contém bits de habilitação de interrupções de periféricos. Essas interrupções só ocasionam chamada

se PEIE estiver em ‘1’.

EEIE: Interrupção de operação de escrita na EEPROM

o 1 = interrupção habilitada o 0 = interrupção desabilitada

CMIE: Interrupção do módulo comparador analógico o 1 = interrupção habilitada o 0 = interrupção desabilitada

RCIE: Interrupção de recepção da USART o 1 = interrupção habilitada o 0 = interrupção desabilitada

TXIE: Interrupção de transmissão da USART o 1 = interrupção habilitada o 0 = interrupção desabilitada

CCP1IE: Interrupção do CCP1 o 1 = interrupção habilitada o 0 = interrupção desabilitada

TMR2IE: Interrupção do Timer 2 o 1 = interrupção habilitada o 0 = interrupção desabilitada

TMR1IE: Interrupção do Timer 1

R/W – 0 R/W – 0 R/W– 0 R/W – 0 R/W – 0 R/W – 0 R/W – 0 R/W – 0

Bit 7 Bit 0

PSPIE ADIE RCIE TXIE SSPIE CCP1IE TMR2IE TMR1IE

PIE1

Page 94: Apostila PIC 16f877a

Exsto Tecnologia

94 Microcontroladores PIC16F877A

o 1 = interrupção habilitada o 0 = interrupção desabilitada

PIR1 (Banco 0)

Contém flags das interrupções de periféricos.

EEIE: Flag de operação de escrita na EEPROM o 1 = operação de escrita completa o 0 = operação de escrita incompleta ou não iniciada

CMIF: Flag do módulo comparador analógico o 1 = houve mudança no estado das saída dos comparadores o 0 = não houve mudança no estado das saída dos comparadores

RCIF: Interrupção de recepção da USART o 1 = o buffer de recepção está cheio o 0 = o buffer de recepção está vazio

TXIF: Interrupção de transmissão da USART o 1 = o buffer de recepção está vazio o 0 = o buffer de recepção está cheio

CCPIF Flag do CCP1 o Modo Captura

1 = ocorreu a captura do registro TMR1 0 = não ocorreu a captura do registro TMR1

o Modo Comparador 1 = ocorreu uma comparação de igualdade com TMR1 0 = não ocorreu uma comparação de igualdade com TMR1

o Modo PWM Não utilizado

TMR2IF: Flag de igualdade entre PR2 e TMR 2 o 1 = ocorreu igualdade entre PR2 e TMR2 o 0 = interrupção desabilitada

TMR1IF : Flag de overflow de Timer 1 o 1 = ocorreu overflow de TMR1 o 0 = não ocorreu overflow de TMR1

PIE2 (Banco 1)

Contém bits de habilitação de interrupções de periféricos. Essas interrupções só ocasionam chamada

se PEIE estiver em ‘1’.

R/W – 0 R/W – 0 R/W– 0 R/W – 0 R/W – 0 U – 0 R/W – 0 R/W – 0

Bit 7 Bit 0

EEIF CMIF RCIF TXIF - CCP1IF TMR2IF TMR1IF

PIR1

R/W – 0 R/W – 0 R/W– 0 R/W – 0 R/W – 0 R/W – 0 R/W – 0 R/W – 0

Bit 7 Bit 0

- CMIE - EEIE BCLIE - - CCP2IE

PIE1

Page 95: Apostila PIC 16f877a

Exsto Tecnologia

95 Microcontroladores PIC16F877A

CMIE: Interrupção do módulo comparador analógico o 1 = interrupção habilitada o 0 = interrupção desabilitada

EEIE: Interrupção de escrita na EEPROM o 1 = interrupção habilitada o 0 = interrupção desabilitada

BCLIE: Interrupção de colisão no barramento I2C o 1 = interrupção habilitada o 0 = interrupção desabilitada

CCP2IE: Interrupção do CCP2 o 1 = interrupção habilitada o 0 = interrupção desabilitada

PIR2 (Banco 0)

Contém flags das interrupções de periféricos.

CMIF: Flag do módulo comparador analógico o 1 = houve mudança no estado das saída dos comparadores o 0 = não houve mudança no estado das saída dos comparadores

EEIF: Flag de operação de escrita na EEPROM o 1 = operação de escrita completa o 0 = operação de escrita incompleta ou não iniciada

BCLIE: Flag de colisão no barramento I2C o 1 = ocorreu uma colisão no barramento I2C (estando o módulo SSP configurado

no modo I2C Master) o 0 = não ocorreu uma colisão no barramento I2C

CCPIF Flag do CCP1 o Modo Captura

1 = ocorreu a captura do registro TMR1 0 = não ocorreu a captura do registro TMR1

o Modo Comparador 1 = ocorreu uma comparação de igualdade com TMR1 0 = não ocorreu uma comparação de igualdade com TMR1

o Modo PWM Não utilizado

O trecho de código abaixo trata salvamento de contextos e pode ser utilizado como base para rotinas

de tratamento de interrupção.

; Definição das variáveis para salvamento CBLOCK 20h INT_W INT_STATUS INT_FSR ENDC ... ; Tratamento de interrupção org 0004H ; Vetor de interrupção

R/W – 0 R/W – 0 R/W– 0 R/W – 0 R/W – 0 U – 0 R/W – 0 R/W – 0

Bit 7 Bit 0

- CMIF - EEIF BCLIF - - CCP2IF

PIR1

Page 96: Apostila PIC 16f877a

Exsto Tecnologia

96 Microcontroladores PIC16F877A

MOVWF INT_W ; salva W em INT_W MOVFW STATUS ; \ MOVWF INT_STATUS ; > salva STATUS em INT_STATUS CLRF STATUS ; zera STATUS MOVFW FSR ; \ MOVWF INT_FSR ; > salva FSR em INT_FSR ; \ ; > tratamento das interrupções ; / MOVFW INT_STATUS ; \ MOVWF STATUS ; > recupera STATUS MOVFW INT_FSR ; \ MOVWF FSR ; > recupera FSR MOVFW INT_W ; recupera W RETFIE ; retorno de interrupção

4.3.2 Interrupção externa em RB0 Das duas interrupções que são acionadas diretamente por elementos externos ao microcontrolador,

a primeira que será estudada é chamada simplesmente de INT e é multiplexada com o bit 0 do portal

B. Essa interrupção destina-se a ser usada para a chamadas de interrupções provenientes das

diversas partes do circuito. Quando existem várias fontes de interrupção deve-se montar uma lógica

externa, de forma a fazer uma operação OU entre todas as fontes de interrupção com uma única

saída ligada a INT.

A interrupção ocorre na mudança de estado lógico no terminal PORTB,0. Isto significa que não é um

determinado estado lógico (‘0’ ou ‘1’) que causa a chamada da interrupção; o flag que indica a

interrupção INT (o bit INTF do registro INTCON) não é uma “cópia” do estado de RB0. A interrupção

pode ser configurada para “disparar” na transição de subida (0 para 1) ou decida (1 para 0). Isso é

feito configurando o bit INTEDG de OPTION_REG conforme mostrado abaixo.

INTEDG = 0 : transição de descida

INTEDG = 1 : transição de subida

A habilitação da interrupção INT é feita setando o bit INTE de INTCON. O bit de habilitação global das

interrupções, GIE de INTCON, também deve ser setado. Da mesma forma que a interrupção por

mudança de estado, INT pode tirar o processador do modo SLEEP.

4.3.3 Interrupção por mudança no portal B Outra interrupção externa existente no microcontrolador é a interrupção por mudança na porta B.

Essa interrupção é chamada toda vez que ocorre uma mudança (seja ela qual for) nos bits 4, 5, 6 e 7

do portal B. Essa interrupção pode ser utilizada da mesma maneira que a interrupção INT, com a

limitação de que a interrupção irá ocorrer toda vez que acontecer uma transição de alto para baixo

ou de baixo para alto em algum pino. Outra possibilidade de uso da interrupção por mudança de

estado no portal B é em conjunto com teclados matriciais. O teclado do kit, conforme estudado, tem

suas linhas conectadas aos pinos do portal B associados à interrupção. Dessa forma, quando uma

tecla é pressionada ocorre uma chamada de interrupção, bastando para isso apenas que as colunas

do teclado estejam todas em nível lógico baixo. Dentro da rotina de tratamento de interrupção pode-

Page 97: Apostila PIC 16f877a

Exsto Tecnologia

97 Microcontroladores PIC16F877A

se executar a rotina de leitura do teclado, identificando a tecla lida e retornando as colunas a nível

lógico baixo.

Esse funcionamento é bastante útil em sistema que ficam muito tempo ociosos. Nesses casos é

possível colocar o microcontrolador em modo de baixo consumo e “acorda-lo” somente quando uma

tecla for pressionada, num processo parecido ao utilizado em celulares.

Page 98: Apostila PIC 16f877a

Exsto Tecnologia

98 Microcontroladores PIC16F877A

5 PERIFÉRICOS DO PIC16F877A

5.1 Timers Um dos periféricos mais comuns em qualquer linha de microcontroladores é Timer/Couter –

Temporizador/ Contador.

Trata-se de nada mais, nada a menos, que um componente contador dentro do microcontrolador. Se

atuar fazendo contagem de eventos externos, aleatórios, é dito no modo contador (Counter). Se o

evento que causa a contagem for um sinal periódico de freqüência conhecida, gerado dentro ou fora

do microcontrolador, é dito no modo temporizador (timer).

O PIC16F877A possui três timer´s: timer 0, Timer 1 e Timer 2. A operação dos três é bastante

semelhante, bastando estudar apenas um (no caso o Timer 1) para se estar habilitado a trabalhar

com os outros dois.

5.1.1 Timer 1 O Timer 1 é um temporizador/contador (timer/counter) de 16 bits. O sinal de clock pode ser

selecionado como interno ou externo. Caso seja usada a fonte de clock interna, o sinal será o do

clock de periféricos, que corresponde à freqüência do oscilador dividida por 4. No caso kit, que utiliza

um cristal de 4MHz, trata-se de um sinal com período de 1 microssegundo. Já no caso de sinal de

clock externo, o sinal deve ser aplicado ao terminal RC0. Quando se utiliza fonte de clock externo é

possível selecionar em qual transição (subida ou descida) o timer incrementa. Existem ainda uma

interrupção no overflow do timer e uma pré-escala programável que permite dividir a freqüência do

sinal de clock até por 8.

A figura 9.1 apresenta o diagrama elétrico simplificado do timer 1. O contador propriamente dito é

composto pelo par de registros TMR1H e TMR1L. Quando ocorre o overflow desse timer o flag

TMR1IF é setado, podendo ocasionar uma interrupção. Para economia de energia o timer pode ser

desabilitado através do bit TMR1ON, que inibe os pulsos de clock para o timer. O sinal de clock, caso

seja externo, pode ser sincronizado ou não com o clock interno; essa escolha é feita através do bit

T1SYNC. A pré-escala permite dividir a freqüência do sinal de clock por 1, 2, 4 ou 8. Através do bit

TMR1CS seleciona-se se a fonte de clock é interna ou externa. Sendo externo, o clock pode ser

gerado por qualquer circuito conectado a RC0 ou por um oscilador próprio do timer, que é ativado

por T1OSCEN. Esse oscilador permite colocar um cristal (tipicamente de 32.768 Hz) entre RC0 e RC1,

e que pode operar quando o microcontrolador estiver em SLEEP, ou seja, com o oscilador principal

desligado.

Page 99: Apostila PIC 16f877a

Exsto Tecnologia

99 Microcontroladores PIC16F877A

Figura 9.1 – Diagrama em blocos do Timer 1

O registro para controle do timer é chamado T1CON, detalhado abaixo.

T1CKPS1: T1CKPS0: seleção da taxa de divisão da pré-escala (tabela 18.4). T1OSCEN: Controle do oscilador do Timer 1

o 1 = oscilador ligado o 0 = oscilador desligado

T1SYNC: Controle de sincronismo de sinal de clock externo o Se TMR1CS = 1

1 = modo assíncrono 0 = modo síncrono

o Se TMR1CS = 0 Esse bit é irrelevante

TMR1CS: seleção de fonte de clock o 1 = Clock externo no terminal RB6/T1CKI (transição de subida) o 0 = Clock de periféricos interno (Fosc/4)

TMR1ON: habilitação do Timer 1 o 1 = timer ligado o 0 = timer desligado

A pré-escala do timer 1 permite a seleção de 4 fatores de divisão, através do bits T1CKPS1 e T1CKPS0,

conforme mostrado na tabela 9.1.

Valor Taxa de divisão

T1CKPS1 T1CKPS0

0 0 1:1

0 1 1:2

1 0 1:4

1 1 1:8

Tabela 9.1 – Pré-escala do timer 1

U – 0 U – 0 R/W– 0 R/W – 0 R/W – 0 R/W – 0 R/W – 0 R/W – 0

Bit 7 Bit 0

- - T1CKPS1 T1CKPS0 T1OSCEN T1SYNC TMR1CS TMR1ON

T1CON

Page 100: Apostila PIC 16f877a

Exsto Tecnologia

100 Microcontroladores PIC16F877A

Há também o bit TMR1ON, que permite desligar todo o timer 1 quando este não for usado,

reduzindo assim o consumo de energia. Ele também pode ser utilizado para parar o timer em

algumas situações que trataremos mais adiante.

O timer 1 tem três modos de operação:

temporizador contador

o síncrono o assíncrono

No modo temporizador, o sinal de clock utilizado é o clock de periférico (TMR1CS = ‘0’). Nesse caso,

seu funcionamento é bem semelhante ao do timer 0, porém realizando contagens de 0000h á FFFFh

(16 bits), além da pré-escala.

O modo contador, por sua vez, utiliza como fonte de clock o sinal aplicado ao terminal RB6. O timer é

incrementado a cada transição de subida nesse pino. Podemos trabalhar no modo síncrono ou

assíncrono. A seleção de modo é feita pelo bit T1SYNC, sendo que ‘0’ indica modo síncrono e ‘1’

modo assíncrono.

No modo síncrono o sinal de clock é amostrado duas vezes a cada ciclo de instrução. Se a taxa de

divisão do pré-escala for 1, significa que o sinal de entrada é aplicado diretamente ao circuito de

sincronismo. Nestas condições, o sinal aplicado deve ter tempos em alto e em baixo de no mínimo 2

ciclos de instrução mais 20 ns. Por outro lado, se o valor da pré-escala for diferente de 1, os tempos

mínimo de alto e baixo são de 10 ns e o período mínimo depende do fator de divisão, conforme é

mostrado na tabela 9.4. Como o modo síncrono depende do sinal de clock, se o microcontrolador for

colocado em modo SLEEP (baixo consumo) o timer para de funcionar.

No modo assíncrono, o contador trabalha de forma completamente independente do clock do

microcontrolador. Essa configuração pode ser utilizada no modo SLEEP, inclusive podendo acionar a

interrupção, fazendo o microcontrolador sair do modo de baixo consumo. Nesse modo, os tempos

mínimos em alto e em baixo são de 30ns e o período mínimo é de 60ns, com ou sem pré escala.

A tabela 9.2 resume os limites de operação do timer 1 nos vários modos.

Parâmetro Condição Valor mínimo Unidade

Largura de pulso (alto e baixo)

Síncrono Sem pré-escala 205,0 +CYT ns

Síncrono Com pré-escala 15 ns

Assíncrono 30 ns

Período

Síncrono. N é o fator da pré-escala. Sem pré-escala, N é 1. N

TCY 40+

ns

Assíncrono 60 ns

Tabela 9.2 – Requisitos mínimos para o timer 1

Novamente devemos tomar cuidados contra bouncing quando a fonte do sinal de contagem for

mecânica.

Page 101: Apostila PIC 16f877a

Exsto Tecnologia

101 Microcontroladores PIC16F877A

5.1.2 Oscilador do timer 1 O timer 1 foi equipado com um circuito oscilador próprio, que nos permite ligar um cristal entre

pinos RC0 e RC1, para gerar uma base de tempo independente do clock do microcontrolador. A

principal função dessa característica é implementar um relógio de tempo real. Tanto que esse

oscilador foi desenvolvido para trabalhar com um cristal de 32.768 Hz. Esse valor é exatamente 215.

Dessa forma podemos gerar uma interrupção a cada segundo, carregando o valor inicial de 32768

(8000h) nos registros do timer ou utilizando o módulo CCP do modo de comparação. Esse oscilador

pode operar durante o modo SLEEP, podendo ser usado para despertar o microcontrolador

periodicamente.

Além do cristal 32.768 Hz são necessários dois capacitores de 15pF dos terminais do cristal a terra.

Para ativar o oscilador, o bit T1OSCEN deve ser setado. Quando isso ocorre, os pinos RC0 E RC1

deixam de trabalhar como I/O e seus estados no PORTB ficam irrelevantes.

5.1.3 Interrupção O bit de habilitação da interrupção do timer é o TMR1IE do registro PIE1. O bit indicador de overflow

do timer é TMR1IF de PIR1.

5.2 Módulo CCP No PIC16F877A existem dois módulos CCP, chamados CCP1 e CCP2. Aqui será tratado o CCP1, mas

todo o raciocínio é válido para CCP2. O módulo CCP (Captura, Comparação e PWM) permite realizar

uma série de funções por hardware. Para exemplificar a versatilidade desse periférico, podemos citar

como exemplos de sua utilização: geração de sinais de PWM, geração de sinais analógicos, medida

de freqüência, medida de largura de pulso, dentre várias.

Existem três modos de operação:

• Captura

• Comparação

• PWM (Modulação por largura de pulso) Esse periférico é controlado por dois registros que operam conjuntamente como um parâmetro de

16 bits (CCP1H e CCP1L) e um registro de controle (CCP1CON). Além disso, nos modos de captura e

comparação é usado e no modo PWM o timer 2 fornece a base de tempo.

Por fim, existe uma interrupção associada ao módulo CCP, que é disparada em situações diferentes

para cada modo.

Os bits CCP1X e CCP1Y são utilizados somente no modo PWM. Os demais bits implementados servem

para seleção de modos de operação, conforme é apresentado na tabela 10.1. Deve-se observar que

após o reset, o módulo CCP fica desativado.

Valor Modo

U – 0 U – 0 R/W– 0 R/W – 0 R/W – 0 R/W – 0 R/W – 0 R/W – 0

Bit 7 Bit 0

- - CCP1X CCP1Y CCP1M3 CCP1M2 CCP1M1 CCP1M0

CCP1CON

Page 102: Apostila PIC 16f877a

Exsto Tecnologia

102 Microcontroladores PIC16F877A

CCP1M3 CCP1M2 CCP1M1 CCP1M0 0 0 0 0 Módulo CCP desligado 0 1 0 0 Captura Transição de descida

0 1 0 1 Transição de subida

0 1 1 0 4 transições de subida

0 1 1 1 16 transições de subida

1 0 0 0 Comparação Pino de saída em ‘1’ na coincidência

1 0 0 1 Pino de saída em ‘0’ na coincidência

1 0 1 0 Somente seta flag de interrupção

1 0 1 1 Reset timer (Special trigger)

1 1 x x PWM

Tabela 10.1 – Modos de operação do módulo CCP

5.2.1 Modo captura No modo captura, o valor do timer 1(TMR1H:TMR1L) é armazenado nos registros CCP1H:CCP1L

quando ocorre um “evento”. Além disso, o flag CCP1IF é setado, permitindo acionar a interrupção.

Esse evento, que é configurado conforme a tabela 10.1 pode ser a ocorrência de :

• 1 transição de descida no terminal RB3/CCP1

• 1 transição de subida no terminal RB3/CCP1

• 4 transições de subida no terminal RB3/CCP1

• 16 transições de subida no terminal RB3/CCP1

Para operação nesse modo, o terminal RB3/CCP1 deve estar configurado como entrada e o timer

deve estar no modo temporizador ou no modo contador síncrono.

O modo captura pode ser utilizado para determinar a diferença de tempo entre dois eventos. Isso

pode ser feito de duas formas. No primeiro evento, o timer é resetado e no segundo, o valor

capturado do timer 1 multiplicado pelo período do seu clock corresponde ao tempo transcorrido

entre os dois eventos. Outra forma é deixar o timer 1 incrementado livremente e capturar seu valor

nos dois eventos. Fazendo uma subtração entre os dois valores capturados, temos o tempo entre os

eventos. Esse procedimento pode ser utilizado para medir velocidade e freqüências (nesse caso

temos o período e sabemos que f = 1/T).

Os modos onde o evento de captura é a ocorrência de 4 ou 16 transições podem ser vistos como

tendo uma pré-escala na entrada. Essa pré-escala pode ser útil para trabalhar com sinais de

freqüências altas, como será mostrado. Sua contagem só pode ser zerada com a mudança de modo

do CCP.

A figura 10.1 apresenta o diagrama em blocos para o modo de captura.

Page 103: Apostila PIC 16f877a

Exsto Tecnologia

103 Microcontroladores PIC16F877A

Figura 10.1 – Diagrama do modo captura

Durante o modo SLEEP, se ocorrer um evento, o flag é setado, mas o valor de Timer 1 não é

capturado, pois o timer 1 (como temporizador ou contador síncrono) não opera durante o SLEEP. No

reset, zera a pré-escala.

5.2.2 Modo comparação

Nesse modo, o par de registros do módulo CCP (CCP1H:CCP1L) é constantemente comparado com o

par de registros do timer 1 (TMR1h:TMR1L). Quando eles coincidem, é setado o flag CCP1IF. Além

disso, podemos zerar o timer 1 ou forçar um estado no pino RB3/CCP1. Quando optamos por zerar o

timer 1, o funcionamento é muito parecido com o do timer 2 em relação ao registro PR2. Quando se

seleciona os modos que forçam estados (‘1’ ou ‘0’) no pino RB3/CCP1, o pino fica no estado oposto

ao desejado até que ocorra a coincidência. Nesse caso, o pino deve ser configurado como saída.

A figura 10.2 apresenta o diagrama do modo comparação.

Figura 10.2 – Diagrama do modo comparação

5.2.3 Modo PWM O módulo PWM permite utilizar sinais modulados em largura de pulso (PWM – Pulse Width

Modulation), que consiste em representar um valor pelo duty-cicle (tempo em alto) de um trem de

Page 104: Apostila PIC 16f877a

Exsto Tecnologia

104 Microcontroladores PIC16F877A

pulsos de freqüência fixa. Por exemplo, admitindo que estamos trabalhando com o PWM do PIC, sua resolução máxima é de 10 bits, ou seja, 1023 corresponde a 100% de duty-cicle. Usando uma regra de três simples, podemos determinar a quanto que corresponde 30%, 25%, 99%, etc. É chamada de modulação porque permite carregar uma informação (expressa no duty-cicle) em uma portadora (trem de pulsos). A maior parte das aplicações de PWM para microcontroladores se aproveita da propriedade da energia de um sinal retangular ser proporcional ao seu duty-cicle (a energia de um sinal está relacionada com a área entre o sinal e o eixo do tempo). Vamos imaginar que um sinal PWM é aplicado a uma lâmpada DC. Um duty-cicle de 100% (sinal sempre em ‘1’) fará a lâmpada acender em sua potência máxima; já um sinal com 70% de tempo em alto entrega a lâmpada 70% da potência máxima, e assim por diante. Essa propriedade é utilizada no acionamento de cargas DC, controle de motores, etc. Outra característica importante do PWM é que, se o sinal for filtrado, podemos obter níveis analógicos, também proporcionais ao duty-cicle. Isso permite que geremos desde níveis analógicos fixos até sinais mais complexos, como tons DTMF (de telefonia). O PWM precisa de uma base de tempo que dará a freqüência do sinal. O módulo CCP utiliza o Timer 2 para conseguir essa base. Isso pode ser observado no diagrame em blocos do PWM, na figura 10.3. Também é necessário que o pino RB3/CCP1 seja configurado como saída.

Figura 10.3 – Diagrama em blocos no modo PWM

A geração do sinal PWM se dá da seguinte maneira. Cada vez que TMR2 coincide com PR2, o pino

RB3/CCP1 é setado e TMR2 é resetado. Isso nos dá a freqüência do sinal. O duty-cicle é conseguido

comparando o CCPR1H concatenado com dois bits de latch com TMR2 concatenado com mais dois

bits, da pré-escala ou gerados pelos ciclos Q; Quando há a coincidência, o pino RB3/CCP1 é zerado.

As concatenações nos dão 10 bits de resolução. Esse processo pode ser observado na figura 10.4.

O registro CCPR1H não é acessível para leitura no modo PWM. O duty-cicle é configurado através de

CCP1L e dos bits 4 e 5 de CCP1CON. Esse valor é atualizado em CCPR1H e nos bits de latch a cada

período.

Page 105: Apostila PIC 16f877a

Exsto Tecnologia

105 Microcontroladores PIC16F877A

Figura 10.4 – Sinal PWM

Configurar o PWM é estabelecer sua freqüência e seu duty-cicle. De posse desses dois parâmetros,

podemos calcular os valores em cada registro.

O período é o inverso da freqüência e é configurado através de PR2 e da pré-escala do TMR2 e pode

ser calculado através da equação 10.1.

)2(4)12( PSTMRTPRT OSCPWM ×××+= (10.1)

Onde:

TPWM : período do PWM

TOSC: período do oscilador

TMR2PS: fator de pré-escala do timer 2

Para encontrar o valor de PR2 a partir de um dado valor de período pode ser usada a equação 10.2.

Valor de PR2 deve ser inteiro e menor que 256. Logo, em alguns casos será necessário arredondar

esse valor, o que gerará um pequeno erro entre a freqüência desejada e a real. Com valores

diferentes de pré-escala podemos chegar a valores menores que 256 e a aproximações que levem a

um erro menor.

124

2 −××

=PSTMRT

TPR

OSC

PWM (10.2)

O duty-cicle por sua vez é configurado através de CCPR1L e dos bits 4 e 5 de CCP1CON. Geralmente

se especifica o duty-cicle em porcentagem do tempo total. Assim, dado um duty-cicle em

porcentagem (DC%), o tempo correspondente a ele é encontrado pela equação 10.3

100%DCTT PWMDC ×=

(10.3)

Esse tempo também pode ser calculado pela equação 10.4.

PSTMRTDCT OSCDC 2]0:9[ ××= (10.4)

Onde:

Page 106: Apostila PIC 16f877a

Exsto Tecnologia

106 Microcontroladores PIC16F877A

TPWM : período do PWM

TOSC: período do oscilador

TMR2PS: fator de pré-escala do timer 2

DC[9:0] : é um valor de 10 bits obtido acrescentando os bit 5 e 4 a esquerda de CCP1RL

Dispondo do tempo do duty-cicle, o valor de DC[9:0] é dado pela equação 10.5. Esse valor deve ser inteiro e menor que 1023. O valor da pré-escala deve ser o mesmo utilizado para a determinação do período.

PSTMRT

TDC

OSC

DC

2]0:9[

×=

(10.5)

O período (e conseqüentemente a freqüência) é dado pelo registro PR2. Para freqüências altas

(períodos pequenos) existe uma perda da resolução, isto é, na verdade trabalhamos com menos de

10 bits. Por exemplo, se o valor usado para PR2 for 63, os dois bits mais significativos são “perdidos”

e 100% de duty-cicle corresponderá á 255. Teremos um PWM de 8 bits. A resolução, dada em bits,

para uma dada freqüência de PWM é dada pela equação 10.6.

)2log(

)log(PWM

OSC

F

F

RESOLUÇÃO= (10.6)

5.2.4 Interrupção O bit de habilitação de interrupção é CCP1IE em PIE1. O flag de interrupção é CCP1IF em PIR1.

O evento que dispara a interrupção depende do modo de trabalho. Assim a interrupção significa:

• Modo Captura: a ocorrência de uma captura

• Modo Comparação: coincidência entre TMR1H:TMR1L e CCPR1H:CCP1L Modo PWM: não há interrupção associada a esse modo.

5.3 Comunicação Serial A comunicação entre circuitos eletrônicos digitais pode ser feita basicamente de duas maneiras: de

forma paralela ou serial.

5.3.1 Comunicação Paralela No envio de dados de forma paralela todos os bits que compõe uma palavra são transmitidos ao

mesmo tempo e por diferentes condutores. O exemplo clássico são os barramentos dos PC´s,

facilmente reconhecíveis pelas diversas trilhas que correm paralelas na placa de circuito impresso.

Esse tipo de condução exige pouco ou nenhum preparo para o envio, visto que os dados são tratados

dentro do processador de forma paralela. Outra característica dessa forma de comunicação é a

velocidade. Como a informação toda é enviada de uma só vez, a transferência de informações ocorre

em tempo mínimo.

Page 107: Apostila PIC 16f877a

Exsto Tecnologia

107 Microcontroladores PIC16F877A

As limitações dessa técnica surgem quando as distâncias entre os pontos que se deseja comunicar

aumentam. Em primeiro lugar para interconexão de equipamentos em distâncias grandes o uso de

comunicação paralela exige conectores de muitos pinos e cabos de várias vias.Como pode ser

intuído, o custo dos cabos e conectores é proporcional ao número de vias do cabo.

Além do custo dos cabos outro impedimento para a comunicação paralela são os efeitos reativos

(capacitivos e indutivos) dos meios de comunicação paralela (sejam eles cabos ou trilhas numa

placa). Em altas taxas de transmissão devemos considerar os condutores a luz da teoria de guias de

ondas, que de forma resumida nos diz que em altas freqüências um fio ou uma trilha não devem ser

encarados como um curto-circuito, mas como uma associação de resistências, capacitâncias e

indutâncias. Em virtude disso os sinais podem se degradas por interferência mútua e também, pelas

próprias características do meio. Outro ponto importante é o ruído (interferência) inserido nos

condutores e proveniente do onde eles estão. Novamente o maior número de condutores agrava a

situação. Esses fatos são inerentes a qualquer linha de transmissão de sinais elétricos, mas o agrava

os problemas na comunicação paralela é que cada linha de transmissão é um meio diferente das

demais, ou seja, cada bit é degradado de forma diferente. Isso pode acarretar problemas na

comunicação de dados a distâncias longas (o critério para dizer se uma distância é “grande” é sua

comparação com o comprimento de onda do sinal que se transmite), limitando assim a comunicação

a pequenas distâncias em alta velocidade (por exemplo, barramentos do PC) ou a distâncias maiores

com baixa taxa de transmissão (por exemplo, comunicação entre PC e impressora).

5.3.2 Comunicação serial A forma encontrada para solucionar os problemas apresentados pela comunicação paralela a foi

transmitir os bits de forma serial, ou seja, um bit de cada vez.

Quanto ao quesito custo essa forma de transmissão é bastante eficiente, porque em sua forma mais

simples pode ser implementada com apenas dois condutores, um para envio de dados e outro de

referência.

A comunicação serial também traz vantagens no aumento das taxas e das distâncias de comunicação.

Técnicas para a redução de ruído e degradação do sinal podem ser aplicadas mais facilmente quando

a informação transita por um único caminho. Além disso, não há problemas em os bits serem

afetados de forma diferente, pois são tratados separadamente.

Em contrapartida, a comunicação serial demanda um circuito mais complexo, uma vez que a

informação que é tratada de forma paralela pelo processador deve ser convertida para o formato

paralelo. Pelo mesmo motivo, a transmissão é mais lenta que a paralela (observando apenas o tempo

do envio de uma informação). O principal problema a ser resolvido na comunicação serial, porém, é

saber quando um bit termina e quando começa o próximo. E ainda, os cabos não deixam de ser guias

de ondas, apresentando os problemas discutidos acima e mantendo sempre uma relação de

compromisso entre o comprimento dos cabos e a taxa transmissão máxima.

Por todas essas razões a quase totalidade das conexões entre equipamentos é feita por comunicação

serial. Entre as formas de comunicação serial mais difundida podemos citar o EIA-232, EIA-485, o USB

e mesmo as LAN´s Ethernet.

A comunicação serial pode se dar de duas maneiras principais, a síncrona e assíncrona, que diferem

na forma de localizar cada bit em uma “rajada”.

Page 108: Apostila PIC 16f877a

Exsto Tecnologia

108 Microcontroladores PIC16F877A

Como o próprio nome diz, na comunicação serial síncrona existe um sincronismo, nesse caso entre o

sinal transmitido e um clock enviado juntamente. O clock permite determinar o exato momento em

que o bit do sinal deve ser lido, evitando assim erros na recepção e a correta montagem do dado na

forma paralela. Entres as formas de comunicação serial síncrona podemos citar o I2C e o SPI, que não

serão tratados aqui.

Já na comunicação assíncrona nenhuma referencia de onde o bit deve ser lido é enviado com o sinal.

A solução nesse caso é “adivinhar” o momento certo de ler o bit. Para isso é necessário que o

receptor saiba a taxa e transmissão, e portanto a duração de cada bit, e que o transmissor indique de

alguma forma onde começa e onde termina a transmissão. Dessa maneira, o receptor aguarda a

chegada da indicação de início, chamado start bit ou bit de início e quando esse é lido ele sabe que a

cada intervalo de tempo, chamado tempo de bit (tB) um bit novo está presente na via de

comunicação. Para minimizar o risco de erro a leitura é feita na metade da duração do bit ou são

feitas algumas amostras durante esse intervalo de tempo.

Aparentemente, se procedermos dessa forma, bastaria enviar um start bit e para sincronizar

receptor e transmissor e depois poderia vir uma seqüência infinita de bits. Na verdade, porém, isso

não ocorre, pois sempre existira uma pequena diferença entre as bases de tempo de TX e RX. Como

uma amostra ocorre tB após a anterior, se esse tempo estiver errado, o erro vais se acumulando até

que se perca o sincronismo. Por exemplo, se o relógio de RX for 5% mais lento ou mais rápido que o

de TX a cada 20 bits recebido o sincronismo será perdido. Na prática os dados são enviados em

“pacotes” de alguns bits, iniciados por um start bit e terminados por um stop bit. O stop bit tem a

função de marcar o fim do pacote, para que um bit de informação não seja confundido com um novo

start bit.

O formato genérico de um “pacote” de comunicação serial é apresentado na figura abaixo.

Figura 11.1 – Transmissão serial genérica

Dos diversos padrões de comunicação serial assíncrona, dois são de especial interesse por sua ampla

utilização nas aplicações de microcontroladores. São eles o EIA-232C e o EIA-485

Tempo ocioso

(opcional)

1, 1 ½ ou 2 stop bits

Bit de paridade (opcional)

5 a 9 bits de dados

1 start bit

Page 109: Apostila PIC 16f877a

Exsto Tecnologia

109 Microcontroladores PIC16F877A

5.3.3 EIA-232C Popularmente conhecido como RS-232, esse protocolo foi inicialmente desenvolvido para permitir a

comunicação entre computadores e modens, para transmissão de dados a longa distância. A norma

que rege o protocolo é a TIA/EIA-232, cuja revisão C é a mais recente (1969).

Devido a sua aplicação inicial como protocolo de comunicação entre um terminal de computador e

um equipamento de comunicação, o protocolo estabelece os conceitos de DTE (Data Terminal

Equipament – Equipamento Terminal de Dados) e DCE (Data Communication Equipament –

Equipamento de comunicação de dados). O sentido dos pinos de comunicação é dado do ponto de

vista do DTE. Como tipicamente o EIA-232 é utilizado para comunicação entre um computador e o

microcontrolador vamos sempre admitir aqui que computador é o DTE e o microcontrolador DTE.

A norma especifica vários pinos mas na prática os mais utilizados são os apresentados na tabela

abaixo. As funções e direções dos pinos são dadas em função do DTE

Pino Função Direção

TxD Transmissão do DTE para o DCE Saída RxD Transmissão do DCE para o DTE Entrada RTS Sinaliza que o DTE está pronto para receber dados do DCE Saída CTS Sinaliza que o DCE está pronto para receber dados do DTE Entrada DSR DCE pronto para operação Entrada DTR DTE pronto para operação Saída

Tabela 11.1 - Pinos de comunicação serial

Os pinos DSR e DTR servem para indicar que os equipamentos estão conectados e prontos para

comunicação. DTS e CTS servem para fazer controle de fluxo: Quando o DTE tem dados para

transmitir ele informa o DCE através de RTS; se o DCE pode receber esses dados CTS é ativado.

As sinalização são ativadas em ‘0’ e desativadas em ‘1’.

Em uma grande maioria dos casos são utilizados apenas os terminais de transmissão e recepção de

dados, podendo ser usado um cabo com apenas 3 fios (TxD, RxD e Terra).

Segundo a norma, a comunicação serial pode suportar taxas de bit (geralmente chamadas baud rate)

de até 20 kbps. É possível realizar comunicação full-duplex, ou seja, nos dois sentidos ao mesmo

tempo.

A distância máxima do cabo de comunicação deve ser inferior a 15 metros (50 pés).

Umas das principais causas da limitação de taxa e distância do EIA-232C é limitação nos tempos de

subida e descida do sinal, que deve ser menor que 4% do tempo de bits.

As especificações elétricas do EIA-232C podem ser observadas na figura abaixo.

Page 110: Apostila PIC 16f877a

Exsto Tecnologia

110 Microcontroladores PIC16F877A

Figura 11.2 – Faixas de tensão do EIA-232C

No transmissor o nível lógico ‘0’ é representado por uma tensão entre +5 e +15 Volts e o nível lógico

‘1’ é representado por tensões entre -5 e -15 Volts. No receptor tensões entre +3 e +15 Volts são

interpretadas como ‘0’ e entre -3 e -15 Volts interpretadas como ‘1’; tensões entre +3 e -3 Volts

levam a estados ideterminados. A diferença entre os limites de tensão no transmissor (-5V e +5V) e

os limites do receptor (-3V e +3V) constitui a margem de segurança, dentro da qual ruídos e eventuas

perdas no cabo não degradam os dados.

As tensões máxima mínima que podem ser aplicadas ao receptor sem que haja dano são,

respectivamente, +25V e -25V. Além disso, a norma especifica que qualquer curto circuito entre

quaisquer pinos, inclusive o pino de terra, não devem causar dano ao circuito.

Como na maioria das aplicações trabalha com circuitos alimentados com +5V são necessários

conversores de nível para criar uma interface elétrica com o EIA-232, dentre os quais os mais

conhecidos são o MAX232 e seus equivalentes.

5.3.4 A USART do PIC16F877A O PIC16F877A, assim como diversos outros microcontrolador, possui um módulo de realiza

comunicação serial. Ele é conhecido como USART (Universal Synchronous Asynchronous Receiver

Transmitter – Receptor e Transmissor Síncrono Assíncrono Universal) ou SCI (Serial Communications

Interface).

A USART pode ser configurada para trabalhar nos seguintes modos:

• Assíncrono (Full Duplex)

• Síncrono Mestre (Half Duplex)

• Síncrono Escravo (Half Duplex)

A diferença entre os módos Síncrono Mestre e Escravo é que o Mestre gera o clock para os escravos.

Abordaremos somente o modo assíncrono, que nos permitirá implementar uma comunicação sob o

protocolo RS-232 com o PC.

Os pinos do microcontrolador associados à USART são RB6 para transmissão (TxD) e RB7 para

recepção (RxD). Quando a USART está habilitada esses pinos deixam de operar como entradas e

saídas digitais.

TX Cabo RX +15V

+5V

-5V

-15V

+15V

+3V

-3V

-15V

‘0’

‘1’

?

Page 111: Apostila PIC 16f877a

Exsto Tecnologia

111 Microcontroladores PIC16F877A

Para configurar transmissão e recepção são utilizados dois registros TXSTA e RCSTA.

CSRC: Seleção de clock. o Modo Assíncrono: não tem efeito o Modo síncrono

1 = Modo mestre, clock gerado internamente. 0 = Modo escravo, clock recebido.

TX9: Habilitação de transmissão de 9 bits o 1 = Transmissão de 9 bits o 0 = Transmissão de 8 bits

TXEN: Habilitação de transmissão o 1 = Transmissão ligada o 0 = Transmissão desligada

SYNC: seleção de modo da USART o 1 = Modo síncrono o 0 = Modo assíncrono

BRGH: Seleção de taxa de transmissão aula o Modo assíncrono

1 = Alta velocidade 0 = Baixa velocidade

o Modo síncrono: não tem efeito TRMT: Status do buffer de transmissão ]

o 1 = buffer vazio o 0 = buffer cheio

TX9D: 9º bit de transmissão, quando TXEN for usado

SPEN: Habilitação da porta serial o 1 = Habilitada (pinos RC6 e RC7 operam como pinos da USART) o 0 = Desabilitada

RX9: Habilitação de recepção de 9 bits o 1 = Recepção de 9 bits o 0 = Recepção de 8 bits

SREN: Habilitação de recepção única o Modo assíncrono: não tem efeito o Modo síncrono:

1 = Habilita recepção única 0 = Habilita transmissão única

CREN: habilitação de recepção contínua o Modo síncrono

1 = habilita recepção contínua 0 = desabilita recepção contínua

o Modo assíncrono

R/W – 0 R/W – 0 R/W– 0 R/W – 0 R/W – 0 U – 0 R/W – 0 R – 1

Bit 7 Bit 0

CSRC TX9 TXEN SYNC - BRGH TRMT TX9D

TXSTA

R/W – 0 R/W – 0 R/W– 0 R/W – 0 R –x R/W – 0 R – 0 R – 0

Bit 7 Bit 0

SPEN RX9 SREN CREN ADDEN FERR OERR RX9D

RCSTA

Page 112: Apostila PIC 16f877a

Exsto Tecnologia

112 Microcontroladores PIC16F877A

1 = habilita recepção contínua 0 = desabilita recepção contínua

ADDEN: Habilitação de detector de endereço o 1 = habilita detecção de endereço o 0 = desabilita detecção de endereço

FERR: Erro de enquadramento o 1 = houve erro de enquadramento (dado recebido com taxa diferente da

configurada) o 0 = não houve erro de enquadramento

OERR: Erro de sobrescrita no buffer de recepção o 1 = houve sobrescrita no buffer de recepção o 0 = não houve sobrescrita no buffer de recepção

RX9D: 9 bit recebido, se RX9 = 1;

Além das configurações feitas pelos registros acima é importante configurar a taxa de transmissão da

comunicação serial. Isso é feito carregando o valor adequado no registro SPBRG, que configura o

gerador de taxa de transmissão do PIC. Para determinar esse valor é usada a equação 11.1, se o bit

BRGH está ‘0’, e a equação 11.2 se BRGH está em ‘1’.

)1(64 +×=

SPBRG

FoscTaxa (11.1)

)1(4 +×=

SPBRG

FoscTaxa (11.2)

5.3.5 Transmissão Durante o processo de transmissão serial assíncrona entra em operação o circuito apresentado na

figura 11.3.

Figura 11.3 - Diagrama em blocos do sistema de transmissão

O processo de transmissão se inicia quando um dado é escrito no registro TXREG. Quando isso ocorre

o valor de TXREG é transferido para o registro interno TSR (desde que esse esteja vazio) e o flag TXIF

é setado. O valor contido em TSR é enviado de forma serial pelo tino RB6/TxD, conforme a taxa de

transmissão selecionada.

Page 113: Apostila PIC 16f877a

Exsto Tecnologia

113 Microcontroladores PIC16F877A

Para realizar um processo de transmissão serial basta seguir os seguintes passos:

1. Carregar SPBRG com o valor correto para a taxa de transmissão desejada. 2. Habilitar comunicação serial síncrona: TXSTA, SYNC 0 e RCSTA, SPEN 1; 3. Habilitar a transmissão: TXSTA, TXEN 1

Feito isso, toda vez que um dado é movido para TXREG o mesmo é automaticamente transmitido de

forma serial.

5.3.6 Recepção Para receber dados de forma serial o circuito interno a USART comporta-se como apresentado na

figura 11.4

Figura 11.4 - Diagrama em blocos do sistema de recepção

Os dados recebidos pela porta serial são rotacionados e alojados no registro interno RSR. Uma vez

verificado a coerência de start bit e stop bit, os dados são transferidos para o buffer de recepção, isto

é, o registro RCREG e o flag RCIF é setado. Caso haja alguma incoerência com os bits de start e stop,

o indicador de erro de equadramento FERR é setado. O flag RCIF é zerado toda quando o registro

RCREG é lido.

Podem ser recebidos até dois bytes sem que faça a leitura do registro RCREG, sendo que o primeiro

recebido fica armazenado em RCREG e o segundo em RSR, sendo transferido para RCREG assim que

este é lido. Caso chegue um terceiro byte RSR é sobrescrito e o bit de erro OERR é setado.

Para realizar recepção de dados enviados pela serial é necessário seguir os seguintes passos:

1. Carregar SPBRG com o valor correto para a taxa de transmissão desejada. 2. Habilitar comunicação serial síncrona: TXSTA, SYNC 0 e RCSTA, SPEN 1; 3. Habilitar a transmissão: RCSTA, RXEN 1

Page 114: Apostila PIC 16f877a

Exsto Tecnologia

114 Microcontroladores PIC16F877A

Feito isso, basta monitorar o bit RCIF, que será setado toda vez que existir um dado válido no registro

RCREG.

5.4 Conversor Analógico para digital – ADC Alguns microcontroladores PIC da família 16Fxxx, dentre eles o PIC16F877A possuem módulos para

conversão de níveis de tensão DC em valores digitais (ADC). O ADC converte a tensão em palavras de

8 bits ou 10 bits, dependendo do componente. Aqui será tratado especificamente do módulo ADC de

10 bits do PIC16F877A, porém o funcionamento desses módulos é o mesmo para demais

componentes com ADCs de 10 bits e muito semelhante para os de 8 bits.

Figura 12.1 - Diagrama em blocos do ADC

PIC16F877A possui um ADC com oito canais analógicos. Isso significa que a tensão a ser escolhida

dentre a de oito entradas diferentes, porém não somente uma entrada pode ser convertida por vez.

Além disso, as tensões de referência para a conversão, tanto superior (Vref+) como inferior (Vref-),

podem ser selecionadas por software entre as tensões de alimentação e tensões presentes em

determinados terminais do microcontrolador. Esses valores de tensão estipulam a faixa de valore a

ser convertida. Por exemplo, sendo Vref+ = Vdd e Vref- = Vss temos uma faixa de 5V,

correspondendo o valor 0 a 0V e 1024 a 5V. Para determinar um qual o valor correspondente dentro

dessa faixa, basta aplicar uma simples regra de três. Essas considerações podem ser observadas na

figura 12.1.

Page 115: Apostila PIC 16f877a

Exsto Tecnologia

115 Microcontroladores PIC16F877A

O módulo ADC realiza todo o processo de “Sample and Hold” (Amostragem e retenção). Esse

processo é realizado quando uma determinada entrada é selecionada e inicia-se a carga de um

capacitor interno CHOLD . Após o tempo de carga do capacitor (THOLD) a entrada é desconectada e

inicia-se o processo de conversão da tensão armazenada no capacitor, que é feito pelo método de

aproximações sucessivas. A figura abaixo apresenta o circuito equivalente da entrada da do ADC.

Figura 12.2 - Circuito Equivalente da entrada do ADC

Requisitos de funcionamento

A resistência da fonte da tensão a ser convertida (Rs no circuito acima) não deve ser superior a 10kΩ,

caso contrário o capacitor CHOLD pode não ser completamente carregado quando se iniciar a

conversão.

Além disso, o processo de conversão só poderá ser iniciado depois de decorrido o tempo de carga do

capacitor (THOLD). A ativação do processo de conversão será explicada mais adiante.

O tempo total de amostragem, que vai do instante em que o canal a ser amostrado é selecionado ao

momento em que o resultado da conversão é armazenado nos registros de resultado do AD, é a

soma do tempo de aquisição com o tempo de conversão. O tempo de aquisição varia em função da a

temperatura, da tensão de alimentação e da resistência da fonte do sinal a ser amostrado. Para

temperaturas inferiores a 25oC, alimentação de 5V o tempo de aquisição encontra-se no intervalo:

11 µs < TAQ < 20µs

onde o menor tempo é conseguido para uma Rs = 0Ω e o maior para Rs = 10kΩ.

Já o tempo de conversão depende do clock de conversão. Esse clock pode ser selecionado como

Fosc/2, Fosc/8, Fosc/32 ou baseado em um oscilador RC interno que varia entre 2 e 6 µs. A seleção

do clock de conversão deve ser tal que o período seja de 1,6µs no mínimo.

Quando utilizando a fonte de clock proveniente do oscilador RC o processo de conversão pode

ocorrer estando o microcontrolador em modo SLEEP. Esse procedimento pode ser utilizado para que

o oscilador do microcontrolador não introduza ruídos na tensão a ser medida.

Finalmente, após uma conversão ser concluída é necessário aguardar 2 períodos do clock de

conversa antes de se reiniciar o processo.

Page 116: Apostila PIC 16f877a

Exsto Tecnologia

116 Microcontroladores PIC16F877A

5.4.1 Configuração e uso Para a utilização do ADC são utilizados 4 registros especiais

ADRESH : registro de resultado do A/D (MSbits);

ADRESL : registro de resultado do A/D (LSbits);

ADCON0 : registro de controle 0;

ADCON1 : registro de controle 1.

Abaixo são apresentadas as funções desse registros.

ADRESH e ADRESL

São os registros onde são armazenados os valores resultantes da conversão. Como se trata de ADC

de 10bits são necessários 2 registros para esse resultado, ficando 2 bits em um registro e 8 em outro.

A disposição desse registro pode ter dois formatos. O formato “justificado a esquerda” é aquele em

os 8 bits mais significativos são armazenados em ADRESH e os 2 menos significativos em ADRESL. Já

no formato “justificado a direita”, os 2 bits mais significativos são armazenados em ADRESH e os 8

menos significativos em ADRESL. O formato é escolhido pelo valor do bit ADFM do registro ADCON1,

conforme ilustrado pela figura abaixo.

Figura 12.3 - Formato do resultado do ADC

Utilizando a justificação à esquerda e desconsiderando os 2 bits menos significativos temos o

comportamento de um ADC de 8 bits.

ADCON0

Bit 7e 6: ADCS1:ADCS0: Bits de seleção do clock de conversão o 00 = Fosc/2 o 01 = Fosc/8 o 10 = Fosc/32 o 11 = FRC (oscilador RC interno)

Bit 5 à 3: CHS2:CHS0: Seleção de canal analógico o 000 = canal 0 (RA0/AN0)

Page 117: Apostila PIC 16f877a

Exsto Tecnologia

117 Microcontroladores PIC16F877A

o 001 = canal 1 (RA1/AN1) o 010 = canal 2 (RA2/AN2) o 011 = canal 3 (RA3/AN3) o 100 = canal 4 (RA5/AN4) o 101 = canal 5 (RE0/AN5) o 110 = canal 6 (RE1/AN6) o 111 = canal 7 (RE2/AN7)

Bit 2: GO/DONE: Status da conversão o 1 = Conversão em progresso o 0 = Conversão concluída

Bit 1: Não implementado Bit 0: ADON: habilitação do ADC

o 1 = ADC habilitado o 0 = ADC desabilitado (para menor consumo de corrente)

ADCON1

Bit 7 ADFM: Seleção de formato de resultado o 1 = justificado direita o 0 = justificado a esquerda

Bit 6 à 4: não implementados Bit 3 à 0 PCFG3:PCFG0: Configuração das portas do ADC

Esses bits permitem configurar a quais dos terminais que são multiplexados com entradas do ADC

serão entradas analógicas e quais serão I/O digitais. As configurações possíveis são apresentadas pela

tabela abaixo.

Tabela 12.1 – Configurações de entradas analógicas

Para a utilização do AD são necessários os seguintes procedimentos:

1. Configurar o AD na inicialização: a. Selecionar clock de conversão b. Definir formato do resultado

Page 118: Apostila PIC 16f877a

Exsto Tecnologia

118 Microcontroladores PIC16F877A

c. Definir quais terminais serão utilizado como entradas do AD d. Habilitar o modo AD

2. Selecionar qual canal será lido 3. Aguardar o tempo de aquisição 4. Iniciar o processo de conversão (fazendo ADCON0, GO/DONE igual a 1). 5. Aguardar que o processo ser concluído (Verificando se ADCON0, GO/DONE é igual a 0.); 6. Aguardar 2 períodos de clock de conversão.

5.5 Memórias EEPROM e Flash

5.5.1 Memória EEPROM A memória EEPROM muitas vezes é necessária para armazenar dados que devem ser mantidos na

falta de energia do sistema, mas porém podem ser alterados. Por exemplo, as senhas armazenadas

em um alarme não podem se perder caso o alarme seja desligado.

O banco de memórias EEPROM é tratado como periférico porque seu funcionamento se assemelha

mais ao de um periférico que as demais memórias. Os endereços de EEPROM não podem ser

acessados diretamente, como endereços de RAM. Seu acesso é feito através de endereçamento

indireto e seguindo certas seqüências obrigatórias de comando. A seguir serão apresentados o

funcionamento dessa memória e as rotinas para acessos de leitura e escrita.

Existem no PIC16F877A 256 bytes de memória EEPROM. O acesso a esses bytes é feito de forma

indireta através dos registros seguintes registros:

• EEDATA : contém o dado lido / a ser escrito

• EEADR: contém o endereço a ser acessado

• EECON1: registro de controle

• EECON2: utilizado na seqüência de proteção Existe uma seqüência de proteção para prevenir escritas acidentais da EEPROM que faz uso do

EECON2, como será mostrado mais adiante. O registro EECON1 apresenta a configuração abaixo.

WRERR: Flag indicador de erro o 1 = houve um erro no processo de escrita da EEPROM, devido a um reset o 0 = o processo de escrita da EEPROM foi concluído com sucesso

WREN: habilitação da escrita da EEPROM o 1 = permite a escrita da EEPROM o 0 = não permite a escrita da EEPROM

WR: controle de escrita o 1 = inicia o processo de escrita o 0 = processo de escrita concluído (zerado pelo hardware)

RD: controle de leitura o 1 = inicia o processo de leitura o 0 = processo de leitura concluído (zerado pelo hardware)

U – 0 U – 0 U – 0 U – 0 R/W – 1 R/W – x R/W – 0 R/W – 1

Bit 7 Bit 0

- - - - WRERR WREN WR RD

EECON1

Page 119: Apostila PIC 16f877a

Exsto Tecnologia

119 Microcontroladores PIC16F877A

O bit WRERR permite que em aplicações de maior segurança sejam tomadas providências caso

ocorra uma falha na gravação de algum dado. O bit WREN impede a escrita acidental da EEPROM.

O processo de leitura se dá da seguinte maneira: o endereço a ser lido é carregado no registro

EEADR; em seguida o bit RD é setado, dando início ao processo de leitura. Quando a leitura foi

finalizada, o bit RD é zerado pelo hardware, indicando que o dado já foi lido e se encontra no registro

EEDATA. O bit RD só pode ser zerado pelo hardware.

Para a escrita da memória, inicialmente os registros EEDATA e EEADR são carregados com o dado a

ser escrito e o endereço, respectivamente. Em seguida deve ser habilitada a escrita, fazendo WREN

igual ‘1’. Em seguida, uma seqüência obrigatória, que consiste em carregar os valor 55h e AAh no

registro EECON2, deve ser realizada para permitir a gravação da memória. Esse é mais um dispositivo

de segurança contra escritas acidentais da EEPROM. Por fim, o bit WR é setado, dando início ao

processo de escrita, e quando ele se torna ‘0’, o processo de gravação foi concluído. WR também só

pode ser setado pelo software.

5.5.2 Rotinas de acesso a EEPROM Para acesso à EEPROM podemos usar as duas rotinas apresentadas abaixo. Elas têm como requisito

que duas variáveis, E2DATA e E2ADR sejam declaradas no últimos 16 bytes do banco 0, isto é, entre

os endereços 70h e 7Fh. Os endereços devem ser estar nessa posição pra minimizar mudança de

banco.

READ_EEPROM realiza a leitura enquanto WRITE_EEPROM é responsável pela escrita.

READ_EEPROM: ; realiza a leitura da EEPROM de dados ; entrada: E2ADR -> endereço a ser lido ; saída: E2DATA -> dado lido ; W -> dado lido BANKSEL EEADR ; muda para o banco de EEADR MOVFW E2ADR ; W <- E2ADR MOVWF EEADR ; EEADR <- W BSF EECON1,RD ; inicia o processo de leitura MOVFW EEDATA ; W <- EEDATA MOVWF E2DATA ; E2DATA <- EEADR BANKSEL PORTA ; retorna ao banco 0 RETURN

WRITE_EEPROM: ; realiza a escrita da EEPROM de dados ; entrada: E2DATA -> Dado a ser escrito ; E2ADR -> Endereço a ser escrito ; saída: nulo BANKSEL EEADR ; seleciona o banco de EEADR MOVFW E2ADR ; W <- E2ADR MOVWF EEADR ; EEADR <- W MOVFW E2DATA ; W <- E2DATA MOVWF EEDATA ; EEDATA <- W BSF EECON1,WREN ; habilita gravação ; BCF INTCON,GIE ; desabilita interrupções MOVLW 55H ;

Page 120: Apostila PIC 16f877a

Exsto Tecnologia

120 Microcontroladores PIC16F877A

MOVWF EECON2 ; sequencia MOVLW 0AAH ; obrigatória MOVWF EECON2 ; BSF EECON1,WR ; inicia processo de gravação CLRWDT ; fica em loop até a gravação ser BTFSC EECON1,WR ; completada GOTO $-2 ; ; BSF INTCON,GIE ; reabilita as interrupções BCF EECON1,WREN ; desabilita gravação BANKSEL PORTA ; retorna ao banco 0 RETURN

5.5.3 Memória FLASH de programa Da mesma forma que a EEPROM, no PIC16F877A é possível ler e escrever dados na memória flash de

programa. Isso é útil não só porque permite utilizar todas as regiões de memória FLAHS não

ocupadas pelo programa como se fossem EEPROM como também permite que o próprio programa

altere seu conteúdo. Isso permite que aplicações onde exista uma comunicação remota possam ser

atualizadas a distância, desde que exista uma parte do programa responsável por isso que não seja

alterada na atualização.

Além dos registros usados para EEPROM existem mais dois necessários ao trabalho com a memória

FLASH, uma vez que são maiores tanto o dado (14 bits) como endereço (13 bits):

• EEDATH : contém a parte mais significativa do dado lido / a ser escrito

• EEADRH: contém a parte mais significativa do endereço a ser acessado

5.5.4 Rotinas de acesso a FLASH. As rotinas para acesso a memória FLASH são muito semelhantes as utilizadas para memória EEPROM

e são apresentadas a seguir.

READ_FLASH: ; realiza a leitura da memória FLASH de programa ; entrada: E2ADR -> LSByte do endereço a ser grav ado(Banco 2) ; E2ADRH -> MSByte do endereço a ser gravado(Ban co 2) ; saída: E2DATA -> LSByte do contendo o dado lido (Banco 2) ; E2DATH -> MSByte do contendo o dado lido (Banc o 2) BCF STATUS,RP0 ; BSF STATUS,RP1 ; Banco 2 MOVFW E2ADR ; parte menos significativa MOVFW EEADR ; do endereço a ser lido MOVFW E2ADRH ; parte mais significativa MOVFW EEADRH ; do endereço a ser lido BSF STATUS,RP0 ; Banco 3 BSF EECON1,EEPGD ; Acesso a memória FLASH BSF EECON1,RD ; Leitura da FLASH NOP ; A memória é lida nesses dois ciclos NOP ;

Page 121: Apostila PIC 16f877a

Exsto Tecnologia

121 Microcontroladores PIC16F877A

BCF STATUS,RP0 ; Banco 2 MOVFW EEDATA ; parte menos significativa do MOVWF E2DATA ; dado lido MOVFW EEDATH ; parte mais significativa do MOVWF E2DATH ; dado lido BCF STATUS,RP1 ; Banco 0 RETURN

WRITE_FLASH: ; realiza a escrita da memória FLASH de programa ; entrada: EEADR -> LSByte do endereço a ser gr avado(Banco 2) ; EEADRH -> MSByte do endereço a ser gravado(Ban co 2) ; EEDATA -> LSByte do dado a ser gravado (Banco 2) ; EEDATH -> MSByte do dado a ser gravado (Banco 2) ; saída: nulo BCF STATUS,RP0 ; BSF STATUS,RP1 ; Banco 2 MOVFW E2ADR ; parte menos significativa MOVFW EEADR ; do endereço a ser escrito MOVFW E2ADRH ; parte mais significativa MOVFW EEADRH ; do endereço a ser escrito MOVFW EEDATA ; parte menos significativa do MOVWF E2DATA ; dado a ser escrito MOVFW EEDATH ; parte mais significativa do MOVWF E2DATH ; dado a ser escrito BCF STATUS,RP0 ;

BSF EECON1,EEPGD ; Acesso a memória FLASH BSF EECON1,WREN ; Habilita gravação BCF INTCON,GIE ; Desabilta interrupções MOVLW 55h ; MOVWF EECON2 ; EECON1 <- 55h MOVLW 0AAh ; MOVWF EECON2 ; EECON1 <- AAh BSF EECON1, WR ; Inicia gravação NOP ; Instruções escritas aqui são ignoradas NOP ; pois o microcontrolador interrompe a ; execução do programa, aguarda a fim do ; processo de escrita e continua da ; terceira instrução. BSF INTCON,GIE ; Habilita as interrupções BCF EECON1,WREN ; Desabilita a escrita BCF STATUS,RP0 ; BCF STATUS,RP1 ; Banco 0 RETURN

Page 122: Apostila PIC 16f877a

Exsto Tecnologia

122 Microcontroladores PIC16F877A

Apêndices

Apêndice A – Conjunto de Instruções do PIC16

Page 123: Apostila PIC 16f877a

Exsto Tecnologia

123 Microcontroladores PIC16F877A

Apêndice B – Mapeamento de memória de dados