Você está na página 1de 220

MICROPROCESSADORES

E MICROCONTROLADORES
Prof. Msc. Ivan Rossato Chrun
Mantenedora e Diretora Geral
Dra. Lucinéia de Caires Bressanin Roschildt

Vice-diretora
Nathalia Roschildt

Direção Acadêmica
Prof. Dr. Antonio Peixoto de Araujo Neto
Prof. Msc. Ivan Rossato Chrun

MICROPROCESSADORES
E MICROCONTROLADORES

Maringá, PR
2023
© Prof. Msc. Ivan Rossato Chrun, 2023.

A reprodução total ou parcial desta publicação somente


será permitida com prévia autorização por escrito da FEITEP.

A FEITEP-EAD segue o Acordo Ortográfico da Língua Portuguesa em vigor no Brasil desde 2009.
A aceitação das alterações textuais e de normalização bibliográfica sugeridas pelo revisor
é uma decisão do autor/organizador.

Dados Internacionais de Catalogação na Publicação (CIP)


Bibliotecária: Nadja Honarra Aranha – CRB-9 – 1972

C557m
Chrun, Ivan Rossato
Microprocessadores e microcontroladores / Ivan Rossato Chrun. - Maringá - PR:
FEITEP, 2023.

220 p. : il.

Inclui referências.
ISBN: 978-65-84930-23-0

1. Código. 2. Fluxograma. 3. Programação. I. Chrun, Ivan Rossato. II. Título.

CDD: 621.3916

Revisão Técnica: Me. Fábio Splendor


Revisão ortográfica e gramatical: Gisele Pasquini
Diagramação, projeto gráfico e capa: Candida Bitencourt Haesbaert | Paruna Editorial

Avenida Paranavaí, 1164 - Zona 06, CEP: 87070-130


Fone: (44) 3029-4500 | (44) 99949-0688
www.feitep.edu.br
Bem-vindos!
Caro(a) aluno(a),

A Educação a Distância é uma modalidade de ensino que tomou grandes propor-


ções na última década e, por isso, desenvolvemos um ensino de excelência para você!
A proposta dessa modalidade de ensino permite um alcance significativo, amplian-
do a efetividade do direito ao acesso ao Ensino Superior.
O cenário atual se constitui por aparatos, instrumentos e estratégias tecnológicas
que reconfiguram os preceitos da prática tradicional de ensino a partir da mescla en-
tre tecnologia, informação e conhecimento.
Essa tríade marca a identidade de uma era educacional que cria oportunidades de
formação e qualificação por meio da construção do saber científico mediada por prin-
cípios interacionistas.
No espaço virtual, a relação entre professor e aluno se estabelece por meio de es-
tratégias inovadoras e efetivas, dentre elas, a necessidade e relevância de um mate-
rial exclusivo que visa a especificidade dessa instituição: a formação em engenharias!
Assim, convidamos você a ingressar no universo acadêmico por meio de cada dis-
ciplina!
Desejamos a você, acadêmico, ótimos estudos!
Coordenação Nead

Fonte: Paruna Editorial

5
O Autor

Prof. Msc. Ivan Rossato Chrun


Graduado em Engenharia Elétrica pela Universidade Tecnológica Federal do Para-
ná, campus Cornélio Procópio, mestre em Engenharia Elétrica e Informática Industrial,
pela Universidade Tecnológica Federal do Paraná, campus Curitiba. Ênfase em pesqui-
sa de Sistemas Inteligentes, navegação autônoma, e navegação robótica. Pesquisador
pela Fundação Araucária, em Metodologia para o Desenvolvimento de Auditorias em
Sistemas Fotovoltaicos Conectados à Rede Elétrica no âmbito do Programa RENOVA-
-PR. Trabalha na área acadêmica desde 2017, atuando como professor e pesquisador.
Link de acesso: http://lattes.cnpq.br/0858072527100289

6
INTRODUÇÃO GERAL
Olá, prezado(a) aluno(a), seja bem-vindo à disciplina de Instrumentação Eletrô-
nica. Por meio deste, vamos ingressá-lo na área de sistemas embarcados e micro-
controladores, para que você possa estudar os dispositivos utilizados em aplicações
de microcontroladores. Além disso, estudaremos conceitos básicos, princípios de fun-
cionamento e metodologias de implementação. Esses conhecimentos fornecem base
para compreender, analisar e desenvolver projetos de sistemas embarcados.
Um sistema embarcado é um sistema de computador—uma combinação de um
processador de computador, memória de computador e dispositivos periféricos de
entrada/saída—que tem uma função dedicada dentro de um sistema mecânico ou
eletrônico maior. Ele é incorporado como parte de um dispositivo completo, geral-
mente incluindo hardware elétrico ou eletrônico e peças mecânicas.
Como um sistema embarcado normalmente controla as operações físicas da má-
quina na qual está embarcado, muitas vezes tem restrições de computação em tem-
po real. Os sistemas integrados controlam muitos dispositivos de uso comum. E, em
2009, estimou-se que noventa e oito por cento de todos os microprocessadores fabri-
cados eram usados em sistemas embarcados (Barr e Massa, 2006).
Os sistemas embarcados modernos geralmente são baseados em microcontrola-
dores (ou seja, microprocessadores com memória integrada e interfaces periféricas),
mas microprocessadores comuns (usando chips externos para memória e circuitos
de interface periférica) também são comuns, especialmente em sistemas mais com-
plexos. Em ambos os casos, o(s) processador(es) usado(s) pode ser dos tipos que vão
desde propósitos gerais até aqueles especializados em uma certa classe de computa-
ção, ou mesmo projetados sob medida para a aplicação em questão.
Como o sistema embarcado é dedicado a tarefas específicas, os engenheiros de
projeto podem otimizá-lo para reduzir o tamanho e o custo do produto, além de au-
mentar sua confiabilidade e desempenho. Alguns sistemas embarcados são produzi-
dos em massa, beneficiando-se de economias de escala. Podendo variar em tamanho,
desde dispositivos pessoais portáteis como relógios digitais e tocadores de MP3, até

7
máquinas maiores como eletrodomésticos, linhas de montagem industriais, robôs, ve-
ículos de transporte, controladores de semáforos e sistemas de imagens médicas.
Muitas vezes constituem subsistemas de outras máquinas como aviônicos em ae-
ronaves e astriônicos em naves espaciais. Grandes instalações como fábricas, tubula-
ções e redes elétricas dependem de vários sistemas integrados conectados em rede.
Os sistemas embarcados variam desde aqueles de baixa complexidade, com um
único chip microcontrolador, até os muito altos com múltiplas unidades, periféricos e
redes, e que podem residir em racks de equipamentos ou em grandes áreas geográfi-
cas conectadas por meio de linhas de comunicação de longa distância.
Nesse contexto, estudaremos o componente essencial para implementação de sis-
temas embarcados, o microcontrolador. Além das características gerais também estu-
daremos alguns pontos específicos do PIC18F4550, um microcontrolador de Micro-
chip, por ser comumente aplicado em placas de desenvolvimento e prototipagem.
Essa disciplina está dividida em quatro unidades. Na Unidade I, estudaremos carac-
terísticas e conceitos básicos dos componentes que compõem um microcontrolador.
Na Unidade II, estudaremos mais a fundo o PIC18F4550 o qual usaremos para progra-
mação. A Unidade III apresentará a introdução da linguagem Assembly e a programa-
ção de microcontroladores em Assembly, e, por fim, a Unidade IV na qual estudare-
mos a programação em C.
Ressalta-se que essas unidades devem ser consideradas como uma ferramenta
norteadora para estudos, ou seja, tópicos e ênfases de temas para estudo das referên-
cias da disciplina. O diferencial entre as unidades e as referências bibliográficas, está
nas informações e metodologias apresentadas, os quais foram atualizadas para o PI-
C18F4550 e os softwares que serão utilizados para programação e simulação.
A UNIDADE I está organizada com a arquitetura do Renascimento e a arquitetura
barroca, a partir da sua contextualização social e política, que permitem compreender
os avanços ocorridos no período que o texto abrange. O conteúdo também abrange a
apresentação das manifestações urbanas características, sem descuidar da apresenta-
ção das construções exemplares.

8
A UNIDADE II é dedicada à produção arquitetônica do século XVIII e XIX, quan-
do ocorrem transformações no âmbito da produção econômica e social, tendo como
foco a Revolução Industrial. O século responde a mudanças que alteraram a tecnolo-
gia e a cultura, abrindo caminhos para novas formas de construir e de organizar as ci-
dades. Neste sentido, o período cobre a produção neoclássica, a arquitetura do ferro,
o ecletismo, até o art nouveau.
Na UNIDADE III apresentam-se os movimentos de vanguarda em arte e arquite-
tura, que rompem com o historicismo do século anterior e abrem caminho para a arte
e a arquitetura moderna. São aqui apresentadas as principais ideias que nortearam as
manifestações artísticas de vanguarda, assim como as ideias e os artistas da Bauhaus,
que influenciou a arquitetura do século XX e também a arquitetura moderna defendi-
da por Le Corbusier e outros mestrs da primeira geração dos modernos. O módulo se
encerra com a apresentação dos principais arquitetos e exemplares do International
Style que, ao mesmo que em que marca o auge da arquitetura moderna, suas disper-
sões prenunciam a crise e novas mudanças, que veremos no próximo módulo.
A UNIDADE IV é dedicada a arquitetura do século XX, iniciando pela crise da ar-
quitetura moderna, que ocorre com a criação do Team X, criado por arquitetos após
a segunda guerra, com objetivo de pôr em xeque o viés racionalista da arquitetura do
International style. Na sequência, abordamos sobre as novas diretrizes da arquitetura
internacional, com o regionalismo e o pós-modernismo, que fecham o debate do pe-
ríodo, quando entra em cena o que se produz atualmente, que se abriga sob a deno-
minação de arquitetura contemporânea.
Nesse novo século, a arquitetura retoma por um lado a sobriedade e o “silêncio”
da arquitetura moderna, incorporando novas tecnologias e influências as mais diver-
sas, inclusive orientais. Por outro lado, o período atual registra as particularidades e ex-
ceções dos arquitetos do star sistem, cuja produção mantém suas marcas registradas.
Frank Ghery e Zaha Hadid estão entre os mais peculiares.
Por fim, mantemos o desafio de solicitar que você, a partir da estrutura apresenta-
da, dê sequência à Linha do Tempo, proposta anteriormente, na qual deve mostrar a
interrelação da história geral com a história da arquitetura, suas principais manifesta-

9
ções e os exemplares que expressam com mais clareza as possibilidades de cada pe-
ríodo e o repertório formal característico.
Essa Linha do Tempo, depois de pronto, deve ser utilizada por você como um guia,
para que alcance os objetivos de aprendizado que nos propomos. Você pode impri-
mir seu arquivo em papel de maior gramatura e utilizá-la (a linha do tempo) como um
encarte, que deve acompanhá-lo no processo de ensino-aprendizagem. As Referên-
cias foram selecionadas para dar suporte às suas pesquisas e descobertas. Para enten-
der a relação entre arquiteturas de diferentes lugares e mesmo tempos históricos, su-
gerimos utilizar o livro Una historia universal de la arquitectura: un análisis cronológico
a través de las culturas.
Repetimos aqui os objetivos que norteiam o conteúdo e a abordagem adotada nos
dois livros:
1. Ajudá-lo a identificar as diferentes linguagens da arquitetura, relacionando-as
com seu tempo histórico;
2. Possibilitar a você o entendimento dos princípios compositivos de cada lingua-
gem que podem e vêm sendo utilizados em diversos momentos;
3. Permiti-lo conhecer as obras exemplares de cada período e os arquitetos res-
ponsáveis pela produção.
Desejo bons estudos e boas leituras!

10
Sumário
INTRODUÇÃO................................................................................................................................................................................ 15
UNIDADE 1........................................................................................................................................................................................ 15
1. HISTÓRIA E EVOLUÇÃO......................................................................................................................................................... 17
2. MICROPROCESSADOR × MICROCONTROLADOR ................................................................................................. 26
2.1 ARQUITETURA DE VON NEUMANN × ARQUITETURA DE HARVARD....................................................... 27
3. DISPOSITIVOS DE MEMÓRIA – CONCEITOS BÁSICOS.......................................................................................... 30
3.1 HIERARQUIA DAS MEMÓRIAS ....................................................................................................................................... 30
REFERÊNCIAS................................................................................................................................................................................... 37
CONSIDERAÇÕES FINAIS........................................................................................................................................................... 39

UNIDADE 2........................................................................................................................................................................................ 41
INTRODUÇÃO.................................................................................................................................................................................. 42
1. PIC18F4550................................................................................................................................................................................... 44
2. CICLO DE INSTRUÇÃO............................................................................................................................................................ 53
3. MEMÓRIA DE PROGRAMA.................................................................................................................................................. 55
4. PILHA (STACK)............................................................................................................................................................................ 57
5. MEMÓRIA DE DADOS VOLÁTIL (RAM)......................................................................................................................... 58
6. INTERRUPÇÕES.......................................................................................................................................................................... 62
REFERÊNCIAS................................................................................................................................................................................... 66
CONSIDERAÇÕES FINAIS........................................................................................................................................................... 67

UNIDADE 3........................................................................................................................................................................................ 68
INTRODUÇÃO.................................................................................................................................................................................. 69
1. FLUXOGRAMA............................................................................................................................................................................ 71
1.1 REGRAS BÁSICAS................................................................................................................................................................... 73
1.1.1 Início........................................................................................................................................................................................... 73
1.1.2 Montagem............................................................................................................................................................................... 73
1.1.3 Uso dos Símbolos................................................................................................................................................................ 74
2. LINGUAGEM ASSEMBLY........................................................................................................................................................ 78
2.1 CONSTRUÇÃO DOS NOMES DAS INSTRUÇÕES.................................................................................................... 81
2.2 CONSTRUÇÃO DOS NOMES DAS INSTRUÇÕES.................................................................................................... 81
2.3 OSCILADORES.......................................................................................................................................................................... 86
2.4 CARACTERÍSTICAS DAS PORTAS................................................................................................................................... 86
2.5 REGISTRADORES ESPECIAIS............................................................................................................................................. 88

11
2.5.1 Status.......................................................................................................................................................................................... 88
2.5.2 INTCONs................................................................................................................................................................................... 89
2.5.3 PIE1 e PIE2............................................................................................................................................................................... 91
2.5.4 PIR1 e PIR2.............................................................................................................................................................................. 91
2.5.5 Contador de Programa – Program Counter :PLCATU, PCLATH e PCL...................................................... 94
2.5.6 Registradores TRISx, PORTx e LATx........................................................................................................................... 94
2.6 MÓDULO TIMER 0.................................................................................................................................................................. 97
2.7 MÓDULO TIMER 1.................................................................................................................................................................. 99
2.8 MÓDULO TIMER 2................................................................................................................................................................101
2.9 MÓDULO TIMER 3................................................................................................................................................................103
2.10 CONFIGURANDO AS OPÇÕES DO PIC....................................................................................................................105
3. PROGRAMAÇÃO – NOÇÕES BÁSICAS.........................................................................................................................107
3.1 ARQUIVOS DE DEFINIÇÃO (INCLUDES)...................................................................................................................107
3.2 CONSTANTES E DEFINIÇÕES..........................................................................................................................................108
3.3 OPERAÇÕES ARITMÉTICAS............................................................................................................................................114
3.4 TRABALHANDO COM PROGRAM COUNTER........................................................................................................120
3.4 CONTAGEM DE TEMPO E GERAÇÃO DE ATRASOS...........................................................................................121
3.5 INTERRUPÇÕES.....................................................................................................................................................................122
4. EXERCÍCIOS.................................................................................................................................................................................126
4.1 EXEMPLO 1..............................................................................................................................................................................126
REFERÊNCIAS.................................................................................................................................................................................136
CONSIDERAÇÕES FINAIS.........................................................................................................................................................137
ANEXO 1............................................................................................................................................................................................138
ANEXO II ...........................................................................................................................................................................................142

UNIDADE 4......................................................................................................................................................................................147
INTRODUÇÃO................................................................................................................................................................................148
1. INTRODUÇÃO A LINGUAGEM C.....................................................................................................................................149
1.1 TIPOS DE DADOS..................................................................................................................................................................151
1.2 DECLARAÇÃO DAS VARIÁVEIS.....................................................................................................................................153
1.3 CÓDIGOS...................................................................................................................................................................................154
1.4 DECLARAÇÃO DAS VARIÁVEIS GLOBAIS E LOCAIS...........................................................................................155
1.5 DECLARAÇÃO DE VETORES E MATRIZES...............................................................................................................155
1.6 PONTEIROS..............................................................................................................................................................................157
2. COMANDOS BÁSICOS ..........................................................................................................................................................159

12
2.1 ATRIBUIÇÃO............................................................................................................................................................................159
2.1.1 Acesso aos SRFs..................................................................................................................................................................159
2.1.2 Entradas e Saídas no XC8...............................................................................................................................................160
2.1.3 Operadores...........................................................................................................................................................................163
2.1.4 Decisão....................................................................................................................................................................................166
2.1.4.1 If .............................................................................................................................................................................................166
2.1.4.2 If-else....................................................................................................................................................................................167
2.1.4.3 Operador Ternário Condicional...............................................................................................................................168
2.1.4.4 Switch...................................................................................................................................................................................169
2.1.4.5 Repetição............................................................................................................................................................................170
2.1.5 Funções...................................................................................................................................................................................172
2.2 INTERRUPÇÕES.....................................................................................................................................................................176
2.3 USANDO ASSEMBLY NO C...............................................................................................................................................182
2.4 FUNÇÕES ÚTEIS.....................................................................................................................................................................183
2.5 DISPLAY 7 SEGMENTOS....................................................................................................................................................184
2.5.1 Display Multiplexados......................................................................................................................................................187
2.5.2 Apresentando Valores em Displays..........................................................................................................................187
2.6 TECLADO MATRICIAL.........................................................................................................................................................188
2.6.1 Teclado Matricial................................................................................................................................................................190
2.7 DISPLAY DE CRISTAL LÍQUIDO – LCD........................................................................................................................191
2.8 BIBLIOTECA LCD.H ..............................................................................................................................................................194
2.9 CONVERSOR ADC................................................................................................................................................................198
2.10 COMPARADOR....................................................................................................................................................................202
2.11 CAPTURA, COMPARAÇÃO E PWM...........................................................................................................................204
2.11.1 Modo de Captura............................................................................................................................................................204
2.11.2 Modo de Comparação..................................................................................................................................................205
2.11.3 Modo de PWM..................................................................................................................................................................205
REFERÊNCIAS.................................................................................................................................................................................210
CONSIDERAÇÕES FINAIS.........................................................................................................................................................211
Anexo I ...............................................................................................................................................................................................212

13
PLANO DE ESTUDO
• Introdução a sistemas embarcados
UNIDADE 1
• Introdução a microcontroladores
• Memórias
• Arquiteturas de microcontroladores
MICROELETRÔNICA
OBJETIVOS DE APRENDIZAGEM
• Conhecer a arquitetura interna de microcontroladores
e microprocessadores
• Compreender conceitos básicos de sistemas
embarcados
• Compreender aplicação e conceitos de memórias
INTRODUÇÃO
Caro(a) estudante, nesta unidade começam seus estudos sobre os Microcontrola-
dores. Estudaremos conceitos básicos de como são construídos e constituídos os mi-
crocontroladores de forma geral, além disso, estudaremos conceitos básicos dos com-
ponentes que compõem um microcontrolador.
Atualmente, temos um grande uso e emprego de microcontroladores e sistemas
microcontrolados, em ampla gama de aplicações que vão desde produtos residenciais
à satélites. Consequentemente, temos vários microcontroladores com características
de processamento, memória, funcionalidades, entre outros, a fim de suprir necessida-
des específicas de cada aplicação.
De forma generalizada, nos referimos a microcontroladores como um sistema
completo, ou, um “computador em um chip”, porém com ênfase em aplicações de
baixo custo. Um exemplo comum, especialmente trabalhos de conclusão de curso, é
o uso do Arduino, referindo a plataforma/placa de prototipagem e possui um micro-
controlador ATmega328p. Ele possui, em um mesmo chip, uma CPU, memória RAM
e ROM, comunicação serial, todos os componentes básicos de um computador con-
vencional menos o processamento gráfico. A título de curiosidade, existem ainda siste-
mas SoC – System on a Chip, os quais possuem todos os componentes de computador
convencional, juntamente com o processamento gráfico, mas não entram na classifi-
cação de microcontroladores. Por exemplo, o chip Snapdragon é um sistema SoC usa-
do em celulares de diversas marcas, como Sony, Xiaomi, Samsung etc.
O interessante ao estudar aplicações com microcontroladores, é poder juntar os
conhecimentos de grande parte das áreas que se estudam em Engenharia. A disciplina
de sinais te ensina sobre amostragem e tratamento de sinais, essencial para aplicações
na qual deseja-se ler um sensor ou um sistema real, utilizando um conversor analógico
digital do microcontrolador. As disciplinas de microeletrônica te ensinam justamente
os princípios de funcionamento desses conversores analógicos-digitais, além sistemas

15
de chaveamento, como, por exemplo a ponte-H, necessária para que um microcon-
trolador possa controlar a velocidade de um motor CC. Além disso, pode-se aplicar
um controle do tipo PID, aprendido na disciplina de Controle.
Nesse contexto, antes de avançarmos para a parte mais específica de microcontro-
ladores, estudaremos conceitos gerais de microcontroladores e uma breve história de
seu desenvolvimento.

16
1. HISTÓRIA E EVOLUÇÃO
Nesta seção, iremos estudar a evolução e história dos microcontroladores, desde
1815 até os dias atuais. George Boole (1815-1864): publicou em 1854 os princípios da
lógica booleana nos quais as variáveis assumem apenas valores 0 e 1 (verdadeiro e fal-
so). Posteriormente, em 1937 Claude Shannon percebeu que a mesma álgebra pode-
ria descrever o comportamento de circuitos elétricos chaveados.
Ainda temos, Herman Hollerith (1860-1929): inventou uma máquina capaz de
processar dados baseada na separação de cartões perfurados. Máquina utilizada para
auxiliar no censo de 1890 e pioneira ao utilizar a eletricidade na separação, contagem
e tabulação dos cartões. A empresa fundada por Hollerith é hoje conhecida como In-
ternational Business Machines ou IBM.
E, Z-1: primeiro computador eletromecânico utilizando relês, construído pelo ale-
mão Konrad Zuse (1910-1995), finalizado em 1938. Zuse tentou vendê-lo ao gover-
no para uso militar, mas foi subestimado pelos nazistas, que não se interessaram pela
máquina.

17
Na Figura 1 temos, Mark I: a marinha dos EUA, em conjunto com a Universidade
de Harvard e a IBM, construiu em 1944 o Mark I, que ocupava 120 m3, tinha milhares
de relês e fazia muito barulho. Uma multiplicação de números de 10 dígitos demora-
va 3 segundos.
Figura 1 – Computador eletromecânico Z1

Fonte: Wikipedia (2023).

18
Na Figura 2 temos, ENIAC: primeiro computador digital eletrônico de grande esca-
la. Criado em fevereiro de 1946 pelos cientistas americanos John Eckert e John Mau-
chly, da Electronic Control Company. Tal projeto foi desenvolvido em segredo pelo
exército americano durante a segunda guerra. Com cerca de 18.000 válvulas, o ENIAC
conseguia fazer 500 multiplicações por segundo. Pesava 30 toneladas, consumia 200
000 watts de potência e ocupava várias salas.
Figura 2 – Mark I – exibição em Harvard

Fonte: Collection of Historical Scientific Instruments (2023).

19
Na Figura 3 temos, John von Neumann (1903-1957): matemático húngaro que for-
malizou o projeto lógico de um computador. Sugeriu que as instruções fossem arma-
zenadas na memória do computador. Até então elas eram lidas de cartões perfurados
e executadas, uma a uma. A maioria dos computadores de hoje em dia segue ainda o
modelo proposto por von Neumann.
Intel 4004: primeiro microprocessador em um chip simples com 4-bits. Fabricado
pela Intel Corporation em 1971, foi também o primeiro disponível comercialmente.
Figura 3 – ENIAC

Fonte: Evolução dos computadores (2023).

20
Na Figura 4, Intel 8008: primeiro microprocessador de 8 bits, lançado em 1972. Su-
cessor do 8080 e do 8085.
Intel 8080: foi um grande sucesso e tornou-se a base para os primeiros microcom-
putadores pessoais na década de 1970 graças ao sistema operacional CP/M.
Figura 4 – Microcontrolador 4004

Fonte: Intel 4004 (2023).

Na figura 5 temos, Motorola 6800: primeiro microprocessador de 8 bits produzi-


do pela Motorola, lançado no mercado pouco depois do Intel 8080 em fins de 1974.
Figura 5 – Microcontrolador intel 8080

Fonte: Intel 8080 (2023).

21
Figura 6 – Microprocessador Motorola 6800

Fonte: Motorola 6800 (2023).

Altair 8800: computador pessoal projetado em 1975, baseado na CPU Intel 8080.
Figura 7 –Altair 8800

Fonte: Altair 8800 (2023).

6501 e 6502: em 1975, a MOS Technology anunciou pôr no mercado os micropro-


cessadores 6501 e 6502 ao preço de $25 cada e que podia satisfazer de imediato to-
das as encomendas. O 6502 tornou-se muito popular e foi utilizado em computado-
res como KIM-1, Apple I, Apple II, Atari, Commodore, Acorn, Oric, Galeb, entre outros.
Figura 8 –Microprocessador MOS 6502

Fonte: MOS 6502 (2023).

22
Z80: microprocessador lançado pela Zilog, com instruções compatíveis com o
8080 e de grande sucesso, comercializado a partir de julho de 1976.
Figura 9 –Microprocessador Z80

Fonte: Zilog Z80 (2023).

Intel 8086: microprocessador de 16 bits lançado em 1978 e faz parte da família x86
da Intel.
Figura 10 –Microprocessador Intel 8086

Fonte: Intel 8086 (2023).

23
Intel 8088: lançado em 1979, foi o primeiro microprocessador que se tornou real-
mente popular. O 8088 evoluiu para o 80286, depois para o 80386, 80486, Pentium,
Pentium II, Pentium III e Pentium 4.
Figura 11 –Microprocessador (a) Intel 8088 (b) Intel Pentium

Fonte: Intel 8088 (2023).

Intel 80386: divisor de águas na indústria de informática, pois foi o primeiro a utili-
zar multitarefa preemptiva (capacidade de executar mais de uma aplicação ao mesmo
tempo), instruções de 32 bits e memória em modo protegido de maneira realmente
eficiente. Foi largamente utilizado em diversos microcomputadores entre 1986 e 1994.
Figura 12 –Microprocessador Intel i386

Fonte: i386 (2023).

24
AMD: aparece inicialmente como fabricante de microprocessadores da linha x86.
A partir de um certo tempo, partiu para o desenvolvimento de sua própria linha de mi-
croprocessadores: K6, Athlon, Duron, Turion, Sempron, etc. Em 2004 e 2005 a AMD foi
pioneira ao lançar os primeiros processadores 64 bits do mercado.
Figura 13 –Microprocessador Amd k6

Fonte: AMD K6 (2023).

PIC: família de microcontroladores fabricada pela Microchip, derivada do PIC1650


originalmente desenvolvido pela General Instruments.
Figura 14 –Microcontrolador PIC1650

Fonte: Microchip MCP1650 (2023).

25
2. MICROPROCESSADOR ×
MICROCONTROLADOR
Podemos diferenciar um microprocessador de um microcontrolador dadas algu-
mas características básicas de cada um dos componentes. Além disso, pode-se dividir
microcontroladores de usos especiais como DSPs.
Microprocessador (processador, unidade central de processamento CPU): circui-
to integrado que realiza as funções de cálculo e tomada de decisão de um computa-
dor. Esse, necessita de memória, dispositivos de entrada/saída, clock, controladores e
conversores de sinais entre outros. Subdivide-se basicamente em (o conjunto é deno-
minado CPU):
 Unidade Lógica Aritmética (ULA): responsável pelos cálculos aritméticos e ló-
gicos e registradores;
 Unidade de Controle (UC): responsável pela tarefa de controle das ações a se-
rem realizadas pelo computador, comandando todos os outros componentes;
 Registradores: pequenas memórias velozes que armazenam comandos ou va-
lores que são utilizados no controle e processamento de cada instrução. Desta-
cam-se: Contador de Programa que sinaliza para a próxima instrução a ser exe-
cutada; Registrador de Instrução que registra a execução da instrução;
Microcontrolador: “computador em um chip”. Integra elementos adicionais em
sua estrutura interna, como memória RAM, memória ROM para armazenamento de
programas, EEPROM para armazenamento permanente de dados, dispositivos peri-
féricos como conversores analógico/-digitais (ADC), conversores digitais/analógicos
(DAC) em alguns casos e interfaces de entrada e saída de dados.
Processador Digital de Sinais (DSP, Digital Signal Processor): são microprocessa-
dores especializados em processamento digital de sinal usados para processar sinais
de áudio, vídeo etc., em tempo real ou off-line. A capacidade de processar grandes
quantidades em pouco tempo é um dos principais benefícios oferecidos pelos DSPs.
Esses equipamentos são muito utilizados na parte de comunicação para tratamento
de dados e informação.

26
2.1 ARQUITETURA DE VON NEUMANN ×
ARQUITETURA DE HARVARD
Existem duas arquiteturas clássicas para os microprocessadores em geral: a arqui-
tetura Von-Neumann, na qual existe apenas um barramento interno por onde circu-
lam instruções e dados e a arquitetura Harvard, que é caracterizada por dois barra-
mentos internos, sendo um de instruções e outro de dados.
Assim, pode-se dizer que a primeira é uma arquitetura serial e a segunda parale-
la. Da mesma forma, pode-se dizer que a arquitetura Von-Neumann permite produ-
zir um conjunto complexo de código de instruções para o processador (CISC – Com-
plex Instructions Set Computer), com um tempo de execução por instrução de vários
ciclos de clock. Já a arquitetura Havard produz um conjunto simples de códigos de ins-
truções e, dado ao paralelismo de sua estrutura, é capaz de executar apenas uma ins-
trução por ciclo de clock.
A arquitetura Von-Neumann é mais simples, com menor número de portas lógi-
cas, entretanto, sua velocidade é menor que a Havard. A arquitetura Havard necessita
de mais linhas de código para executar a mesma tarefa. Enquanto a arquitetura Von-
-Neumann possui muito mais tipos de instruções.
Um esquemático é mostrado a seguir:
 Modelo de Von Neumann:
– Única estrutura de memória para armazenar dados e instruções separada-
mente;
– Dados e instruções compartilham o mesmo barramento;
– Mais simples, mais barato, menos eficiente.
– Com raras exceções, os computadores pessoais possuem arquitetura basea-
da no modelo de Von Neumann.

27
Figura 15 –Arquitetura Von Newmann

Fonte: Floyd (2015).

 Modelo de Harvard:
– Memórias separadas para dados e instruções;
– Dados e instruções em barramentos distintos;
– Permite que quando uma instrução é executada outra seja buscada na me-
mória (pipeline);
– Mais caro, mais complexo, mais rápido.

Figura 16 – Arquitetura Harvard

Fonte: Floyd (2015).

28
 CISC (Complex Instruction Set Computer):
– Quanto maior a complexidade da instrução, mais espaço ela ocupa na me-
mória;
– Conjunto relativamente grande de instruções.

 RISC (Reduced Instruction Set Computer):


– Conjunto de instruções reduzido, bem menor do que no caso CISC;
– Apenas uma posição de memória utilizada por instrução;
– Vantagem: possui aprendizado mais dinâmico;
– Desvantagem: necessidade de construir funções, pois o conjunto disponível
é bem restrito.

29
3. DISPOSITIVOS DE MEMÓRIA –
CONCEITOS BÁSICOS
Esses dispositivos são circuitos que podem armazenar uma grande quantidade de
bits, organizados em palavras e posições. São mais lentos quando comparados com
os registradores. Nesta seção veremos os tipos de memórias usadas em microcontro-
ladores e sistemas computacionais de maneira geral.

3.1 HIERARQUIA DAS MEMÓRIAS


Podemos dividir a memória de acordo com seu uso/objetivo, assim como em ca-
racterísticas construtivas. Porém, devemos conhecer alguns conceitos básicos gerais
de memórias, são elas:
Memória principal: são memórias cujo processador pode endereçar diretamen-
te. A função principal está em conter a informação necessária para o processador num
determinado momento, como, por exemplo, os programas em execução. Nesta cate-
goria insere-se memória RAM, memória ROM, registradores e memórias cache.
Memória secundária: não podem ser endereçadas diretamente. A informação
precisa ser carregada na memória principal antes de poder ser tratada pelo proces-
sador. São não-voláteis, permitindo guardar os dados permanentemente. Incluem-se,
nesta categoria, os discos rígidos, CDs, DVDs e disquetes.
Diante dessas duas definições, podemos também estudar sobre a forma como a
memória está disposta fisicamente no chip, e como é feito o acesso da informação
contida nela. Dessa forma, definimos:
 Célula de memória: dispositivo ou circuito elétrico usado para armazenar um
único bit (0 ou 1).
 Arranjo de memória: memórias são constituídas de arranjos de células, carac-
terizando um arranjo de memória. Origina um endereço e um conjunto de in-
formação. Por exemplo, na Figura 17a, poderíamos acessar a informação em

30
azul pelo endereço 7. Já na Figura 17b, o acesso à informação em azul, se daria
pelo endereço linha 2 e coluna 8.
Figura 17 –Arranjo de memória (a) uma dimensão (b) duas dimensões.

Fonte: Adaptado de Thomas (2023).

 Palavra de memória: conjunto de bits que pode ser, simultaneamente, lido ou


escrito (gravado) na memória. Tamanhos típicos de palavra de memória: 1, 4,
8, 16 ou 32 bits.
 Posição de memória: local onde se armazena uma palavra. Cada posição pos-
sui um endereço (acessa a posição).
 Endereço: número (binário, hexadecimal) que identifica a posição de uma pa-
lavra na memória. Apresentados ao módulo através da via de endereço (ad-
dress bus).
 Capacidade: específica quantos bits (ou bytes) podem ser armazenados em
um dispositivo de memória.
– Produto número de posições # tamanho da palavra.
– linhas de endereços → endereços.
– bits por endereço → 1 palavra = n bits.
– Capacidade é 2k # n bits.
– Por exemplo: Memória de 1024 posições 8 bits 8192 bits de capacidade, ou
1024 bytes (byte, onde 1k = 1024 posições).
– A capacidade geralmente é um múltiplo de 1.024 (K, kilo), 1.048.576
(M, mega), 1.073.741.824 (G, giga).

31
 Modo de Acesso:
– Sequencial: tempo de acesso progressivo, função da posição (distância em
relação à posição inicial). O acesso a uma determinada posição requer que
se “caminhe” sobre todas as posições anteriores. Exemplo: Fita magnética e
HD.
– Direto ou Randômico: (RAM, Random Access Memory): seleção direta
de qualquer posição. Mesmo tempo de acesso para qualquer posição.
Ex: memória RAM (Random Access Memory ) e memória ROM (Read Only
Memory).
 Volatilidade: Capacidade de reter dados armazenados na ausência de energia
elétrica. Memórias RAM são voláteis; memórias ROM não voláteis.
 Operação de Leitura: operação que detecta uma palavra binária armazenada
em uma determinada posição (endereço) de memória e a transfere para outro
dispositivo. Um código binário (endereço) é inserido no barramento de ende-
reços (address bus) e os decodificadores internos decodificam o endereço para
determinar a posição a ser lida. Assim, o dado é então movido da posição es-
pecificada para o barramento de dados (data bus).
Figura 18 –Esquemático de funcionamento da memória para leitura.

Fonte: Floyd (2015).

32
 Operação de Escrita: operação que coloca uma palavra em uma determina-
da posição (endereço) da memória. A operação de escrita é designada como
operação de armazenamento. Decodificadores internos decodificam o endere-
ço para determinar a posição a ser escrita. O dado é então movido do barra-
mento de dados para a posição especificada.
Figura 19 –Esquemático de funcionamento da memória para gravação.

Fonte: Floyd (2015).

Além disso, podemos caracterizar dado o objetivo de uso das memórias, dada al-
gumas características”:
 Memória RAM: Random Access Memory
– Memória RAM é para armazenamento temporário.
– Memória de escrita/leitura.
– Pode armazenar dados apenas quando é alimentada, ou seja, é volátil.
– Divide-se em duas categorias: RAM estática (SRAM) e RAM dinâmica
(DRAM).
– SRAM: Uma vez inserido o dado numa localidade, este lá permanece. Célu-
la de memória formada por flip-flops ou por latches.
– DRAM: Deve ser atualizada de tempos em tempos (refresh) pois, de acor-
do com as características de seus elementos internos, perdem informações
após um determinado tempo. Célula de memória formada por capacitores
e transistores.

33
– SRAM é mais rápida do que DRAM, mas com maior complexidade, tama-
nho maior e mais cara. Utilizadas como memórias cache (associadas ao pro-
cessador).
– DRAM possui capacidade e custos mais baixos do que as memórias está-
ticas, porém são mais lentas. Utilizadas como a memória principal de um
computador.
– SRAM Assíncrona: a operação não é sincronizada com o clock do sistema.
– SRAM Síncrona: a operação é sincronizada com o clock do sistema.

 Memórias ROM: Read-Only Memory


– Não permite alteração da informação armazenada;
– Não perde a informação quando a alimentação é retirada;
– Ciclo de leitura semelhante à RAM;
– Vantagem: alta densidade; custo de produção muito baixo quando produzi-
da em grandes quantidades;
– Desvantagem: sem flexibilidade para alteração do conteúdo.

 PROM: Programmable Read-Only Memory


– Semelhante a uma ROM, mas permite uma única programação por parte do
utilizador;
– Vantagem: alta densidade; redução de custos na produção de circuitos em
pequenas quantidades;
– Desvantagem: pouca flexibilidade (uma única programação).

 EPROM: Erasable Programmable Read-Only Memory


– Permite múltiplas programações;
– Para reprogramar o dispositivo, o conteúdo é armazenado. Isso é feito por
meio da radiação ultravioleta durante algumas dezenas de minutos (janelada).
– Vantagem: alta densidade; permite a reutilização de ROM durante a fase de
desenvolvimento de um sistema digital;

34
– Desvantagem: para produções em grandes quantidades possui um custo
significativamente mais elevado que uma ROM.
 EEPROM: Electrically-Erasable Programmable Read-Only Memory
– Utilização idêntica à EPROM, mas com reprogramação através de impulsos
elétricos;
– Vantagem: grande flexibilidade por reunir a funcionalidade da RAM e da
ROM;
– Desvantagem: operações de escrita muito mais lentas que numa RAM, ape-
sar das operações de leitura serem da mesma ordem de grandeza; baixa
densidade.

 FLASH EEPROM: Electrically-Erasable Programmable Read-Only Memory


– Mantém a capacidade da EEPROM de ser programada sem ser retirada e
densidade comparável à ROM e à EPROM.

35
SUGESTÃO DE LEITURA

SOUZA, David José de. Desbravando o PIC:


ampliado e atualizado para PIC16F628A.
12. ed. São Paulo: Érica, 2013.
Capítulo 2

PEREIRA, Fábio. Microcontrolador PIC18 detalhado:


hardware e software: PIC18F4520. São Paulo: Érica, 2010.
Capítulo 1

36
REFERÊNCIAS
ALTAIR 8800. Altair 8800: 45 anos do computador que deu início à Revolução Digital.
Disponível em: https://meiobit.com/433555/altair-8800-45-anos-do-computador-que-
deu-inicio-a-revolucao-digital/. Acesso em: 18 ago. 2023.
AMD K6. WIKIPEDIA, a enciclopédia livre. Disponível em: https://pt.wikipedia.org/wiki/
AMD_K6. Acesso em: 18 ago. 2023.
BARR, Michael Massa, A. J. “Introduction”. Programming embedded systems: with C
and GNU development tools. O’Reilly. 2006.
ENIAC. Evolução dos computadores. Disponível em: https://medium.com/@
gustavosales086/evolu%C3%A7%C3%A3o-dos-computadores-bd87102e01cf. Acesso
em: 18 ago. 2023.
INTEL 4004. WIKIPEDIA, a enciclopédia livre. Disponível em: https://pt.wikipedia.org/
wiki/Intel_4004. Acesso em: 18 ago. 2023.
INTEL 8080. Emulando o Intel 8080. Disponível em: https://www.mentebinaria.com.br/
artigos/tudo/emulando-o-intel-8080-r88/. Acesso em: 18 ago. 2023.
INTEL 8086. WIKIPEDIA, a enciclopédia livre. Disponível em: https://en.wikipedia.org/
wiki/Intel_8086. Acesso em: 18 ago. 2023.
INTEL 8088. WIKIPEDIA, a enciclopédia livre. Disponível em: https://en.wikipedia.org/
wiki/Intel_8088. Acesso em: 18 ago. 2023.
i386. In: WIKIPEDIA, a enciclopédia livre. Disponível em: https://en.wikipedia.org/wiki/
I386. Acesso em 18 ago. 2023.
FLOYD, T. L. Digital Fundamentals. 11e. Pearson. 2015.
MARK I. Collection of Historical Scientific Instruments Mark I. Disponível em: https://
www.atlasobscura.com/places/mark-i. Acesso em: 18 ago. 2023.
MOTOROLA 6800. WIKIPEDIA, a enciclopédia livre. Disponível em: https://en.wikipedia.
org/wiki/Motorola_6800. Acesso em: 18 ago. 2023.
MOS 6502. WIKIMEDIA COMMONS. Disponível em: https://commons.wikimedia.org/
wiki/File:MOS_6502_1.jpg. Acesso em: 18 ago. 2023.

37
Microchip MCP1650. MCP1650 - 750 KHz Step-Up DC/DC Controller. Disponível em:
https://www.microchip.com/en-us/product/MCP1650. Acesso em: 18 ago. 2023.
MIYADAIRA, Alberto N. Microcontroladores PIC18: aprenda e programe em
linguagem C. 4 ed. São Paulo: Érica, 2013.
PEREIRA, Fábio. Microcontrolador PIC18 detalhado: hardware e software:
PIC18F4520. São Paulo: Érica, 2010.
SOUZA, David José de. Desbravando o PIC: ampliado e atualizado para PIC16F628A.
12. ed. São Paulo: Érica, 2013.
SOUZA, Fábio. O que são sistemas embarcados? Disponível em: https://embarcados.
com.br/o-que-sao-sistemas-embarcados/. Acesso em: 01 de agosto de 2023.
Swissbit 2GB PC2-5300U-555. WIKIPEDIA, a enciclopédia livre. Disponível em: https://
pt.m.wikipedia.org/wiki/Ficheiro:Swissbit_2GB_PC2-5300U-555.jpg. Acesso em: 18 ago.
2023.
ZANCO, Wagner da Silva. Microcontroladores PIC®: técnicas de software hardware para
projetos de circuitos eletrônicos: com base no PIC 16F877A. 2. ed. São Paulo: Érica, 2006.
Z1. WIKIPEDIA, a enciclopédia livre. Disponível em: https://pt.wikipedia.org/wiki/Z1.
Acesso em: 18 ago. 2023.
Zilog Z80. WIKIPEDIA, a enciclopédia livre. Disponível em: https://en.wikipedia.org/wiki/
Zilog_Z80. Acesso em: 18 ago. 2023.

38
CONSIDERAÇÕES FINAIS
Caro(a) estudante, depois de todo o estudo e dedicação destinados a esta primei-
ra Unidade, você já conhece as principais características funcionais dos microcontrola-
dores, sua arquitetura e sua forma de armazenamento.
Vale mencionar como os conceitos de memórias, vistos nessa unidade, podem ser
expandidos para basicamente qualquer sistema computacional. De forma resumida,
para se acessar uma memória é necessário um endereço, e consequentemente esse
endereço irá conter um bloco de informação. Esse endereçamento nada mais é um
conjunto de bits, que quando acessado possuem uma determinada quantidade de in-
formação, por exemplo, o PIC18F que é um microcontrolador de 8 bits, ou seja, cada
endereço da memória contém 8 bits (ou 1 byte). Essa memória está distribuída em 16
bancos, na qual cada banco possui 256 bytes de endereçamento, ou seja, cada banco
possui 256 endereços, e cada endereço possui 8 bits. Dessa forma, cada banco pode
armazenar 2048 bytes, ou 2MB de memória. Isso equivale também a outros tipos de
memória, por exemplo, você já deve ter visto uma memória RAM de computador, e
ter notado que há alguns chips em suas faces. Assim, cada chip possui uma quantida-
de de endereçamento e de dados. Esses chips podem ter um armazenamento de 2
GB, por exemplo: se sua memória possui dois chips desses, teria, portanto, uma capa-
cidade total de 4 GB.
Um outro exemplo, pode ser visto na Figura 20 que apresenta uma memória RAM
de 2GB. Nota-se que possui 16 chips de memória E 1108 ACBG-6E-E da Elpida. Ao
olhar o datasheet, podemos ver que cada chip desse possui 16 milhões de palavras
(endereçamento) e cada uma com 8 bits e que são usadas em conjuntos de 8, ou seja,
os 8 chips, com 8 bits, e 16M endereços. Dessa forma, esse conjunto corresponde a
1GB, como essa memória em específico possui em cada lado 8 chips desses, sua ca-
pacidade de memória seria 2GB, conforme especificado.

39
Figura 20 –Memória RAM 2GB

Fonte: Swissbit 2GB PC2-5300U-555 (2023).

40
PLANO DE ESTUDO
• Apresentar PIC18F4550
UNIDADE 2
• Visão geral e arquitetura do PIC
• Memória de programa
• Memória de dados;
• Interrupções. MICROELETRÔNICA
OBJETIVOS DE APRENDIZAGEM
• Compreender a funcionamento do PIC18F4550
• Conhecer as características das conexões de entrada
e saída PIC18F4550
• Compreender conceitos gerais sobre interrupção
e vetorização da memória.
INTRODUÇÃO
Nesta unidade, estudaremos as características de funcionamento e a arquitetura
dos microcontroladores, em específico o PIC18F4550. Os microcontroladores PICs são
divididos em famílias. Cada família ou linha 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 algumas poucas alterações, que se referem principalmente aos periféricos.
Cada família tem seu próprio set (conjunto) de instruções. Portanto, ao se estudar
um componente específico, adquire-se um conhecimento para trabalhar com os
microprocessadores de toda a família.
Podemos citar como famílias de microcontroladores PIC: PIC10, PIC12, PIC14,
PIC16, PIC17, PIC18, PIC24F/PIC24H, dsPIC30/dsPIC33 e PIC32. De acordo com Adria-
no (2014), as famílias mais usadas e com maior número de componentes são as PIC12,
PIC16 e PIC18. PIC14 e PIC17 foram famílias intermediárias na evolução da linha. A fa-
mília PIC24F/PIC24H é composta por componentes de 16 bits e é a mais recente. Já
os dsPIC30/dsPIC33 são controladores híbridos de 16 bits.
No final de 2007 foi lançada também a família PIC32, composta por componentes
de 32 bits. Quanto ao tipo de memória, os componentes mais antigos (que ainda con-
tinuam sendo fabricados) tem memória do tipo OTP e EPROM. Já os mais novos uti-
lizam somente Flash. A tendência do mercado é trabalhar somente com Flash, princi-
palmente nas etapas de ensino e desenvolvimento. O tipo de memória Flash pode ser
identificado por uma letra “F” no nome do componente (por exemplo PIC12F679, PI-
C16F628, PIC18F4550).
O quesito “periféricos” é uma das principais características dos PIC. Dentre os dis-
poníveis, nas várias famílias, podemos citar: temporizadores, conversores A/D, compa-
radores analógicos, módulos USART (comunicação serial RS232), Módulos MSSP (I2C
e SPI master), módulos CCP (Captura, comparação e PWM) etc...

42
Nosso enfoque na disciplina será no PIC18F4550, que são utilizados nos kits didáti-
cos do curso, e, podemos também citar a facilidade em encontrá-lo no comércio com
custo acessível, a facilidade de gravação, por possuir encapsulamento PDIP (o que per-
mite sua montagem em proto-board de maneira simples) e por possuir periféricos que
permitem o desenvolvimento das mais modernas soluções, tais como, comunicação
USB, USART entre outros.

43
1. PIC18F4550
A linha PIC18 é composta por microcontroladores com core de 8 bits de alto de-
sempenho. Buscou-se manter certa compatibilidade com a linha PIC16, o que pode
ser observado no funcionamento de diversos periféricos e no conjunto de instruções.
Podemos ver na Tabela 1 algumas características de acordo com o seu datasheet (fa-
bricante Microchip) em comparação aos outros microcontroladores da família PIC18F.
Com mais informações do datasheet, o PIC18F4550 possui as seguintes características
 Memória FLASH para armazenamento de programa: 32 KBytes;
 Memória SRAM para armazenamento de dados: 2 KBytes
 Memória EEPROM de dados: 256 Bytes;
 Portas configuráveis como entradas ou saídas digitais: 35;
 Portas configuráveis como canais de entradas analógicas: 13
 Módulo CCP (Capture/Compare/PWM)
 Porta paralela de 8-bits (SPP – Streaming Parallel Port).
 Temporizadores de 8 e 16-bit;
 Watchdog Timer;
 Frequência de operação de até 48MHz;
 Múltiplas fontes de interrupção (20);
 Dois comparadores;
 Periféricos avançados de comunicação: Porta de comunicação serial, Porta de
comunicação USB 2.0;
 Arquitetura Harvard, tecnologia RISC com um conjunto de 75 instruções;
 Pilha de 31 níveis.

44
Tabela 1 - Características dos dispositivos PIC.

Fonte: datasheet PIC18F4550 (2023).

Esse microcontrolador pode vir em quatro formas de encapsulamento (Packages),


o mais comum a ser utilizado nos processos de prototipagem e aprendizado é 40-pin
PDIP, podendo ser facilmente utilizado em protoboards (Figura 1). É também possível
visualizar os vários pinos que possuem várias funções, a escolha e a configuração des-
sas funções é feita diretamente no código, alterando-se bits em registradores específi-
cos. De acordo com as setas, podemos ver se o pino em específico pode ser configu-
rado como entrada ou saída.

45
Figura 1 - Encapsulamento e Pinagem PIC18F4550 – 40-pin PDIP

Fonte: datasheet PIC18F4550 (2023).

A Tabela 2 apresenta uma descrição das funções de cada pino para entendermos
melhor o significado de cada nomenclatura utilizada.

46
Tabela 2 - Descrição dos pinos de entrada e saída.

Fonte: datasheet PIC18F4550 (2023).

47
Tabela 2 - Descrição dos pinos de entrada e saída. (Continuação)

Fonte: datasheet PIC18F4550 (2023).

48
Tabela 2 - Descrição dos pinos de entrada e saída. (Continuação).

Fonte: datasheet PIC18F4550 (2023).

49
Tabela 2 - Descrição dos pinos de entrada e saída. (Continuação).

Fonte: datasheet PIC18F4550 (2023).

50
Tabela 2 - Descrição dos pinos de entrada e saída. (Continuação)

Fonte: datasheet PIC18F4550 (2023).

Por exemplo, o pino 3 (DPID) possui como descrição RA1/AN1, ou seja, ele faz par-
te dos conjuntos de pinos bidirecionais do PORTA e têm funções específicas de “Entra-
da/saída digital” e “Entrada analógica 1”.
Outro exemplo, é o pino 34 (DPID) que possui como descrição RB1/AN10/INT1/
SCK/SLC, portanto faz parte do conjunto de pinos bidirecionais PORTB, e tem como
funções “Entrada/saída digital”, “entrada analógica 10”, “Interrupção externa 1”, “Clock
de entrada/saída de comunicação síncrona SPI”, e “Clock de entrada/saída de comu-
nicação síncrona I2C”.
O diagrama mostrado na Figura 2 apresenta um esquemático dos componentes
que compõem esse microcontrolador. Em vermelho, temos a unidade lógica aritmé-
tica (ALU) e próximo a ela temos um hardware de multiplicação 8x8 bits com resulta-
do de 16 bits, disposto em dois registradores próprios (PRODH e PRODL). Em azul, te-
mos o contador de programa (Program Counter) responsável por armazenar a “linha”

51
do código que está sendo executada. O acesso a essa unidade é feito em três registra-
dores (PCU, PCH, e PCL), e é atualizado durante a execução do programa. Temos ain-
da 31 níveis de pilha (Level Stack). Em marrom, temos a memória do programa (Flash)
de 32 kbytes. Em verde, temos a memória de dados (RAM) em que temos os registra-
dores especiais (SFR – Special Function Register). Ainda, na cor laranja, temos os pinos
de saída/entrada (PORTA, PORTB, PORTC, PORTD e PORDE), e em amarelos temos
os blocos representando os periféricos como temporizadores, comparadores, USB,
EEPROM, USART etc.
Figura 2 – Diagrama de bloco do PIC18F4550

Fonte: Adaptado pelo autor (datasheet PIC18F4550, 2023).

52
2. CICLO DE INSTRUÇÃO
No PIC18F4550 (e na maioria dos MC da linha PIC), a frequência do clock interno
é igual à frequência do clock externo dividida por quatro. Por exemplo, um cristal ex-
terno a 4 MHz, resulta em uma frequência para CKint igual a 1 MHz. Portanto, o ciclo
de instrução (ciclo de máquina), nesse caso, é dado por .
Por que é dividido por quatro? Para execução de uma única instrução, várias
operações precisam ser realizadas. Tais operações são executadas em subciclos do
ciclo de máquina (Q1, Q2, Q3 e Q4), originados pela divisão de . Portanto, podemos
representar como:

O contador de programa (PC) é incrementado no início de Q1. Durante o decorrer


de Q1 a Q4, a instrução previamente carregada para dentro da ULA é executada, tro-
cando informações com a memória dos dados e o registrador WORK (W) sempre que
necessário. Por fim, no final de Q4, a próxima instrução é buscada para ser executada
(PC já incrementado nesse ponto).
Buscar a informação em um ciclo de máquina e executá-la no seguinte é conheci-
da como PIPELINE. Permite que quase todas as instruções sejam executadas em ape-
nas um ciclo (1 µs para CKout = 4 MHz). Com exceções de instruções que geram saltos
no PC, como chamadas de rotinas e retornos, que consomem dois ciclos de máquina.
O diagrama na Figura 3 ilustra os quatro subciclos (Q1 a Q4) e o conceito de Pipeline.

53
Figura 3 – (a) Ciclo de clock/instruções (b) Fluxo de instrução “pipeline”

(a)

(b)
Fonte: datasheet PIC18F4550 (2023).

54
3. MEMÓRIA DE PROGRAMA
Para o PIC18F4550 é de 21 bits e 16.384 posições, do tipo FLASH. Antes de conti-
nuarmos, precisamos definir dois pontos:
 Vetor de reset (Reset Vector): primeiro endereço da memória de programa
que será executado após um Start-up (energização inicial) ou Reset. O vetor de
endereço do reset é 0000h (representada em hexadecimal).
 Vetor de interrupção (Interrupt Vector): possui 20 tipos de interrupções
quando qualquer uma delas acontece, o programa será desviado para um pon-
to específico, que é denominado vetor de interrupção. Encontra-se na posição
0008h, para alta prioridade, e 0018h para baixa da prioridade.
A Figura 4 apresenta o mapeamento dos vetores de reset e interrupção. De forma
simplificada, o código será “armazenado” a partir do vetor 0019h, o qual a distribuição
é feita automaticamente pela IDE de programação utilizada.
Apesar de possuírem valores disponíveis para leitura na memória a partir de 8000h,
eles não são implementados no PIC18F4550, e qualquer leitura desses vetores retor-
narão o valor 0.

55
Figura 4 – Mapeamento da memória de programa e da pilha (Stack).

Fonte: datasheet PIC18F4550 (2023).

56
4. PILHA (STACK)
Local onde serão armazenados os endereços de retorno quando utilizarmos instru-
ções de desvio para rotinas de chamada. Quando o programa é desviado para o co-
meço de uma rotina através da instrução correta (CALL ou interrupção), o endereço
seguinte ao ponto que estava sendo executado é armazenado na pilha para que, ao
fim da rotina, o programa possa retornar ao ponto em que estava.
Esse PIC possui uma pilha de 31 níveis, isto é, possível armazenamento de 31 en-
dereços de retorno, possibilitando 31 desvios consecutivos. Caso se tente chamar um
número de rotinas maior que o tamanho da pilha, o endereço de retorno mais anti-
go é perdido.

57
5. MEMÓRIA DE DADOS
VOLÁTIL (RAM)
Serve para guardar as variações e os registradores utilizados pelo programa. Essa
memória armazena dados de 8 bits e é volátil, ou seja, quando o PIC é desenergiza-
do, ela é automaticamente perdida. Podemos dividi-la em dois grupos: registradores
especiais (SFR - Special Function Registers) e registrados de uso geral (GPR – General
Purpose Registers).
Registradores Especiais: nessa região da memória encontram-se todos os regis-
tradores especiais, SFR, e que são utilizados pelo microcontrolador para a execução
do programa e processamento da ULA. Esses registradores podem ser escritos e lidos
tanto pelo usuário quanto pelo hardware e serve também para a configuração de mui-
tas funções e para utilização de todos os periféricos. As figuras a seguir irão apresentar
um esquemático desses registradores, porém para melhor detalhamento de suas pro-
priedades e funções específicas, deve-se consultar o datasheet do PIC.
Registradores de uso geral: trata-se de uma área destinada ao armazenamento
de variáveis definidas pelo usuário para serem escritas e lidas pelo programa.
Essa memória é dividida em 16 bancos. As instruções que manipulam dados na
memória RAM fornecem 8 bits para compor esse endereço; os outros quatro são for-
necidos pelo registro de seleção de banco: BSR. Um esquemático do mapeamento
pode ser visto na Figura 5.
Diferentemente das famílias anteriores, o PIC18 possui um banco de acesso rápido
de 256 bytes, o qual facilita e simplifica o acesso ao usuário.

58
Figura 5 – Mapeamento da memória de dados.

Fonte: datasheet PIC18F4550 (2023).

59
O banco de acesso é usado pelas instruções principais do PIC18 que incluem o bit
de RAM de acesso (o parâmetro ‘a’ na instrução). Quando ‘a’ é igual a ‘1’, a instrução
usa o BSR e o endereço de 8 bits incluído no código para o endereço de memória de
dados. Quando ‘a’ é ‘0’, no entanto, a instrução é forçada a usar o mapa de endereços
do Access Bank, e o valor atual do BSR é totalmente ignorado.
Pegue como exemplo a instrução MOVF, que serve para mover um valor de um
registrador específico para o registrador W, e a instrução MOWF para mover o valor
do registrador W para um registrador específico (Figura 6). O valor de “a” representa-
do na sintaxe determina se vai acessar os bancos normais ou o banco de acesso. No
exemplo de MOVF, irá mover o valor salvo no registrador STATUS para o registrador
W, usando acessando o Access Bank ( a = ACCESS ou 0), já no exemplo de MOWF, irá
mover o valor do Registrador W para o registrador PORTB, porém nesse caso, deve-se
tomar cuidado para que o banco selecionado seja o correto de onde está o vetor da
memória associado ao PORTB.
Caso a sintaxe for utilizar Access Bank, pode-se omitir o “a” complementarmente
da sintaxe, e, portanto, “MOVF STATUS, W, ACCESS” seria igual a “MOVF STATUS, W”.
Figura 6 – Exemplificação de acesso ao Access Bank

Fonte: Souza (2023)

O uso desse endereçamento “forçado” permite que a instrução opere em um ende-


reço de dados em um único ciclo sem atualizar o BSR primeiro. Para endereços de 8 bits
de 60h à FFh, isso significa que os usuários podem avaliar e operar em SFRs com mais
eficiência. A RAM de acesso abaixo de 00h a 60h é um bom local para valores de dados
que o usuário pode precisar acessar rapidamente, como resultados computacionais
imediatos ou variáveis de programa comuns. A RAM de acesso também permite eco-
nomia de contexto e troca de variáveis mais rápidas e eficientes em termos de código.

60
A Figura 7 apresenta o mapeamento dos vetores para os registradores especiais.
Serão nesses registradores que iremos configurar o funcionamento do PIC.
Figura 7 – Mapeamento dos SFR

Fonte: datasheet (2023).

61
6. INTERRUPÇÕES
Uma interrupção é um evento que faz com que o processador pare a execução do
programa corrente e desvie a execução para um bloco de código chamado rotina de
interrupção (normalmente são decorrentes de operações de E/S – Entrada/Saida). O
vetor de interrupções é o endereço de memória que aponta para as rotinas de trata-
mento de interrupção. Quando uma interrupção é gerada, o processador salva o seu
estado atual e começa a executar o tratamento de interrupção apontado pelo vetor.
Desse modo, sempre que uma interrupção ocorre, o programa guarda o endereço da
próxima linha a ser executada na pilha e desvia a execução do programa para o ende-
reço fixo da memória de programação.
O PIC18F4550 possui um total de 20 interrupções diferentes. Todas gerarão o des-
vio do programa para os vetores de interrupção 0008h ou 0018h, dependendo se es-
tiverem configuradas como interrupção com prioridade alta ou baixa, respectivamen-
te. De maneira resumida, basta escrever nesse endereço a rotina que irá reconhecer
e tratar a interrupção. Quando a rotina de interrupção é terminada, o programa retor-
na automaticamente para o ponto em que estava antes dessa interrupção acontecer.
Há dez registradores os quais são usados para controlar e configurar a operação
de interrupção, eles são: RCON, INTCON1, INTCON2, INTCON3, PIR1, PIR2, PIE1, PIE2,
IPR1 e IPR2. Cada fonte de interrupção possui três bits para controlar sua operação. As
funções desses bits são:
 Bit sinalizador (Flag bit): para indicar que ocorreu um evento de interrupção.
 Bit de habilitação (Enable bit), que permite que a execução do programa se
desvie para o endereço do vetor de interrupção quando o bit de sinalização é
definido.
 Bit de prioridade (Priority bit) para selecionar alta prioridade ou baixa prioridade.
O recurso de prioridade de interrupção é ativado setando o bit IPEN (RCON<7> -
leia-se como bit 7 do registrador RCON, o qual é nomeado IPEN). Quando a priorida-
de de interrupção está habilitada, existem dois bits que habilitam as interrupções glo-

62
balmente. Setar o bit GIEH (INTCON<7>) ativa todas as interrupções que têm o bit de
prioridade setado (alta prioridade).
Setar o bit GIEL (INTCON<6>) ativa todas as interrupções que têm o bit de prio-
ridade resetado (baixa prioridade). Quando o sinalizador de interrupção, o bit de ha-
bilitação e o bit de habilitação de interrupção global apropriado são setados, a inter-
rupção será pular imediatamente para o endereço 0008h ou 00018h, dependendo da
configuração do bit de prioridade. Interrupções individuais podem ser desabilitadas
por meio de seus bits de habilitação correspondentes.
Quando o bit IPEN é resetado (estado padrão), os bits de prioridade de interrupção
para cada interrupção não têm efeito. INTCON<6> é o bit PEIE que ativa/desativa to-
das as fontes de interrupção periféricas. Nessa condição, INTCON<7> é o bit GIE que
habilita/desabilita todas as fontes de interrupção, e portanto, todas as interrupções ra-
mificam para o endereço 0008h.
A lógica de interrupção pode ser vista na Figura 8 onde é possível ver o padrão dos
bits relacionados às interrupções, por exemplo:
TMR1IF: TMR1 significa timer1, I interrupção e F flag, ou seja, o bit de flag de in-
terrupção do timer1. Caso esse bit seja 1, a interrupção gerada foi devido ao estouro
do timer 1.
TMR1IE: TMR1 significa timer1, I interrupção e E enable (habilitação), ou seja, o bit
de habilitação de interrupção do timer1. Caso esse bit esteja alto, o timer1 está confi-
gurado para gerar uma interrupção caso haja seu estouro.
TMR1IP: TMR1 significa timer1, I interrupção e P prioridade, ou seja, o bit de confi-
guração de prioridade da interrupção do timer1. Caso esse bit esteja alto, o timer1 está
configurado com prioridade alta para interrupção.
Algumas das interrupções e temporizadores serão vistos de maneira específica nas
Unidades III e IV, na parte de programação. Porém, ressalta-se a importância de ler o
datasheet do PIC18F4550 para melhor compreender todas as funções disponíveis do
microcontrolador ou alguma função em específico que queira utilizar.

63
A Figura 9 apresenta as relações dos Flags mostrados na Figura 8 e seus devidos re-
gistradores especiais. Essa figura pode auxiliar a encontrar em quais registradores es-
tão as flags ou bits referentes a funções específicas assim como sua nomenclatura. Por
exemplo, o bit GIE/GIEH é o nome dado para o bit na posição 7 do registrador INT-
CON, e é através dele que habilitamos ou desabilitamos todas as interrupções. Alguns
dos registradores mais importantes para o uso e programação do PIC serão vistos na
próxima unidade.
Figura 8 – Diagrama Lógico das interrupções

Fonte: datasheet (2023).

64
Figura 9 – Mapeamento das Flags de interrupção aos seus SFRs

Fonte: Souza (2010).

SUGESTÃO DE LEITURA
SOUSA, D. R. Desbravando o Microcontrolador PIC18: Recursos
Avançados. 1ed. São Paulo. Érica, 2010.
Capítulo 2 – O PIC18F4520

MICROCHIP. PIC18F4550
Datasheet. 2006.

65
REFERÊNCIAS
ADRIANO, J. D. Exsto – Xm118 – Microcontroladores PIC18, 2014.
FLOYD, T. L. Digital Fundamentals.11ed. Prentice Hall, 2014.
Datasheet, MICROCHIP. PIC18F4550. 2006.
PEREIRA, V. Microcontroladores PIC 16F e 18F – Teoria e Prática. São Paulo, 2013.
TORRE, F. E., MARTINS, H. R. Sistemas microcontrolados. INOVA – UFMG, 2012.
SOUZA, D. R. Desbravando o Microcontrolador PIC18: Recursos Avançados. 1ed.
São Paulo. Érica, 2010.

66
CONSIDERAÇÕES FINAIS
Caro(a) estudante, essa unidade teve como objetivo apresentar o diagrama de fun-
cionamento de um dos microcontroladores da família PIC18, o PIC18F4550. Foram
apresentadas algumas características desse microcontrolador e sua forma de funcio-
namento. Isso se faz necessário, pois toda a configuração deste microcontrolador é fei-
ta através de alteração de bits específicos em determinados registradores.
Por exemplo, podemos utilizar o PIC para um controle de um motor de corrente
contínua, apesar de ser necessário a implantação de um sistema de chaveamento com
mosfets ou transistores, dado o consumo de corrente do motor; toda a parte de con-
trole de sinais e comando pode ser feito pelo microcontrolador onde devemos gerar
um sinal PWM para os mosfets, e, portanto, os bits relacionados a essa função deverá
ser ativada, assim como os pinos de saída referente ao PWM também devem ser se-
tados para que sejam ligados ao periférico do PWM. Podemos ainda fazer o comando
através de um potenciômetro, e, portanto, devemos utilizar uma entrada analógica, e
da mesma forma, precisamos saber quais pinos podem assumir essa função e deve-
mos então habilitá-los.
Toda a programação de microcontroladores, por se tratar de chips de uso geral, se
dá primeiramente conhecer as características e as funções disponíveis do microcon-
trolador, e, na sequência, como é feito a configuração de determinada funcionalida-
de que queremos usar, pois, como vimos, os pinos podem compartilhar múltiplas fun-
ções, o que é extremamente comum para todos os microcontroladores.
Além disso, esses conhecimentos podem ser expandidos e utilizados para outros
PIC da mesma família PIC18, e para outras famílias também PIC12, PIC16 etc., com al-
gumas alterações nas lógicas implementadas.

67
PLANO DE ESTUDO
• Técnicas e metodologia de programação;
UNIDADE 3
• Introdução a Linguagem Assembly;
• Programação em Assembly do PIC18F;
• Ambiente de desenvolvimento MPLAB;
• Ambiente de simulação PicSimLab. MICROELETRÔNICA
OBJETIVOS DE APRENDIZAGEM
• Compreender as metodologias e técnicas
de programação;
• Desenvolver e implementar lógica de programação
em Assembly;
• Desenvolver projetos de sistemas microcontrolados;
• Conhecer conceitos e características de programação
para o PIC18F4550.
INTRODUÇÃO
Caro(a) estudante, nesta unidade começam seus estudos sobre a programação do
PIC18F4550. Um programa é um conjunto ordenado de instruções capazes de exe-
cutar uma ação útil em um sistema computacional, o qual pode ser representado de
diversas formas (linguagens). Em última análise, o processador só entende uma lin-
guagem: a da máquina, constituída de “zeros” e “uns”. Com o objetivo de facilitar o
entendimento, surgiu uma série de linguagens de programação que são, basicamen-
te, formas mais elaboradas de se desenvolver o raciocínio computacional de maneira
mais inteligível (Torre e Martins, 2014).
Para programar o PIC na linguagem que iremos estudar nesta unidade e na pró-
xima, utilizaremos o MPLAB X IDE, o MPLAB XC8 (para a linguagem C). Ambos são
programas que não necessitam de licenças pagas, e, portanto, podem ser facilmente
baixados nos endereços. Sua instalação é simples, basta executar os arquivos .exe e
instalar na pasta recomendada pelo programa.
Para simulação, podemos usar o PROTEUS que é uma ótima ferramenta de simu-
lação, no qual é possível montar o circuito elétrico, comando, o microcontrolador, e
simular os PIC de maneira didática, porém é necessário obter uma licença para uso.
Como alternativa, podemos usar o PICSimLab, que é um simulador que não necessi-
ta a licença e podemos implementar o nosso código de maneira adequada, mas fica-
mos restritos às “placas base” fornecida pelo simulador, já que o PICSimLab simula kits
didáticos do PIC.
Abaixo estão os sites para download. Na aula gravada entraremos nos detalhes
em como utilizar cada um desses softwares. Ressalta-se que, para o MPLAB precisa-
mos instalar a versão 5.35 ou 5.30, pois versões superiores deixaram de dar suporte ao
compilador MPASM, necessário para compilar o código em Assembly.
Por simplicidade, abaixo há os links diretos para download, e na sequência os links
para as páginas de cada software.

69
Links diretos
Assembly
MPLAB X IDE 5.35
https://ww1.microchip.com/downloads/en/DeviceDoc/MPLABX-v5.35-windows-
installer.exe

Linguagem C
MPLAB XC8 64bits
http://www.microchip.com/mplabxc8windows

MPLAB X IDE 6.15


https://ww1.microchip.com/downloads/aemDocuments/documents/DEV/
ProductDocuments/SoftwareTools/MPLABX-v6.15-windows-installer.exe

PICSimLab
Windows 64 bits
https://ufpr.dl.sourceforge.net/project/picsim/v0.9.0/PICSimLab_0.9.0_230729_win64_
setup.exe
Windows 32 bits
https://ufpr.dl.sourceforge.net/project/picsim/v0.9.0/PICSimLab_0.9.0_230729_win32_
setup.exe

Links para o site de cada software


MPLAB X IDE - https://www.microchip.com/en-us/tools-resources/develop/mplab-x-ide
MPLAB XC8 - https://microchipdeveloper.com/xc8:installation
PICSimLab - https://sourceforge.net/projects/picsim/files/

70
1. FLUXOGRAMA
Segundo Filho (2007), um fluxograma é a representação gráfica da definição, aná-
lise ou solução de um problema cujos símbolos são utilizados para representar ope-
rações, dados, fluxos, equipamentos etc. É uma ferramenta originalmente criada na
indústria de computadores para mostrar os diversos passos envolvidos em um pro-
grama. Provavelmente é o método mais antigo criado para representar uma sequên-
cia de atividades ou comandos.
O fluxograma é constituído por um diagrama que utiliza figuras geométricas (qua-
drados, retângulos, losangos, círculos etc.) conectados por linhas e flechas, onde cada
figura representa um passo no programa e cada uma das flechas representa a sequên-
cia em que os passos ocorrem.
A utilização de fluxograma apresenta algumas vantagens: São fáceis de fazer e
compreender (melhor que um texto descritivo). Demonstram claramente o fluxo do
programa ou atividade usando símbolos padronizados, e podem ser facilmente atuali-
zados ou modificados. A Figura 1 apresenta os símbolos utilizados nessa metodologia.

71
Figura 1 - Símbolos usados em fluxogramas.

Fonte: Filho (2007).

72
1.1 REGRAS BÁSICAS
De forma direta, clareza e simplicidade na construção de um fluxograma são es-
senciais. E dessa forma, detalhes de sistema ou complexidades devem ser evitados
logo no início do desenvolvimento do fluxograma. Pode-se incluir, de forma breve,
textos explicativos de alguns trechos de comandos/instruções. Tem-se o intuito de
combinar o fluxograma e textos explicativos para simplificar a compreensão manten-
do a lógica desenvolvida.

1.1.1 Início
Montar um esquemático completo com as seguintes informações:
 Diagrama funcional: contendo os sinais de entrada (vindos do campo – sen-
sores, botões etc.) e saída (retornam para o campo – lâmpadas, relés etc.).
 Tabela de Estado ou Tabela Verdade: indica todas as possibilidades que os
sinais de entrada/saída podem assumir.
 Gráfico Funcional: mostra como os diversos elementos de entrada e saída se
relacionam no tempo.
 Descritivo funcional: conhecimento e descrição do processo a ser controla-
do detalhadamente.

1.1.2 Montagem
O fluxograma é a sequência de um raciocínio lógico, portanto também deve ter
uma disposição dos diversos símbolos de forma lógica. Então, algumas regras simples
devem ser seguidas:
1. Iniciar do topo para a base da folha;
2. Desenvolvimento lateral deve ser da esquerda para a direita, preferencialmente;
3. Nas quebras de página, identificar numericamente a página de destino/retorno;
4. Sempre empregar as flechas de sentido para maior clareza do fluxo de raciocínio;
5. Numerar as páginas sequencialmente;
6. Escrever as operações dentro dos símbolos de forma clara e compacta;
7. Fazer comentários quando a descrição das operações não for suficiente;

73
1.1.3 Uso dos Símbolos
O uso dos símbolos também segue algumas regras. Evitar criar novos símbolos e,
se não houver alternativa, explicar a função do novo símbolo detalhadamente.
1. Os símbolos possuem apenas uma entrada e uma saída (com exceção do sím-
bolo de decisão) como mostra a Figura 2.
Figura 2 – Entrada/Saída símbolos funcionais.

Fonte: Filho (2007).

2. O símbolo de decisão possui apenas 1 entrada, mas pode ter 2 ou 3 saídas de


acordo com as necessidades da lógica. A Figura 3 mostra as opções possíveis.
Figura 3 - Opções de saída para símbolo de decisão.

Fonte: Filho (2007).

74
3. Toda a lógica admite vários caminhos para atingir uma mesma solução. Portan-
to, escolher um caminho lógico entre vários exige uma decisão com o empre-
go do símbolo adequado (losango), como mostra a Figura 4a. O desvio a partir
de uma linha de interligação (Figura 4b) não é possível.
Figura 4 - Opção Correta de desvio ou derivação lógica.

Fonte: Filho (2007)

4. Vários caminhos lógicos convergindo para uma única solução é comum. A um


símbolo lógico associa-se uma única entrada. A consequência é que os vários ca-
minhos convergentes se unem sobre uma linha de interligação (Figura 5a). Evitar
o uso igual ao da Figura 5b para maior clareza e organização do fluxograma.
Figura 5 - Convergência de Caminhos lógicos.

Fonte: Filho (2007)

75
Podemos verificar que as Figuras 2, 3, 4 e 5 mostram símbolos lógicos conectados
por linhas de interligação, e nestas foram colocadas flechas de sentido, indicando com
clareza o fluxo do raciocínio lógico ou da informação. É importante o uso da flecha de
sentido (não deve haver dúvida quanto à direção do raciocínio).
A função/instrução ou operação desejada deve ser escrita no interior do símbolo
e deve ser sucinta, compacta, suficiente para total compreensão. Se houver necessi-
dade de maior detalhe, este pode ser escrito externamente ao símbolo como um co-
mentário.
A Figura 6 mostra a disposição dos símbolos lógicos na área de uma página. Não se
trata de uma norma, mas uma regra que a experiência mostra ser bastante funcional.
A disposição do fluxograma em uma folha (A4) pode ser em três ou quatro colunas
onde a coluna central recebe o fluxo principal do raciocínio. Derivações ou retornos
ocupam as demais colunas. Observe que nesta disposição surgem áreas para comen-
tários ou observações, ao mesmo tempo em que mantém o trabalho organizado.

76
Figura 6 – Exemplo de fluxograma.

Fonte: Filho (2007)

77
2. LINGUAGEM ASSEMBLY
Todo programa de computador, em qualquer linguagem, deverá ser traduzido
(através de um compilador ou de um interpretador) para a linguagem de máquina.
Uma das linguagens de mais baixo nível (mais próxima da máquina) é o Assembly.
Essa linguagem constitui-se de instruções simples (mnemônicos), que são a represen-
tação simbólica da linguagem de máquina.
Antes de entrarmos na parte de programação, devemos conhecer alguns dos ter-
mos utilizados na construção do conjunto de instruções:
 Work (W): registrador temporário para as operações da ULA. É conhecido
como Work, W ou WREG.
 File (F): Referência a um registrador (posição de memória). A letra F é utilizada
para representação nos nomes das instruções.
 Acess (a): referência ao acesso da RAM via Access Bank ou via banco através
do registrador BSR. Utilizamos a letra “a” nos argumentos das instruções.
 Literal (L): Um número qualquer (decimal, hexadecimal ou binário). A letra L é
utilizada para sua representação nos nomes de instruções. Pode aparecer como
a letra “k” nos argumentos do conjunto de instruções.
 Destino (d): Local que armazena o resultado da operação. Duas possibilidades:
f, que guarda o resultado no próprio registrador passado como argumento ou
w, que coloca o resultado em W. Na sintaxe das instruções o destino deve ser
expresso pelos números 0 (W) e 1 (f ). No entanto, as letras f e W são definidas
no include para facilitar a programação.
 Não (N): refere-se a uma operação NOT (inversão), um estado Oposto (rese-
tado, ou bit 0). Utilizamos a letra N para sua representação nos nomes das ins-
truções.
 Borrow (B): refere-se ao bit Borrow (ou o “vem 1” de uma operação de sub-
tração) do registrador STATUS. Utilizamos a letra B para sua representação nos
nomes das instruções.

78
 Carry (C): refere-se ao bit Carry (ou o “vai 1” de uma iteração de soma) do re-
gistrador STATSU. Utilizamos a letra C para sua representação nos nomes das
instruções
 Overflow (OV): refere-se ao bit Overflow do registrador STATUS. Quando um
operação aritmética estoura a capacidade de armazenamento do registrador
temos o “estouro” ou “overflow”.Utilizamos as letras OV para sua representação
nos nomes das instruções
 Toogle (T): refere-se ao ato de inverter o estado de um bit. Utilizamos a letra
T para representá-los nos nomes das instruções.
 Bit (B): Um bit específico dentro de um byte. A letra B é utilizada para sua re-
presentação nos nomes das instruções.
 Teste (T): Testar o estado de um bit (se ele é zero ou um). A letra T é utilizada
para representá-lo nos nomes das instruções.
 Skip (S): Utilizado para criar desvios, pulando a próxima linha. A letra S é utili-
zada para representá-lo nos nomes das instruções.
 Set (S): Forçar nível UM em um bit. A letra S é utilizada para representá-lo nos
nomes das instruções.
 Clear (C): Forçar nível ZERO em um bit. A letra C é utilizada para representá-lo
nos nomes das instruções.
 Zero (Z): Algumas instruções podem gerar desvios se o resultado da opera-
ção efetuada for zero. Neste caso utilizaremos a letra Z para indicar tal condição.
Em seguida são listados alguns termos referentes às ações realizadas pelas instru-
ções:
 ADD: Somatória.
 AND: Lógica “E”,
 CLR: Limpar, zerar (Clear).
 COM: Complemento.
 CPF: comparar registrador
 DEC: Decremento de uma unidade.
 EQ: igual
 GT: maior que ( > )

79
 INC: Incremento de uma unidade.
 IOR: Lógica “OU”.
 LT: menor que ( < )
 MOV: Mover, transferir para algum lugar.
 MUL: multiplicar
 RD: leitura
 RL: Rotacionar 1 bit para a esquerda.
 RR: Rotacionar 1 bit para a direita.
 SET: setar todos o(s) bit(s) de um registrador
 SUB: Subtração.
 SWAP: Inversão entre as partes alta e baixa de um registrador.
 TST: teste
 TBL: tabela
 XOR: Lógica “OU exclusivo”.
 WT: escrita

80
2.1 CONSTRUÇÃO DOS NOMES DAS INSTRUÇÕES
Com base nos termos demonstrados é mais fácil entender o significado de uma
instrução por intermédio do seu nome, pois ele é composto pela junção desses ter-
mos. Por exemplo, digamos que você deseja decrementar o valor de um determina-
do registrador. A instrução que faz isso é composta pelos termos referentes à ação que
você quer fazer:
Decrementar (DEC) um registrador (F) = DECF

Podemos também fazer a análise ao contrário, isto é, partindo do nome de uma


instrução, e descobrir para que ela serve. Por se tratar de um conjunto de instrução pe-
quena disponível, esse é o método mais utilizado na programação do Assembly.
DECFSZ = Decrementa (DEC) o registrador (F) e pula (S) se o resultado for zero (Z)

2.2 CONSTRUÇÃO DOS NOMES DAS INSTRUÇÕES


O conjunto de instrução do PIC18F4550 é composto por 75 instruções, divididas
em cinco grupos: operação com registradores, operação com literais, operação com
bits, controle e operação de leitura e escrita de dados na memória do programa. A Fi-
gura 7 apresenta essas instruções com informações adicionais de descrição e bits afe-
tados. Ele também possui um conjunto de instrução estendido, para maiores informa-
ções sobre esse conjunto verificar o datasheet do componente.
Também é possível visualizar cada instrução de forma individual pelo datasheet
do componente. A Figura 8 apresenta a apresentação das funções MOVF e MOVWF.

81
Figura 7 – Conjunto de instruções.

82
Figura 7 – Conjunto de instruções. (Continuação)

83
Figura 7 – Conjunto de instruções. (Continuação)

Fonte: Souza (2010).

84
Figura 8 – Descrições das instruções MOVF e MOVWF

Fonte: Datasheet (2023).

85
2.3 OSCILADORES
Alguns modelos de PIC possuem oscilador interno, como é o caso do PIC18F4550.
Mesmo os modelos que possuem oscilador interno, há casos em que a ligação de os-
ciladores externos é necessária, seja por motivo de precisão ou por necessidade de
uma frequência diferenciada.
Por simplicidade, utilizaremos o oscilador interno de 8 MHz ou o oscilador monta-
do na placa do kit didático. Maiores informações sobre os circuitos usados e valores de
resistores e capacitores para implementar osciladores podem ser encontradas na Se-
ção 2 do Datasheet do PIC18F4550

2.4 CARACTERÍSTICAS DAS PORTAS


O PIC18F4550 possui suas portas de I/Os (Input/Output – Entrada/Saída) divididas
da seguinte forma:
 1 PORT de 6 l/Os (PORTA);
 3 PORTs de 8 l/Os (PORTB, PORTC e PORTD)
 1 PORT de 3 l/Os (PORTE).
No total há 33 I/Os que podem ser configurados como entrada ou saída pelo pro-
gramador, conforme as necessidades do projeto. Outra característica importante so-
bre essas portas, diz respeito à sua operação elétrica. Internamente esses pinos são li-
gados de formas diferentes, principalmente pela sobrecarga de recursos aplicados a
cada um deles.
Um ponto importante a ser observado é que algumas portas são do tipo TTL e ou-
tras são do tipo Schmitt Trigger (ST). Este dado é muito relevante quando uma porta
é configurada como entrada, porque interfere diretamente nos níveis de tensão inter-
pretados pelo PIC como O (zero) e 1 (um).

86
Figura 9 – Comparativo TTL - ST

Fonte: datasheet (2023).

As entradas ST necessitam de um nível de tensão bem mais elevado para que o


PIC interprete a mudança de estado. Isso é muito útil para enquadrar uma senoide, por
exemplo. Por outro lado, isso é ruim quando há um hardware que gera níveis de ten-
são menores, como pode acontecer quando sobrecarregamos o mesmo pino com di-
versas funções.

87
2.5 REGISTRADORES ESPECIAIS

A seguir veremos alguns dos registradores especiais do PIC18F4550.

2.5.1 Status
Contém os estados do ULA, ou seja, sempre que for executada uma operação arit-
mética, os valores dos bits desses registradores irão alterar de acordo com o resulta-
do. Por exemplo, no PIC18F as memórias são de 8bits, podendo então ser represen-
tadas por valores decimais de 0 a 255. Caso some-se dois valores, e o resultado é um
valor maior que 255, tem-se o “estouro” do registrador, nesse caso o bit C estará alto,
indicando isso.
Também é possível ver a permissão de acesso que pode ser feita em cada bit, re-
presentado por R/W, ou seja, pode-se ler e escrever nesse bit. A coluna de RESET re-
presenta o valor que esse bit irá assumir quando houver um reset do microcontrola-
dor. Essa explicação pode ser expandida para os outros registradores.
Figura 10 – Registrador Status

Fonte: Souza (2010).

88
2.5.2 INTCONs
Este registrador contém bits de habilitação de todas as interrupções. Opera com as
interrupções principais: Timer 0, interrupção externa e interrupção por mudança de
estado. Possui chave geral para todas as interrupções e chave geral para as interrup-
ções de periféricos.
De forma similar, os registradores INTCON2 e INTCON3 configuram e habilitam al-
gumas interrupções de alguns periféricos.
Figura 11 – Registradores INTCON, INTCON2 e INTCON3

89
Fonte: Souza (2010).

90
2.5.3 PIE1 e PIE2
Esses registradores habilitam ou desabilitam algumas interrupções de periféricos,
assim como possuem também alguns flags de interrupções. Esses podem ser vistos na
Figura 12.

2.5.4 PIR1 e PIR2


Esses registradores armazenam os flags de interrupção de vários periféricos e dos
Timer 1, 2 e 3. Podem ser vistos na Figura 13.
Figura 12 – Registradores PIE1 e PIE2

91
Fonte: Souza (2010).

92
Figura 13 – Registradores PIR1 e PIR2

93
Fonte: Souza (2010).

2.5.5 Contador de Programa – Program Counter :PLCATU, PCLATH e PCL


O contador de programa (PC) especifica o endereço da instrução a ser buscada
para execução. O PC tem 21 bits de largura e está contido em três registradores se-
parados de 8 bits. O byte baixo, conhecido como registrador PCL, é legível e gravá-
vel. O byte alto, ou registrador PCH, contém os bits PC<15:8>; não é diretamente
legível ou gravável. As atualizações no registrador PCH são realizadas através do regis-
trador PCLATH. O byte superior é chamado de PCU. Este registrador contém os bits
PC<20:16>; também não é diretamente legível ou gravável. As atualizações no regis-
tro da PCU são realizadas por meio do registro PCLATU.

2.5.6 Registradores TRISx, PORTx e LATx


Os registradores TRISx servem para configurar as portas como entrada ou como
saída. Quando colocado “1” em um bit do TRIS, o pino relacionado a ele é configura-
do como entrada. Quando colocado “0” o pino é configurado como saída. Já os POR-
Tx, quando um pino dessas portas é configurado como entrada, ao ler o seu bit rela-
cionado, encontra-se diretamente o seu nível lógico aplicado a esse pino. Da mesma
forma, quando configurado como saída, pode-se alterar o seu estado, escrevendo di-
retamente no bit relacionado.

94
Os LATx possuem a mesma função dos PORTx, porém os valores escritos neles são
salvos nos latches da respectiva PORTx. Para a parte introdutória, ambos podem ser
usados para escrita ou leitura da variável. Leia-se o “x” como A, B, C, D e E, portanto,
TRISA é o registrador que configura se o pino é uma entrada ou saída digital, PORTA
e LATA são registradores onde pode-se ler os valores dos pinos ou alterar os valores
de saída. As Figuras 14 a 18 apresentam um resumo de cada registrador relacionados
a cada PORTx. Os valores em cinza não são utilizados pela respectiva PORTx, ou seja,
possuem outra função que não está diretamente relacionado com o PORTx específico.
Figura 14 – Sumário dos registradores do PORTA

Fonte: Datasheet (2023).

Figura 15 – Sumário dos registradores do PORTB

Fonte: Datasheet (2023).

95
Figura 16 – Sumário dos registradores do PORTC

Fonte: Datasheet (2023).

Figura 17 – Sumário dos registradores do PORTD

Fonte: Datasheet (2023).

Figura 18 – Sumário dos registradores do PORTE

Fonte: Datasheet (2023).

96
2.6 MÓDULO TIMER 0
O módulo Timer0 incorpora as seguintes características:
 Operação selecionável por software como temporizador ou contador nos mo-
dos de 8 ou 16 bits;
 Registradores legíveis e graváveis;
 Prescaler programável de software dedicado de 8 bits;
 Clock de incremento selecionável (interna ou externa);
 Seleção de borda para clock externo;
 Interrupção no estouro de contagem.
O registrador TMR0L armazena a parte baixa e TMR0H armazena a parte alta do
contador. Se estiver programado somente para 8 bits, pode-se desconsiderar TMR0H.
As Figuras 19 e 20 apresentam os registradores para configuração do Timer 0, e um
sumário dos registradores associados ao timer0.

97
Figura 19 – T0CON: Registrador para configuração do Timer 0

Fonte: Datasheet (2023).

Figura 20 – Sumário dos registradores do Timer 0

Fonte: Datasheet (2023).

98
Quando configurado para 8 bits, pode-se encontrar o tempo de contagem pela
equação:
T8bits = TCY · prescaler · (256 – carga inicial)

Onde é o clock de máquina, e a carga inicial é o valor salvo no registrador TMR0L.


Para 16 bits, a equação é a seguir:

T16bits = TCY · prescaler · (65536 – carga inicial)

Onde a carga inicial é o valor de 16bits salvo em TMR0H e TMR0L.

2.7 MÓDULO TIMER 1


O módulo temporizador/contador Timer1 incorpora estes recursos:
 Operação selecionável por software como um temporizador ou contador de
16 bits;
 Registradores de 8 bits legíveis e graváveis (TMR1H e TMR1L);
 Fonte de clock selecionável (interna ou externa) com clock do dispositivo ou
opções internas do oscilador Timer1;
 Interrupção no estouro;
 Reinicialização do Módulo no Acionador de Evento Especial CCP;
 Sinalizador de status do relógio do dispositivo (T1RUN).
A Figura 21 e a 22 apresenta os registradores para configuração do Timer 1, e um
sumário dos registradores associados ao timer1. O cálculo de tempo do timer 1 pode
ser feito igual ao timer 0 com 16bits, trocando a parte alta e baixa do registrador pe-
los do timer1.

99
Figura 21 – T1CON: Registrador para configuração do Timer 1

Fonte: Datasheet (2023).

100
Figura 22 – Sumário dos registradores do Timer 1

Fonte: Datasheet (2023).

2.8 MÓDULO TIMER 2


O temporizador do módulo Timer2 incorpora os seguintes recursos:
 Temporizador de 8 bits e registradores de período (TMR2 e PR2, respectiva-
mente);
 Legível e gravável (ambos os registradores);
 Prescaler programável por software (1:1, 1:4 e 1:16);
 Postscaler programável por software (1:1 a 1:16);
 Interrupção na correspondência de TMR2 para PR2.
Diferentemente dos outros timers, no timer 2 é possível associar a um valor “máximo”
de contagem, usando PR2. Ele também possui um segundo multiplicador, o postsca-
ler. Dessa forma seu tempo de contagem pode ser visto com a seguinte equação:

T = TCY · [prescaler · (valor em PR2 + 1 – carga inicial) · postscaler]

As Figuras 22 e 23 apresentam os registradores associados ao timer 2 e um sumá-


rio do mesmo.

101
Figura 23 – T2CON: Registrador para configuração do Timer 1

Fonte: Datasheet (2023).

Figura 24 – Sumário dos registradores do Timer 1

Fonte: Datasheet (2023).

102
2.9 MÓDULO TIMER 3
O temporizador/contador do módulo Timer3 incorpora estes recursos:
 Operação selecionável por software como um temporizador ou contador de
16 bits;
 Registradores de 8 bits legíveis e graváveis (TMR3H e TMR3L);
 Clock selecionável (interna ou externa) com clock do dispositivo ou opções in-
ternas do oscilador do Timer1;
 Interrupção no estouro;
 Reinicialização do Módulo no CCP.
Normalmente utilizado para temporização dos módulos CCP. O cálculo do tempo
é feito da mesma forma que o Timer 1. As Figuras 24 e 25 apresentam os registradores
associados ao timer 2 e um sumário dos registradores associados a ele.

103
Figura 25 – T3CON: Registrador para configuração do Timer 3

Fonte: Datasheet (2023).

104
Figura 26 – Sumário dos registradores do Timer 3

Fonte: Datasheet (2023).

2.10 CONFIGURANDO AS OPÇÕES DO PIC


Deve-se configurar corretamente as opções do PIC (configuration bits ou configu-
ration word); isso pode ser feito no MPLab, na opção: Configure > Configuration Bits.
No entanto, recomenda-se efetuar a configuração no próprio programa fonte;
Algumas definições:
 BOR (Brown-out Reset): força um reset do PIC sempre que a tensão de alimen-
tação cair abaixo de 4V durante um intervalo de tempo maior que 100µs. A du-
ração do reset é de 72ms e, enquanto a tensão de alimentação não for superior
aos 4V, esse temporizador não ser inicializado.
 WDT (Watchdog Timer): espécie de temporizador que força um reset no mi-
crocontrolador de tempos em tempos. Utilizado para evitar que o sistema trave
por algum tipo de falha ou por um loop infinito. WDT deve ser periodicamen-
te zerado (instrução CLRWDT) para não gerar um reset. WDT possui oscilador
próprio e continua operando mesmo em modo SLEEP. O período de estouro
do WDT é de aproximadamente 18ms. Há um prescaler para o WDT, caso seja
desejado um período maior
 POR (Power-on Reset): Circuito interno ao microcontrolador que o mantém
em reset até que VDD alcance o nível suficiente quando a alimentação é liga-
da, para que o PIC possa funcionar corretamente e não sofra problemas duran-
te a energização.

105
 PWRT (Power-up Timer): temporizador que pode ser ativado para garantir que
o microcontrolador somente comece a operar depois que a fonte de alimenta-
ção estiver estabilizada (72ms depois de pulso POR). É ativado por meio de um
bit de configuração (PWRTE). Funciona como uma proteção adicional ao POR.
A diretriz do compilador CONFIG configura diretamente as opções de gravação.
Algumas opções podem ser vistas abaixo. Uma lista completa pode ser vista no Ane-
xo 1. Pode-se utilizar um CONFIG por linha ou usar “,” (vírgula) para separá-los de for-
ma sequencial.
Tabela 1 - Exemplos de Configurações do PIC

FOSC = XT_XT XT oscillator (XT) – Oscilador externo nos pinos OSC1 OSC2
FOSC = INTOSCIO_ EC Oscilador interno.
Pino RA6 como I/O
PWRT = ON Power-up Timer habilitado
PWRT = OFF Power-up Timer desabilitado
BOR = OFF Brown-out Reset habilitado
BOR = ON Brown-out Reset desabilitado
WDT = OFF Watchdog Timer habilitado
WDT = ON Watchdog Timer desabilitado
MCLRE = OFF MasterClear desabilitado. Pino RE3 como entrada.
MCLRE = ON MasterClear habilitado. Pino RE3 é usado para o MCLR.
Fonte: Adaptado do Datasheet (2023).

Para o oscilador interno, pode-se configurar o clock em OSCON<IRCF2:IRCF0>


(ver datasheet) de acordo com a Tabela 2. A configuração padrão é de 1 MHz, ou seja,
caso não for alterado o oscilador interno do PIC terá uma frequência de 1 MHz.
Tabela 2 – Configuração do oscilador interno, registrador OSCCON.

IRCF2:IRCF0 Frequência

111 8 MHz
110 4 MHz
101 2 MHz
100 1 MHz
011 500 kHz
010 250 kHz
001 125 kHz
000 31 kHz
Fonte: Adaptado do Datasheet (2023).

106
3. PROGRAMAÇÃO –
NOÇÕES BÁSICAS
Um bom programa em linguagem Assembly necessita de estruturação, de organi-
zação e de comentários

3.1 ARQUIVOS DE DEFINIÇÃO (INCLUDES)


 Arquivos de texto ou mesmo código fonte incluídos no programa;
 A Microchip já criou um arquivo include para cada tipo de microcontrolador,
onde estão definidos todos os nomes e endereços dos SFRs, além de outras de-
finições necessárias;
 Com tais arquivos evita-se a redigitação de todas essas informações na hora de
começar um novo programa;
 Possuem extensão “.INC”. Estão disponíveis automaticamente juntos à instala-
ção do MPLab.
A seguinte sintaxe deve ser utilizada:

#INCLUDE <nome_do_arquivo.inc>
Fonte: autor (2023).

Pode-se criar um arquivo include. Neste caso, para inserção, tem-se a seguinte sin-
taxe:

#INCLUDE “Drive:diretorio\nome_do_arquivo.inc”
Fonte: autor (2023).

107
3.2 CONSTANTES E DEFINIÇÕES
A diretiva EQU é uma diretiva para o compilador. Associa um nome a um núme-
ro. Com isso, fica mais fácil fazer referência a uma variável por um nome em vez de seu
endereço de memória. Utilizado também para definir constantes que serão utilizadas
no decorrer da programação. Sintaxe:
nome_da_variavel EQU endereço_da_memoria
Fonte: autor (2023).

Ou
nome_da_constante EQU valor_da_constante
Fonte: autor (2023).

Um número pode ser representado de várias formas em assembly do PIC. Decimal


(D’??’ ou .?? ou ??), Hexadecimal (H’??’ ou 0X??), Binário (B’????????’) ou ASCII (A’?’).
Onde “?’ seria o número. Por exemplo, o valor decimal 255, pode ser representado por
255 em decimal, B’11111111’ em binário, 0xFF em hexadecimal.
A diretiva #DEFINE pode ser utilizada para substituir nomes por números e expres-
sões inteiras, comumente utilizada para definir os pinos de entrada e saída do sistema.
Nesse caso, deve-se especificar o bit correto dentro do registrador da porta em ques-
tão. Exemplo:

#DEFINE LED PORTB,1


Fonte: autor (2023).

Após essa definição, o pino RB1 fica referenciado pela palavra LED. Ao alterarmos
ou lermos o valor do LED, irá automaticamente fazer a leitura ou escrita do pino RB1
(PORTB<1>)
ORG: diretiva de compilação. Direciona para a posição de memória de programa-
ção. Utilizado no início do programa para direcionar para o vetor de reset e no início
de interrupções para direcionar para o vetor de interrupções.
END: diretiva que deve ser colocada no final do programa indicando o final da
compilação.

108
CBLOCK e ENDC: maneira simplificada de definir vários EQUs com endereços se-
quenciais. Tal recurso é muito utilizado na definição de variáveis do sistema, onde se
deve indicar somente o endereço da primeira variável. Exemplo:

CBLOCK 0X00 ;endereço inicial do banco de acesso


FLAG ;registrador criado para flags
W_TEMP ;registrador temporário p/ armazenar W
CONT ;registrador contador
ENDC

Fonte: autor (2023).

Ressalta-se que o comentário em assembly vem após o ponto e vírgula “;”.


FLAG é um registrador geralmente criado para serem utilizados como chaves on/
off. Em um único espeço de memória pode-se guardar até oito flags. Por exemplo, um
flag pode sinalizar se um byte já foi transmitido ou não. Após a definição do registrador
FLAG, fica mais fácil definir um nome específico para cada um dos bits (flags), como
por exemplo:

#DEFINE transmitido FLAG,0


#DEFINE recebido FLAG,1

Fonte: autor (2023).

Constantes: com a criação de constantes, pode-se substituir um número por um


nome qualquer:

TEMPO_DLY EQU .20 ;cte. para indicar um tempo de atraso


FREQ_PISCA EQU .50 ;freq. de piscada do led

Fonte: autor (2023).

109
Registrador W (work): O registrador temporário é muito utilizado nas operações
da ULA.
Comandos MOVLW, MOVWF, MOVF, CLRF e CLRW. As sintaxes são:

MOVLW k ;move literal k para W


MOVWF f ;move W para o registrador f
MOVF f,d ;move registrador para d (W ou f)

Fonte: autor (2023).

Note que para guardar um número em uma posição de memória, deve-se primei-
ro movê-lo para W e depois de W para a posição desejada. Por exemplo, para configu-
rar os pinos do PORTB como entrada ou saída, pode-se fazer:

MOVLW B’00000111’
MOVWF TRISB

Fonte: autor (2023).

Com isso, RB0 a RB2 serão entradas enquanto RB3 a BR7 serão saídas. Note que:

MOVLW B’00000000’
MOVWF TRISB

Fonte: autor (2023).

pode ser substituído por

CRLF TRISB
Fonte: autor (2023).

O comando CLRF f limpa o registrador f. Similarmente, o comando CLRFW limpa


o registrador W.

110
Definindo as Entradas e Saídas: antes de começar a escrever o código, deve-se
definir como será o hardware. As entradas e saídas do sistema devem ser bem defini-
das. Assim, pode-se utilizar a diretiva #DEFINE para definir no programa as entradas e
saídas, o que facilita a criação e análise do código. Suponha que seja desejado um bo-
tão no pino RA0 e LEDS nos pinos RB0 a RB2. Assim:

CLRF PORTA ;desliga saidas do PORTA


CLRF PORTB ;desliga saidas do PORTB
MOVWL .10
MOVWF CONT ;inicia variável cont com 10 (decimal)

Fonte: autor (2023).

Rotinas de desvio: Pulos no programa por meio da instrução GOTO. Utilizadas,


geralmente, para deixar o programa mais organizado. Pode-se tomar decisões utilizan-
do estruturas de desvio. Sintaxe:

BRA parte_1 ;parte_1 é nome do local que se deseja ir

Ou
GOTO parte_1 ;parte_1 é nome do local que se deseja ir
Fonte: autor (2023).

O símbolo $ é utilizado para representar a linha atual do programa. Para o PI-


C18F4550, dado a forma que é salvo o código, deve-se utilizar um multiplicador de 2
para linha. Ou seja, para fazer o código voltar para a linha anterior, deve-se usar $ -2.
Logo:

GOTO $+4 ;salta 2 linhas para baixo


GOTO $-2 ;volta uma linha

Fonte: autor (2023).

111
Tal técnica não é recomendada para pulos muito grandes, pois dificulta o entendi-
mento e manutenção do código.

Rotinas de chamada: utilizada quando uma tarefa deve ser repetida várias vezes
(como uma função). A instrução CALL é utilizada. Nesse caso, o próximo ponto do
programa (PC+1) é guardado na pilha para que o sistema retorne a ele mais tarde. Por
exemplo, se o sistema precisa de um atraso em diversos pontos, pode-se criar uma ro-
tina denominada DLY e chamá-la quantas vezes forem necessárias. Sintaxe:

CALL DLY
Fonte: autor (2023).

Para retornar de uma rotina as instruções RETURN ou RETLW são empregadas:

RETURN ;finaliza rotina e volta ao último


; endereço da pilha
RETLW k ;finaliza rotina e volta ao último endereço
;da pilha com o valor k em W

Fonte: autor (2023).

Tomando Decisões e fazendo Desvios:


Testando bits e flags: As instruções para testar bits, que podem ser portas ou flags,
são: BTFSC e BTFSS. Sintaxes

BTFSC f,b ;f é o registrador e b o bit a ser testado


LINHA_1 ; passa por esta linha se o bit for 1
LINHA_2 ; pula para esta linha se o bit for 0

BTFSS f,b ;f é o registrador e b o bit a ser testado


LINHA_1 ; passa por esta linha se o bit for 0
LINHA_2 ; pula para esta linha se o bit for 1

Fonte: autor (2023).

112
Mudando bits e flags: As instruções para alterar um bit são: BSF e BCF. Sintaxes

BSF f,b ;f é o registrador e b o bit a ser setado


BCF f,b ;f é o registrador e b o bit a ser zerado

Fonte: autor (2023).

Leitura de Portas: Portas podem ser lidas como um conjunto ou individualmen-


te. Para ler todo o PORTB pode-se fazer:

MOVF PORTB,W ;escreve o valor de PORTB em W


MOVWV DADO ;DADO recebe o valor de PORTB

Fonte: autor (2023).

Para ler apenas um pino de uma porta pode-se utilizar BTFSS ou BTFSC, como já
visto anteriormente, e consequentemente já tomar uma decisão ou salto de acordo
com a leitura.
Escrita em Portas: similar ao processo de leitura. No entanto, na escrita, se altera
um latch intermediário (a cada pino é associado um latch). Se o pino estiver configu-
rado como saída, seu valor também é afetado, mas se for uma entrada, então só o la-
tch é afetado. Devido a isso, pode-se escrever um valor em um pino que é entrada e,
quando alterado para saída, seu estado será garantido. Por exemplo:

BSF TRISB,0 ;transforma RB0 em entrada


BSF PORTB,0 ;escreve 1 no latch do RBO
;que ainda é entrada
BCF TRISB,0 ;muda RBO para saída. Devido ao latch, o pino
;irá para 1
Fonte: autor (2023).

Pode-se usar também LATB ao invés de PORTB para tal. Souza (2010), por exem-
plo, recomenda usar PORTx para leitura, e LATx para escrita.

113
3.3 OPERAÇÕES ARITMÉTICAS

ADIÇÃO: há seis instruções: INCF, INCFSZ, INFSNZ, ADDWF, ADDWFC, ADDLW.


Sintaxe:

INCF f,d ;incrementa f, salva em d


INCFSZ f,d ;incrementa f e guarda resultado em d
;pula linha se = 0
INFSNZ f,d ; incrementa f e guarda resultado em d
;pula linha se 0
ADDWF f,d ;adiciona F em W, salva em d
ADDWFC f,d ;adiciona W e Carry com F, salva em d
ADDLW k ;adiciona literal k com W
Fonte: autor (2023).

Ressalta-se que D pode assumir F para salvar no registrador especificado, ou


W para salvar no registrador W.
INCF pode ser especialmente utilizada para controlar contadores unitários, tal
como no exemplo seguinte

CLRF CONT ;zera contador CONT


LOOP
CALL BIP ;chama rotina chamada BIP
INCF CONT,F ;incrementa CONT e salva em CONT
BTFSS CONT,3 ;testa o bit 3 de CONT
;caso seja 1 (contagem até 8)
;pula uma linha
GOTO LOOP ;CONT menor que 8. Continua contando
FIM
Fonte: autor (2023).

INCFSZ além de incrementar, testa se o resultado é igual a zero. Nesse caso, como
a palavra é de 8 bits, sempre que o limite 255 é ultrapassado, o valor retorna para zero
e então o programa pula a linha seguinte. O exemplo seguinte implementa um conta-
dor de 246 a 256.

114
MOVLW .246
MOVWF CONT
LOOP
CALL BIP ;chama rotina chamada BIP
INCFSZ CONT,F ;CONT = CONT + 1
;Estourou? (CONT = 0 ?)
GOTO LOOP ;NÃO, retorna ao LOOP
FIM
Fonte: autor (2023).

A seguir são apresentados alguns exemplos de soma.

MOVLW .10
MOVWF NUM_1 ;inicia NUM_1 com 10
MOVLW .20
MOVWF NUM_2 ;inicia NUM_2 com 20
CLRF RESULT ;inicia RESULTADO com 0
SOMA1
MOVF NUM_1,W ;move NUM_1 para W
ADDLW .5 ;soma 5 a W (NUM_1)
MOVWF RESULT ;resultado salvo em RESULT
SOMA2
MOVF NUM_1,W ;move NUM_1 para W
ADDWF NUM_2,W ;soma W (NUM_1) a NUM_2 e salva em
W
MOVWF RESULT ;resultado salvo em RESULT
FIM
Fonte: autor (2023).

O que deve ser feito se o resultado da soma “estourar” oito bits? Os bits C, DC e Z
do registrador STATUS devem ser monitorados.

115
CLRF BYTE_BAIXO ;inicia BYTE_BAIXO com 0
CLRF BYTE_ALTO ;inicia BYTE_ALTO com 0
MOVF NUM_1,W ;move NUM_1 para W
ADDWF NUM_2,W ;W = W + NUM_2
BTFSC STATUS,C ;houve estouro?
INCF BYTE_ALTO,F ;se sim, incrementa BYTE_ALTO
MOVWF BYTE_BAIXO ;armazena soma em BYTE_BAIXO
FIM

Fonte: autor (2023).

SUBTRAÇÃO: há sete instruções: DECF, DECFSZ, DCFSNZ, SUBWF, SUBLW, SUB-


FWB e SUBWFB. Sintaxe:

DECF f,d ;decrementa f, salva em d


DECFSZ f,d ;decrementa f e guarda resultado em d
;pula linha se = 0
DCFSNZ f,d ; decrementa f e guarda resultado em d
;pula linha se 0
SUBWF f,d ;subtrai F em W, salva em d
SUBWFB f,d ;subtrai W de F com borrow, salva em d
SUBFWB f,d ;subtrai F de W com borrow, salva em d
SUBLW k ;subtrai literal k com W

Fonte: autor (2023).

Exemplo de contador utilizando DECFSZ.

CLRF CONT ;zera contador CONT


MOVLW .10
MOVWF CONT ;inicia CONT com 10
LOOP
CALL BIP ;chama rotina chamada BIP
DECFSZ CONT,F ;CONT = CONT - 1
;se = 0, pula linha
GOTO LOOP ;se > 0, continua
FIM

Fonte: autor (2023).

116
A seguir são apresentados exemplos das instruções SUBLW e SUBWF.

MOVLW .10
MOVWF NUM_1 ;inicia NUM_1 com 10
MOVLW .20
MOVWF NUM_2 ;inicia NUM_2 com 20
CLRF RESULT ;inicia RESULTADO com 0
SUB1
MOVF NUM_1,W ;move NUM_1 para W
SUBLW .30 ;(30 – W = 30 – 10 = 20)
MOVWF RESULT ;salva em RESULT
SUB2
MOVF NUM_1,W ;move NUM_1 para W
SUBWF NUM_2,W ;(NUM_2 – W = 20 – 10 = 10 )
MOVWF RESULT ;resultado salvo em RESULT
FIM
Fonte: autor (ano).

Por meio da análise do flag de carry (C) do STATUS, pode-se verificar se o resulta-
do de uma subtração é negativo, positivo ou zero.
 Negativo: C vale 0. Nesse caso o valor é a diferença de resposta para 256.
 Positivo: C vale 1.
 Zero: C vale 1 e o flag de zero (Z) também vale 1.
No exemplo seguinte, o módulo do resultado da subtração é armazenado em RESP
e o flag NEG é setado sempre que o resultado for negativo.

117
MOVLW .10
MOVWF NUM_1 ;inicia NUM_1 com 10
MOVLW .20
MOVWF NUM_2 ;inicia NUM_2 com 20
CLRF RESP ;inicia RESULTADO com 0
SUB1
MOVF NUM_1,W ;move NUM_1 para W
SUBLW .30 ;(30 – W = 30 – 10 = 20)
BTFSS RESP ;resultado negativo?
GOTO TRATA_NEG ;sim, trata resultado negativo
;não. Resultado positivo ou zero
MOVWF RESP ;salva resultado em RESP
BCF NEG ;limpa o flag número negativo
GOTO FIM

TRATA_NEG ;RESP = 256 – W


SUBLW .0 ;0 – W -> W
MOVWF RESP ;coloca result. Em RESP
BSF NEG ;SETA flag número engativo
FIM
Fonte: autor (2023).

COMPARAÇÕES (maior que, e, menor que): A instrução SUBWF pode ser utiliza-
da com este intuito. Ou pode-se utilizar CPFSEQ, CPFGT e CPFLT (esses funcionam de
forma similar dos INCFSZ ou SUBFSZ)

CPFSEQ f,d ;compara f com W, pula linha se =


CPFSGT f,d ;compara f com W, pula linha se f > W
CPFSLT f,d ;compara f com W, pula linha se f < W

Fonte: autor (2023).

118
Exemplos utilizando SUBWF:
COMPARA
MOVF NUM_1,W ;move NUM_1 para W
SUBWF NUM_2,W ;(W = NUM_2 − W)
BTFSS STATUS,C ;resultado negativo?
GOTO RESP1 ;sim. Logo, NUM_2 < NUM_1
GOTO RESP2 ;não. Logo, NUM_2 >= NUM_1
FIM
Fonte: autor (2023).

COMPARA
MOVLW k ;move literal k para W
SUBWF NUM_2,W ;(W = NUM_2 − W)
BTFSS STATUS,C ;resultado negativo?
GOTO RESP1 ;sim. Logo, NUM_2 < k
GOTO RESP2 ;não. Logo, NUM_2 >= k
FIM

Fonte: autor (2023).

MULTIPLICAÇÃO e DIVISÃO: estas operações são relativamente complicadas


de se implementar em Assemby. Para multiplicação, pode-se utilizar as instruções
MULWF e MULLW. Para divisão, que é relativamente complicada de se implementar
em Assemby, a função RRF (desloca bit para direita) é constantemente utilizada como
parte do processo. Para maiores detalhes, consulte as referências utilizadas.

119
3.4 TRABALHANDO COM PROGRAM COUNTER
Program Counter contém o endereço da próxima instrução a ser executada. Caso
o seu valor seja alterado, muda-se o ponto de execução do programa. Deve ser utili-
zado com cuidado, pois pode mover para um ponto desconhecido. Pode-se utilizar o
PCL (parte menos significativa do program counter) para causar um desvio para uma
rotina específica de acordo com um índice. Por exemplo, o número do botão pressio-
nado (0 a 7) é colocado na variável TECLA. Utilizando o PCL, o programa é desviado
para a rotina que tratará cada tecla separadamente.
TRATA_TECLA
MOVLW B’00000111’
ANDWF TECLA,W ;mascará para limitar valor em 7
ADDWF PCL,F
GOTO TECLA0
GOTO TECLA1
GOTO TECLA2
GOTO TECLA3
GOTO TECLA4
GOTO TECLA5
GOTO TECLA6
GOTO TECLA7
RETURN
Fonte: autor (2023).

Um outro exemplo de aplicação para alteração do PCL é a criação de uma tabela.


Ao invés de desviar para uma rotina específica, um número é retornado para cada va-
lor do índice somado ao PCL. Por exemplo:
CONVERTE ;rotina de conversão (W = NUM * 3 + 2)
MOVLW B’00000111’
ANDWF NUM,W ;mascara para limitar valor em 7
ADDWF PCL,F
RETLW .2
RETLW .5
RETLW .8
RETLW .11
RETLW .14
RETLW .17
RETLW .20
RETLW .23
Fonte: autor (2023).

120
3.4 CONTAGEM DE TEMPO E GERAÇÃO DE ATRASOS
O tempo dentro do PIC pode ser medido de três maneiras diferentes:
 Contagem dos ciclos de máquina por meio dos loops e registradores temporá-
rios (fácil implementação, mas não é muito preciso);
 Contando os ciclos de máquina por intermédio do contador TMRO ou TMR1,
TMR2 ou TMR3 (uso de estouro dos timers para gerar interrupções);
 Contando os pulsos externos por meio da entrada T0CKl e do TMR0 ou da en-
trada T1CKl e do TMR1.
As duas primeiras maneiras dependem do clock do sistema, enquanto a terceira
depende de um clock externo.
Registradores temporários para atraso: A ideia é criar contadores dentro de outros
contadores para contar ciclos de máquina e, consequentemente, gerar um atraso. De-
ve-se calcular corretamente a quantidade de ciclos utilizados para cada loop. A quan-
tidade de ciclos para cada função pode ser vista na coluna “ciclos” da Figura 7.

DELAY
MOVLW .250
MOVWF TEMP1 ;inicia TEMP1 com 250
DL_1
NOP ;gasta um ciclo de máquina
DECFSZ TEMP1,F ;decrement TEMP1. Acabou?
GOTO DL_1 ;não. Continua decrementando
RETURN ;sim. Finaliza.

Fonte: autor (ano).

Cada Loop (DL_1) dura quatro ciclos, 4 × 1µs, para oscilar a 4MHz. Como o con-
tador TEMP1 é decrementado 250 vezes, a rotina dura 1ms. Note que mais dois ciclos
serão gastos para a chamada CALL e mais dois na inicialização do contador TEMP1. A
instrução NOP não faz nada, mas gasta um ciclo de máquina.

121
3.5 INTERRUPÇÕES

A seguir serão descritas as rotinas de tratamento de interrupções. Os registrado-


res INTCON, INTCON2, INTCON3, PIE1, PIR1, PIE2, PIR2, IPR1 e IPR2 já estudados de-
vem ser observados antes de se criar uma rotina de interrupção. Neles estão presen-
tes os bits que habilitam as interrupções e os bits (flags) de identificação da ocorrência
de uma dada interrupção.
Para qualquer interrupção, o bit GIE de INTCON deve ser habilitado, pois represen-
ta a chave geral das interrupções.
Sempre que uma interrupção ocorre o programa é desviado para o endereço
0X0008 (interrupções de alta prioridade) ou 0X0016 (interrupções de baixa priorida-
de) da memória de programa, que corresponde ao vetor de interrupção. Caso a prio-
ridade não for habilitada, todas as interrupções são desviadas para o vetor 0x0008. A
habilitação de interrupção com prioridade é feita setando o bit IPEN do registrador
RCON, e os bits referentes de cada interrupção.
No código em Assembly, a rotina de interrupção deve vir seguida do comando:

ORG 0X0008 ; ENDEREÇO DO VETOR DE INTERRUPÇÃO

ORG 0X0018 ; ENDEREÇO DO VETOR DE INTERRUPÇÃO

Fonte: autor (ano).

É muito importante que os registradores prioritários (STATUS, WREG e BSR), que


podem ser alterados tanto dentro como fora das interrupções, sejam salvos em regis-
tradores temporários e, posteriormente, sejam recuperados. Se estiver usando ambas
prioridades de interrupção, deve-se criar dois conjuntos de variáveis para tal, sendo
uma para prioridade alta e outra para prioridade baixa. Caso não estiver usando prio-
ridade de interrupção, pode-se usar somente um conjunto de variáveis na RAM para
armazenar os registradores prioritários. Por exemplo:

122
ORG 0X0008 ;VETOR DE INTERRUPÇÃO (ALTA PRIORIDADE
GOTO SALVA_CONTEXTO_H ; salta para rotina SALVA_CONTEXTO_H
SALVA_CONTEXTO_H
MOVFF WREG,WREG_TEMP_H ;salva reg. W em WREG_TEMP_H
MOVFF STATUS,STATUS_TEMP_H ;salva reg. STATUS em STATUS_
TEMP_H
MOVFF BSR,BSR_TEMP_H ;salva reg. BSR em BSR_TEMP_H

SALVA_CONTEXTO_H
MOVFF WREG,WREG_TEMP_H ;salva reg. W em WREG_TEMP_H
MOVFF STATUS,STATUS_TEMP_H ;salva reg. STATUS em STATUS_
TEMP_H
MOVFF BSR,BSR_TEMP_H ;salva reg. BSR em BSR_TEMP_H
GOTO TRATA_INT_H ;pula para a rotina de tratamento da int.

ORG 0X0018 ;VETOR DE INTERRUPÇÃO (BAIXA PRIORIDADE)


GOTO SALVA_CONTEXTO_L ; salva para a rotina SALVA_CONTEXTO_L

SALVA_CONTEXTO_L
MOVFF WREG,WREG_TEMP_L ;salva reg. W em WREG_TEMP_L
MOVFF STATUS,STATUS_TEMP_L ;salva reg. STATUS em STATUS_TEM-
P_L
MOVFF BSR,BSR_TEMP_L ;salva reg. BSR em BSR_TEMP_L
GOTO TRATA_INT_L ;pula para a rotina de tratamento da int.

Fonte: autor (ano).

Antes de se executar a interrupção propriamente dita costuma-se testar se o flag


da interrupção gerada está ativado, em suas respectivas rotinas e prioridades específi-
cas. Por exemplo, caso somente as interrupções de TMR0 e TMR1 estejam habilitadas,
e não foram configuradas como prioridade, pode-se fazer o seguinte teste.

BTFSS INTCON,TMR0IF ;foi interrupção de TMR0 ?


GOTO INT_TMR1 ;não – então pula para INT_TRM1
GOTO INT_TMR0 ;sim – então pula para INT_TMR0;

Fonte: autor (ano).

123
Dessa forma, como só existem dois componentes que possam gerar a interrupção,
podemos testar uma, e caso ela for falsa, consequentemente será a outra fonte de in-
terrupção.
No final da rotina de tratamento da interrupção, deve-se limpar o flag da interrup-
ção correspondente e restaurar os registradores salvos no início da rotina. Exemplo:

SAI_INT_TMR0
BCF INTCON,TMR0IF ;limpa flag da interrupção de
TMR0
GOTO SAI_INT_H ;pula para SAI_INT_H

SAI_INT_H ;rotina de retorno da interrupçãp


MOVFF WREG_TEMP_H,WREG ;recupera WREG
MOVFF STATUS_TEMP_H,STATUS ;recupera STATUS
MOVFF BSR_TEMP_H ,BSR ;recupera BSR
RETFIE ;retorna da interrupção

Fonte: autor (ano).

Lembre-se que o comando RETFIE (ou RETLW – retorna com um literal salvo no
registrador W) é utilizado para retornar da rotina de interrupção.
A tabela 3 apresenta um sumário das interrupções do PIC18F4550, com flag de in-
terrupção, bits de habilitação e prioridade.

124
Tabela 3 – Controle de Interrupções

Flag Habilitação Prioridade


Evento de interrupção 1 = ocorreu 1 = Habilitada 1 = Alta
0 = n˜ao ocorreu 0 = Desabilitada 0 = Baixa
INTCON INTCON INTCON2
Interrupção externa INT0 INT0IF INT0IE Sempre alta
Estouro do timer 0 TMR0IF TMR0IE TMR0IP
Mudança de estado na porta B RBIF RBIE RBIP
INTCON3 INTCON3 INTCON3
Interrupção externa INT1 INT1IF INT1IE INT1IP
Interrupção externa INT2 INT2IF INT2IE INT2IP
PIR1 PIE1 IPR1
Leitura ou escrita da porta paralela escrava PSPIF PSPIE PSPIP
Conversão do AD completa ADIF ADIE ADIP
Recepção serial USART RCIF RCIE RCIP
Transmissão serial TXIF TXIE TXIP
Transmissão/recepção completa pelo MSSP SSPIF SSPIE SSPIP
Interrupção do módulo CCP1 CCP1IF CCP1IE CCP1IP
Estouro do timer 2 TMR2IF TMR2IE TMR2IP
Estouro do timer 1 TMR1IF TMR1IE TMR1IP
PIR2 PIE2 IPR2
Falha no oscilador OSCFIF OSCFIE OSCFIP
Alteração no estado do comparador CMIF CMIE CMIP
Término de escrita na EEPROM EEIF EEIE EEIP
Colisão no barramento SPI BCLIF BCLIE BCLIP
Detecção de baixa/alta tensão HLVDIF HLVDIE HLVDIP
Estouro do timer 3 TMR3IF TMR3IE TMR3IP
Interrupção do módulo CCP2 CCP2IF CCP2IE CCP2IP

Fonte: Adriano (2014).

125
4. EXERCÍCIOS

4.1 EXEMPLO 1
Dada a Figura 27, desenvolva o código para que o LED acenda quando BT1 é pres-
sionado.
Figura 27 – Diagrama Elétrico do exemplo .

Fonte: autor (2023)

Primeiro devemos compreender o funcionamento do circuito. Pegue o circuito do


Botão. Quando o botão está solto tem-se 5V sendo jogado a entrada RB0, o que re-
presenta o sinal lógico 1 ou “ALTO’. Ao se pressionar o botão, conecta-se a referência
ao circuito, efetivamente, tem-se o sinal lógico 0 ou “baixo”. Portanto:
 BT pressionado envia o sinal lógico 0 para o pino RB0
 BT solto, envia o sinal lógico 1 para o pino RB0.

126
Podemos fazer a mesma análise para o LED. O pino RD0 deverá ser configurado
como saída. Verificando o funcionamento do LED, queremos que ele acenda e apague
de acordo com o nosso botão. Se o sinal em RD1 for “0”, o LED estará apagado pois o
circuito interno do RD1 estará fornecendo a referência entre a alimentação e o resis-
tor. Porém, quando RD1 estiver em “1”, o LED estará sendo alimentado com tensão e,
portanto, ligará. Dessa forma:
 Se RD1 = 1, o LED irá acender;
 Se RD = 0, o LED irá apagar.
Portanto podemos montar o fluxograma que corresponde a nossa lógica, apresen-
tado na Figura 28
Figura 28 – Fluxograma exemplo 1 .

Fonte: Souza (2010)

127
De maneira genérica, os blocos de início, Vetor reset..., e configurações iniciais se-
rão comuns para todos os exercícios, mas deverão ser implementados no código de
maneira específica para cada exercício. Na sequência, temos a lógica a ser implemen-
tada. Dessa forma, primeiro testamos o botão, se ele estiver pressionado (RB0 recebe
BAIXO) liga-se o LED, e se caso o botão não estiver pressionado (RB0 recebe ALTO).
O quadro 1 apresenta o código para esse problema. Lembre-se que ponto e vírgula repre-
senta um comentário. Na sequência será visto parte a parte do código.

Quadro 1 – Código do Exemplo 1.

;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;* ARQUIVOS DE DEFINIÇÕES *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
#INCLUDE <P18F4550.INC> ;ARQUIVO PADRÃO MICROCHIP PARA 18F4550

CONFIG WDT = OFF ;WDT DESLIGADO


CONFIG PBADEN = OFF ;PINOS RB<4:0> COMO ENTRADA DIGITAL
CONFIG MCLRE = OFF ;MASTERCLEAR RESET DESATIVADO
CONFIG FOSC = INTOSCIO_EC ;CLOCK PELO OSCILADOR INTERNO

;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;* PAGINAÇÃO DE MEMÓRIA *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;DEFINIÇÃO DE COMANDOS DE USUÁRIO PARA ALTERAÇÃO DA PÁGINA
;DE MEMÓRIA

;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;* VARIÁVEIS *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; DEFINIÇÃO DOS NOMES E ENDEREÇOS DE TODAS AS VARIÁVEIS UTILIZADAS
; PELO SISTEMA

Continua

128
CBLOCK 0X00 ;ENDEREÇO INICIAL DA MEMÓRIA DE USUÁRIO

ENDC ;FIM DO BLOCO DE MEMÓRIA

;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;* CONSTANTES *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; DEFINIÇÃO DE TODAS AS CONSTANTES UTILIZADAS PELO SISTEMA

;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;* ENTRADAS *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; DEFINIÇÃO DE TODOS OS PINOS QUE SERÃO UTILIZADOS COMO ENTRADA
; RECOMENDAMOS TAMBÉM COMENTAR O SIGNIFICADO DE SEUS ESTADOS (0 E 1)

#DEFINE BT PORTB,0;BOTÃO
; 0 -> PRESSIONADO
; 1 -> LIBERADO

;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;* SAIDAS *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; DEFINIÇÃO DE TODOS OS PINOS QUE SERÃO UTILIZADOS COMO ENTRADA
; RECOMENDAMOS TAMBÉM COMENTAR O SIGNIFICADO DE SEUS ESTADOS (0 E 1)

#DEFINE LED PORTD,0 ;LED


; 0 -> DESLIGADO
; 1 -> LIGADO

;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;* VETOR DE RESET *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Continua

129
ORG 0x0000 ;ENDEREÇO INICIAL DE PROCESSAMENTO
GOTO INICIO

;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;* VETOR DE RESET *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

ORG 0x0008 ;ENDEREÇO INICIAL DE PROCESSAMENTO


RETFIE

;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;* VETOR DE RESET *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
ORG 0x0018 ;ENDEREÇO INICIAL DE PROCESSAMENTO
RETFIE

;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;* INICIO DO PROGRAMA *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; Configurações inicias das portas, timers, interrupções
;etc

INICIO
CLRF PORTB ;LIMPA O PORTB
CLRF PORTD ;LIMPA O PORTD

MOVLW B’00000001’
MOVWF TRISB ;DEFINE RB0 COMO ENTRADA

MOVLW B’00000000’
MOVWF TRISD ;TODO O PORTD COMO SAÍDA

Continua

130
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;* INICIALIZAÇÃO DAS VARIÁVEIS *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;* ROTINA PRINCIPAL *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

PRINCIPAL
BTFSC BT ; O BOTAO ESTÁ PRESSIONADO?
GOTO BOTAO_LIB ;NAO, ENTAO TRATA BOTAO LIBERADO
GOTO BOTAO_PRES ;SIM, ENTRA TRATA BOTAO PRESSIONADO

BOTAO_LIB
BCF LED ;APAGA O LED
GOTO PRINCIPAL ;RETORNA AO LOOP PRINCIPAL

BOTAO_PRES
BSF LED ;ACENDE O LED
GOTO PRINCIPAL ;RETORNA AO LOOP PRINCIPAL

;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;* FIM DO PROGRAMA *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

END ;OBRIGATÓRIO

Fim

131
Figura 29 – Exemplo 1

Fonte: autor (2023)

Na Figura 29, temos o #INCLUDE <P18F4550.INC>, nesse arquivo tem-se todas as


definições dos valores de configuração e definição das variáveis. Todos os arquivos de-
vem iniciar com ele. Na sequência tem-se as configurações do PIC.
Figura 30 – Exemplo 1.

Fonte: autor (2023)

Na Figura 30 definimos a palavra BT para o bit 0 do PORTB, ou seja, estamos asso-


ciando a palavra BT para o pino RB0. De forma similar, na Figura 31, associamos a pa-
lavra LED com o pino RD0.

132
Figura 31 – Exemplo 1.

Fonte: autor (2023)

Figura 32 – Exemplo 1

Fonte: autor (2023)

Na Figura 32, temos a configuração do funcionamento das portas. Para garantirmos


que os valores dos registradores estejam zerados, utilizamos CLRF para zerar PORTB
e PORTD. Na sequência precisamos configurar o funcionamento dos pinos do de RBx
e RDx. Como queremos que RB0 seja entrada, devemos, portanto, setar o bit 0 do re-
gistrador TRISB e queremos que o RD0 funcione como saída, assim podemos zerar o
registrador TRISD. Lembre-se que para os registradores TRISx, o valor “0” representa o
pino como saída e “1” como entrada.

133
Figura 33 – Exemplo 1

Fonte: autor (2023)

A Figura 33 apresenta a rotina principal do código onde testamos o botão (BT) pela
instrução BTFSC (pula uma linha se o bit verificado for zero), e de acordo com a nossa
lógica, se o BT estiver lendo como 0 ele está pressionado. Dessa forma, irá executar a
rotina BOTAO_PRES, o qual irá setar o LED e voltar para a rotina principal. De forma si-
milar, se BT estiver como 1, ele está liberado, e consequentemente desligamos o LED
através da rotina BOTAO_LIB.

134
SUGESTÃO DE LEITURA
SOUSA, D. R. Desbravando o Microcontrolador PIC18: Recursos
Avançados. 1ed. São Paulo. Érica, 2010.
Capítulo 2 – O PIC18F4520

MICROCHIP. PIC18F4550
Datasheet. 2006.

SOUZA, David José de. Desbravando o PIC:


ampliado e atualizado para PIC16F628A.
12. ed. São Paulo: Érica, 2013.
Capítulo 2

PEREIRA, Fábio. Microcontrolador PIC18 detalhado:


hardware e software: PIC18F4520. São Paulo: Érica, 2010.
Capítulo 1

135
REFERÊNCIAS
ADRIANO, J. D. Exsto – Xm118 – Microcontroladores PIC18, 2014.
FLOYD, T. L. Digital Fundamentals, 11ed. Prentice Hall, 2014 MICROCHIP. PIC18F4550
Datasheet. 2006.
PEREIRA, V. Microcontroladores PIC 16F e 18F – Teoria e Prática. São Paulo - Brasil -
2013
TORRE, F. E., MARTINS, H. R. Sistemas microcontrolados. INOVA – UFMG, 2012.
SOUZA, D. R. Desbravando o Microcontrolador PIC18: Recursos Avançados. 1ed. São
Paulo. Érica, 2010.

136
CONSIDERAÇÕES FINAIS
Caro(a) estudante, depois de todo o estudo e dedicação destinado a essa tercei-
ra Unidade, você já conhece as principais características do PIC18F4550, o hardware
básico implementado neles, o seu funcionamento, bem como a utilização da lingua-
gem Assembly.
Essa linguagem tem como características ser uma das linguagens “baixa” de pro-
gramação, ou seja, você está instruindo o PIC passo a passo, de acordo com o seu fun-
cionamento físico (hardware), o que ele deve fazer. E, portanto, conseguimos ter um
entendimento básico de como um microcontrolador funciona.
Por justamente ser uma linguagem baixa, o aprendizado dessa linguagem acaba
sendo oneroso, porém, de acordo com a necessidade, é uma ótima linguagem para
otimização do código e do funcionamento de microcontrolador.
Porém, para aplicações de periféricos, focaremos na linguagem C, tópico de discus-
são e estudo da próxima unidade, já que outros sistemas de prototipagem podem ser
facilmente programados por C e são bastante utilizados para trabalhos de conclusão
de curso, como por exemplo, os mais comuns utilizados são os kits de desenvolvimen-
to usando ESP32, ESP8266, ou Arduino.

137
ANEXO 1.

Lista completa de Configurações iniciais do PIC18F4550


; PLL Prescaler Selection bits:
; PLLDIV = 1 No prescale (4 MHz oscillator input drives PLL directly)
; PLLDIV = 2 Divide by 2 (8 MHz oscillator input)
; PLLDIV = 3 Divide by 3 (12 MHz oscillator input)
; PLLDIV = 4 Divide by 4 (16 MHz oscillator input)
; PLLDIV = 5 Divide by 5 (20 MHz oscillator input)
; PLLDIV = 6 Divide by 6 (24 MHz oscillator input)
; PLLDIV = 10 Divide by 10 (40 MHz oscillator input)
; PLLDIV = 12 Divide by 12 (48 MHz oscillator input)
;
; System Clock Postscaler Selection bits:
; CPUDIV = OSC1_PLL2 [Primary Oscillator Src: /1][96 MHz PLL Src: /2]
; CPUDIV = OSC2_PLL3 [Primary Oscillator Src: /2][96 MHz PLL Src: /3]
; CPUDIV = OSC3_PLL4 [Primary Oscillator Src: /3][96 MHz PLL Src: /4]
; CPUDIV = OSC4_PLL6 [Primary Oscillator Src: /4][96 MHz PLL Src: /6]
;
; USB Clock Selection bit (used in Full-Speed USB mode only; UCFG:FSEN = 1):
; USBDIV = 1 USB clock source comes directly from the primary oscillator block with no postscale
; USBDIV = 2 USB clock source comes from the 96 MHz PLL divided by 2
;
; Oscillator Selection bits:
; FOSC = XT_XT XT oscillator (XT)
; FOSC = XTPLL_XT XT oscillator, PLL enabled (XTPLL)
; FOSC = ECIO_EC EC oscillator, port function on RA6 (ECIO)
; FOSC = EC_EC EC oscillator, CLKO function on RA6 (EC)
; FOSC = ECPLLIO_EC EC oscillator, PLL enabled, port function on RA6 (ECPIO)
; FOSC = ECPLL_EC EC oscillator, PLL enabled, CLKO function on RA6 (ECPLL)
; FOSC = INTOSCIO_EC Internal oscillator, port function on RA6, EC used by USB (INTIO)
; FOSC = INTOSC_EC Internal oscillator, CLKO function on RA6, EC used by USB (INTCKO)
; FOSC = INTOSC_XT Internal oscillator, XT used by USB (INTXT)
; FOSC = INTOSC_HS Internal oscillator, HS oscillator used by USB (INTHS)
; FOSC = HS HS oscillator (HS)
; FOSC = HSPLL_HS HS oscillator, PLL enabled (HSPLL)
;
; Fail-Safe Clock Monitor Enable bit:
; FCMEN = OFF Fail-Safe Clock Monitor disabled
; FCMEN = ON Fail-Safe Clock Monitor enabled
;
; Internal/External Oscillator Switchover bit:
; IESO = OFF Oscillator Switchover mode disabled
; IESO = ON Oscillator Switchover mode enabled
;

138
; Power-up Timer Enable bit:
; PWRT = ON PWRT enabled
; PWRT = OFF PWRT disabled
;
; Brown-out Reset Enable bits:
; BOR = OFF Brown-out Reset disabled in hardware and software
; BOR = SOFT Brown-out Reset enabled and controlled by software (SBOREN is enabled)
; BOR = ON_ACTIVE Brown-out Reset enabled in hardware only and disabled in Sleep mode (SBOREN is disabled)
; BOR = ON Brown-out Reset enabled in hardware only (SBOREN is disabled)
;
; Brown-out Reset Voltage bits:
; BORV = 0 Maximum setting 4.59V
; BORV = 1 Setting 2 4.33V
; BORV = 2 Setting 1 2.79V
; BORV = 3 Minimum setting 2.05V
;
; USB Voltage Regulator Enable bit:
; VREGEN = OFF USB voltage regulator disabled
; VREGEN = ON USB voltage regulator enabled
;
; Watchdog Timer Enable bit:
; WDT = OFF WDT disabled (control is placed on the SWDTEN bit)
; WDT = ON WDT enabled
;
; Watchdog Timer Postscale Select bits:
; WDTPS = 1 1:1
; WDTPS = 2 1:2
; WDTPS = 4 1:4
; WDTPS = 8 1:8
; WDTPS = 16 1:16
; WDTPS = 32 1:32
; WDTPS = 64 1:64
; WDTPS = 128 1:128
; WDTPS = 256 1:256
; WDTPS = 512 1:512
; WDTPS = 1024 1:1024
; WDTPS = 2048 1:2048
; WDTPS = 4096 1:4096
; WDTPS = 8192 1:8192
; WDTPS = 16384 1:16384
; WDTPS = 32768 1:32768
;
; CCP2 MUX bit:
; CCP2MX = OFF CCP2 input/output is multiplexed with RB3
; CCP2MX = ON CCP2 input/output is multiplexed with RC1
;
; PORTB A/D Enable bit:
; PBADEN = OFF PORTB<4:0> pins are configured as digital I/O on Reset
; PBADEN = ON PORTB<4:0> pins are configured as analog input channels on Reset
;
; Low-Power Timer 1 Oscillator Enable bit:

139
; LPT1OSC = OFF Timer1 configured for higher power operation
; LPT1OSC = ON Timer1 configured for low-power operation
;
; MCLR Pin Enable bit:
; MCLRE = OFF RE3 input pin enabled; MCLR pin disabled
; MCLRE = ON MCLR pin enabled; RE3 input pin disabled
;
; Stack Full/Underflow Reset Enable bit:
; STVREN = OFF Stack full/underflow will not cause Reset
; STVREN = ON Stack full/underflow will cause Reset
;
; Single-Supply ICSP Enable bit:
; LVP = OFF Single-Supply ICSP disabled
; LVP = ON Single-Supply ICSP enabled
;
; Dedicated In-Circuit Debug/Programming Port (ICPORT) Enable bit:
; ICPRT = OFF ICPORT disabled
; ICPRT = ON ICPORT enabled
;
; Extended Instruction Set Enable bit:
; XINST = OFF Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
; XINST = ON Instruction set extension and Indexed Addressing mode enabled
;
; Background Debugger Enable bit:
; DEBUG = ON Background debugger enabled, RB6 and RB7 are dedicated to In-Circuit Debug
; DEBUG = OFF Background debugger disabled, RB6 and RB7 configured as general purpose I/O pins
;
; Code Protection bit:
; CP0 = ON Block 0 (000800-001FFFh) is code-protected
; CP0 = OFF Block 0 (000800-001FFFh) is not code-protected
;
; Code Protection bit:
; CP1 = ON Block 1 (002000-003FFFh) is code-protected
; CP1 = OFF Block 1 (002000-003FFFh) is not code-protected
;
; Code Protection bit:
; CP2 = ON Block 2 (004000-005FFFh) is code-protected
; CP2 = OFF Block 2 (004000-005FFFh) is not code-protected
;
; Code Protection bit:
; CP3 = ON Block 3 (006000-007FFFh) is code-protected
; CP3 = OFF Block 3 (006000-007FFFh) is not code-protected
;
; Boot Block Code Protection bit:
; CPB = ON Boot block (000000-0007FFh) is code-protected
; CPB = OFF Boot block (000000-0007FFh) is not code-protected
;
; Data EEPROM Code Protection bit:
; CPD = ON Data EEPROM is code-protected
; CPD = OFF Data EEPROM is not code-protected
;

140
; Write Protection bit:
; WRT0 = ON Block 0 (000800-001FFFh) is write-protected
; WRT0 = OFF Block 0 (000800-001FFFh) is not write-protected
;
; Write Protection bit:
; WRT1 = ON Block 1 (002000-003FFFh) is write-protected
; WRT1 = OFF Block 1 (002000-003FFFh) is not write-protected
;
; Write Protection bit:
; WRT2 = ON Block 2 (004000-005FFFh) is write-protected
; WRT2 = OFF Block 2 (004000-005FFFh) is not write-protected
;
; Write Protection bit:
; WRT3 = ON Block 3 (006000-007FFFh) is write-protected
; WRT3 = OFF Block 3 (006000-007FFFh) is not write-protected
;
; Configuration Register Write Protection bit:
; WRTC = ON Configuration registers (300000-3000FFh) are write-protected
; WRTC = OFF Configuration registers (300000-3000FFh) are not write-protected
;
; Boot Block Write Protection bit:
; WRTB = ON Boot block (000000-0007FFh) is write-protected
; WRTB = OFF Boot block (000000-0007FFh) is not write-protected
;
; Data EEPROM Write Protection bit:
; WRTD = ON Data EEPROM is write-protected
; WRTD = OFF Data EEPROM is not write-protected
;
; Table Read Protection bit:
; EBTR0 = ON Block 0 (000800-001FFFh) is protected from table reads executed in other blocks
; EBTR0 = OFF Block 0 (000800-001FFFh) is not protected from table reads executed in other blocks
;
; Table Read Protection bit:
; EBTR1 = ON Block 1 (002000-003FFFh) is protected from table reads executed in other blocks
; EBTR1 = OFF Block 1 (002000-003FFFh) is not protected from table reads executed in other blocks
;
; Table Read Protection bit:
; EBTR2 = ON Block 2 (004000-005FFFh) is protected from table reads executed in other blocks
; EBTR2 = OFF Block 2 (004000-005FFFh) is not protected from table reads executed in other blocks
;
; Table Read Protection bit:
; EBTR3 = ON Block 3 (006000-007FFFh) is protected from table reads executed in other blocks
; EBTR3 = OFF Block 3 (006000-007FFFh) is not protected from table reads executed in other blocks
;
; Boot Block Table Read Protection bit:
; EBTRB = ON Boot block (000000-0007FFh) is protected from table reads executed in other blocks
; EBTRB = OFF Boot block (000000-0007FFh) is not protected from table reads executed in other blocks

141
ANEXO II

Código em branco base


Utilize esse código para implementar no MPLAB as lógicas. Lembre-se de comen-
tar e organizar o código seguindo os cabeçalhos. COPIE E COLE NO MPLAB.

;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;* ARQUIVOS DE DEFINIÇÕES *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
#INCLUDE <P18F4550.INC> ;ARQUIVO PADRÃO MICROCHIP PARA 18F4550

CONFIG WDT = OFF ;WDT DESLIGADO


CONFIG PBADEN = OFF ;PINOS RB<4:0> COMO ENTRADA DIGITAL
CONFIG MCLRE = OFF ;MASTERCLEAR RESET DESATIVADO
CONFIG FOSC = INTOSCIO_EC ;CLOCK PELO OSCILADOR INTERNO

;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;* PAGINAÇÃO DE MEMÓRIA *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;DEFINIÇÃO DE COMANDOS DE USUÁRIO PARA ALTERAÇÃO DA PÁGINA DE MEMÓRIA

;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;* VARIÁVEIS *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; DEFINIÇÃO DOS NOMES E ENDEREÇOS DE TODAS AS VARIÁVEIS UTILIZADAS
; PELO SISTEMA

CBLOCK 0X00 ;ENDEREÇO INICIAL DA MEMÓRIA DE USUÁRIO


STATUS_TEMP_H

142
WREG_TEMP_H
BSR_TEMP_H
STATUS_TEMP_L
WREG_TEMP_L
BSR_TEMP_L

ENDC ;FIM DO BLOCO DE MEMÓRIA

;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;* CONSTANTES *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; DEFINIÇÃO DE TODAS AS CONSTANTES UTILIZADAS PELO SISTEMA

;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;* ENTRADAS *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; DEFINIÇÃO DE TODOS OS PINOS QUE SERÃO UTILIZADOS COMO ENTRADA
; RECOMENDAMOS TAMBÉM COMENTAR O SIGNIFICADO DE SEUS ESTADOS (0 E 1)

#DEFINE BT PORTB,0;BOTÃO
; 0 -> PRESSIONADO
; 1 -> LIBERADO

;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;* SAIDAS *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; DEFINIÇÃO DE TODOS OS PINOS QUE SERÃO UTILIZADOS COMO ENTRADA
; RECOMENDAMOS TAMBÉM COMENTAR O SIGNIFICADO DE SEUS ESTADOS (0 E 1)

#DEFINE LED PORTD,0 ;LED


; 0 -> DESLIGADO
; 1 -> LIGADO

143
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;* VETOR DE RESET *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

ORG 0x0000 ;ENDEREÇO INICIAL DE PROCESSAMENTO


GOTO INICIO

;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;* VETORES DE INTERRUPCAO *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

ORG 0x0008 ;ENDEREÇO INICIAL DE PROCESSAMENTO


GOTO TRATA_INTERRUPCAO_H

ORG 0x0018 ;ENDEREÇO INICIAL DE PROCESSAMENTO


GOTO TRATA_INTERRUPCAO_L

;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;* TRATAMENTO INTERRUPCAO ALTA *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

TRATA_INTERRUPCAO_H
SALVA_CONTEXTO_H
MOVFF WREG,WREG_TEMP_H ;salva reg. W em WREG_TEMP_H
MOVFF STATUS,STATUS_TEMP_H ;salva reg. STATUS em STATUS_TEMP_H
MOVFF BSR,BSR_TEMP_H ;salva reg. BSR em BSR_TEMP_H

;SEU CÓDIGO DE INTERRUPÇAO COM PRIORIDADE ALTA, OU SEM


CONFIGURAR
;A PRIORIDADE, DEVE SER FEITO AQUI.


RESTAURA_CONTEXTO_H ;rotina de retorno da interrupçãp

144
MOVFF WREG_TEMP_H,WREG ;recupera WREG
MOVFF STATUS_TEMP_H,STATUS ;recupera STATUS
MOVFF BSR_TEMP_H ,BSR ;recupera BSR
RETFIE

;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;* TRATAMENTO INTERRUPCAO BAIXA *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

TRATA_INTERRUPCAO_L
SALVA_CONTEXTO_L
MOVFF WREG,WREG_TEMP_L ;salva reg. W em WREG_TEMP_L
MOVFF STATUS,STATUS_TEMP_L ;salva reg. STATUS em STATUS_TEMP_L
MOVFF BSR,BSR_TEMP_L ;salva reg. BSR em BSR_TEMP_L

;SEU CÓDIGO DE INTERRUPÇAO COM PRIORIDADE ALTA, OU SEM CONFIGURAR


;A PRIORIDADE, DEVE SER FEITO AQUI.


RESTAURA_CONTEXTO_L ;rotina de retorno da interrupçãp
MOVFF WREG_TEMP_L,WREG ;recupera WREG
MOVFF STATUS_TEMP_L,STATUS ;recupera STATUS
MOVFF BSR_TEMP_L ,BSR ;recupera BSR
RETFIE

;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;* INICIO DO PROGRAMA *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
; Configurações inicias das portas, timers, interrupções
;etc

INICIO
CLRF PORTB ;LIMPA O PORTB
CLRF PORTD ;LIMPA O PORTD

145
MOVLW B’00000001’
MOVWF TRISB ;DEFINE RB0 COMO ENTRADA

MOVLW B’00000000’
MOVWF TRISD ;TODO O PORTD COMO SAÍDA

;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;* INICIALIZAÇÃO DAS VARIÁVEIS *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;* ROTINA PRINCIPAL *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
PRINCIPAL

;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;* FIM DO PROGRAMA *
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

END ;OBRIGATÓRIO

146
PLANO DE ESTUDO
• Introdução a Linguagem C;
UNIDADE 4
• Programação em C do PIC18F;
• Apresentação e programação dos periféricos
do PIC18F4550;
• Metodologias e implementação de LCDs, MICROELETRÔNICA
Teclados Matriciais, Displays Leds.

OBJETIVOS DE APRENDIZAGEM
• Compreender as metodologias e técnicas de
programação;
• Desenvolver e implementar lógica de programação
em C;
• Desenvolver projetos em C de sistemas
microcontrolados;
• Compreender e implementar a programação dos
periféricos do PIC.
INTRODUÇÃO
Caro(a) estudante, nesta unidade começam seus estudos sobre a programação em
C do microcontrolador. E, portanto, será apresentada uma introdução à linguagem C,
sua forma de programação e características de sintaxes. Também iremos utilizaremos
o MPLAB para programação e o PicsimLab.
C é uma linguagem de alto nível de propósito geral que foi originalmente desenvol-
vida por Dennis Ritchie para o sistema operacional Unix. Foi implementado pela pri-
meira vez no computador Digital Equipment Corporation PDP-11 em 1972.
O sistema operacional Unix e praticamente todos os aplicativos Unix são escritos
na linguagem C. C agora se tornou uma linguagem profissional amplamente usada por
vários motivos, são eles:
 Fácil de aprender linguagem estruturada;
 Produz programas eficientes;
 Ele pode lidar com atividades de baixo nível;
 Pode ser compilado em uma variedade de computadores.
Dessa forma, utilizaremos a linguagem C para programação de alto nível, simplifi-
cando, assim, nossa interpretação lógica de interpretação do microcontrolador, em es-
pecial quando configuramos e utilizamos os periféricos do PIC.

148
1. INTRODUÇÃO A LINGUAGEM C
Antes de iniciarmos a linguagem C, devemos apresentar algumas convenções que
tornarão mais clara a explanação. Essas considerações referem-se à padronização
ANSI (American National Standard for Information Systems).
Em primeiro lugar, comentários em C são indicados pelos símbolos “/*”, “*/” e “//”.
Comentários aparecem no código fonte, mas são ignorados pelo compilador. Os sím-
bolos “/*” e */” informar que a informação que está entre eles é um comentário. O “//”
é um símbolo definido na linguagem C++, mas a maioria dos compiladores C o aceita.
Tem-se por convenção utilizar “//” para comentários explicativos e “/*” e “*/” para man-
ter ignoradas partes ou blocos de código ou informações, descritivos etc. Por exemplo:

/* Isto é um comentário */
// Isto também é um comentário
/*Desta maneira podemos fazer comentário que, por
algum motivo qualquer, ocupem diversas linhas. Do mesmo
modo podemos transformar trechos do programa em comentá-
rio */

Fonte: Adriano (2014).

Ressalta-se: Todo comando em C termina, obrigatoriamente, com um “;”.


Os nomes de funções, variáveis, constantes etc. são chamados de identificadores e
não devem conter caracteres acentuados, espaços, “ç”, e devem começar com letras
(o símbolo “_” é tratado como letra). Letras maiúsculas e minúsculas são consideradas
diferentes, isto é, “Maria” é considerado um identificador diferente de “maria”.
Existem palavras reservadas que não podem ser usadas como identificadores. A
definidas pelo padrão ANSI são apresentadas a seguir, mas pode haver outras próprias
do compilador.

149
Figura 1 – Palavras padrão do modelo ANSI

Fonte: Adriano (2014).

Os programas em C são organizados em funções. A função main, como o nome


em inglês indica, é a função principal do programa; por ela que o programa começa a
ser executado. Todo programa deve ter pelo menos uma função (no caso de apenas
uma, ela deve ser obrigatoriamente chamada main). Juntamente com a função main,
criada pelo programador, o compilador C cria um código a ser executado antes da fun-
ção main ser chamada. Sua função é realizar as configurações necessárias à execução
do programa desenvolvido (Adriano, 2014).
As chaves ( { e } ) delimitam um bloco de instruções. Um bloco de instruções é vis-
to e tratado como uma única instrução. O operador de atribuição em C e o símbolo
“=”. Os demais operadores serão tratados oportunamente
A forma geral de um programa em C pode ser dada por:

< diretivas do pré−processador >

< protótipos >

< declarações globais >;

main()
{
< declarações locais >; /* comentário */

< instruções >;


}

< outras funções >


Fonte: autor (2023).

150
1.1 TIPOS DE DADOS
Em C existem cinco tipos de dados básicos:
Tabela 1 – Tipo de Variáveis

Tipo Categoria

char Caractere
int Inteiro
float Real de ponto flutuante
double Real de ponto flutuante com dupla precisão

void Sem valor

Fonte: Souza (2010).

Tais tipos (exceto void) podem estar acompanhados por “modificadores” na decla-
ração de variáveis:
Tabela 2 – Modificadores

Tipo Categoria

Bit mais significativo (MSB) é utilizado como sinal, informa que o dado é do tipo sinalizado (valores
signed
positivos e negativos);
unsigned MSB é parte do número, e informa que o dado é do tipo não sinalizado (somente valores positivos);
long informa que o inteiro é uma variação maior que o padrão;
short informa que o inteiro é uma variação menor que o padrão.

Fonte: Souza (2010).

151
A tabela 3 ilustra o tamanho de alguns dos tipos de dados em C em máquinas de
32 bits.
Tabela 3 – Tipos de dados inteiros
Faixa de valores
Tipo Tamanho
Mínimo Máximo
char 8 bits -128 127

signed char 8 bits -128 127

unsigned char 8 bits 0 255

int 16 bits -32.768 32.767

unsigned int 16 bits 0 65.536

Short 16 bits -32.768 32.767

Unsigned short 16 bits 0 65.536

Short long 24 bits -8.388.608 8.388.607

Unsigned shot long 24 bits 0 16.777.215

Long 32 bits -2.147.483.648 2.147.483.647

Unsigned long 32 bits 0 4.294.967.295

Fonte: Souza (2010).

Os tipos de dados float e double para variáveis com parte fracionárias (chamados
de floating points - ponto decimal flutuante) definidos para como variáveis de 32 bits,
que se comportam de forma idêntica. A tabela a seguir traz os tipos de dados suporta-
dos em C bem como as faixas de valores.
Tabela 4 – Tipos de dados

Faixa de valores
Tipo Tam.
Mínimo Máximo
2−126
2128
float 32 bits (aprox. 1.7014e–38)
(aprox. 3.402823e–38)

2−126 2128
double 32 bits
(aprox. 1.7014e–38) (aprox. 3.402823e–38)

Fonte: Souza (2010).

152
Figura 2 – Palavras padrão do modelo ANSI

Fonte: Adriano (2014).

1.2 DECLARAÇÃO DAS VARIÁVEIS


Podem ser feitas conforme mostrado abaixo. Coloca-se primeiro o identificador de
tipo, acompanhado ou não do modificar, seguido pela lista de variáveis desse tipo, se-
paradas por “,”. Ao final da declaração é necessário acrescentar o sinal “;”

char x,y; //varíavel x e y são tipo char


shor long medida; w
unsigned int dado = 0x35; //dado é do tipo int sem
sinal
//e é inicializado com o
valor
//hexadecimal 35
float pi = 3.1459; //pi é do tipo float com e inicia-
lizado
//com o numero decimal 3.1456
Fonte: Adriano (2014).

A declaração de constantes é feita de forma bastante semelhante, bastando acres-


centar o identificador “constantes da declaração. Observe que é necessário informar o
tipo de dado da constante, conforme o exemplo a seguir
const unsigned int SetPoint = 60000;
const char Letra = ‘A’;
Fonte: Adriano (2014).

153
A representação de valores nas diferentes bases é feita conforme a tabela a seguir,
onde “y” representa o valor a ser expresso. O símbolo usado para separar as partes in-
teiras e fracionárias de um número é o ponto ( . ). A representação de caracteres é fei-
ta entre apóstrofos ( ‘ ).
Tabela 5 – Representação dos Valores
Tipo Notação Exemplos
Decimal yyy 31, 1025, -3, 50000
Hexadecimal 0xyyy 0x31, 0xABCD, 0x0008
Bin´ario 0byyy 0b10101010, 0b1111000011110000
Octal 0oyyy 0o31, 0o123, 0o1543
Fonte: Adriano (2014).

1.3 CÓDIGOS
A linguagem C utiliza vários códigos que são chamados de códigos de barra inver-
tida. Esses códigos permitem ao programador inserir alguns caracteres do ASCII que
não podem ser inseridos diretamente em uma constante string.
São diversos os motivos que impedem a inserção de determinados caracteres,
mas, podemos citar o retorno de carro (que é aquele inserido pela tecla ENTER) e o
caractere de aspas ‘ “ ‘., por exemplo. O primeiro não pode ser inserido diretamente
pelo teclado, pois o retorno de carro é inserido no código fonte, provocando um efei-
to indesejado. O segundo, mesmo estando facilmente disponível no teclado, não pode
ser inserido diretamente na string porque o compilador irá interpretá-lo como sinal do
término da string. (Torre e Martins, 2014)
Tabela 6 – Representação de códigos
Código Significado
\b Retrocesso ( “backspace” )
\f Avanço de formulárop ( “form feed” )_
\n Nova linha ( “new line” )
\t Tabulação horizontal ( “tab” )
\” Aspas
\’ Apóstrofo
\0 Nulo (0 em decimal)
\\ Barra invertida “ \ “
\v Tabulação vertical
\r Retorno ( “Enter” )
Fonte: Torre e Martins (2014).

154
1.4 DECLARAÇÃO DAS VARIÁVEIS GLOBAIS E LOCAIS

Uma variável pode ser declarada de forma global ou local. Variáveis locais são de-
claradas dentro de funções ou blocos de instruções (delimitados por chaves) e são re-
conhecidas somente dentro da função ou do bloco. Variáveis globais são declaradas
fora das funções e são reconhecidas por todas as funções do programa.
O uso de variáveis globais é necessário em algumas situações quando determinada
variável deve ser vista e alterada por diversas funções, como, por exemplo, na troca de
dados entre funções de tratamento de interrupção e outras funções. Contudo, seu uso
deve ser restrito, pois ocupam uma posição de memória constantemente.
Já as variáveis locais são criadas quando a função é executada e “destruídas “quan-
do a função retorna. Isso significa que o mesmo endereço de memória pode ser usa-
do por diversas variáveis no decorrer do programa, o que garante um melhor uso de
memória. Caso variáveis locais tenham o mesmo nome de variáveis globais, as globais
serão ignoradas naquela função (ou bloco) (ADRIANO, 2014).

1.5 DECLARAÇÃO DE VETORES E MATRIZES


É possível criar vetores e matrizes de dados dos tipos básicos. Vetores e matrizes
são conjuntos de diversas variáveis de mesmo tipo que são referenciadas por um mes-
mo identificador, sendo discriminadas por um índice. Vetores são unidimensionais, en-
quanto matrizes podem ter duas dimensões ou mais.
Para atribuir valores à constantes ou valores iniciais às variáveis enumera-se os va-
lores de cada elemento entre chaves, separados por vírgulas. Um caso particular de
vetores são os vetores de caracteres, chamados de strings, que são úteis para armaze-
nar palavras e frases. Nesses casos, o conjunto de caracteres pode ser atribuído a um
vetor constante simplesmente usando aspas para marcar início e fim.
Na criação de um vetor ou matriz é necessário informar o número de elementos
que essa contém. Isso é feito colocando o número de elementos entre colchetes na
declaração. No caso de um vetor de caracteres constantes não é preciso colocar o nú-
mero de elementos, pois esse determinado pelo número de elementos atributos.

155
Para fazer referência a um elemento em particular dentro de uma matriz ou vetor
usa-se a posição desse elemento (índice). Índices podem ser valores fixos ou variáveis.
Atenção: em C as posições começam em 0, portanto em um vetor de 10 elementos o
índice poderá assumir valores de 0 a 9.

int Medidas[16];
const char nome[] = “Domingos”;
char Empresa[] = “Faculdade Engenharia”;
unsigned int InitLCD[6] = {0x33,0x32,0x28,0x06,0x-
0C,0x01};
Fonte: Adriano (2014).

O acesso a dados em vetores e constantes são feitos através do uso de índice, con-
forme mostrado no exemplo abaixo.

unsigned char i;
int x;
int Medidas[10];
const int Valores[5] = {0x25, 0x31, 0x33, 0x02,
0x55};
...
Medida[i] = 15;
x = Valores[3];

Fonte: Adriano (2014).

156
1.6 PONTEIROS

Um tipo especial de variáveis é o tipo ponteiros. Ponteiros são variáveis que con-
tém o endereço de outras variáveis. Sua função é “apontar” onde a variável está na me-
mória dado seu nome.
Ponteiros são muito usados em C e um dos motivos é que permitem a implemen-
tação do código de forma bastante otimizada. Uma arquitetura de microcontrolador
otimizado para a linguagem C deve ter um eficiente sistema de ponteiros.
Para declarar um ponteiro usamos uma sintaxe parecida com a declaração de va-
riável, porém com significado diferente. Deve ser colocado o tipo de dado que o pon-
teiro aponta e o nome do ponteiro, precedido por “*”.
Tabela 7 – Representação de códigos

Operador Descrição
& Endereço do operando
* Conteúdo do endereço apontado pelo operando

Fonte: Torre e Martins (2014).

Por exemplo, na declaração a seguir x é uma variável do tipo inteiro enquanto ip é


um ponteiro que aponta para variáveis do tipo inteiro.

int x; // x é um inteiro
int *ip; // ip é um ponteiro que aponta inteiros

Fonte: Adriano (2014).

Para atribuir a um ponteiro o endereço de uma variável usamos o operador “&”.


Para manipular o conteúdo da variável apontada pelo ponteiro usamos o operador “*”.
O exemplo a seguir ilustra alguns usos de ponteiros.

157
int x = 1, y = 2, z[10]; // x e y são inteiros
// z é um vetor de intei-
ros
int *ip, *iq; // ip e iq são ponteiros que
// apontam inteiros
ip =&x; // ip aponta para x
iq = &y; // iq aponta para y
y = ip; // y agora vale 1
ip = 0; // x agora vale 0
ip = &z[0]; // ip agora aponta para z[0]
iq = ip; // iq agora aponta para Z[0] também
Fonte: Adriano (2014).

158
2. COMANDOS BÁSICOS
O C é uma linguagem de programação estruturada. Isso significa que segue seus
comandos básicos e tem o objetivo de implementar os três tipos básicos de estrutu-
ras: atribuição, decisão e repetição. Além disso, possui diversos operadores que permi-
tem realizar operações lógicas e matemáticas.

2.1 ATRIBUIÇÃO

O comando de atribuição é realizado simplesmente com o uso do operador “=”. O


identificador à esquerda recebe o valor da expressão à direita. Alguns exemplos são
apresentados a seguir.
Nesses casos devemos evitar o uso do termo “igual” para evitar equívocos. Dize-
mos, por exemplo, “x recebe dois” e não “x igual a dois”. O C permite substituir a ex-
pressão “”por “”, como o mesmo efeito

x = 2;
y = 3;
x = 2 + y;
y = x;

Fonte: Adriano (2014).

2.1.1 Acesso aos SRFs


No arquivo de cabeçalho que existe para cada microcontrolador PIC (ex.:
P18F4550.h) estão definidos todos os registros de uso especial. Dessa maneira, é pos-
sível manipular diretamente os registros como se fossem variáveis e envolvê-los em
operações com os operadores estudados. Para o compilador XC8, basta adicionarmos
o cabeçalho “xc.h” que o cabeçalho referido ao PIC usado no projeto do MPLAB é adi-
cionado ao código.

159
Os exemplos abaixo mostram com isso pode ser feito:
#include <xc.h>
void main(void)
{
TMR0L = 0x25; // carrega valor no timer 0
T1CON = 0b0001001; // configura o timer 1
TRISA = 0xAA; // configura direção das por-
tas
INTCON = 0xC0; // habilita interrupções
}
Fonte: Adriano (2014).

Da mesma maneira, estão definidos os bits de cada registro, na forma de estrutu-


ras, conforme os exemplos a seguir. Basta colocar o nome de registro seguido de “bits.”
e o nome do bit em questão (muita atenção com as letras, pois C diferencia maiúscu-
las de minúsculas.)
#include <xc.h>
void main(void)
{
RCONbits.IPEN = 1; // ativa prioridade de
int.
INTCONbits.GIE = 1; // habilita interrup-
ções
ADCON0bits.ADON = 0; // desliga o ADC
TXSTAbits.TXEN = 1; // Ativa recepção se-
rial
}
Fonte: Adriano (2014).

2.1.2 Entradas e Saídas no XC8


O compilador XC8, assim como qualquer compilador C, não define comandos ou
funções especiais para realizar operações de entrada e saída de dados. Mas como no
PIC18 os portais de I/O são registros de funções especiais e, portanto, definidos no ar-
quivo de cabeçalho de cada microcontrolador, podemos manipulá-los como se fos-
sem variáveis.

160
Os registros que controlam a direção dos pinos dos portais, isto é, o registro TRISx,
podem ser acessados por dois nomes: TRISx (TRISA, TRISB, TRISC, etc...) ou DDRx.
Pode-se configurar o portal todo de uma vez ou os registros individualmente.
Exemplo:

// da na mesma fazer
TRISB = 0b00110101;
// ou
TRISBbits.TRISB0 = 1; // 1 = Entrada
TRISBbits.TRISB1 = 0; // 0 = Saída
TRISBbits.TRISB2 = 1;
TRISBbits.TRISB3 = 0;
TRISBbits.TRISB4 = 1;
TRISBbits.TRISB5 = 1;
TRISBbits.TRISB6 = 0;
TRISBbits.TRISB7 = 0;
// ou
TRISBbits.RB0 = 1; // 1 = Entrada
TRISBbits.RB1 = 0; // 0 = Saída
TRISBbits.RB2 = 1;
TRISBbits.RB3 = 0;
TRISBbits.RB4 = 1;
TRISBbits.RB5 = 1;
TRISBbits.RB6 = 0;
TRISBbits.RB7 = 0;

Fonte: Adriano (2014).

Para acesso aos portais existem dois registros, LATx e PORTx. O acesso a esses re-
gistros pode ser feito conforme apresentado no exemplo a seguir

LATA = 0x00;
x = PORTB;
PORTBbits.RB0 = 1;
LATBbits.LATB1 = PORTAbits.RA5;

Fonte: Adriano (2014).

161
Para tornar o código mais compreensível e facilitar alterações na configuração de
hardware podemos usar a diretiva #define para atribuir nomes aos pinos dos portais,
conforme apresentado a seguir.

// Esse programa acende o LED se a chave estiver


//pressionada
#include<xc.h>

#pragma config WDT = OFF //WDT DESLIGADO


#pragma config PBADEN = OFF //PINOS RB<4:0> COMO ENTRADA DI-
GITAL
#pragma config MCLRE = OFF //MASTERCLEAR RESET DESATIVADO
#pragma config FOSC = INTOSC_HS //CLOCK PELO OSCILADOR INTERNO

#define LED PORTDbits.RD0


#define Chave PORTBbits.RB0

void main (void)


{
TRISDbits.RD0 = 0; // Saida para o LED
TRISBbits.RB0 = 1; // entrada para chave
for(;;) // laço infinito
{
if (!Chave)LED = 1;
else LED = 0;
}
}

Fonte: Adriano (2014).

162
2.1.3 Operadores
Para a execução de expressões e condições o C dispõe de diversos operadores,
além do operador ‘=’ (atribuição) já tratado. Os operadores matemáticos são apresen-
tados na tabela abaixo
Tabela 8 – Operadores matemáticos

Operador Operação
+ Adição
- Subtração
* Multiplicação
/ Divisão
% Resto da Divisão
++ Incremento
-- Decremento

Fonte: Adriano (2014).

Exemplos:

int x, y = 3, z = 2;
x = y + z; // o valor de x será 5
x = y - z; // o valor de x será 1
x = y * z; // o valor de x será 6
x = y / z; // o valor de x será 1 (parte inteira)
x = y % z; // o valor de x será 1 (resto da divi-
são)
Fonte: Adriano (2014).

Há também os operadores de incremento (++) e decremento ({). Numa, se usar-


mos os operadores a direita do dado, seu valor vai ser alterado (incrementado ou de-
crementado) antes da atribuição; se os usarmos à esquerda, seu valor será alterado de-
pois. Observemos o exemplo a seguir.

163
y = 5; // y recebe 5
x = ++y; // y contém 6 e o valor de x _e 6
y = 5; // y recebe 5
x = y++; // y contém 6 MAS x contem 5
Fonte: Adriano (2014).

Existem também os operadores relacionais utilizados para comparar dados.


Tabela 9 – Operadores Comparativos

Operador Operação
> Maior que
>= Menor ou igual que
< Menor que
<= Menor ou igual que
== Igual a
!= Diferente de
Fonte: Adriano (2014).

Uma operação relacional resulta em “verdadeiro” ou “falso”. Os exemplos a seguir


mostram o resultado de algumas operações relacionais.
Para x = 10 e y = 8:
 x > y, Verdadeiro
 x >= y, Verdadeiro
 x < y, Falso
 x <= y, Falso
 x == y, Falso
 x ! = y, Verdadeiro
Os operadores lógicos são divididos em dois tipos. O primeiro tipo realiza opera-
ções lógicas comparando o estado de cada operando, se ‘falso’ (igual a 0) ou ‘verda-
deiro’ (diferente de 0). Esses operadores permitem criar condições com expressões

164
lógicas, envolvendo inclusive operadores relacionais. Mais exemplos de sua aplicação
serão apresentados quando se tratar de comandos de decisão. Tais operadores são
apresentados na tabela a seguir
Tabela 10 – Operadores Comparativos

Operador Operação
&& E (AND)
|| OU (OR)
! COMPLEMENTO (NOT)

Fonte: Adriano (2014).

O segundo tipo de operador lógico realiza operações lógicas bit a bit em seus ope-
randos. Os operadores pertencentes a esse segundo tipo estão na tabela a seguir.
Tabela 11 – Operadores Comparativos

Operador Operação
& E (AND)
| OU (OR)
∧ OU-EXCLUSIVO (XOR)
∼ COMPLEMENTO (NOT)
>> Deslocamento a direita
<< Deslocamento a esquerda

Fonte: Adriano (2014).

Exemplo:

char a,b,s;
a = 0b11110000;
b = 0b10101010;
s = a & b; // o valor de x será 0b10100000
s = a | b; // o valor de x será 0b11110000
s = a ^ b; // o valor de x será 0b01011010
s = ~b; // o valor de x será 0b01010101

Fonte: Adriano (2014).

165
2.1.4 Decisão
As estruturas de decisão permitem ao programa tomar decisões baseadas na ava-
liação de uma condição, e, é avaliado se essa condição seria verdadeira ou falsa.

2.1.4.1 If
A estrutura if (se) executa um bloco de comandos se a condição for verdadeira.
Caso contrário, segue a execução do programa. Seu aspecto geral é apresentado abai-
xo, assim como um exemplo de utilização.

if (<condição>)
{
<Bloco verdadeiro>
}

Fonte: Adriano (2014).

Caso o if tenha somente uma expressão, pode-se escrever como:

if (<condição>) <expressão/função para verdadeiro>;


Fonte: o autor.

Exemplo:

if(x > 5)
{
printf(“\n x maior que 5”);
}

//ou

if(x > 5) printf(“\n x maior que 5”);


Fonte: Adriano (2014).

Uma condição é considerada falsa se é igual a 0. Caso contrário, é considerada ver-


dadeira. Isso se aplica não só ao resultado de operadores relacionais como também na
avaliação de variáveis e bits, conforme mostrado a seguir

166
if (TMR0) // verdadeiro se TMR0 diferente de 0
{
printf(“TMR0 é diferente de 0”);
}
if(!PORTBbits.RB0) //verdadeiro se RB0 for ‘0’ (note o ‘ !’)
{
LigaMotor();
}
if(PIR1bits.TMR1IF)
{
RTITimer1(); // chama a função se TMR1IF for ‘1’
}

Fonte: Adriano (2014).

2.1.4.2 If-else
A estrutura if-else (se-senão) executa um bloco de comandos se a condição for
verdadeira ou outro bloco de comando se a condição for falsa. Temos a seguir, a for-
ma geral dessa estrutura e, também, um exemplo de utilização.

if (<condição>)
{
<Bloco verdadeiro>
}
else
{
<Bloco falso>
}

Fonte: Adriano (2014).

Caso o if-else tenha somente uma expressão, pode-se escrever como:

if (<condição>) <expressão/função para verdadeiro>;


else < expressão/função para falso >;

Fonte: o autor.

167
Exemplo:

if(x > 5)
{
printf(“\n x maior que 5”);
}
else
{
printf(“\n x menor que 5”);
}

Fonte: Adriano (2014).

2.1.4.3 Operador Ternário Condicional


Para situações na qual uma decisão implica no valor a ser atribuído a uma variável,
existe uma forma alternativa de se realizar a estrutura se-senão. Isso é feito através do
operador ternário condicional. Sua sintaxe é:
Variável = Condição ? Expressão1 : Expressão2;

Fonte: Adriano (2014).

Sendo Condição uma expressão cujo resultado vai ser avaliado em verdadeiro ou
falso e Expressão1 e Expressão2 expressões quaisquer cujo valor pode ser atribuído à
variável. Se Condição for verdadeiro, a variável recebe o resultado de Expressão1; se-
não, a variável recebe o resultado de Expressão2. A seguir o uso do operador ternário
condicional é explicado
Exemplo:
x = (y >= 10) ? y*2 : y*3;
//equivale a
if( y >= 10) x = y * 2;
else x = y * 3;

Fonte: Adriano (2014).

PORTDbits.RD0 = (valor <= 128) ? 1 : 0;


//equivale a
if( valor <= 128) PORTDbits.RD0 = 1;
else PORTDbits.RD0 = 1;

Fonte: Adriano (2014).

168
2.1.4.4 Switch
O comando switch permite a implementação de uma estrutura caso. A seguir te-
mos a forma genérica desse comando

switch(<variável>)
{
case <valor1>:
<comandos>
break;
case <valor1>:
<comandos>
break;
case <valor1>:
<comandos>
break;
default:
<comandos>
break;
}

Fonte: Adriano (2014).

O que o comando switch faz é comparar <variável> com os valores que ela pode
assumir (valor1, valor2 etc). Caso a variável possua um desses valores, o bloco associa-
do ao valor é executado. O último bloco, chamado default, é opcional e só é executa-
do se <variável> não é igual a nenhum dos valores.
A seguir, como exemplo, temos uma aplicação típica do comando switch:
switch(x)
}
case 1:
printf(“\n x igual a 1”);
break;
case 2:
printf(“\n x igual a 2”);
break;
case 3:
printf(“\n x igual a 3”);
break;
default:
printf(“\n x diferente de 3, 2 e 1”);
break;
}
Fonte: Adriano (2014).

169
2.1.4.5 Repetição
Em C existem três comandos que implementam estruturas de repetição:
 Do-While;
 While;
 For.

Do-While
Esse comando implementa uma estrutura Faça-Enquanto. Sua função é executar
um bloco de instruções enquanto uma condição for satisfeita. Sua principal caracte-
rística é que o bloco é executado antes do teste ser realizado. Ou seja, o bloco é exe-
cutado pelo menos uma vez, independente da condição ser verdadeira ou falsa. Esse
funcionamento é particularmente útil quando a condição a ser testada é afetada pelo
bloco. A seguir temos sua forma padrão e um exemplo de utilização. Exemplo da es-
trutura do comando:

do
}
<bloco de instruções>
}while(<condição verdadeira>);

Fonte: Adriano (2014).

Exemplo:

//fica imprimindo a mensagem enquanto n < 5;


int n = 10;
do
}
printf(“\n Bloco do do-while!!”);
n--;
}while(n < 5);

Fonte: Adriano (2014).

170
While
Da mesma forma de Do-While, o comando While repete um bloco enquanto uma
determinada condição é verdadeira. A principal diferença entre os dois comandos é
que com While o teste é feito antes de se executar o bloco. Em outras palavras, o blo-
co só vai ser executado se em algum momento a condição for satisfeita.
Exemplo da estrutura do comando:

while(<condição verdadeira>)
{
<bloco de instruções>
}

Fonte: Adriano (2014).

Exemplo:
//fica imprimindo a mensagem enquanto n < 5;
int n = 10;
int x = 4;
while(n != x)
{
printf(“\n Bloco do while!!”);
n--;
}

Fonte: Adriano (2014).

For
O comando For é utilizado para repetir um bloco por um número pré-determina-
do de vezes. Sua estrutura básica é apresentada a seguir.

for(<Contador> = <ValorInicial>; <Condição>; <Passo>)


{
<Bloco>
}

Fonte: Adriano (2014).

171
Obrigatoriamente deve existir uma variável contadora (<contador>). Essa variável
é carregada com um valor inicial quando a estrutura for começar a ser executada. A
cada repetição do bloco de instruções é dado um “passo” em <contador>, isto é, seu
valor é alterado de alguma maneira. Tipicamente o passo é um incremento ou um de-
cremento. O bloco de instruções é repetido enquanto a condição que relaciona <con-
tador> com um valor final é satisfeita.
No exemplo a seguir, for é usado para apresentar valores de uma multiplicação.
A repetição foi implementada com um passo de decremento, o que quer dizer que é
subtraído 1 do contador (cujo valor inicial é 10) até que a condição (contador > 0) não
seja mais satisfeita.
Exemplo:

for(i = 10; i > 0; i-- )


{
n = 5*i;
printf(“\n 5 vezes %d igual a %d”,i,z);
}

Fonte: Adriano (2014).

Comando break
Quando executado dentro de um laço de repetição, o comando break causa a ime-
diata interrupção, fazendo o programa saltar para fora do laço.

2.1.5 Funções
Uma função é um trecho de código que deve executar uma função específica e bem
definida. Seu objetivo é permitir que um programa seja modular, isto é, composto de
blocos cujas responsabilidades dentro do programa são bem claras. Modularidade é um
princípio da programação estruturada e C é uma linguagem estruturada por natureza.
Assim como uma função matemática (daí seu nome), uma função em linguagem C
tem operadores, chamados de parâmetros. Há parâmetros de entrada (que passam in-
formações para a função), também chamados de argumentos, e parâmetros de saída
(trazem informação gerada na execução da função). Assim como para variáveis e cons-
tantes, é necessário informar o tipo de dado dos parâmetros, sendo válidas as mesmas

172
convenções usadas para declaração de variáveis. Há casos em que não há parâme-
tros de entrada e/ou de saída. Nesse caso eles são definidos como sendo do tipo void.
A seguir temos a sintaxe geral da definição de uma função.

<tipo> nome_da_função(<tipo1> <arg1>, <tipo2> <arg2>, ... )


{
/* geralmente aqui temos uma declaração de variáveis
*/
/* os comando da função veem em seguida */
return(<var>); /* retorno o parâmetro de saída */
}

Fonte: Adriano (2014).

Para exemplificar, suponhamos que se deseja construir uma função que some o va-
lor de dois inteiros e retorne o resultado dessa soma, também em formato inteiro. Essa
função poderia ser desenvolvida da seguinte maneira:

int SomaDoisNumeros(int x, int y)


// Função que soma dois números
// Entrada: x e y contendo os valores
// Saída: a soma de x e y
{
int z; // Declaração de variáveis
z = x + y; // comandos da função
return(z); // retorna o resultado
}

Fonte: Adriano (2014).

O nome da função é SomaDoisNumeros e obedece às mesmas regras para no-


mes de variáveis. Seu parâmetro de saída é do tipo int. Diz-se que “SomaDoisNumeros
retorna um inteiro”. Seus argumentos são dois dados do tipo inteiro. Quaisquer dois
dados do tipo dos argumentos podem ser passados para a função, sejam eles cons-
tantes, variáveis ou valores imediatos. Esses valores são copiados para as variáveis in-
ternas x e y.
As variáveis declaradas em uma função, assim como seus argumentos, só existem
dentro da função. Isso significa que podemos ter outras variáveis chamadas x em ou-
tras funções e estas são tem qualquer relação com a variável x que existe em Soma-
DoisNumeros.

173
O exemplo a seguir ilustra como a função pode ser chamada na função principal.

void main(void)

{
int x,z;
z = 5;
x = SomaDoisNumeros(8,z);
}

Fonte: Adriano (2014).

Em C a posição onde a função se encontra no código fonte é importante. Uma fun-


ção (incluindo a função main) só pode chamar outra que esteja escrita acima (antes)
de si mesma. Isso pode ser feito organizando a ordem em que as funções aparecem
no código ou através da dentição do “protótipo” de todas as funções no início do ar-
quivo. Por exemplo, o protótipo da função SomaDoisNumeros é:

int SomaDoisNumeros(int x, int y);

Fonte: Adriano (2014)

Funções não “enxergam” variáveis declaradas fora de si mesmas (com exceção de


variáveis globais) assim como não é possível “enxergar” as variáveis de fora de uma
função. Em outras palavras, a chamada de uma função não pode alterar o valor de va-
riáveis passadas como argumentos. O método para realizar isso, que também pode ser
usado para funções que retornam vetores ou mais de um parâmetro, é chamado de
passagem de parâmetro por referência e é feito com o uso de ponteiros. Ressalta-se
que, uma função pode alterar valores de variáveis globais.
Por exemplo, admitindo a necessidade de construir uma função capaz de somar 5
a três variáveis, pode-se escrever a seguinte função:

174
void Soma5em3Variaveis(int *ptrA, int *ptrB, int *ptrC)
// Função que soma 5 aos argumentos
// Entrada: os endereços de três variáveis do tipo int
// Sadia: as variáveis referenciadas
{
ptrA = *ptrA + 5;
ptrB = *ptrB +5;
ptrC = *ptrC +5;
}

Fonte: Adriano (2014).

Os argumentos da função são na verdade os endereços das variáveis. A função ma-


nipula o conteúdo das variáveis apontadas por esses endereços, portanto toda altera-
ção feita dentro da função é feita com variáveis que foram declaradas fora da função.
O mesmo processo pode ser usado para argumentos que sejam string ou vetor.
Usando o nome da string ou do vetor como argumento, o ponteiro é associado ao pri-
meiro elemento. O exemplo abaixo mostra como poderia ser usada uma função que
imprime os valores contidos em uma string.

void ImprimeString(char *ptrA)


{
while(*ptrA != ‘\0’) // repete até o fim da string
{
printf(“\n %c”, *ptrA);
ptrA++; // incrementa o endereço
}
}
void main (void)
{
const char Seq[] = “Faculdade Engenharia”;
ImprimeString(Seq);
}

Fonte: Adriano. (Adaptado 2014).

175
2.2 INTERRUPÇÕES
Muitas vezes um projeto exige que providências sejam tomadas imediatamente
quando um determinado evento ocorre, porém não se pode ficar o tempo todo veri-
ficando as entradas associadas a esse evento
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 de-
terminados eventos, parando a execução normal no momento em que ocorre o even-
to, executando o código armazenado em uma posição de memória vinculada a inter-
rupção e depois retornam à execução normal do programa. As interrupções podem
ser consideradas chamadas de sub-rotinas realizadas pelo hardware.
Como vimos na unidade 3, quando ocorre um pedido de interrupção para a CPU, o
programa é desviado para um endereço pré-estabelecido, o vetor de interrupção. No
PIC18F4550 existem dois vetores de interrupção, um de alta prioridade (0x0008) e um
de baixa prioridade (0x0018).
Desse endereço em diante é feito o chamado tratamento de interrupção, isto é, são
executadas as rotinas que se deseja associar ao evento causador da interrupção.
O PIC18F4550 possui 20 fontes de interrupções. A cada interrupção são associa-
dos três bits:
 Bit de habilitação: Indica se a interrupção está ativa (0 = interrupção desativa-
da, 1 = interrupção ativa);
 Bit de flag: indica se ocorreu o evento associado à interrupção (0 = não ocor-
reu, 1 = ocorreu);
 Bit de prioridade: indica a prioridade da interrupção (0 = baixa prioridade, 1 =
alta prioridade).
Existem dois níveis de prioridade de interrupções, alto e baixo. Uma interrupção de
baixa prioridade interrompe a execução do programa e causa o desvio para o vetor de
interrupção de baixa prioridade. Já a interrupção de alta prioridade interrompe não só
a execução normal do programa como também interrompe a rotina de tratamento de
interrupção de baixa prioridade (se estiver sendo executada). Cada fonte de interrup-

176
ção pode ser configurada para atuar com baixa ou alta prioridade, sendo que para isso
basta definir se o bit de prioridade é 0 (baixa) ou 1 (alta).
Na linguagem C, o salvamento do contexto, ou seja, dos registradores especiais
STATUS, WREG e BSR, são salvos automaticamente, e, portanto, só precisamos imple-
mentar a nossa lógica do tratamento da interrupção e zerar o flag associado a aquela
interrupção em específico.
Por simplicidade, os registradores associados a interrupção INTCON, INTCON2 e
INTCON3 serão apresentados novamente nas figuras abaixo, assim com um sumário
relacionando as outras interrupções.
Figura 3 – Registradores INTCON, INTCON2 e INTCON3

177
Fonte: Souza (2010).

178
A demais interrupção tem seus bits de flag, habilitação prioridade distribuídos nos
registros PIRx, PIEx e IPRx, respectivamente, como mostrado na tabela a seguir:
Tabela 12 – Controle de Interrupções

Flag Habilitação Prioridade


Evento de interrupção 1 = ocorreu 1 = Habilitada 1 = Alta
0 = n˜ao ocorreu 0 = Desabilitada 0 = Baixa
INTCON INTCON INTCON2
Interrupção externa INT0 INT0IF INT0IE Sempre alta
Estouro do timer 0 TMR0IF TMR0IE TMR0IP
Mudança de estado na porta B RBIF RBIE RBIP
INTCON3 INTCON3 INTCON3
Interrupção externa INT1 INT1IF INT1IE INT1IP
Interrupção externa INT2 INT2IF INT2IE INT2IP
PIR1 PIE1 IPR1
Leitura ou escrita da porta paralela escrava PSPIF PSPIE PSPIP
Conversão do AD completa ADIF ADIE ADIP
Recepção serial USART RCIF RCIE RCIP
Transmissão serial TXIF TXIE TXIP
Transmissão/recepção completa pelo MSSP SSPIF SSPIE SSPIP
Interrupção do módulo CCP1 CCP1IF CCP1IE CCP1IP
Estouro do timer 2 TMR2IF TMR2IE TMR2IP
Estouro do timer 1 TMR1IF TMR1IE TMR1IP
PIR2 PIE2 IPR2
Falha no oscilador OSCFIF OSCFIE OSCFIP
Alteração no estado do comparador CMIF CMIE CMIP
Término de escrita na EEPROM EEIF EEIE EEIP
Colisão no barramento SPI BCLIF BCLIE BCLIP
Detecção de baixa/alta tensão HLVDIF HLVDIE HLVDIP
Estouro do timer 3 TMR3IF TMR3IE TMR3IP
Interrupção do módulo CCP2 CCP2IF CCP2IE CCP2IP

Fonte: Adriano (2014).

179
No compilador XC8, devemos habilitar e configurar individualmente cada interrup-
ção de forma específica, porém podemos usar a função ei() para habilitar as interrup-
ções de forma geral e habilitar as interrupções de periféricos de forma geral, e di() para
desabilitar as interrupções. Basicamente ei() seta GIE e PEIE, e di() reseta GIE e PEIE.
di(); // desabilita as interrupções de modo geral

ei(); // habilita as interrupções de modo geral


Fonte: autor (2023).

Para tratar as interrupções, deve-se usar criar uma função interrupt e definir se a
prioridade, por high_priority (pode-se omitir esse termo) e low_priority. Lembre-se
que se a prioridade de interrupção não for habilitada, todas as interrupções serão tra-
tadas como alta prioridade.
Exemplo de interrupção de prioridade alta. Como não estaremos prioridade nas
interrupções, iremos usar o modelo abaixo.

void __interrupt() nome_da_funcao(void)


//interrupção prioridade alta ou não configurada

{
if <testa flag da interrupção 1>
{
<zera flag interrupção 1>
<seu código>;
return;

}
if <testa flag da interrupção 2>
{
<zera flag interrupção 2>
<seu código>
return;

}
...
}

Fonte: autor (2023).

180
Ou, podemos implementar a interrupção de alta prioridade como

void __interrupt(high_priority) nome_da_funcao(void)


//interrupção prioridade alta ou não configurada
{
if <testa flag da interrupção 1>
{
<zera flag interrupção 1>
<seu código>
return;

}
if <testa flag da interrupção 2>
{
<zera flag interrupção 2>
<seu código>
return;

}
...
}

Fonte: autor (2023).

Para a interrupção de baixa prioridade, faz-se:

void __interrupt( low_priority )nome_da_funcao(void)


//interrupção prioridade baixa
{
if <testa flag da interrupção 1>
{
<zera flag interrupção 1>
<seu código>
return;
}
if <testa flag da interrupção 2>
{
<zera flag interrupção 2>
<seu código>
return;

}
...
}

Fonte: o autor.

181
2.3 USANDO ASSEMBLY NO C
Por mais eficiente que sejam uma linguagem de programação e um compilador,
dificilmente eles geram um código tão eficiente quanto um bom programador assem-
bly. Em aplicações críticas, nas quais cada microssegundo conta, podemos utilizar có-
digo assembly dentro do programa em C, de forma a acelerar e/ou aperfeiçoar a sua
execução.
De maneira geral, podemos dizer que os principais alvos deste tipo de otimização
são: Rotinas de tratamento de interrupção (nos casos da ocorrência de um elevado
número de interrupções num curto espaço de tempo), rotinas de manipulação de da-
dos como conversão: binário/decimal/hexadecimal, dentre várias outras.
A linguagem assembly pode ser inserida no código C em qualquer ponto, utilizan-
do as diretivas #asm e #endasm. As variáveis C conservam seus nomes na utilização
da linguagem assembly.

...
#asm
<código em assembly>
#endasm
...

Fonte: o autor.

182
2.4 FUNÇÕES ÚTEIS
A seguir são apresentadas algumas funções (padronizadas do C ou específicas do
XC8) que podem ser úteis em diversas situações.
Tabela 13 – Funções de conversão – stdlib.h

Funções Descrição
atof Converte em um valor fracionário
atoi Converte em um valor de 16 bits sinalizado
atol Converte em um valor inteiro longo
abs Calcula valor absoluto
itoa Converte um valor de 16 bits sinalizado em uma string
ltoa Converte um valor inteiro longo sinalizado em uma string
Fonte: autor.

Tabela 14 – Funções de conversão – xc.h

Funções Descrição
Gera um delay de “x” milissegundos.
__delay_ms(x) Deve ser definido no início:
#define __XTAL_FREQ valor_clock_oscilador
Gera um delay de “x” microssegundos
__delay_us(x) Deve ser definido no início:
#define __XTAL_ FREQ valor_clock_oscilador
READTIMERx(y) Escreve um valor “y” no timer x (x sendo 0, 1 e 3)
WRITETIMERx(y) Lê um valor timer x (x sendo 0, 1 e 3)
Fonte: autor.

183
2.5 DISPLAY 7 SEGMENTOS
Um dos modos mais comuns de apresentar informação para o usuário em um sis-
tema eletrônico é através de displays de LEDs. Esse tipo de display nada mais é que
um conjunto de LEDs numa disposição que permite formar diferentes caracteres con-
forme são acionados. Eles podem ser de dois tipos: anodo comum ou catodo comum
e podem ser vistos na figura a seguir em (b) e (c). A figura a seguir mostra a nomen-
clatura comumente utilizada para os segmentos que compõem os dígitos e o ponto.
Figura 4 – Displays de LED: (a) disposição dos segmentos, (b) catodo comum
e (c) anodo comum

Fonte: Adriano (2014).

Como pode ser observado na figura anterior, o display de anodo comum tem seus
segmentos acionados quando aplicamos ‘0’, ficando o anodo (comum) na alimenta-
ção. Já os de catodo comum são acionados com ‘1’ e o catodo (comum) é ligado à
terra. Para escrevermos um determinado valor no display é necessário converter, ou
dedicar, o valor originalmente em binário para combinações que acionem o display
corretamente. Isso pode ser feito através de circuitos integrados feitos para esse fim,
mas por motivo de economia de componentes é mais interessante que essa conver-
são seja feita por softwares e o acionamento seja feito diretamente pelo microcontro-
lador. A conversão deve ser feita obedecendo a tabela a seguir.

184
Tabela 15 – Acionamento display sete segmentos, com anodo comum.

Valor Anodo comum


(Hexadecimal) g f e d c b a
0 1 0 0 0 0 0 0
1 1 1 1 1 0 0 1
2 0 1 0 0 1 0 0
3 0 1 1 0 0 0 0
4 0 0 1 1 0 0 1
5 0 0 1 0 0 1 0
6 0 0 0 0 1 0 0
7 1 1 1 1 0 0 0
8 0 0 0 0 0 0 0
9 0 0 1 0 0 0 0
A 0 0 0 1 0 0 0
B 1 1 0 0 0 0 0
C 0 1 1 0 0 0 1
D 1 0 0 0 0 1 0
E 0 1 1 0 0 0 0
F 0 1 1 1 0 0 0

Fonte: Adriano (2014).

185
Tabela 16 – Acionamento display sete segmentos, com catodo comum.

Valor Catodo comum


(Hexadecimal) g f e d c b a
0 0 1 1 1 1 1 1
1 0 0 0 0 1 1 0
2 1 0 1 1 0 1 1
3 1 0 0 1 1 1 1
4 1 1 0 0 1 1 0
5 1 1 0 1 1 0 1
6 1 1 1 1 0 1 1
7 0 0 0 0 1 1 1
8 1 1 1 1 1 1 1
9 1 1 0 1 1 1 1
A 1 1 1 0 1 1 1
B 0 0 1 1 1 1 1
C 1 0 0 1 1 1 0
D 0 1 1 1 1 0 1
E 1 0 0 1 1 1 1
F 1 0 0 0 1 1 1
Fonte: Adriano (2014).

Tabelas como as apresentadas são facilmente implementadas em C por vetores,


uma vez que o índice do vetor representa a coluna de valor e os valores das posições
correspondem aos acionamentos do LED. Abaixo é apresentada uma declaração de
vetor de constantes que correspondem a tabela acima para catodo comum.

const char catodo[]={00111111, // 0


00000110, //1
01011011, //2
01001111, //3
01100110, //4
01101101, //5
01111101, //6
00000111, //7
01111111, //8
01100111}; //9

Fonte: Adriano (2014).

186
2.5.1 Display Multiplexados
Uma técnica utilizada para reduzir custos de hardware é a de multiplexar displays.
Essa técnica se aproveita de uma característica da visão humana chamada persistên-
cia retiniana: a retina “mantém” uma imagem projetada presente por algum tempo de-
pois que essa desaparece do campo de visão. Graças a essas propriedades que pode-
mos enxergar imagens se movendo na TV, que na verdade são sequências de imagens
paradas. Fazendo uso dessa propriedade também podemos acionar sequencialmen-
te diversos displays e dar a impressão a quem olha que todos estão acesos ao mesmo
tempo respectivos de cada display em paralelo e acionar o terminal comum (anodo
ou catodo) um por vez. Dessa maneira, com 7 pinos mais um pino por display é pos-
sível assinar diversos a displays.

2.5.2 Apresentando Valores em Displays


Um display pode apresentar valores de 0 a 9 (ou até F se quisermos apresentar va-
lores em hexadecimal) e vários displays podem ser usados conjuntamente usando a
técnicas de multiplexação. Porém, como apresentar valores com 123 ou 5000? Para
isso, é necessário decompor uma variável em unidades, dezenas, centenas, etc, e apre-
sentar individualmente cada parte em um dígito. Os trechos de código abaixo decom-
põem variáveis do tipo char e int (não sinalizados) para apresentação em displays. A
partir delas é possível desenvolver rotinas para outros tipos de dados.
// *** Decomposição de unsigned char
//unid, dez, cent são caracteres não sinalizado
cent = valor / 100;
valor = valor % 100;
dez = valor / 10;
unid = valor % 10;

Fonte: Adriano (2014).

// *** Decomposição de unsigned int


//unid, dez, cent, mil e dezmil são caracteres não
sinalizado
dezmil = valor / 10000;
valor = valor % 10000;
mil = valor / 1000;
valor = valor % 1000;
cent = valor / 100;
valor = valor % 100;
dez = valor / 10;
unid = valor % 10;

Fonte: Adriano (2014).

187
2.6 TECLADO MATRICIAL
Uma forma muito comum de usuário de um sistema microcontrolado passar infor-
mações ao sistema é através de teclas. Em muitas aplicações o número de teclas exis-
tentes pode ser bastante grande. Nesses casos, a leitura dessas teclas simplesmente
conectando-as aos terminais do microcontrolador incorre na utilização de muitos ter-
minais. Nessa aplicação é apresentado um sistema de varredura que permite fazer um
uso otimizado dos terminais do microcontrolador de forma a reduzir o número de ter-
minais utilizados.
Esse processo permite realizar a leitura de um número de teclas N utilizando me-
nos 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 entradas, num total de 8 terminais. A varredura funciona da seguin-
te maneira: o teclado é organizado de forma a ter 4 colunas e 4 linhas, conforme a fi-
gura abaixo. Cada linha é ligada a uma entrada, e cada coluna a uma saída. Existem re-
sistores 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 colunas 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 leem-se as linhas, e assim 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 à coluna que
está em zero no momento a linha ligada a ela estará em também. As linhas que con-
té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:

188
Tabela 17 – Dígitos/Linhas/Colunas de um teclado matricial

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

Fonte: Adriano (2014).

189
O circuito do teclado é apresentado na figura abaixo.
Figura 5 – Displays de LED: (a) disposição dos segmentos, (b) catodo comum e

Fonte: Adriano (2014).

Geralmente, em kits didáticos do PIC, o teclado vem conectado nos ports B, já


que para utilizar leitura de teclado deve-se ter resistores de pull-up; e pode-se ativar
os resistores internos de pull-up no PIC18F4550e alguns outros modelos. Para o PI-
C18F4550, deve-se limpar o bit (), tendo a flag de interrupção em

2.6.1 Teclado Matricial


Como é muito comum a utilização de teclados por varredura, os microcontrola-
dores PIC já tem uma funcionalidade pensada para permitir associar uma interrupção
ao teclado. Essa funcionalidade é a interrupção por mudança de estado na porta B. O
evento que sinaliza essa interrupção é a mudança do estado dos pinos RB7, RB6, RB5
ou RB4. Observe que se esses pinos estão ligados a linhas do teclado, portanto são en-
tradas. Assim, qualquer tecla pressionada causará o pedido de interrupção. Ao se fazer
o tratamento da interrupção faz-se a varredura para determinar qual a tecla lida. Mas
atenção! Para que esse procedimento funcione, as colunas devem ser mantidas sem-
pre em 0, quando fora do tratamento de interrupção.

190
2.7 DISPLAY DE CRISTAL LÍQUIDO – LCD
Para que informações do sistema sejam passadas ao usuário pode-se utilizar uma
série de recursos, porém muitos deles não são nada maleáveis e alguns poucos ami-
gáveis. Por exemplo, um modo bastante simples de se ter informações do sistema é
através de um painel com LEDs, cada um indicando uma determinada situação. Em-
bora em muitas aplicações só isso seja suficiente, em muitas outras, principalmente
quando a quantidade e variedade de informações são grandes, 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 LCDs no mercado. Existem displays gráficos e dis-
plays que aceitam somente caracteres, estes últimos chamados displays alfanuméri-
cos. Esses podem ter diferentes quantidades de linha e colunas. LCDs 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 (po-
dendo também ser configurado para trabalhar com 4 bits), um bit EN (Enable - Habili-
taçã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 reconhe-
cidos quando RS = 0, são instruções para o display (limpar a tela, ir para a segunda li-
nha, 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.

191
Abaixo é apresentada uma tabela resumida de códigos hexadecimais de coman-
dos do LCD.
Tabela 18 – Códigos hexadecimais de comando do LCD

Código do
Descrição do
Modo RS R/W Comando
Comando
(Hexadecimal)

Ativo (sem cursor) 0 0 0C


Controle do display
Inativo 0 0 0A, 08

Limpeza do Display com retorno do cursor 0 0 01

Retorno do cursor à 1a linha e da


0 0 02
mensagem à sua posição inicial

Ativo (ligado, fixo) 0 0 0E


Inativo 0 0 0C
Alternado 0 0 0F
Controle do Cursor Desloc. à esquerda 0 0 10
Desloc. à direita 0 0 14
Retorno 0 0 02
Piscante 0 0 0D
Para esquerda 0 0 04
Sentido de deslocamento do cursor na
Para direita 0 0 06
entrada de um novo caractere

Para esquerda 0 0 07
Deslocamento da mensagem com a entrada
Para direita 0 0 05
de um novo caractere

Para esquerda 0 0 18
Deslocamento da mensagem sem entrada
Para direita 0 0 1C
de um novo caractere

1aLinha 0 0 80
Endereço da primeira posição (à esquerda)
2aLinha 0 0 C0

Fonte: Adriano (2014).

192
Os endereços de cada posição no display são dados pela tabela abaixo. Para que
um caractere seja escrito em uma determinada posição, é enviado o valor dessa posi-
ção como comando e em seguida envia-se o caractere a ser escrito.
Tabela 19 – Endereços de posição no display LCD 16x2

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

Fonte: Adriano (2014).

A figura abaixo apresenta o circuito básico LCD.


Figura 6 – Esquema básico de conexão de um LCD

Fonte: Adriano (2014).

193
2.8 BIBLIOTECA LCD.H
Essa biblioteca possui as funções listadas abaixo, que permitem inicializar o display
e escrever simples caracteres ou strings.
Deve-se adicionar o <lcd.h> no início do código. Tambem estraremos em maior
detalhe de sua configuração na aula gravada. Isso pode ser feito usando o endere-
ço das pastas até o arquivo, por exemplo, se o LCD estiver na pasta downloads den-
tro do C:
#include <C:\downloads\lcd.h>

Fonte: autor (2023).

Por utilizar funções de delay, deve-se também garantir que esteja definido a frequ-
ência do oscilador (seja interno ou externo), por:

#define __XTAL_FREQ frequencia_oscilador

Fonte: autor (2023).

Por exemplo, caso o oscilador interno esteja configurado com 1 MHz, faz-se:

#define __XTAL_ FREQ 1000000


Fonte: autor (2023).

É necessário definir também os pinos de conexão com o LCD. Por exemplo, o pino
do LCD EN conectado em RE1, RS conectado em RE2 e as conexões de D0 a D7 na
porta D:

#define LENA PORTEbits.RE1 //Lcd ENable - pino EN do LCD


#define LDAT PORTEbits.RE2 //Lcd DATa - pino RS do LCD
#define LPORT PORTD // Porta conectada nos D0 a D7 do LCD

Fonte: autor (2023).

194
Na tabela abaixo é apresentado as funções dessa biblioteca:
Tabela 20 – Funções de conversão – lcd.h

Funções Descrição
lcd_init() Inicializa o LCD
lcd_dat(x) Escreve no LCD um caractere do tipo “char”
lcd_str(str) Escreve um conjunto de “char” (string) no LCD
lcd_cmd(hex) Envia um comando para o LCD (Tabela 18)

Fonte: autor (2023).

Por simplicidade, pode-se usar lcd_cmd com os seguintes argumentos (além dos
apresentados na tabela 18):
Tabela 21 – Argumentos da função lcd_cmd(arg)

Argumentos Hexadecimal enviado Descrição


L_ON 0x0F Liga o LCD
L_OFF 0x08 Desliga LCD
L_CLR 0x01 Limpa LCD e volta pra posição inicial do display
L_L1 0x80 Move cursor para posição inicial na primeira linha
L_L2 0xC0 Move cursor para posição inicial na segunda linha
L_CR 0x0F Ativa cursor “underline” e “blinking”
L_NCR 0x0C Desativa cursor “underline” e “blinking”

Fonte: autor (2023).

Tabela 22 – Funções de conversão – stdio.h

Funções
sprintf(s, “string e formatação”,variáveis)

Descrição
Formata uma string e armazena em “s”
Fonte: autor (2023).

195
Podemos simplificar a escrita usando a função sprintf da biblioteca stdio.h, por
exemplo:
Para o código:

#include <stdio.h>
int main(void)
{
char sbuf[100], s[]=”Apresenta essa string”;
int x = 1, y;
char a = ‘\n’;
y = sprintf(sbuf, “%s %d vez%c”, s, x, a);
printf(“Numero de caracteres apresentados para
o buffer da string = %d\n”, y);
printf(“String = %s\n”, sbuf);
}

Fonte: autor (2023).

Teríamos:

Numero de caracteres apresentados para o buffer da string = 22


String = Apresenta string 1 vez

Fonte: autor (2023).

Os valores %s %d %c refere-se a formatação do dado que será adicionado de for-


ma sequencial pelas variáveis após a primeira vírgula “(... , s, x, a);” e essa nova string
está sendo salva em sbuf.
A tabela a seguir apresenta os tipos de dados e formação que podem ser apresen-
tados. Ressalta-se também que pode se limitar valores decimais através da adição de
“x.y”. Ou seja, caso queira apresentar uma variável float somente duas casas decimais,
pode-se usar %.2f.

196
Tabela 23 – Controle de Interrupções

Tipo Descrição
d, i Signed int
o unsigned int octal
u unsigned int in decimal.
x unsigned int in lowercase hexadecimal.
X unsigned int in uppercase hexadecimal.
e, E Double in scientific notation.
f Double in decimal notation.
g, G double (takes the form of e, E or f as appropriate).
c Char - a single character.
s string.
p value of a pointer.
The associated argument shall be an integer pointer into which is placed the number of
n
characters written so far. No characters are printed.
% A % character is printed.

Fonte: Microchip (2019).

197
2.9 CONVERSOR ADC
O módulo do conversor digital-analógico possui 13 entradas para p pic18f4550.
Esse módulo permite a conversão de um sinal analógico correspondendo-o a um nú-
mero de 10bits.
Esse módulo possui cinco registradores:
 ADRESH - Parte alta do resultado da conversão A/D
 ADRESL - Parte baixa do resultado da conversão A/D
 ADCON0 – Registrador 0 do controle A/D
 ADCON1 - Registrador 1 do controle A/D
 ADCON2 - Registrador 2 do controle A/D
O registrador ADCON0 controla a operação do módulo A/D. ADCON1 configura
o funcionamento dos pinos do port. E ADCON2 configura a fonte do clock, tempo de
aquisição e justificação.
Figura 7 – Registrador ADCON0

Fonte: datasheet (2023).

198
Figura 8 – Registrador ADCON1

Fonte: datasheet (2023).

199
Figura 9 – Registrador ADCON2

Fonte: datasheet (2023).

Cada pino de porta associado ao conversor A/D pode ser configurado como uma
entrada analógica ou como uma E/S digital. Os registradores ADRESH e ADRESL con-
têm o resultado da conversão A/D. Quando a conversão A/D é concluída, o resultado
é carregado no par de registradores ADRESH:ADRESL, o bit (registrador ADCON0) é
limpo e o bit de sinalizador de interrupção A/D, ADIF, é setado.
Os canais de entrada analógica devem ter seus bits do TRIS correspondentes con-
figurados como entrada. A tensão de referência analógica é selecionável por software

200
para a tensão de alimentação positiva e negativa do dispositivo (VDD e VSS) ou o ní-
vel de tensão nos pinos RA3/AN3/VREF+ e RA2/AN2/VREF-/CVREF.
Os seguintes passos devem ser feitos para configurar e usar o módulo de conver-
são A/D:
1. Configurar o módulo A/D
a. Configurar pinos analógicos, referência de tensão e E/S digital (ADCON1)
b. Selecione o canal de entrada A/D (ADCON0)
c. Selecione o tempo de aquisição A/D (ADCON2)
d. Selecione o clock de conversão A/D (ADCON2)
e. Ligue o módulo A/D (ADCON0)
2. Configure a interrupção A/D (se desejar):
a. Limpar bit ADIF
b. Setar bit ADIE
c. Setar bit GIE
3. Aguarde o tempo de aquisição necessário (se necessário).
4. Inicie a conversão:
a. Setar o bit GO / DONE (registrador ADCON0)
5. Aguarde até que a conversão A/D seja concluída:
a. Verificar o bit GO / DONE, o qual é zerado no fim da conversão
Ou
b. Esperar pela interrupção A/D
6. Ler registradores de resultado A/D (ADRESH:ADRESL);
7. Limpe o bit ADIF, se necessário.
8. Para a próxima conversão, vá para a etapa 1 ou 2, conforme necessário. O tem-
po de conversão A/D por bit é definido como TAD. É necessária uma espera mí-
nima de 3 TAD antes do início da próxima aquisição. (Esse tempo está relacio-
nado com a configuração do sistema do clock. Para mais detalhes é necessário
ver o datasheet e associar as informações com a montagem do PIC na placa.
Por simplicidade, podemos usar um tempo de 20ms de espera para conversão).

201
2.10 COMPARADOR

Quando trabalhamos com microcontroladores, podemos ter situações em que de-


sejamos uma comparação rápida entre dois ou mais valores analógicos para que seja
tomada alguma ação sem uma intervenção do programa principal. Isso poderia ser
vantajoso se fosse feito de forma automática pelo microcontrolador ao invés de se ter
módulos A/D para fazer este tipo de tarefa.
No microcontrolador 18F4550 temos um periférico que possui essa característica.
O módulo de comparação analógica contém dois comparadores que podem ser con-
figurados de várias formas diferentes. As entradas podem ser pinos multiplexados de
entrada do portal A (RA0 até RA5), bem como podem ser referências de tensões obti-
das dentro do microcontrolador. As saídas digitais podem ser obtidas com valores nor-
mais ou inversos, estando disponíveis na saída do módulo comparador ou ainda po-
dem ser lidas através do registro de controle.
Abaixo temos o registro que serve para configuração da entrada e da saída do mó-
dulo comparador dentro do microcontrolador.
Figura 10 – Registrador CMCON

Fonte: Adriel (2014).

C2OUT: Armazena o valor de saída do comparador 2, onde:


 Quando C2INV for zero, temos o valor um quando o valor de entrada Vin+ do
comparador 2 for maior que Vin- e zero quando o valor de entrada de Vin+ for
menor que Vin-;
 Quando C2INV for um temos exatamente a situação contrária da anterior.
C1OUT: Armazena o valor de saída do comparador 1, onde:
Quando C1INV for zero, temos o valor um quando o valor de entrada Vin+ do
comparador 1 for maior que Vin- e zero quando o valor de entrada de Vin+ for me-
nor que Vin-;
Quando C1INV for um temos exatamente a situação contrária da anterior.

202
C2INV e C1INV: Como já pode ser notado, quando possuem valor um inverte o va-
lor de saída do comparador C2 e C1 respectivamente e quando em zero não inverte;
CM2:CM1:CM0: Estes três registros são responsáveis pela seleção do modo de fun-
cionamento dos dois comparadores, onde sua aplicação pode ser vista na Figura 11.
Figura 11 – Modos de operação do módulo comparador.

Fonte: Adriel (2014).

203
2.11 CAPTURA, COMPARAÇÃO E PWM

O módulo CCP (Captura, Comparação e PWM) permite realizar uma série de fun-
ções por hardware. Para explicar 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 frequê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, dependendo do modo selecionado, o módulo CCP interagem com os ti-
mers. Por _m, existe uma interrupção associada ao módulo CCP, que é disparada em
situações diferentes para cada modo

2.11.1 Modo de 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, permi-
tindo acionar a interrupção.
Esse evento 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 neste modo, o terminal RB3/CCP1 deve estar configurado como
entrada. 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 é reini-
ciado e no segundo, o valor capturado do timer 1 multiplicado pelo período do seu

204
clock corresponde ao tempo transcorrido entre os dois eventos. Outra forma é dei-
xar 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 frequências (nesse caso te-
mos o período e sabemos que ).
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 frequências altas. Sua contagem só pode ser zerada com a mu-
dança de modo do CCP.
Interrupções: O bit CCPxIF quando ocorre um evento de captura

2.11.2 Modo de Comparação


Nesse modo, o par de registros do módulo CCP (CCP1H:CCP1L) é constantemen-
te comparado com o par de registros do timer 1 (TMR1h:TMR1L). Quando eles coin-
cidem, é setado o flag CCP1IF. Além disso, podemos zerar o timer 1 ou forçar um esta-
do 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 mo-
dos 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.
Interrupção O bit CCPxIF é setado quando o Timer 1 e o valor de CCPRxH:CCPR-
xL coincidem

2.11.3 Modo de PWM


No modo PWM o módulo CCP permite utilizar sinais modulados em largura de
pulso (PWM - Pulse Width Modulation), que consiste em representar um valor pelo
duty-cycle (isto é, tempo em alto) de um trem de pulsos de frequência fixa. Por exem-
plo, admitindo-se que trabalhando com o PWM do PIC, sua resolução máxima é de 10
bits, ou seja, 1023 correspondem a 100% de duty-cycle.
Usando uma regra de três simples, podemos determinar a quanto que correspon-
de 30%, 25%, 99%, etc. Este processo é chamado de modulação porque permite car-
regar uma informação (expressa no duty-cycle) em uma portadora (trem de pulsos)

205
O PWM precisa de uma base de tempo que dará a frequência do sinal. O módu-
lo CCP utiliza o Timer 2 para conseguir essa base. Isso pode ser observado no diagra-
ma de blocos do 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 é reiniciado. Isso nos dá a frequência do
sinal. O duty-cycle é 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.
O registro CCPR1H não é acessível para leitura no modo PWM. O duty-cycle é
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
Figura 12 – Sinal PWM

Fonte: datasheet (2023).

Configurar o PWM é estabelecer sua frequência e seu duty-cycle. De posse desses


dois parâmetros, podemos calcular os valores em cada registro. O período é o inver-
so da frequência e é configurado através de PR2 e da pré-escala do TMR2 e pode ser
calculado através da equação a seguir
Tpwm = (PR2 + 1) * 4 * Tosc * (TMR2PS)
Onde: TPWM : período do PWM; TOSC: período do oscilador; TMR2PS: fator de
pré-escala do timer 2

206
Para encontrar o valor de PR2 a partir de um dado valor de período pode ser usada
a equação abaixo Valor de PR2 deve ser inteiro e menor que 256. Logo, em alguns ca-
sos será necessário arredondar esse valor, o que gerará um pequeno erro entre a fre-
quência desejada e a real. Com valores diferentes de pré-escala podemos chegar a va-
lores menores que 256 e a aproximações que levem a um erro menor

O duty-cycle por sua vez é configurado através de CCPR1L e dos bits 4 e 5 de CCP-
1CON. Geralmente se especifica o duty-cycle em porcentagem do tempo total. Assim,
dado um duty-cycle em porcentagem (DC%), o tempo correspondente a ele é encon-
trado pela equação abaixo.

Ou pela equação:

Onde: 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 à esquerda de CCP1RL.
Dispondo do tempo do duty-cycle, o valor de DC[9:0] é dado pela equação abaixo.
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

O período (e consequentemente a frequência) é dado pelo registro PR2. Para fre-


quências altas (períodos pequenos) existe uma perda da resolução, isto é, na verdade
trabalhamos com menos de dez bits. Por exemplo, se o valor usado para PR2 for 63,
os dois bits mais significativos são “perdidos” e 100% de duty-cycle à 255. Teremos um

207
PWM de 8 bits. A resolução, dada em bits, para uma dada frequência de PWM é dada
pela equação abaixo:

Por simplificação, utilizaremos uma biblioteca pronta para PWM, possuindo três
funções. Teremos um exemplo na aula gravada de uso e configuração do PWM.
Tabela 24 – Funções de PWM – PWM.h e PWM.c

Funções Descrição
PWM1_Start() Configura o periférido do PWM1 – porta RC2

PWM1_Init( freq. ) Configura o PWM1 para a frequência do número inteiro “freq”

Altera o valor do DutyCycle para DC.


Para 0% -> DC = 0
PWM1_Set_Duty( DC )
Para 100% -> DC = 255
Para outros casos aplique uma regra de três

Fonte: autor (2023).

Ressalta-se que, o registrador que controla o DutyCycle do PWM é um registrador


de 8 bits, e, portanto, representa um valor decimal de 0 à 255 (ou 256 variações). O
PWM associa esse valor a uma porcentagem, por exemplo, para 0% de DC, basta que
seja jogado o valor “0” na função PWM1_set_Duty(). Caso queiramos ajustar o valor
do DC para 50%, podemos fazer uma regra de três e encontraremos:

100% – 256
50% – X

X = 128

Portanto, PWM1_set_Duty(128) nos daria um DC de ~50%.

208
SUGESTÃO DE LEITURA

SOUSA, D. R. Desbravando o Microcontrolador PIC18:


Recursos Avançados. 1ed. São Paulo. Érica, 2010.
Capítulo 2 – O PIC18F4520

MICROCHIP. PIC18F4550 Datasheet. 2006.

MIYADAIRA, Alberto N. Microcontroladores PIC18:


aprenda e programe em linguagem C. 4 ed.
São Paulo: Érica, 2013.

PEREIRA, Fábio. Microcontrolador PIC18 detalhado:


hardware e software: PIC18F4520.
São Paulo: Érica, 2010.

209
REFERÊNCIAS
ADRIANO, J. D. Exsto – Xm118 – Microcontroladores PIC18, 2014.
FLOYD, T. L. Digital Fundamentals. 11ed. Prentice Hall, 2014.
MIYADAIRA, Alberto N. Microcontroladores PIC18: aprenda e programe
em linguagem C. 4 ed. São Paulo: Érica, 2013.
MICROCHIP. PIC18F4550 Datasheet. 2006.
PEREIRA, V. Microcontroladores PIC 16F e 18F – Teoria e Prática. São Paulo, 2013.
TORRE, F. E., MARTINS, H. R. Sistemas microcontrolados. INOVA – UFMG, 2012.
SOUZA, D. R. Desbravando o Microcontrolador PIC18: Recursos Avançados.
1ed. São Paulo. Érica, 2010.

210
CONSIDERAÇÕES FINAIS
Caro(a) estudante, depois de todo o estudo e dedicação destinados a esta Unida-
de, você já conhece as características e sintaxes da linguagem C aplicadas à programa-
ção de microcontroladores, em específico o PIC18F4550.
Vimos como podemos configurar os periféricos do PIC, e como podemos utilizá-
-los para desenvolver e projetar sistemas microcontrolados. Ressalta-se que os conhe-
cimentos adquiridos podem ser aplicados a outras aplicações, e não somente ao PIC.
Como, por exemplo, a metodologia e técnicas de programação podem ser levadas
para Matlab, Python, ou alguma outra linguagem de programação, apesar das sintaxes
serem diferentes, as lógicas de implementação podem ser traduzidas para tal lingua-
gem de maneira simples.
Além de forma organizacional que o fluxograma simplifica a implementação de ló-
gicas complexas; sendo ela uma ferramenta extremamente útil para qualquer tipo de
aplicação.

211
Anexo I
#pragma config <setting>=<named value>
For example:
// PLL Prescaler Selection bits : No prescale (4 MHz oscillator input drives PLL directly)

// System Clock Postscaler Selection bits : [Primary Oscillator Src: /1][96 MHz PLL Src: /2]

// USB Clock Selection bit (used in Full-Speed USB mode only; UCFG:FSEN = 1) : USB clock source co-
mes directly from the primary oscillator block with no postscale

#pragma config PLLDIV = 1, CPUDIV = OSC1_PLL2, USBDIV = 1


Register: CONFIG1L @ 0x300000

PLLDIV PLL Prescaler Selection bits

12 Divide by 12 (48 MHz oscillator input)

10 Divide by 10 (40 MHz oscillator input)

6 Divide by 6 (24 MHz oscillator input)

5 Divide by 5 (20 MHz oscillator input)

4 Divide by 4 (16 MHz oscillator input)

3 Divide by 3 (12 MHz oscillator input)

2 Divide by 2 (8 MHz oscillator input)

1 No prescale (4 MHz oscillator input drives PLL directly)

CPUDIV System Clock Postscaler Selection bits

OSC4_PLL6 [Primary Oscillator Src: /4][96 MHz PLL Src: /6]

OSC3_PLL4 [Primary Oscillator Src: /3][96 MHz PLL Src: /4]

OSC2_PLL3 [Primary Oscillator Src: /2][96 MHz PLL Src: /3]

OSC1_PLL2 [Primary Oscillator Src: /1][96 MHz PLL Src: /2]

212
USBDIV USB Clock Selection bit (used in Full-Speed USB mode only; UCFG:FSEN = 1)

2 USB clock source comes from the 96 MHz PLL divided by 2

1 USB clock source comes directly from the primary oscillator block with no postscale

Register: CONFIG1H @ 0x300001

FOSC Oscillator Selection bits

HSPLL_HS HS oscillator, PLL enabled (HSPLL)

HS HS oscillator (HS)

INTOSC_HS Internal oscillator, HS oscillator used by USB (INTHS)

INTOSC_XT Internal oscillator, XT used by USB (INTXT)

INTOSCéC Internal oscillator, CLKO function on RA6, EC used by USB (INTCKO)

INTOSCIOéC Internal oscillator, port function on RA6, EC used by USB (INTIO)

ECPLLéC EC oscillator, PLL enabled, CLKO function on RA6 (ECPLL)

ECPLLIOéC EC oscillator, PLL enabled, port function on RA6 (ECPIO)

ECéC EC oscillator, CLKO function on RA6 (EC)

ECIOéC EC oscillator, port function on RA6 (ECIO)

XTPLL_XT XT oscillator, PLL enabled (XTPLL)

XT_XT XT oscillator (XT)

FCMEN Fail-Safe Clock Monitor Enable bit

ON Fail-Safe Clock Monitor enabled

OFF Fail-Safe Clock Monitor disabled

IESO Internal/External Oscillator Switchover bit

ON Oscillator Switchover mode enabled

OFF Oscillator Switchover mode disabled

213
Register: CONFIG2L @ 0x300002

PWRT Power-up Timer Enable bit

OFF PWRT disabled

ON PWRT enabled

BOR Brown-out Reset Enable bits

ON Brown-out Reset enabled in hardware only (SBOREN is disabled)

Brown-out Reset enabled in hardware only and disabled in Sleep mode (SBOREN is
ONàCTIVE
disabled)

SOFT Brown-out Reset enabled and controlled by software (SBOREN is enabled)

OFF Brown-out Reset disabled in hardware and software

BORV Brown-out Reset Voltage bits

3 Minimum setting 2.05V

2 Setting 1 2.79V

1 Setting 2 4.33V

0 Maximum setting 4.59V

VREGEN USB Voltage Regulator Enable bit

ON USB voltage regulator enabled

OFF USB voltage regulator disabled

214
Register: CONFIG2H @ 0x300003

WDT Watchdog Timer Enable bit

ON WDT enabled

OFF WDT disabled (control is placed on the SWDTEN bit)

WDTPS Watchdog Timer Postscale Select bits

32768 1:32768

16384 1:16384

8192 1:8192

4096 1:4096

2048 1:2048

1024 1:1024

512 1:512

256 1:256

128 1:128

64 1:64

32 1:32

16 1:16

8 1:08

4 1:04

2 1:02

1 1:01

215
Register: CONFIG3H @ 0x300005

CCP2MX CCP2 MUX bit

ON CCP2 input/output is multiplexed with RC1

OFF CCP2 input/output is multiplexed with RB3

PBADEN PORTB A/D Enable bit

ON PORTB<4:0> pins are configured as analog input channels on Reset

OFF PORTB<4:0> pins are configured as digital I/O on Reset

LPT1OSC Low-Power Timer 1 Oscillator Enable bit

ON Timer1 configured for low-power operation

OFF Timer1 configured for higher power operation

MCLRE MCLR Pin Enable bit

ON MCLR pin enabled; RE3 input pin disabled

OFF RE3 input pin enabled; MCLR pin disabled

216
Register: CONFIG4L @ 0x300006

STVREN Stack Full/Underflow Reset Enable bit

ON Stack full/underflow will cause Reset

OFF Stack full/underflow will not cause Reset

LVP Single-Supply ICSP Enable bit

ON Single-Supply ICSP enabled

OFF Single-Supply ICSP disabled

ICPRT Dedicated In-Circuit Debug/Programming Port (ICPORT) Enable bit

ON ICPORT enabled

OFF ICPORT disabled

XINST Extended Instruction Set Enable bit

ON Instruction set extension and Indexed Addressing mode enabled

OFF Instruction set extension and Indexed Addressing mode disabled (Legacy mode)

DEBUG Background Debugger Enable bit

OFF Background debugger disabled, RB6 and RB7 configured as general purpose I/O pins

ON Background debugger enabled, RB6 and RB7 are dedicated to In-Circuit Debug

217
Register: CONFIG5L @ 0x300008

CP0 Code Protection bit

OFF Block 0 (000800-001FFFh) is not code-protected

ON Block 0 (000800-001FFFh) is code-protected

CP1 Code Protection bit

OFF Block 1 (002000-003FFFh) is not code-protected

ON Block 1 (002000-003FFFh) is code-protected

CP2 Code Protection bit

OFF Block 2 (004000-005FFFh) is not code-protected

ON Block 2 (004000-005FFFh) is code-protected

CP3 Code Protection bit

OFF Block 3 (006000-007FFFh) is not code-protected

ON Block 3 (006000-007FFFh) is code-protected

Register: CONFIG5H @ 0x300009

CPB Boot Block Code Protection bit

OFF Boot block (000000-0007FFh) is not code-protected

ON Boot block (000000-0007FFh) is code-protected

CPD Data EEPROM Code Protection bit

OFF Data EEPROM is not code-protected

ON Data EEPROM is code-protected

218
Register: CONFIG6L @ 0x30000A

WRT0 Write Protection bit

OFF Block 0 (000800-001FFFh) is not write-protected

ON Block 0 (000800-001FFFh) is write-protected

WRT1 Write Protection bit

OFF Block 1 (002000-003FFFh) is not write-protected

ON Block 1 (002000-003FFFh) is write-protected

WRT2 Write Protection bit

OFF Block 2 (004000-005FFFh) is not write-protected

ON Block 2 (004000-005FFFh) is write-protected

WRT3 Write Protection bit

OFF Block 3 (006000-007FFFh) is not write-protected

ON Block 3 (006000-007FFFh) is write-protected

Register: CONFIG6H @ 0x30000B

WRTC Configuration Register Write Protection bit

OFF Configuration registers (300000-3000FFh) are not write-protected

ON Configuration registers (300000-3000FFh) are write-protected

WRTB Boot Block Write Protection bit

OFF Boot block (000000-0007FFh) is not write-protected

ON Boot block (000000-0007FFh) is write-protected

WRTD Data EEPROM Write Protection bit

OFF Data EEPROM is not write-protected

ON Data EEPROM is write-protected

219
Register: CONFIG7L @ 0x30000C

EBTR0 Table Read Protection bit

OFF Block 0 (000800-001FFFh) is not protected from table reads executed in other blocks

ON Block 0 (000800-001FFFh) is protected from table reads executed in other blocks

EBTR1 Table Read Protection bit

OFF Block 1 (002000-003FFFh) is not protected from table reads executed in other blocks

ON Block 1 (002000-003FFFh) is protected from table reads executed in other blocks

EBTR2 Table Read Protection bit

OFF Block 2 (004000-005FFFh) is not protected from table reads executed in other blocks

ON Block 2 (004000-005FFFh) is protected from table reads executed in other blocks

EBTR3 Table Read Protection bit

OFF Block 3 (006000-007FFFh) is not protected from table reads executed in other blocks

ON Block 3 (006000-007FFFh) is protected from table reads executed in other blocks

Register: CONFIG7H @ 0x30000D

EBTRB Boot Block Table Read Protection bit

OFF Boot block (000000-0007FFh) is not protected from table reads executed in other blocks

ON Boot block (000000-0007FFh) is protected from table reads executed in other blocks

220

Você também pode gostar