Monografia Renato Vasques Beraldo Final 12 12
-
Upload
renato-vasques-beraldo -
Category
Documents
-
view
65 -
download
3
Transcript of Monografia Renato Vasques Beraldo Final 12 12
PONTIFÍCIA UNIVERSIDADE CATÓLICA DE MINAS GERAISDepartamento de Ciência da Computação - Campus Poços de Caldas
DESENVOLVIMENTO DE UM KIT DIDÁTICO UTILIZANDO MICROCONTROLADORES PIC
RENATO VASQUES BERALDO
Poços de Caldas2006
RENATO VASQUES BERALDO
DESENVOLVIMENTO DE UM KIT DIDÁTICO UTILIZANDO MICROCONTROLADORES PIC
Trabalho apresentado à disciplina de Trabalho de Diplomação do Departamento de Ciência da Computação da Pontifícia Universidade Católica de Minas Gerais - Campus Poços de Caldas.
Poços de Caldas2006
Beraldo, Renato Vasques B482d Desenvolvimento de um kit didático utilizando microcontroladores
PIC. Poços de Caldas, 2006.152f.
Orientador: Prof. M.Sc. Eduardo Barrére
CDU 681.31
Renato Vasques BeraldoDesenvolvimento de um kit didático utilizando microcontroladores PIC
Trabalho apresentado à disciplina de Trabalho de Diplomação da Pontifícia Universidade Católica de Minas Gerais, Poços de Caldas, 2006.
___________________________________________________Prof. M.Sc. Eduardo Barrére (Orientador) – PUC Minas
___________________________________________________Prof. Dr. Cláudio Faria – PUC Minas
___________________________________________________Prof. Dr. Udo Fritzke Junior – PUC Minas
Agradecimentos
Primeiramente agradeço a Deus por me iluminar nesta longa caminhada; aos meus
pais que nunca deixaram de me apoiar e não mediram esforços durante todo o tempo; a minha
namorada Gisele que sempre esteve presente em todos os momentos; homenageio aqui
também todos que ao longo desta caminhada de alguma forma me ajudaram com
ensinamentos, experiências ou até mesmo com a simples amizade; e por último e não menos
importante o meu grande e querido amigo orientador prof. M.Sc. Eduardo Barrére, agradeço
pela amizade, atenção e dedicação para a concretização deste trabalho.
Resumo
Neste trabalho estão demonstrados os dados de pesquisa e resultados obtidos para o
desenvolvimento de um kit didático utilizando microcontroladores PIC para ser aplicado em
aulas de laboratório e para projetos isolados dentro de disciplinas do curso de Ciência da
Computação.
Após a analise dos resultados obtidos ficou definido que o desenvolvimento do kit é
viável, portanto neste trabalho também serão abordados assuntos como a montagem do kit e
seus elementos, a montagem de um módulo periférico básico que será utilizado para testar os
exemplos contidos neste trabalho, a montagem de um módulo periférico de comunicação
entre o kit e um microcomputador através da porta serial e também são sugeridas aplicações
que podem vir a ser desenvolvidas em outros trabalhos.
Estão disponibilizados em anexos diversos códigos-fonte e bibliotecas para testes,
além disso, também está em anexo um tutorial explicando como utilizar os softwares
abordados neste trabalho.
Abstract
In this work the research data are demonstrated and results gotten for the development
of a didactic kit using microcontrollers PIC to be applied in laboratory lessons and for isolated
projects inside of you discipline of the course of Computer science.
After it analyzes it of the gotten results was definite that the development of the kit is
viable, therefore in this work also they will be boarded subjects as the assembly of the kit and
its elements, the assembly of basic a peripheral module that will be used to test the examples
contained in this work, the assembly of a peripheral module of communication between the
kit and a microcomputer through the serial door and also is suggested applications that can
come to be developed in other works.
Code-source and libraries for tests are disponibilizados in diverse annexes, moreover,
also it is in annex a tutorial one explaining as to use softwares boarded in this work.
Sumário
1 Introdução...........................................................................................................................15
2 Microcontroladores da Família PIC.................................................................................17
2.1 Definição....................................................................................................................17
2.2 Arquitetura.................................................................................................................17
2.3 Características............................................................................................................20
2.4 Modo de Funcionamento...........................................................................................22
2.5 Aplicações..................................................................................................................24
3 Módulo Educacional...........................................................................................................25
3.1 Aplicações nas Disciplinas........................................................................................25
3.2 Funcionalidades.........................................................................................................26
3.3 Seleção do Microcontrolador PIC..............................................................................27
4 Kit Microcontrolado...........................................................................................................30
4.1 Arquitetura.................................................................................................................30
4.1.1 O Circuito Gravador.......................................................................................31
4.1.2 O Circuito de Clock........................................................................................31
4.1.3 O Circuito de Alimentação.............................................................................32
4.1.4 O Circuito de Alimentação de Externa...........................................................32
4.1.5 O Circuito de Controle de LED’s...................................................................32
4.1.6 O Microcontrolador e suas Portas..................................................................32
4.2 O Circuito do Kit........................................................................................................33
4.3 Testes.........................................................................................................................36
4.3.1 O Circuito Gravador.......................................................................................36
4.3.2 O Circuito de Testes.......................................................................................37
5 Módulos Periféricos de Interface......................................................................................39
5.1 Pinos do Microcontrolador........................................................................................39
5.2 Módulo Periférico Básico..........................................................................................43
5.3 Comunicação Serial entre o Kit e o Microcomputador..............................................47
5.4 Memória EEPROM Interna.......................................................................................50
6 Trabalhos Futuros..............................................................................................................51
6.1 Módulo LCD..............................................................................................................51
6.2 Comunicação entre Kits.............................................................................................53
6.3 Armazenamento de Dados em Memórias..................................................................55
6.3.1 O SPI...............................................................................................................55
6.3.2 Memórias EEPROM Serial............................................................................57
6.3.3 MMC (MultMediaCard).................................................................................60
7 Conclusão............................................................................................................................61
Referência Bibliográfica.........................................................................................................62
Anexo A....................................................................................................................................64
A.1 Tabela com Conjunto de Instruções em Linguagem Assembler...............................64
Anexo B....................................................................................................................................66
B.1 Código utilizado para teste com display de sete segmentos em Linguagem Assembly
66
B.2 Código utilizado para teste com display de sete segmentos em linguagem C...........69
Anexo C....................................................................................................................................71
C.1 Layout da Placa de Construção do Kit Sem Componentes (vista de trás) e no
Tamanho Real...........................................................................................................................71
C.2 Layout da Placa de Construção do Kit Com Componentes e Pontes (vista de frente)
72
Anexo D....................................................................................................................................73
D.1 Layout da Placa de Construção do Módulo Básico Sem Componentes (vista de trás)
e no Tamanho Real...................................................................................................................73
D.2 Layout da Placa de Construção do Módulo Básico Com Componentes e Pontes
(vista de frente).........................................................................................................................74
D.3 Código de exemplo utilizando um display de 7 segmentos anodo comum e o teclado
75
D.4 Código de exemplo utilizando os leds vermelhos para testar o funcionamento das
portas ....................................................................................................................................80
D.5 Código de exemplo utilizando o led verde para demonstrar o funcionamento do
PWM ....................................................................................................................................82
D.6 Códigos de exemplo utilizando dois ou mais displays de 7 segmentos.....................84
D.6.1 Código de exemplo para displays de 7 segmentos anodo comum.................84
D.6.2 Código de exemplo para displays de 7 segmentos catodo comum.................88
D.7 Código de exemplo utilizando o led verde para demonstrar o funcionamento do
PWM, o teclado para ajustes no nível do PWM e displays anodo comum para mostrar o nível
do PWM ....................................................................................................................................92
Anexo E..................................................................................................................................100
E.1 Código exemplificando a Transmissão e Recepção de Dados via Comunicação
Serial Padrão RS-232..............................................................................................................100
Anexo F..................................................................................................................................101
F.1 Código exemplificando a Gravação e Leitura de Dados na Memória EEPROM
Interna, Mostrando os Dados Correntes em Displays de 7 Segmentos..................................101
Anexo G..................................................................................................................................106
G.1 Conjunto de Comandos para Programar o Módulo LCD........................................106
G.2 Biblioteca em C para Manipulação e Programa Fonte para Testes com Módulo LCD
utilizando 4 bits.......................................................................................................................107
Anexo H..................................................................................................................................111
H.1 Biblioteca I2C...........................................................................................................111
Anexo I...................................................................................................................................115
I.1 Biblioteca 25640.c...................................................................................................115
I.2 Exemplo utilizando comunicação serial com microcomputador e leitura / escrita em
memória EEPROM 25640......................................................................................................118
Anexo J...................................................................................................................................120
J.1 Biblioteca mmc.c.....................................................................................................120
Anexo K..................................................................................................................................125
K.1 Variáveis de Configuração do Microcontrolador PIC 16F877-A............................125
K.2 Tabela com os Tipos de Dados suportados pelos compiladores CCS.....................127
K.3 Tabela com as Principais Funções em Linguagem C para compiladores CCS.......128
Anexo L..................................................................................................................................134
L.1 Planilha de Microcontroladores Selecionados.........................................................134
Anexo M.................................................................................................................................135
M.1 Tutorial.....................................................................................................................135
Lista de TabelasTabela 1: Exemplo de características de microcontroladores....................21
Tabela 2: Características do microcontrolador PIC 16F877-A....................28
Tabela 3: Componentes para a construção do kit......................................35
Tabela 4: Características dos pinos do PIC16F877-A.................................40
Tabela 5: Componentes para a construção do kit......................................45
Tabela 6: Comandos de 8 bits para SPI......................................................57
Tabela 7: Funcionalidades dos Pinos da Memória EEPROM 25LC640........58
Lista de FigurasFigura 1: Diagrama de Organização das Arquiteturas...............................18
Figura 2: Diagrama da Arquitetura Interna do PIC 16F877-A.....................19
Figura 3: Diagrama da Arquitetura do kit..................................................30
Figura 4: Modos de Funcionamento do kit.................................................31
Figura 5: Foto do kit...................................................................................33
Figura 6: Circuito de construção do kit......................................................34
Figura 7: Circuito de construção do gravador............................................36
Figura 8: Circuito para execução de testes com display............................37
Figura 9: Foto do kit executando código de testes....................................38
Figura 10: Pinos do microcontrolador PIC16F877-A...................................39
Figura 11: Circuito do Módulo Periférico de Interface Básico.....................44
Figura 12: Diagrama de blocos kit e módulo periférico básico..................46
Figura 13: Kit e módulo básico trabalhando em conjunto..........................47
Figura 14: Pinagem porta serial.................................................................48
Figura 15: Circuito de Comunicação com Porta Serial utilizando C.I.
MAX232...............................................................................................49
Figura 16: Circuito de Comunicação com Porta Serial utilizando
Transistores.........................................................................................49
Figura 17: Circuito de execução de testes com módulo LCD.....................52
Figura 18: Exemplo de barramento para comunicação entre kits.............54
Figura 19: Diagrama de Comunicação entre dois Dispositivos utilizando
SPI........................................................................................................56
Figura 20: Diagrama de Comunicação entre um mestre e diversos
dispositivos escravos utilizando SPI.....................................................56
Figura 21: Pinos da memória EEPROM 24LC16B........................................57
Figura 22: Conexão de um MMC ao microcontrolador...............................60
Lista de Abreviaturas
ALU Arithmetic Logic Unit
BCD Binary Coded Decimal
C.I. Circuitos Integrados
CPU Unidade Central de Processamento
CS Chip Select
EEPROM Electrically Erasable Programmable Read-Only Memory
ENIAC Electronic Numerical Integrator and Computer
I/D Instruction / Data
I/O Input / Output
I2C Inter Integrated Comunication
ICSP In-Circuit Serial Programming
LCD Liquid Crystal Display
MMC Mult Media Card
OTP One Time Programmable
PIC Peripherals Interface Controller
PWM Pulse Width Modulation
R/W Read / Write
RAM Random Access Memory
RISC Reduced Instruction Set Computer
ROM Read Only Memory
RS Register Selector
SI Serial In
SO Serial Out
SPI Serial Port Interface
SPI Serial Peripheral Interface
USART Universal Synchronous Asynchronous Receiver Transmitter
USB Universal Serial Bus
15
1 Introdução
Os sistemas computacionais passaram por uma grande evolução desde a década de 40,
onde foram desenvolvidas as primeiras máquinas de calcular, como por exemplo, o Electronic
Numerical Integrator and Computer (ENIAC). Essas máquinas foram construídas a partir de
válvulas que eram ativadas e desativadas conforme a necessidade. Devido ao seu grande
porte as máquinas ocupavam muito espaço, tinham alto custo e eram de difícil operação.
Na década de 50 um novo tipo de componente eletrônico foi desenvolvido, o
transistor, cujo custo de produção era baixo e seu porte bem menor do que o das válvulas,
ocasionando consequentemente à substituição destas pelos transistores.
Em meados da década de 60 surgiram os circuitos integrados (C.I.´s), chips que
tinham como base para sua fabricação os transistores. Estes chips possuíam várias funções
embutidas e podem ser considerados os pais dos microcontroladores e dos
microprocessadores. Em 1970 a Intel recebeu a encomenda de alguns C.I.´s para calculadoras
e um de seus engenheiros propôs a fabricação de um C.I. que contivesse um programa
armazenado e este determinaria as suas funções, surgindo assim os microprocessadores. A
partir desta descoberta, a Intel lançou em 1974 um microprocessador que poderia executar
diversas funções. Desde então, a evolução não parou e hoje temos microprocessadores com
núcleo duplo ou mais.
Por volta de 1974, além dos microprocessadores, foram desenvolvidos os
microcontroladores, que nada mais são do que microprocessadores com vários periféricos
integrados em um único chip, como por exemplo, random access memory (memória de acesso
randômico – memória RAM), contadores, interface para dispositivos de Input / Output
(entrada / saída, I / O), etc. (MATIC, 2003).
Com o avanço dos sistemas computacionais (hardware e software) um novo conceito
chamado de Computação Embarcada ou “Computação Invisível” vem sendo desenvolvido
junto com a crescente disponibilidade de aparelhos e dispositivos que não efetuam uma
computação convencional, citando como exemplo sistemas que controlam computadores de
bordo, sensores, painéis de equipamentos eletrônicos, controle de tração em carros, celulares,
16
robôs, pen-drive’s e palm’s. O conceito de sistemas embarcados se aplica aos sistemas onde
um microprocessador e toda a sua estrutura tornariam inviável a sua implantação. (BASSO,
2004).
Além dos sistemas embarcados, os microcontroladores tem sua importância para o
aprendizado sendo empregados na construção de kit’s didáticos para alunos de diversos
cursos.
Este trabalho tem como objetivo o desenvolvimento de um kit didático de baixo custo
e com uma vasta gama de aplicações. Antes de ser escolhida a família de microcontroladores
a serem empregados no kit, foram realizadas pesquisas analisando os vários tipos de
microcontroladores e suas respectivas famílias. Após estes estudos, a família de
microcontroladores escolhida para utilização no kit foi à família PIC ou “Peripherals
Interface Controller” (Interface Controladora de Periféricos) da Microchip Technology Inc.
O capítulo 2 destaca os conceitos básicos sobre os microcontroladores PIC e seu modo
de operação.
O capítulo 3 traz informações sobre o módulo educacional ou kit didático como é
comumente chamado neste trabalho.
O capítulo 4 é dedicado à construção e testes dos circuitos que compõem o kit didático
microcontrolado.
O capítulo 5 apresenta a descrição dos pinos do microcontrolador além de trazer a
implementação de um módulo básico de interface e um módulo de comunicação serial.
O capítulo 6 demonstra possíveis módulos que podem ser construídos para serem
utilizados com o kit.
Treze anexos fecham este trabalho com informações complementares, como as
instruções para programação do microcontrolador, diversas bibliotecas de software, o layout
das placas do kit e dos módulos e códigos fonte para testes.
17
2 Microcontroladores da Família PIC
Os microcontroladores PIC são fabricados pela Microchip Technology Inc
(MICROCHIP, 2006), empresa norte-americana fundada em 1989, que além de
microcontroladores também fabrica memórias seriais (I2C e SPI), produtos para segurança
(Keeloq), identificadores por RF (RFID), conversores Analógico/Digitais, circuito integrado
de supervisão de funcionamento(Brown out) e amplificadores operacionais.
2.1 Definição
O nome PIC vem de “Peripherals Interface Controller” (interface controladora de
periféricos), tendo como principais características incorporarem internamente a unidade
central de processamento (CPU), memórias de programa e dados e vários periféricos como
timers, watchdog timers, comunicação serial, conversores analógicos digitais, geradores de
Pulse Width Modulation (modulação por largura de pulso – PWM), etc.
Suas instruções são do tipo “Reduced Instruction Set Computer” (computador com
número de instruções reduzidas – RISC) e sua arquitetura do tipo Harvard.
2.2 Arquitetura
A grande maioria dos computadores atuais utiliza a arquitetura de Von Neumann,
onde o programa (instruções) e dados são armazenados em uma mesma memória. Nos
microcontroladores PIC a arquitetura utilizada é a de Harvard, que utiliza memórias
separadas (memória de dados e memória de programa) e barramento distinto para acesso as
mesmas. O diagrama da figura 1 ilustra a organização das duas arquiteturas.
18
Figura 1: Diagrama de Organização das Arquiteturas.FONTE: (MATIC, 2003).
A arquitetura de Harvard proporciona ganho de desempenho devido à possibilidade de
ler/escrever instruções e dados concorrentemente, mas em contrapartida isto torna sua
utilização mais cara e complexa, por isso ela é geralmente utilizada em microcontroladores e
processadores de sinais. (MARK’S, 2006).
Os microcontroladores que possuem arquitetura Harvard têm seu conjunto de
instruções reduzido (instruções do tipo RISC) proporcionando ganho de desempenho, uma
vez que cada instrução leva apenas um ciclo de clock para ser executada (exceto no caso de
instruções de salto e ramificações). A utilização deste tipo de instruções torna possível o
paralelismo na execução de instruções devido ao uso de pipelining.
Os microcontroladores PIC, como anteriormente mencionado, possuem internamente
várias estruturas podendo ser citadas entre estas a CPU também conhecida como “Arithmetic
Logic Unit” (Unidade Lógico Aritmética – ULA em português ou ALU em inglês), conversor
analógico/digital e timers. A figura 2 ilustra a organização interna do microcontrolador PIC
16F877-A.
Memória de
Programa
Memória de
Dados
Memória de
Programa e Dados
CPU
Arquitetura Von Neumann
Arquitetura Harvard
CPU
19
Figura 2: Diagrama da Arquitetura Interna do PIC 16F877-A.FONTE: (MICROCHIP, 2006).
Entre as diferenças básicas das arquiteturas de Von Neumann e de Harvard (vide
figura 1), nota-se que nos microcontroladores (arquitetura de Harvard) as memórias são
separadas em memória de dados e memória de programa.
A memória de dados é dividida em múltiplos bancos e contém registradores de
funções especiais e registradores de uso geral. Entre os registradores de funções especiais
estão o registrador TMR0, o contador de programa (PC), o registrador de status, os
registradores de I/O e o registrador de seleção (FSR). Além disso, os registradores de funções
especiais são utilizados para controlar as configurações das portas de I/O. Já os registradores
de uso geral são utilizados para dados e controle de informações sob comandos das instruções.
20
A memória de programa, além de armazenar a aplicação que será executada pelo
microcontrolador, também armazena o vetor de interrupções e o vetor de reset, sendo
importante salientar que a memória de programa não pode ser acessada diretamente.
(MICROCHIP, 2006).
2.3 Características
A família de microcontroladores PIC é muito extensa para ser abordada em sua
totalidade, podendo ser dividida em subgrupos cada qual com suas particularidades.
As principais características são:
Arquitetura do barramento de dados: 8 bits e 16 bits;
Tipo da Memória
o Flash: Tipo de memória que pode ser apagada e/ou escrita ilimitadas
vezes;
o OTP (One Time Programmable, programável uma única vez): Tipo de
memória que só pode ser programada/escrita uma única vez;
o ROM (Read only memory, memória de somente leitura): Tipo de
memória utilizada quando o microcontrolador somente irá executar
uma função no circuito, portanto não à necessidade de reprogramação.
Memória RAM (medida em bytes);
Memória de Programas (espaço destinado à gravação do programa, é medido
em Kwords);
Velocidade de Clock: variando de 4MHz a 64MHz de clock máximo;
Quantidade de Pinos: variando entre 6 e 100 pinos;
Quantidade de Pinos de I/O: variando de 0 a 70 pinos configuráveis como I/O;
21
Protocolo de Comunicação com o microcomputador: USB, Serial e Ethernet.
A própria fabricante dos microcontroladores PIC possui uma divisão que consiste em
agrupar os PIC’s em subfamílias de acordo com suas características principais. Estas
subfamílias são: PIC 10, PIC 12, PIC 14, PIC 16, PIC 17, PIC 18 e PIC 24.
A tabela 1 exibe as características de dois microcontroladores da família PIC.
Tabela 1: Exemplo de características de microcontroladores
MODELO PIC 16F877-A PIC 18F2455
Arquitetura 8 bits 8 bits
Tipo da Memória de Programa Flash Flash
Tamanho da Memória de Programa
14 Kbytes / 8 Kwords 24 Kbytes / 12 Kwords
Tamanho da Memória de Dados 256 bytes 256 bytes
Tamanho da Memória Ram 368 bytes 2048 bytes
Quantidade de Pinos de I / O 33 pinos 23 pinos
Quantidade Total de Pinos 40 pinos 28 pinos
Velocidade de Clock Máximo 20 MHz 48 MHz
Protocolo de Comunicação com Microcomputador
AUSARTMI²C
Compatible/SPI
EUSARTMI²C Compatible/SPI
USB 2.0
FONTE: (MICROCHIP, 2006)
Além das características descritas acima, temos outras que são comuns em todas as
subfamílias de microcontroladores PIC, como exemplo:
Tipo de oscilador externo: RC (baixo custo), XT (cristal padrão), HS (cristal de
alta velocidade) e LP (cristal de baixa freqüência);
Proteção de Código Programável;
Modo de baixo consumo de energia (SLEEP);
4 bytes para identificação do microcontrolador programáveis;
22
Temporizador e Contadores Internos.
Algumas destas características são habilitadas por linhas de comando no código fonte
da aplicação ou até mesmo no software de transferência.
2.4 Modo de Funcionamento
De um modo geral, os microcontroladores necessitam de um hardware especial para
fazer a transferência do programa a ser executado para a sua memória de programa. No caso
dos microcontroladores PIC este hardware é chamado de gravador.
Existem vários gravadores para microcontroladores PIC, alguns são produzidos pela
própria fabricante do microcontrolador e há também disponíveis em livros e na internet
gravadores similares (PABLIN, 2005; JDM,2000; INSTRUCTABLES, 2006; MARK’S,
2006), com custo relativamente baixo em relação aos gravadores da Microchip Technology
Inc.
O objetivo deste trabalho foi desenvolver um kit de baixo custo e para tal foram
realizadas várias pesquisas e testes com os gravadores disponíveis em livros e na internet. O
resultado obtido com os testes levou a escolha de um gravador cuja interface com o
computador é feita via porta serial, mas há também gravadores de interface paralela e USB.
Os gravadores paralelos utilizam fonte de energia externa, pois a porta paralela não consegue
fornecer tensões apropriadas para a gravação, elevando o custo e inviabilizando assim a sua
construção. Já os gravadores USB são mais complexos de serem desenvolvidos uma vez que a
gravação dos microcontroladores PIC é feita serialmente. Portanto, para se desenvolver um
gravador USB seria necessário conhecer como é feita a conversão dos dados USB para serial.
Antes de ser desenvolvido o gravador que será utilizado no kit, foram pesquisados,
descarregados e testados a maioria dos softwares livres utilizados para a transferência da
aplicação desenvolvida para o microcontrolador, pois era necessário saber se estes softwares
suportavam o gravador. O software que se adequou melhor às necessidades foi o IC-PROG
que não precisa ser instalado, deve apenas ser descarregado e descompactado. (IC-PROG,
2005).
23
Para o desenvolvimento da aplicação é necessário que se tenha um software que
possibilite ao desenvolvedor escrever o código fonte e compilá-lo. Como este kit será
utilizado para fins didáticos é desejável também que este software ofereça ferramentas que
possibilitem a simulação da aplicação antes mesmo de ser gravada no microcontrolador. A
própria Microchip coloca a disposição em seu sitio um software para desenvolvimento das
aplicações, o MPLAB-IDE (MICROCHIP, 2006) que possui boas ferramentas para suporte ao
desenvolvedor, este deve ser descarregado do sítio e instalado.
Abaixo estão descritos os passos que devem ser seguidos para colocar o
microcontrolador em operação:
1º Ter todos os softwares necessários para o desenvolvimento já operando;
2º Ter os circuitos de gravação e de clock já montados;
3º Definida a aplicação que o microcontrolador irá executar, esta deverá ter seu
código escrito e compilado;
4º Se não houver erros de compilação, o código hexadecimal será gerado e estará
pronto para ser gravado no microcontrolador;
5º Com o código hexadecimal gerado, o gravador poderá ser conectado ao
microcomputador e também ao microcontrolador;
6º Carrega-se o código hexadecimal no software de transferência e se necessário
podem ser feitos ajustes em algumas configurações no software;
7º Com o código hexadecimal carregado, já é possível executar a gravação no
microcontrolador;
8º Se não houver erros de gravação o microcontrolador já estará com a aplicação
armazenada em sua memória de programa;
9º Agora o microcontrolador já pode ser conectado no circuito de clock e também
ao circuito da aplicação;
24
10º Finalmente poderá ser ligada à fonte de energia que alimentará o circuito
possibilitando a visualização da aplicação em execução.
Caso os resultados obtidos tenham sido os esperados, isso comprova que todos os
passos foram executados de forma correta.
2.5 Aplicações
Após serem realizadas várias pesquisas para identificar as possíveis aplicações para
microcontroladores, descobriu-se a existência de inúmeras utilidades para eles. Os
microcontroladores PIC (MICROCHIP, 2006) são utilizados nas indústrias automobilísticas
(controle de freios, controle de tração, etc.), em eletrodomésticos (controlando os displays que
mostram informações, processando comandos de controle remoto, etc.) e em robótica, por
exemplo. Isto comprova que os microcontroladores estão em todos os lugares onde é
necessário processamento de dados e que seria inviável a utilização de um microcomputador.
25
3 Módulo Educacional
O principal objetivo deste projeto é a construção de um kit didático, para ser utilizado
em aulas de laboratório das disciplinas de Organização de Computadores e Arquitetura de
Computadores da PUC MINAS – campus de Poços de Caldas.
3.1 Aplicações nas Disciplinas
As disciplinas de Organização de Computadores e Arquitetura de Computadores já
possuem em suas aulas de laboratório um kit, porém este apresenta restrições, além de ser de
difícil manutenção e usabilidade. Este foi um dos principais motivos para o desenvolvimento
deste kit didático. O kit desenvolvido será mais prático de ser utilizado e proporcionará
melhor rendimento e aprendizado nas aulas.
A disciplina de Organização de Computadores tem como objetivo expor aos alunos o
funcionamento da programação de microprocessadores em sua linguagem nativa (assembly) e
também apresentar sua organização interna. Nesta disciplina o kit será empregado para o
aprendizado da linguagem nativa (nível básico), onde o aluno poderá programar o kit com
aplicações definidas pelo professor e realizar simulações para verificação de resultados.
Também dentro desta mesma disciplina o aluno poderá desenvolver projetos isolados, como
por exemplo, controle de dispositivos e implementação de periféricos.
A disciplina de Arquitetura de Computadores é uma continuação da disciplina de
Organização de Computadores, tendo os mesmos objetivos, porém com nível de
conhecimento mais aprofundado. O kit também será utilizado para simulações e
desenvolvimento de aplicações definidas pelo professor, porém proporcionando ao aluno o
nível de aprendizado intermediário da linguagem nativa. Fora da disciplina o aluno poderá
desenvolver projetos avançados como, por exemplo, a comunicação entre dispositivos
microcontrolados, troca de dados entre o kit e um computador (compartilhamento de recursos)
e aplicações não convencionais.
O kit também poderá ser programado em linguagem C, ficando a cargo do(s)
professor(es) escolher(em) se será abordado ou não este tipo de programação.
26
No anexo A está disponibilizada uma tabela contendo o conjunto de instruções em
linguagem Assembler. As funções utilizadas para programação em linguagem C não serão
abordadas em sua totalidade, pois variam de compilador para compilador (anexo K).
3.2Funcionalidades
Os laboratórios, como já citados, possuem kits que são de difícil usabilidade. O aluno
tem que desenvolver o código (linguagem nativa) da sua aplicação e depois consultar
datasheets (manuais) para fazer a conversão deste para a linguagem aceita pelo kit
(codificação em códigos hexadecimais). Toda essa conversão é feita manualmente gerando o
código hexadecimal da aplicação, que é inserido no kit através de um teclado já acoplado.
Neste processo erros são inadmissíveis, pois, se um código for convertido erroneamente toda
a sua aplicação estará comprometida fazendo com que o desenvolvedor (aluno) tenha o
trabalho de verificar linha por linha de código a fim de detectar o erro. Já se o erro ocorreu na
inserção dos códigos hexadecimais no kit todo o seu código terá que ser inserido novamente.
O kit desenvolvido neste projeto não funciona desta maneira o que melhora muito o
rendimento da sua aplicação. Quando em modo de operação o processo de codificação da
aplicação e transferência deve ocorrer da seguinte forma:
O aluno poderá desenvolver o código da sua aplicação, em linguagem nativa
(assembly) ou em linguagem C no microcomputador, ficando a cargo do professor a definição
de qual linguagem será utilizada;
O microcomputador terá um software compilador, que por sua vez, fica
encarregado de converter o código da aplicação em código hexadecimal próprio para o
microcontrolador do kit;
Gerado o arquivo com o código hexadecimal da aplicação, este é isento de erros
de conversão, estando pronto para ser transferido para o microcontrolador presente no kit;
A transferência do código hexadecimal armazenado no microcomputador para o
microcontrolador do kit é feito através de um software de transferência – que deve estar
previamente instalado – e de um gravador que já vem embutido no kit;
27
O software de transferência fica encarregado de transformar o código hexadecimal
em sinais elétricos que ativam o circuito de gravação, que por fim ativa determinados pinos
do microcontrolador, que entende estes sinais e os guardam em sua memória de programa
ficando assim disponível para execução e testes.
As vantagens do kit desenvolvido para o kit já utilizado nas aulas de laboratório são as
seguintes:
A aplicação desenvolvida para o kit poderá ser programada tanto em assembly ou
linguagem C;
Oferece um software onde podem ser simulados os códigos da aplicação antes de
serem transferidos para o microcontrolador do kit;
O kit proverá interface para módulos de periféricos variados, abrangendo
displays, teclados, motores de passo, etc., além de poder ser utilizado com módulos
implementados pelos próprios alunos como, por exemplo, um testador de cabos de rede;
Por ser um kit de baixo custo, proporcionará aos alunos a oportunidade de
adquirirem ou até mesmo a universidade disponibilizá-los para empréstimo, permitindo aos
alunos colocarem seus conhecimentos em prática fora do ambiente de laboratório.
3.3 Seleção do Microcontrolador PIC
Existem em fabricação mais de 150 (cento e cinqüenta) modelos de
microcontroladores da família PIC.
Visto que o projeto tem como meta desenvolver um kit didático com baixo custo de
produção, é importante que os softwares utilizados para gravação e para codificação da
aplicação sejam livres ou sem custo de licenças.
Os principais critérios de seleção em ordem de análise foram: disponibilidade em
mercado, custo, compatibilidade com softwares livres ou sem custo de licença, quantidades de
pinos de I/O, quantidade de memória (RAM e para programas) e velocidade de clock.
28
Foram montadas planilhas (anexo L) seguindo os critérios acima, selecionamos os
microcontroladores que apareceram mais vezes em destaque sendo estes separados e
possibilitando assim, o descarte de boa parte dos modelos.
Com uma gama já reduzida de modelos, foi possível analisar melhor as características
de cada um. Alguns microcontroladores, por serem mais avançados, ainda não são suportados
pelo software de gravação escolhido (o ICPROG), sendo descartada a possibilidade de
utilização destes no kit, pois o software de gravação escolhido funcionou perfeitamente com o
gravador desenvolvido.
Comparando os modelos pré-selecionados com os utilizados em livros, tutoriais e
artigos constatou-se que os mesmos eram utilizados como base em muitos destes.
Entramos em contato com um dos autores citado na referência bibliográfica (ZANCO,
2006) pedindo ajuda na escolha do modelo e ele nos atendeu prontamente indicando o mesmo
microcontrolador que ele utilizou como base para escrever o livro. Acatando a sugestão do
autor foi definido que o modelo utilizado para os primeiros testes seria o PIC 16F877-A I/P
que tem suas características principais citadas na tabela 2. É importante ressaltar que este
constava como um dos modelos pré-selecionados.
Tabela 2: Características do microcontrolador PIC 16F877-A
MODELO PIC 16F877-A
Arquitetura 8 bits
Tipo da Memória de Programa Flash
Tamanho da Memória de Programa 14 Kbytes / 8 Kwords
Tamanho da Memória de Dados 256 bytes
Tamanho da Memória Ram 368 bytes
Quantidade de Pinos de I / O 33 pinos
Quantidade Total de Pinos 40 pinos
Velocidade de Clock Máximo 20 MHz
Protocolo de Comunicação com MicrocomputadorAUSART
MI²C Compatible/SPI
Conversor Analógico / Digital 10 bits
29
MODELO PIC 16F877-A
Número de Timers 3
Número de Portas de I/O 5
FONTE: (MICROCHIP, 2006)
30
4 Kit Microcontrolado
Este capítulo aborda as principais características sobre o kit desenvolvido e expõem os
circuitos e testes que foram efetuados.
4.1Arquitetura
A arquitetura proposta para este kit consiste em um circuito que pode ser dividido em
circuitos menores que são: o circuito gravador, o circuito de clock, o circuito de alimentação,
o circuito de alimentação externa, o circuito de controle de leds e o microcontrolador com
suas portas separadas.
Com o circuito do kit montado a conexão com os periféricos será feita através de
cabos, pois os periféricos serão modulares tendo assim a possibilidade de várias
configurações. O diagrama da figura 3 ilustra a arquitetura do kit.
Figura 3: Diagrama da Arquitetura do kit.
Gravador
AlimentaçãoExterna
Alimentação Clock
Controle de
Leds
Seleçãode
Entradas
Microcon-trolador
Habilitaou
Desabilita
PortasdeI/O
31
O diagrama da figura 4 ilustra os modos de funcionamento (gravação e execução) do
kit.
Figura 4: Modos de Funcionamento do kit.
Cada parte da arquitetura tem uma determinada funcionalidade para o kit e serão
detalhadas a seguir.
4.1.1 O Circuito Gravador
O circuito gravador é o meio de ligação entre o microcomputador e o
microcontrolador sendo responsável pela “gravação” da aplicação desenvolvida na memória
de programa do microcontrolador. O circuito de gravação fica encarregado de ativar as portas
do microcontrolador para recepção do programa.
4.1.2 O Circuito de Clock
32
O circuito de execução é responsável pela ativação do microcontrolador para execução
do programa armazenado na memória ficando encarregado de definir a velocidade (clock, em
MHz) em que o microcontrolador irá operar.
4.1.3 O Circuito de Alimentação
O circuito de alimentação possui uma entrada de energia (cinco volts e terra). Este
serve para a alimentação do circuito de clock e do microcontrolador (enquanto estiver sendo
executada uma aplicação).
4.1.4 O Circuito de Alimentação de Externa
O circuito de alimentação externa é formado por uma ponte entre o circuito de
alimentação e algum circuito externo que necessite de alimentação (cinco volts e terra) para
operar, não necessitando da utilização de outra fonte.
4.1.5 O Circuito de Controle de LED’s
O circuito de controle de led’s é composto por três led’s que servem para indicar o
estado em que o kit se encontra:
Led amarelo aceso: indica que a fonte de alimentação está conectada ao kit;
Led vermelho aceso: indica que o kit está operando em modo de gravação;
Led verde aceso: indica que o kit está operando em modo de execução.
4.1.6 O Microcontrolador e suas Portas
O microcontrolador a ser utilizado no kit possui 33 pinos de I/O que são divididos em
cinco portas (A, B, C, D, E), cada qual com um número determinado de pinos: A, seis pinos;
B, C e D, oito pinos e a porta E com três pinos. Estas portas na sua maioria não têm a sua
distribuição de pinos em seqüência no microcontrolador. A porta C, por exemplo, está
distribuída entre os pinos de 15 a 18 e de 23 a 26 do microcontrolador. Por isso foi definido
que no circuito do kit seria utilizada uma interface distinta para cada porta. Essa medida
facilitará a manutenção e a usabilidade do kit.
33
4.2 O Circuito do Kit
O circuito do kit será montado sobre uma placa de cobre única, contendo todos os itens
que compõem a arquitetura do kit discutidos na seção 4.1..
A seguir na figura 5 está uma foto do kit após a sua construção com base no circuito
ilustrado na figura 6, que contém as ligações e o posicionamento dos componentes do kit.
Figura 5: Foto do kit.
Figura 6: Circuito de construção do kit.
34
Os componentes utilizados para a construção do kit estão listados na tabela 3.
Tabela 3: Componentes para a construção do kit
NOME DO COMPONENTE ID NA PLACA QUANTIDADE
Cabo flat IDE MICRO 1
Capacitor cerâmico 22pF C4, C5 2
Capacitor eletrolítico 100μF-40V C1 1
Capacitor eletrolítico 22μF-40V C2 1
Conector DB9 fêmea para cabo MICRO 1
Conector DB9 macho para cabo GRAV, EXEC 2
Conector DB9 macho para placa DB9_GRAVACAO 1
Jack para fonte COM_FONTE 1
Led Amarelo L2 1
Led Verde L3 1
Led Vermelho L1 1
Microcontrolador PIC 16F877A – I/P
PLUGADO NO SOCKET_40PIN
1
Oscilador de 4MHz O1 1
Placa de Cobre 10 x 15 cm - 1
Resistor 10K Ω R4 1
Resistor 1K5 Ω R1 1
Resistor 200 Ω R5, R6, R7 3
Resistor 560 Ω R2, R3 2
Socket para CI de 40 pinos SOCKET_40PIN 1
Socket torneado para CI de 14 pinos PORTA_A, PORTA_E 1
Socket torneado para CI de 8 pinosPORTA_B, PORTA_C,
PORTA_D 3
Transistor 1N4148 D1, D2, D5, D6 D7 5
Transistor 5V1 D3 1
Transistor 8V2 D4 1
Transistor BC547 T1, T2 2
35
4.3 Testes
Para comprovar o funcionamento dos circuitos que irão compor o kit foram realizados
vários testes até se chegar ao circuito considerado ideal. A seguir serão descritos estes testes.
4.3.1 O Circuito Gravador
O circuito gravador é uma peça chave do kit, pois sem ele não podemos transferir a
aplicação para o microcontrolador, sendo assim, deverá receber atenção especial. Antes da
construção do gravador que foi utilizado na fase de testes, estudaram-se vários tipos: com
fonte de alimentação externa, com interface com o microcomputador via porta paralela, com
interface com o microcomputador via porta serial, etc. Alguns até chegaram a ser montados
no protoboard (matriz de contatos) e testados, mas não apresentaram resultados satisfatórios.
Continuando as pesquisas foi descoberto um gravador que se tivesse seu circuito adaptado às
exigências do projeto seria ideal, pois era de fácil construção e de baixo custo, além de gravar
vários modelos de microcontroladores da família PIC.
O circuito escolhido é derivado de um famoso gravador disponível na internet (JDM,
2000), o “JDM PROGRAMMER”, que pode ser modificado livremente desde que não tenha
suas características funcionais alteradas. Em um dos livros citados na bibliografia (ZANCO,
2006) há o esquema de um gravador que é baseado no “JDM PROGRAMMER” e a partir
deste foram feitas adaptações de acordo com as necessidades do projeto chegando ao circuito
gravador apresentado na figura 7.
Figura 7: Circuito de construção do gravador.
36
Com o circuito do gravador da figura 6 montado no protoboard foi possível testar seu
efetivo funcionamento. Utilizando um exemplo de código fonte de um livro (ZANCO, 2006),
foi feito todo o processo até se obter o código hexadecimal e de posse deste efetuaram-se
testes de gravação no microcontrolador. O circuito gravador funcionou, porém o código não
estava de acordo com os resultados esperados.
Passamos agora a fase de teste de execução no microcontrolador.
4.3.2 O Circuito de Testes
O circuito utilizado para testes era composto pelo circuito de clock, um display de sete
segmentos e o microcontrolador já com a aplicação provavelmente gravada. A figura 8 ilustra
o circuito utilizado para testes. Não tínhamos como testar antes o funcionamento do gravador,
pois somente com o teste completo é que poderia ser comprovado o seu funcionamento.
Figura 8: Circuito para execução de testes com display.FONTE: (ZANCO, 2006)
A aplicação escolhida para o teste tinha como objetivo efetuar a contagem de 0 a 9
mostrando os números correntes no display. O resultado obtido neste primeiro teste indicou
que o circuito de gravação e de clock funcionaram perfeitamente. O único problema foram os
números apresentados no display que não estavam corretos, porém este era um problema no
código da aplicação, que posteriormente seria resolvido.
37
O software utilizado no desenvolvimento da aplicação, o MPLAB-IDE (MICROCHIP,
2006), possui acoplado em sua interface uma ferramenta poderosa para debugger, que permite
a simulação do código da aplicação podendo acompanhar passo a passo a sua execução. Esta
ferramenta foi utilizada para simular e detectar os problemas no código (anexo B) que foram
corrigidos e gravados no microcontrolador.
No segundo teste os resultados de execução da aplicação foram os esperados, o
microcontrolador efetuou a contagem e mostrou corretamente os dígitos no display.
A figura 9 mostra o kit em funcionamento com o código utilizado para testes.
Figura 9: Foto do kit executando código de testes.
Com os testes realizados podemos concluir que os circuitos funcionam e que o
microcontrolador pode ser utilizado juntamente com estes para compor o kit.
O layout da placa para construção do kit está disponível em tamanho real no anexo C.
38
5 Módulos Periféricos de Interface
Após a realização dos testes que comprovaram o funcionamento do kit, são abordados
neste capítulo, os principais módulos periféricos de interface que irão compor o conjunto de
experiências ilustradas na apostila que será disponibilizada juntamente com o kit e a
metodologia para desenvolvimento de novos módulos.
5.1 Pinos do Microcontrolador
Antes de iniciar o desenvolvimento dos módulos periféricos de interface é necessário o
conhecimento detalhado de cada pino do microcontrolador, pois só assim será obtido êxito na
construção do módulo. A figura 10 mostra o diagrama com os pinos do microcontrolador
PIC16F877-A os quais serão detalhados a seguir. Lembrando que o microcontrolador
PIC16F877-A é o microcontrolador utilizado no kit.
Figura 10: Pinos do microcontrolador PIC16F877-AFONTE: (ZANCO, 2006)
Os pinos e as suas respectivas características são descritas na tabela 4.
39
Tabela 4: Características dos pinos do PIC16F877-A
NÚMERO DO PINO
PORTAMODO DE OPERAÇÃO
CARACTERÍSTICAS
1 - GravaçãoMCLR (Master Clear Reset ) / Vpp: Entrada de tensão de programação.
1 - Execução Entrada de tensão de alimentação.
2 A ExecuçãoRA0: I/O digital.AN0: Entrada analógica.
3 A ExecuçãoRA1: I/O digital.AN1: Entrada analógica.
4 A Execução
RA2: I/O digital.AN2: Entrada analógica.Vref-: Entrada de tensão baixa para o conversor analógico/digital.CVref: Saída do comparador Vref.
5 A Execução
RA3: I/O digital.AN3: Entrada analógica.Vref+: -: Entrada de tensão alta para o conversor analógico/digital.
6 A ExecuçãoRA4: I/O digital.T0CKI: Entrada de clock externo para o Timer0.C1OUT: Saída do comparador 1.
7 A Execução
RA5: I/O digital.AN4: Entrada analógica.SS: Seletora de entrada escrava (SPI).C2OUT: Saída do comparador 2.
8 E ExecuçãoRE0: I/O digital.RD: Controle de leitura para porta paralela escrava.AN5: Entrada analógica.
9 E ExecuçãoRE1: I/O digital.WR: Controle de escrita para porta paralela escrava.AN6: Entrada analógica.
40
NÚMERO DO PINO
PORTAMODO DE OPERAÇÃO
CARACTERÍSTICAS
10 E Execução
RE2: I/O digital.CS: Controle de seleção de chip para porta paralela escrava.AN7: Entrada analógica.
11 - ExecuçãoVdd: Entrada de tensão alta para alimentação das portas lógicas e pinos de I/O.
12 - ExecuçãoVss: Entrada de tensão baixa para alimentação das portas lógicas e pinos de I/O.
13 - Execução
OSC1: Entrada do oscilador de cristal.CLKIN: Entrada externa da fonte de clock.Lembrando que este pino está sempre associado ao pino 14 (OSC2 / CLKOUT).
14 - ExecuçãoOSC1: Saída do oscilador de cristal.CLKOUT: Saída externa da fonte de clock.
15 C ExecuçãoRC0: I/O digital.T1OSO: Saída do oscilador do Timer1.T1CLKI: Entrada de clock externo para Timer1.
16 C Execução
RC1: I/O digital.T1OSI: Entrada do oscilador do Timer1.CCP2: Entrada do capturador2 / Saída do comparador2 / Saída do PWM2.
17 C ExecuçãoRC2: I/O digital.CCP1: Entrada do capturador1 / Saída do comparador1 / Saída do PWM1.
18 C ExecuçãoRC3: I/O digital.SCK: I/O de clock serial síncrono para modo SPI.SCL: I/O de clock serial síncrono para I2C.
19 D ExecuçãoRD0: I/O digital.PSP0: Dados da porta paralela escrava.
20 D ExecuçãoRD1: I/O digital.PSP1: Dados da porta paralela escrava.
41
NÚMERO DO PINO
PORTAMODO DE OPERAÇÃO
CARACTERÍSTICAS
21 D ExecuçãoRD2: I/O digital.PSP2: Dados da porta paralela escrava.
22 D ExecuçãoRD3: I/O digital.PSP3: Dados da porta paralela escrava.
23 C ExecuçãoRC4: I/O digital.SDI: Saída de dados da SPI.SDA: I/O de dados do I2C.
24 C ExecuçãoRC5: I/O digital.SDO: Entrada de dados da SPI.
25 C ExecuçãoRC6: I/O digital.TX: Transmissão assíncrona USART.CK: Clock síncrono USART1.
26 C ExecuçãoRC7: I/O digital.RX: Recepção assíncrona USART.DT: Dado síncrono USART.
27 D ExecuçãoRD4: I/O digital.PSP4: Dados da porta paralela escrava.
28 D ExecuçãoRD5: I/O digital.PSP5: Dados da porta paralela escrava.
29 D ExecuçãoRD6: I/O digital.PSP6: Dados da porta paralela escrava.
30 D ExecuçãoRD7: I/O digital.PSP7: Dados da porta paralela escrava.
31 -Execução / Gravação
Vss: Entrada de tensão baixa para alimentação das portas lógicas e pinos de I/O.
32 -Execução / Gravação
Vdd: Entrada de tensão alta para alimentação das portas lógicas e pinos de I/O.
33 B Execução RB0: I/O digital.
42
NÚMERO DO PINO
PORTAMODO DE OPERAÇÃO
CARACTERÍSTICAS
INT: Interrupção externa.
34 B Execução RB1: I/O digital.
35 B Execução RB2: I/O digital.
36 B Gravação PGM: Tensão baixa para ICSP.
36 B Execução RB3: I/O digital.
37 B Execução RB4: I/O digital.
38 B Execução RB5: I/O digital.
39 B Gravação PGC: In-circuit debugger e clock para ICSP.
39 B Execução RB6: I/O digital.
40 B Gravação PGD: In-circuit debugger e dados para ICSP.
40 B Execução RB7: I/O digital.
FONTE: (MICROCHIP, 2006)
De posse das possíveis configurações de cada pino do microcontrolador, foi
desenvolvido um módulo periférico básico composto por displays de sete segmentos, teclado
matricial e leds, sendo detalhado no item 5.2..
5.2Módulo Periférico Básico
Conforme descrito anteriormente, o módulo periférico básico abordado neste item
suporta até 4 displays de sete segmentos, possui teclado matricial 4X4 com teclas do tipo
click (totalizando 16 teclas configuráveis) e 9 leds (8 vermelhos e 1 verde). Todos os
exemplos desenvolvidos neste trabalho poderão ser testados no módulo básico, exceto os
descritos no tópico 5.3 e no capítulo 6, pois estes necessitam de hardware adicional.
43
Para cada conjunto de componentes que integram o módulo básico existe uma
biblioteca, que faz a comunicação entre o kit (microcontrolador) e o dispositivo. Com o
módulo básico o desenvolvedor poderá programar desde calculadoras e relógios até mesmo
aplicações mais avançadas, integrando-o com outros módulos desenvolvidos conforme
necessário.
A figura 11 mostra o circuito do módulo básico. Nesta figura pode ser notado dois C.I.
´s, o SN74LS47 e o CD4511, os dois são decodificadores BCD (codificação de binário para
decimal ou vice-versa) para 7 segmentos. O primeiro é utilizado juntamente com displays do
tipo anodo comum e o segundo serve para displays catodo comum, lembrando que os C.I´s
acima não podem ser utilizados ao mesmo tempo na placa.
44
Figura 11: Circuito do Módulo Periférico de Interface Básico
Este módulo básico foi criado a partir de um exemplo mais complexo abordado em
uma das bibliografias consultadas. (ZANCO, 2006).
Os componentes utilizados para a construção do kit estão listados na tabela 5.
Tabela 5: Componentes para a construção do kit
NOME DO COMPONENTE ID NA PLACA QUANTIDADE
Botões tipo click B1 a B16 16
CD 4511 CD 1
45
CI 74LS47 CI 1
Display de 7 segmentos (tipo anodo ou catodo)
D1, D2, D3, D41 até 4
Led Verde L1 1
Led Vermelho L2 a L9 1
Placa de Cobre 10 x 15 cm - 1
Resistor 100K Ω R13 a R16 4
Resistor 20K Ω R20 a R23 4
Resistor 270 ΩR1 a R12 e R17 a
R198
Socket para CI de 16 pinos CD e CI 2
Socket para CI de 18 pinos Displays 1
Socket para CI de 20 pinos Displays 1
Socket torneado para CI de 8 pinosTeclado, Displays e
Leds 4
Transistor BC547 T2, T4, T6 e T8 4
Transistor BC557 T1, T3, T5 e T7 4
A fileira de 8 leds vermelhos pode ser utilizada para fazer testes com as portas do
microcontrolador ou mesmo sinalizar algum evento como por exemplo, o click de uma tecla.
Já o led verde, será a princípio, utilizado para demonstrar o funcionamento do controle de
PWM incorporado ao microcontrolador e posteriormente poderá ser utilizado em outras
funções.
A placa do módulo básico foi projetada para no máximo 4 displays de sete segmentos
ficando a cargo do desenvolvedor construí-la com 1 ou até 4 displays. Os displays servem
para mostrar informações como, por exemplo, resultados de somas, se for uma calculadora,
mostrar as horas, se a aplicação for um relógio, etc.
O teclado também é uma peça que pode variar neste módulo, pois são disponibilizadas
16 teclas que podem ser configuradas de acordo com a necessidade da aplicação. Como por
exemplo, podemos utilizá-lo como teclado numérico e mais algumas teclas especiais que
46
podem ser as operações matemáticas no caso de uma calculadora ou teclas de configuração de
hora e minutos para um relógio.
Para facilitar a programação estão disponibilizados no anexo D exemplos com funções
genéricas para serem utilizadas com o módulo básico, estes foram escritos em linguagem C e
estão arquivos separados, ou seja, um para o teclado, um para os leds, um para os displays e
um para o led verde com a finalidade de exemplificar o funcionamento do PWM.
No anexo K estão disponibilizadas uma lista com as variáveis de configuração e duas
tabelas uma com os tipos de dados e outra com as principais funções em linguagem C dos
compiladores CCS e no anexo M temos um tutorial passo-a-passo de como escrever e gravar
um programa no kit.
A figura 12 mostra o digrama de blocos representando a ligação do kit com o módulo
básico.
Figura 12: Diagrama de blocos kit e módulo periférico básico.
A figura 13 mostra o kit e o módulo básico sendo utilizados para testar o código de
exemplo contido no anexo B.
47
Figura 13: Kit e módulo básico trabalhando em conjunto.
5.3Comunicação Serial entre o Kit e o Microcomputador
Atualmente encontramos a venda microcontroladores que possuem porta USB para
comunicação com o microcomputador, porém estes são caros e ainda não temos hardware e
software livres compatível com os mesmos.
O microcontrolador utilizado no kit, descrito neste trabalho, conta com um módulo de
transmissão e recepção de dados serial chamado de USART. Embora a USART possa
transmitir e receber dados tanto da forma assíncrona quanto da forma síncrona, este tópico
abordará somente a forma assíncrona de funcionamento. “Na comunicação serial, a
informação a ser transmitida é fracionada em pequenas partes (bits) que são enviadas ao
equipamento receptor uma após a outra, em série, daí a denominação de comunicação serial”.
(PEREIRA, 2003, p.262).
Como o kit (microcontrolador) já possui incorporado em hardware o protocolo de
comunicação, temos apenas que entender como funciona o padrão RS-232 ou também
chamado de EIA-232.
48
“O padrão RS-232 ou EIA-232 define uma faixa de tensão que deve ser identificada
pelos terminais como níveis lógicos 0 e 1. O nível lógico 1 é representado pela faixa de
valores de -3V a -15V”. (ZANCO, 2006, p.266). Respectivamente temos os para o nível 0 a
faixa de valores +3V e +15V. Levando em consideração a faixa de valores do padrão RS-232
não podemos ligar diretamente o kit ao microcomputador, pois as tensões fornecidas pelo kit,
<= 0,6V para nível lógico 0 e >= 5V – 0,6V para nível lógico 1, não são compatíveis com as
tensões do padrão RS-232.
Existe atualmente no mercado um C.I., o MAX232, que faz a conversão dos níveis de
tensão permitindo assim a conexão entre o kit e dispositivos que utilizam o padrão RS-232. A
figura 14 apresenta a descrição de cada pino da porta serial.
Figura 14: Pinagem porta serial.FONTE: (PABLIN, 2005)
A figura 15 apresenta o circuito de ligação entre o microcontrolador e o C.I.
MAX232.
49
Figura 15: Circuito de Comunicação com Porta Serial utilizando C.I. MAX232.FONTE: (PEREIRA, 2003)
Além do C.I. MAX232 uma alternativa viável para a interface de dispositivos com a
porta serial pode ser construída utilizando transistores, o que a torna em alguns lugares mais
barata e fácil de encontrar. O circuito mostrado na figura 16 substitui o C.I. MAX232, ele foi
encontrado em um sítio (PABLIN, 2005), mas apresentou problemas tendo que ser
modificado.
Figura 16: Circuito de Comunicação com Porta Serial utilizando Transistores.
A utilização da porta serial para comunicação entre o kit e o microcomputador é
codificada de maneira muito simples em linguagem C, utilizando-se apenas “printf´s” e “gets
´” o desenvolvedor consegue enviar e receber dados. No anexo E está disponibilizado um
50
código que efetua o envio de uma “string” teste para o microcomputador e aguarda o
recebimento de uma tecla qualquer pelo kit, esta tecla será retransmitida ao microcomputador
dando a certeza ao desenvolvedor que a aplicação recebe e envia dados.
Para usuários que não dispõem de comunicação serial no microcomputador onde
haverá troca de informações, é aconselhado à utilização de um cabo USBSerial para
conectar o kit ao microcomputador, lembrando que esta prática do cabo não serve para fazer
gravações de programas na memória do microcontrolador.
5.4Memória EEPROM Interna
O microcontrolador utilizado no kit possui memória EEPROM interna de 256 bytes
podendo ser utilizada para salvar dados que não são voláteis, como por exemplo, se a
aplicação medir temperaturas, estas podem ser armazenadas de tempos em tempos para uma
futura análise.
No anexo F está disponibilizado um exemplo onde são gravados os números de 1 a 10
e depois é feita a leitura destes, lembrando que tanto na gravação como na leitura os dados
gravados ou lidos são apresentados em displays de 7 segmentos.
51
6 Trabalhos Futuros
A partir do desenvolvimento de aplicações utilizando o kit e o módulo periférico de
interface básico, o aluno terá os conhecimentos essenciais para desenvolver novos módulos
periféricos de interface, que poderão ser utilizados em aulas ou até mesmo em projetos de
iniciação científica. Além dos novos módulos e de projetos de iniciação científica os alunos
poderão desenvolver bibliotecas para facilitar a implementação de novos programas de
exemplo, utilizando os novos módulos periféricos, mantendo as apostilas e tutoriais sempre
atualizados.
Neste capítulo serão propostos três novos módulos periféricos de interface envolvendo
displays de cristal líquido, comunicação entre kits e armazenamento de dados em bancos de
memória. Todo o material disponibilizado neste capítulo não foi testado, pois não faz parte do
escopo global deste trabalho.
6.1Módulo LCD
Atualmente a forma mais simples e barata de apresentação de grande quantidade de
dados é feita através de módulos LCD. Um módulo de display LCD é formado basicamente
por um display de cristal líquido e um controlador de display. Basicamente os displays são
classificados em dois tipos: os de caracteres e os gráficos. Neste trabalho abordaremos os
displays de caracteres, pois são mais baratos e possuem menor grau de complexidade de
programação.
Além do tipo do display utilizado, também devemos prestar muita atenção em qual
controlador será empregado no módulo. “Os mais populares são o KS0066, fabricado pela
Samsung Eletronics e o HD44780, fabricado pela Hitachi”. (ZANCO, 2006, p.78). O
controlador LCD é vital para o módulo LCD, pois permite uma interface simples com
sistemas microcontrolados e microprocessados funcionando como um padrão para acesso ao
display. Esses controladores possuem barramento de dados selecionável para 4 ou 8 bits,
requerendo ainda mais três linhas de sinalização: ENABLE, RS (I/D) e R/W. Cada controlador
tem suas particularidades que podem ser encontradas em seus datasheets.
52
Para exemplificar este tópico será utilizado um display de caracteres com duas linhas
controlado por um chip HD44780 conectado ao microcontrolador através de um barramento
de dados de 4 bits, o que permite a otimização do número de pinos do microcontrolador, pois
somente serão utilizados 7 pinos (3 para controle e 4 para dados) do mesmo.
A comunicação feita por apenas 4 bits é realizada utilizando quatro linhas mais
significativas de dados. Para este exemplo, utilizaremos os pinos D7 a D4 para dados e os
pinos D2 a D0 para controle, dividindo o byte em dois níveis que serão transmitidos sempre
do mais para o menos significativo.
Esses controladores possuem memória que pode ser utilizada pelo programador para
definir ou criar novos caracteres e armazená-los, mas este tipo de implementação foge ao
escopo genérico deste trabalho.
No anexo G está disponibilizada a tabela com o conjunto de comandos utilizados para
programar um módulo LCD com controlador HD44780.
Abaixo na figura 17 podemos visualizar o esquema de ligação entre o
microcontrolador e o módulo LCD.
Figura 17: Circuito de execução de testes com módulo LCDFONTE: (ZANCO, 2006)
53
Após a implementação do hardware o aluno poderá utilizar a biblioteca e o código-
fonte, disponibilizados no anexo G, para realizar testes de comunicação entre o módulo LCD
e o kit.
6.2Comunicação entre Kits
Antes de ser proposta alguma implementação para a comunicação entre dois ou mais
kits devemos conhecer bem o protocolo que será utilizado para a troca de informações.
Existe um protocolo desenvolvido pela Philips chamado de I2C (Comunicação entre
Integrados) (ZANCO, 2006), que é um dos mais utilizados na comunicação de dispositivos
dentro de um mesmo circuito ou equipamento eletrônico. Esse protocolo é do tipo síncrono do
tipo mestre-escravo e possui barramento de duas linhas, uma para clock e outra para dados,
além disso, ele também suporta o chamado “multimastering” que nada mais é do que a
presença de diversos dispositivos mestres no barramento. O I2C suporta velocidades de até 3.4
Megabits por segundo, porém a maioria dos dispositivos opera entre 100 e 400 Kilobits por
segundo.
O modo de funcionamento do protocolo baseia-se nos seguintes princípios:
1. Somente a leitura de informações das linhas de dados quando a linha de
clock estiver em sua fase alta;
2. O nível da linha de dados só pode ser alterado na fase baixa da linha de
clock;
3. Quando o barramento estiver ocioso, as duas linhas devem estar em nível
baixo.
Esta breve introdução sobre o protocolo I2C se faz necessária, pois este será à base da
comunicação entre os kits.
Para o desenvolvimento e implementação da comunicação entre kits será necessária
uma memória, a qual será compartilhada tanto para escrita como para leitura. O barramento
será composto, por exemplo, de dois kits e uma memória (figura 18).
54
Figura 18: Exemplo de barramento para comunicação entre kits.
A troca de informações onde o kit 1 envia dados para o kit 2, que por sua vez recebe os
dados e envia uma reposta para o kit 1, será realizada da seguinte forma:
1. Define-se neste caso um endereço de memória para cada kit, este servirá para
armazenar as informações a serem trocadas e para armazenar flags de controle;
o tamanho dos dados a serem trocados depende diretamente do tamanho da
memória utilizada;
2. Primeiramente o kit1 verifica se não há ninguém utilizando as linhas do
barramento;
3. Verificadas as linhas, se estas estiverem liberadas, o kit 1 envia os dados para a
memória salvando primeiro o flag, que indica que existe dados para leitura,
depois o endereço da posição inicial dos dados e por último os dados;
4. Enquanto as linhas estiverem ociosas, os kits irão de tempos em tempos checar
o flag para ver se tem dado aguardando leitura;
5. Realizando esta checagem o kit 2 descobrirá que existe dados prontos para
serem lidos por ele, assim ele tentará ocupar o barramento;
6. Se a ocupação for possível, o kit 2 poderá ler os dados gravados pelo kit 1 e
logo em seguida gravar dados para o kit 1 ler.
Esta é uma forma simples de entender como pode ser implementada a comunicação
entre kits. No anexo H está disponibilizada uma biblioteca com funções relacionadas ao I2C.
55
6.3Armazenamento de Dados em Memórias
Quando falamos sobre armazenamento de dados em memória temos que analisar
previamente os tipos dos dados e a quantidade de informações que serão armazenadas.
A maioria dos microcontroladores possui uma pequena quantidade de memória não
volátil, vale observar que esta memória tem como principal função armazenar dados que não
podem ser perdidos mesmo se houver interrupção na energia de alimentação do kit
(microcontrolador). Existem no mercado memórias que podem ser adquiridas para aumentar a
capacidade ou até mesmo serem adicionadas a projetos onde o microcontrolador não dispõe
da mesma. Essas memórias geralmente são do tipo EEPROM, trata-se de memórias que
podem ser escritas e apagadas diversas vezes. Além do tipo citado anteriormente, também
serão abortadas memórias do tipo MMC (Cartão de Memória Multimídia), trata-se de
memórias EEPROM modernas e com grande capacidade de armazenamento.
A comunicação entre o microcontrolador e memórias externas é realizada utilizando-
se de protocolos de comunicação como, por exemplo, o SPI (Interface Serial de Periféricos), o
I2C (Comunicação entre Integrados), ente outros. Os protocolos citados anteriormente também
são utilizados para a “construção” de barramentos de comunicação entre outros dispositivos
como, por exemplo, conversores A/D, potenciômetros digitais, entre outros.
Para este tópico abordaremos o protocolo SPI como exemplo.
6.3.1 O SPI
O SPI foi desenvolvido originalmente pela Motorola para a linha de processadores da
família MC68K e adotado por diversos fabricantes ao longo do tempo (o microcontrolador
PIC16F877-A possui suporte). O SPI conta com uma interface física implementada pelas
seguintes linhas:
CS (Seleção de Dispositivo) ou SS: é utilizada para habilitar o dispositivo com
o qual se deseja comunicar e também para encerrar a execução dos comandos
transmitidos pelo dispositivo mestre;
56
Clock ou SCLK: utilizado para sincronizar o dispositivo mestre e o dispositivo
escravo;
SI ou MOSI (Entrada Serial): serve para recepção de dados;
SO ou MISO(Saída Serial): serve para enviar dados.
Abaixo na figura 19 é mostrado o diagrama de comunicação entre dois dispositivos
utilizando SPI.
Figura 19: Diagrama de Comunicação entre dois Dispositivos utilizando SPI.
Na figura 20 podemos observar a comunicação entre o dispositivo mestre e vários
dispositivos escravos utilizando o protocolo SPI. Note que a seleção é feita pelo pino SS, no
caso da comunicação de um mestre com diversos dispositivos escravos, requerem do
microcontrolador um número grande de pinos de seleção.
Figura 20: Diagrama de Comunicação entre um mestre e diversos dispositivos escravos utilizando SPI.
57
O SPI é um protocolo de comunicação síncrono e opera no modo full-duplex. Outra
característica do protocolo é que todas as operações são sempre precedidas por comandos de 8
bits (tabela 6) utilizados para descrever o tipo de operação que será executada.
Tabela 6: Comandos de 8 bits para SPI
COMANDO BINÁRIO DESCRIÇÃO
READ 0000 0011 Lê o dado da posição atual de memória
WRITE 0000 0010 Escreve um dado na posição atual de memória
WREN 0000 0110 Habilita escrita na memória
WRDI 0000 0100 Desabilita escrita na memória
RDSR 0000 0101 Lê o registrador de estado da memória
WRSR 0000 0001 Escreve no registrador de estado da memória
FONTE: (PEREIRA, 2003)
Para exemplificar a troca de informações entre o kit e memórias será abordada nos
próximos tópicos a comunicação utilizando SPI e memórias EEPROM, e também SPI e
MMC.
6.3.2 Memórias EEPROM Serial
Neste tópico iremos abordar as operações de leitura e de escrita em memórias
EEPROM. Antes de começarmos, precisamos entender a figura 21, que identifica os pinos de
uma memória EEPROM, neste caso o modelo utilizado é o 25LC640 que tem capacidade de
armazenamento de 64Kbits (8K * 8).
Figura 21: Pinos da memória EEPROM 24LC16B. FONTE: (PEREIRA, 2003)
58
Na tabela 7 estão descritas as funcionalidades de cada pino da memória ilustrada na
figura 21.
Tabela 7: Funcionalidades dos Pinos da Memória EEPROM 25LC640
PINO NOME FUNÇÂO
1 CS Habilita ou desabilita a memória
2 SO Saída de dados
3 WP Entrada de proteção de escrita
4 VSS Terra
5 SI Entrada de dados
6 SCK Sincronização da comunicação
7 Hold Suspender a transmissão de um dado
8 VCC Alimentação da memória
FONTE: (MICROCHIP, 2006)
Agora que já conhecemos os pinos vamos entender como funcionam as operações de
leitura e escrita. Antes de efetuar uma leitura ou escrita devemos verificar se a linha CS está
em nível lógico 0, pois se ela estiver em nível lógico 1 significa que já existe um comando
sendo executado (os comandos estão descritos na tabela 5).
Operações de leitura seguem os seguintes passos nesta ordem (supondo que a linha CS
esteja em nível lógico 0):
Envio do comando READ, seguindo pelos 16 bits do endereço da memória (do
mais significativo para o menos significativo);
Depois de enviado o último bit do endereço, a memória passa a transmitir o
dado contido naquele endereço (iniciando pelo mais significativo);
Caso somente seja necessária a leitura de uma posição de memória, após a
recepção do ultimo bit do dado, devemos colocar nível lógico 0 na linha CS
para permitir o recebimento de novos comandos pela memória;
59
Também é possível continuar a leitura, pois as memórias SPI possuem um
registrador de endereços interno que é incrementado automaticamente após
cada byte enviado e para continuar a leitura basta continuar o envio de pulsos
de clock (oito para cada novo byte a ser lido);
Para terminar uma operação de leitura, basta colocar a linha CS em nível
lógico 0 após o ultimo bit de dado ter sido recebido.
Operações de escrita seguem os seguintes passos nesta ordem (supondo que a linha CS
esteja em nível lógico 0):
Envio do comando WRITE, seguindo pelos 16 bits do endereço da memória
(do mais significativo para o menos significativo);
Depois de enviado o último bit do endereço, o dispositivo mestre
(microcontrolador) passa a transmitir o dado a ser escrito naquele endereço
(iniciando pelo mais significativo);
Estas memórias suportam um modo chamado de Page-Write (escrita de página
ou bloco) que permite gravar simultaneamente até 32 bytes, reduzindo o tempo
necessário para gravação da memória. Neste modo, após o envio do primeiro
byte, enviam-se os bytes seguintes, um após o outro, até um máximo de 32;
A operação de gravação chega ao fim quando a linha CS é colocada em nível
lógico 1 em ambos os casos (escrita de byte simples ou blocos), lembrando que
esta operação só deve ser realizada após o envio do último bit (menos
significativo) para a memória.
No anexo I é fornecida uma biblioteca de comunicação SPI que pode ser encontrada
no arquivo 25640.c da pasta drivers disponibilizada na instalação do Compilador CCS versão
3. (CCS, 2006). Também está disponibilizado no anexo I um código fonte exemplo para
leitura e escrita de dados enviados/recebidos do microcomputador para a memória via porta
serial.
60
6.3.3 MMC (MultMediaCard)
As memórias do tipo MMC são muito utilizadas hoje em dia tendo como principais
aplicabilidades às câmeras digitais, palm´s e celulares.
Neste tópico abordaremos a utilização deste tipo de memória para armazenamento de
dados gerados por aplicações que necessitem de grande quantidade de memória não volátil.
A figura 22 ilustra a conexão de um MMC ao microcontrolador.
Figura 22: Conexão de um MMC ao microcontrolador.
Existem alguns compiladores C que fornecem bibliotecas prontas para trabalhar com
cartões de memória, é o caso do mikroC (MIKROE, 2006) e do PIC C Compiler (CCS, 2006),
mas também existem outras formas, por exemplo, utilizando comunicação SPI.
No anexo J está disponibilizada uma biblioteca implementada utilizando SPI para
comunicação entre o microcontrolador e a MMC, está pode ser encontrada no sítio
(MICROCHIPC, 2005), só lembrando que a comunicação entre o kit e memórias MMC não
foi testada, pois não faz parte do escopo global deste trabalho.
61
7 Conclusão
Através do estudo realizado sobre os principais componentes envolvidos neste
trabalho, pode-se concluir que todos os fatores analisados indicaram que a implementação do
kit utilizando microcontroladores da família PIC seria viável, o que nos motivou ainda mais
para projetar e construí-lo.
Devido a grande quantidade de pinos de I/O do microcontrolador escolhido, há a
possibilidade de implementação de periféricos variados além dos descritos neste trabalho,
pois o kit possui comunicação para com estes dispositivos através de interfaces padronizadas.
O circuito de construção do kit, apresentado na figura 5, foi desenvolvido para se obter
melhor aproveitamento de espaço e seguindo as especificações dos componentes, o que o
torna de fácil construção e manutenção, além de ter seu custo reduzido proporcionando
benefícios aos interessados em obtê-lo ou até mesmo construí-lo.
O módulo periférico básico, descrito no capítulo 5, foi projetado para atender as
necessidades de um desenvolvedor iniciando seus estudos, podendo também ser utilizado com
outros módulos adicionais, pois possui conectores padronizados.
O capítulo 6 mostra mais algumas das inúmeras aplicações onde podemos utilizar
microcontroladores PIC, ficando as aplicações mostradas como sugestões para futuras
implementações.
De forma geral o kit mostrou-se viável quanto a sua implementação e utilização, o que
permite concluir que o trabalho de conclusão de curso alcançou os seus objetivos e abriu
novas oportunidades para a utilização deste nas disciplinas do curso de Ciência da
Computação.
No que diz respeito ao aspecto pessoal e intelectual, o desenvolvimento deste trabalho
me proporcionou conhecimento em uma nova área que vem crescendo muito, a dos
microcontroladores. Além do conhecimento adquirido, foi possível entender o funcionamento
de vários dispositivos utilizados no dia-a-dia, os quais eu não conhecia os aspectos técnicos de
suas implementações.
62
Referência Bibliográfica
(BASSO, 2004) BASSO, Fabio Paulo. A MDA Como um Auxílio no Desenvolvimento de Sistemas Embarcados. 2004. 100f. Trabalho de Pós Graduação em Ciência da Computação.Pontifícia Universidade Católica do Rio Grande do Sul, Porto Alegre.
(CCS, 2006) ESTADOS UNIDOS DA AMÉRICA. Custom Computer Services, Inc. CCS, Inc. – Home. 2006. Disponível em <http://www. ccsinfo.com/>. Acessado em: 02 mar. 2006.
(IC-PROG, 2005) ESTADOS UNIDOS DA AMÉRICA. IC-Prog. IC-Prog Prototype Programmer. 2005. Disponível em <http://www.ic-prog.com /index1.htm>. Acessado em: 10 abr. 2006.
(INSTRUCTABLES, 2006)
ESTADOS UNIDOS DA AMÉRICA. Instructables. JDM2 based PIC Programmer. 2006. Disponível em <http://www.instructables.com/ex/i/6D80A0F6DA311028931A001143E7E506/?ALLSTEPS>. Acessado em: 05 abr. 2006.
(IOVINE, 2000) IOVINE, John. PIC Microcontroller: Project Book. 1. ed. Tab Books, 2000.
(JDM, 2000) DINAMARCA. Jens Dyekjær Madsen. Pic Programmer 2. 2000. Disponível em <http://www.jdm.homepage.dk/newpic.htm>. Acessado em: 03 abr. 2006.
(MARK’S, 2006) REINO UNIDO. Mark´s Project Pages. PIC Programming. 2006. Disponível em <http://www.mhennessy.f9.co.uk/pic.htm>. Acessado em: 06 mai. 2006.
(MATIC, 2003) MATIC, Nebojsa. MikroElektronika-Romanian. Livro on-line Microcontroladores PIC. 2003. Disponível em <http://www.mikroelektronika.co.yu/portuguese/product/books/picbook/00.htm>. Acesso em: 04 jun. 2006.
(MICROCHIP, 2006)
ESTADOS UNIDOS DA AMÉRICA. Microchip Technology Inc. Microchip Technology Inc. 2006. Disponível em <http://www.microchip.com>. Acessado em: 09 fev. 2006.
(MICROCHIPC, 2005)
ESTADOS UNIDOS DA AMÉRICA. Shane Tolmie. Program Microchip PIC micros with C. 2005. Disponível em <http://www.microchipc.com/>. Acessado em: 25 out. 2006.
(MIKROE, 2006) BELGRADE. mikroElektronika. mikroElektronika. 2006.
63
Disponível em <http://www.mikroe.com/en/>. Acessado em: 25 out. 2006
(PABLIN, 2005) ARGENTINA. Pablin. Pablin. 2005. Disponível em <http://www.pablin.com.ar/main.htm>. Acessado em 24 abr. 2006.
(PEREIRA, 2003) PEREIRA, Fábio. Microcontroladores PIC: Programação em C. 5. ed. São Paulo: Érica, 2003.
(ZANCO, 2006) ZANCO, Wagner da Silva. Microcontroladores PIC®: Técnicas de Software e Hardware para Projetos de Circuitos Eletrônicos com Base no PIC16F877A. 1. ed. São Paulo: Érica, 2006.
64
Anexo A
A.1 Tabela com Conjunto de Instruções em Linguagem
Assembler
MnemônicosOperandos ou Argumentos
Descrição
Operações com Registradores
ADDWF f, d d (W + f)
ANDWF f, d d (W and f)
CLRF F Limpa f
COMF f, d d complemento de f
DECF f, d d (f – 1)
DECFSZ f, d d (f – 1) e salta próxima linha se resultado for 0
INCF f, d d (f + 1)
INCFSZ f, d d (f + 1) e salta próxima linha se resultado for 0
IORWF f, d d (W ou f)
MOVF f, d d cópia de F
MOVWF F f cópia de W
RLF f, d Rotaciona f um bit para a esquerda
RRF f, d Rotaciona f um bit para a direita
SUBWF f, d d (f – W)
SWAPF f, d Inverte nível alto com nível baixo e guarda o resultado em d
XORWF f, d d (W xor f)
Operações com Bits
BCF f, b Clear (0) bit b do registrador f
BSF f, b Set (1) bit b do registrador f
BTFSC f, b Testa bit b do registrador f e salta a próxima linha se ele for 0
BTFSS f, b Testa bit b do registrador f e salta a próxima linha se ele for 1
Operações com Literais (valores numéricos)
65
MnemônicosOperandos ou Argumentos
Descrição
ADDLW K W (W + K)
ANDLW K W (W and K)
IORLW K W (W ou K)
MOVLW K W K
SUBLW K W (K – W)
XORLW K W (W xor K)
Operações de Controle
CLRW - Limpa Work
NOP - Não faz nada, apenas gasta tempo
CALL K Chamada á sub-rotina
CLRWDT - Limpa WDT
GOTO K Desvio para endereço
RETFIE - Retorno de Interrupção
RETLW K Retorno de sub-rotina com K em W
RETURN - Retorno de sub-rotina
SLEEP - Coloca PIC em modo Sleep para economia de energia
66
Anexo BB.1 Código utilizado para teste com display de sete
segmentos em Linguagem Assembly
;/***********************************************************************; TESTA_DISPLAY7SEG.ASM; Código utilizado para teste com display de 7 segmentos; Autor: Renato Vasques Beraldo;***********************************************************************/
;Biblioteca Padrão do PIC 16F877A#include<p16f877a.inc>
;Configurações __CONFIG _CP_OFF&_WRT_OFF&_DEBUG_OFF&_CPD_OFF&_LVP_OFF&_WDT_OFF&_BODEN_ON&_PWRTE_ON&_XT_OSC
;VariáveisDado EQU 0x73Cont EQU 0x74Zera EQU 0x75
;Variáveis de tempoDelayl EQU 0x70Delaym EQU 0x71Delayh EQU 0x72
;ConstantesNum EQU .0Inc EQU .1Vezes EQU .50Max EQU .11
BANK0 MACRObcf STATUS,RP0bcf STATUS,RP1
ENDM
BANK1 MACRO bsf STATUS,RP0
bcf STATUS,RP1 ENDM
67
ORG 0x00Goto Main
ORG 0x04RETFIE;mainMain
BANK1movlw B'00000000'movwf TRISBmovlw B'10000100'movwf OPTION_REG
;INTERRUPCOES DESABILITADASmovlw B'00000000'
movwf INTCONmovlw B'00000110'movwf ADCON1BANK0clrf PORTBmovlw VezesmovwfContGoto inicio
inicio;inicialiazação das variáveismovlw NummovwfDadomovlw MaxmovwfZera
;inicializando o contador de execução decfsz Cont,W
Goto atualiza_contGoto Fim
;chama as principais funçõesteste
Call AcendeCall IncrementaCall Contamovwf ZeraCall DelayCall DelayGoto teste
;atualiza o número de execuções do programaatualiza_cont
movwf ContGoto teste
68
;acende displayAcende movf Dado,W ;Dado para decodificar call Tabela ;Decodificação do dado movwf PORTB ;Coloca os dados na porta
return
;incrementa o valor de dadoIncrementa
movf Dado,W addlw Inc movwf Dado return
;rotina que conta até nove e zera tudoConta
decfsz Zera,W return
Goto inicio
;rotina que dá um delay Delay
clrf Delaylclrf Delaymmovlw 3hmovwf Delayh
Waitdecfsz Delaylgoto Waitdecfsz Delaymgoto Waitdecfsz Delayhgoto Waitreturn
;decodifica o dado (esta tabela é para display anodo comum, para utilizar catodo ;troque os números 0´s por 1´s e os 1´s por 0´s => B'11000000' => B'11111100'Tabela addwf PCL,F
;display pgfedcba RETLW B'11000000' ;0 RETLW B'11111001' ;1
RETLW B'10100100' ;2 RETLW B'10110000' ;3
RETLW B'10011001' ;4 RETLW B'10010010' ;5 RETLW B'10000010' ;6 RETLW B'11111000' ;7 RETLW B'10000000' ;8
69
RETLW B'10011000' ;9 RETLW B'01111111' ;Acende o ponto
FimEnd
B.2 Código utilizado para teste com display de sete
segmentos em linguagem C
/***********************************************************************TESTA_DISPLAY7SEG.CCódigo utilizado para teste com display de 7 segmentosAutor: Renato Vasques Beraldo
***********************************************************************/
// Biblioteca e variáveis de configuração#include <16F877A.h>#device adc=8#use delay(clock=4000000)#fuses NOWDT,XT, PUT, NOPROTECT, NODEBUG, BROWNOUT, NOLVP, NOCPD, NOWRT
//variável global que indica o digito que estará sendo //mostrado no displayint posicao = 0;
//tabela de conversão de digitos para binariobyte const tabela[]= 0b11000000, // - 0 0b11111001, // - 1 0b10100100, // - 2 0b10110000, // - 3 0b10011001, // - 4 0b10010010, // - 5 0b10000010, // - 6 0b11111000, // - 7 0b10000000, // - 8 0b10011000, // - 9 0b01111111, // - ponto 0b00000000, // - acende tudo ;
//função que trata a interrupção do timer #int_timer0void trata_t0 () static int conta;
70
set_timer0(131+get_timer0()); conta++; if(conta==125) conta = 0; if(posicao==0) output_b(tabela[posicao]); posicao = posicao +1; else if((posicao>0)&&(posicao<11)) output_b(tabela[posicao]); posicao = posicao +1; else output_b(tabela[11]); posicao = 0; void main() //variaveis de configuração setup_adc_ports(NO_ANALOGS); setup_adc(ADC_OFF); setup_psp(PSP_DISABLED); setup_spi(FALSE); setup_timer_0(RTCC_INTERNAL|RTCC_DIV_64); setup_timer_1(T1_DISABLED); setup_timer_2(T2_DISABLED,0,1); setup_comparator(NC_NC_NC_NC); setup_vref(FALSE); //teste de display output_b(tabela[11]); delay_ms(2000); //seta o timer para provocar um atraso de 1 seg set_timer0(131); enable_interrupts(global | int_timer0);
while(true);
Anexo C
71
C.1 Layout da Placa de Construção do Kit Sem
Componentes (vista de trás) e no Tamanho Real
72
C.2 Layout da Placa de Construção do Kit Com
Componentes e Pontes (vista de frente)
73
Anexo D
D.1 Layout da Placa de Construção do Módulo Básico
Sem Componentes (vista de trás) e no Tamanho
Real
D.2 Layout da Placa de Construção do Módulo Básico
Com Componentes e Pontes (vista de frente)
74
As marcas azuis são jumpers de seleção (displays catodo ou anodo), as roxas são os terminais
de 5v, as amarelas são GND e a verde é positivo do controle PWM.
D.3 Código de exemplo utilizando um display de 7
segmentos anodo comum e o teclado
/***********************************************************************
75
Teclado+DisplayAnodo.CCódigo que mostra no display de 7 segmentos anodo comum o valor de
um botão pressionado no teclado.Autor: Renato Vasques Beraldo
***********************************************************************/
//Bibliotecas e Configurações do kit #include <16F877A.h>#device adc=8#use delay(clock=4000000)#fuses NOWDT,XT, NOPUT, NOPROTECT, NODEBUG, BROWNOUT, NOLVP, NOCPD, NOWRT
/* Definições do Teclado utilizando a porta B
O teclado ficara como seguinte layout
c1 c2 c3 c4 l1 1 2 3 - l2 4 5 6 - l3 7 8 9 - l4 * 0 # -*///Colunas#define c1 pin_b4#define c2 pin_b5#define c3 pin_b6//Descomente a linha abaixo para utilizar a coluna 4 do teclado// e também descomente as linhas respectivas a c4 dentro das funções//#define c4 pin_b7
//Linhas#define l1 pin_b0#define l2 pin_b1#define l3 pin_b2#define l4 pin_b3
/* Definições do Display de 7seg utilizando a porta D*///Display7 linhas de Dados#define a pin_d0#define b pin_d1#define c pin_d2#define d pin_d3
//Display7 linha de Seleção#define ca pin_d4
76
#define ponto pin_e0
//Variaveis Globaischar tecla= 'n';
//Funções//Função que identifica a tecla pressionadavoid varretecla();
//Função que acende o displayvoid acendedisp();
//Função que zera o displayvoid zeratudo();
void main()
setup_adc_ports(NO_ANALOGS); setup_adc(ADC_OFF); setup_psp(PSP_DISABLED); setup_spi(FALSE); setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1); setup_timer_1(T1_DISABLED); setup_timer_2(T2_DISABLED,0,1); setup_comparator(NC_NC_NC_NC); setup_vref(FALSE);
//Coloca as colunas em nivel lógico 0 output_low(c1); output_low(c2); output_low(c3); //output_low(c4);
while(true) zeratudo(); acendedisp(); delay_ms(10);
void varretecla() //varre a coluna 1 output_low(c1); output_high(c2);
77
output_high(c3); //output_high(c4);
if(input(l1)==0) tecla = '1'; else if(input(l2)==0) tecla = '4'; else if(input(l3)==0) tecla = '7'; else if(input(l4)==0) tecla = '*';
//varre a coluna 2 output_low(c2); output_high(c1); output_high(c3); //output_high(c4);
if(input(l1)==0) tecla = '2'; else if(input(l2)==0) tecla = '5'; else if(input(l3)==0) tecla = '8'; else if(input(l4)==0) tecla = '0';
//varre a coluna 3 output_low(c3); output_high(c1); output_high(c2); //output_high(c4);
if(input(l1)==0) tecla = '3'; else if(input(l2)==0) tecla = '6'; else if(input(l3)==0) tecla = '9'; else if(input(l4)==0) tecla = '#';
/* Não utilizada neste programa para utilizar retire os comentários*//* //varre a coluna 4 output_low(c4);
78
output_high(c1); output_high(c2); output_high(c3);
if(input(l1)==0) tecla = 13; else if(input(l2)==0) tecla = 14; else if(input(l3)==0) tecla = 15; else if(input(l4)==0) tecla = 12;*/
void zeratudo() output_low(a); output_high(b); output_low(c); output_high(d); output_low(ponto); output_low(ca);
void acendedisp() varretecla(); switch(tecla) case '0': output_low(a); output_low(b); output_low(c); output_low(d); output_low(ca); break;
case '1': output_high(a); output_low(b); output_low(c); output_low(d); output_low(ca); break;
case '2': output_low(a); output_high(b); output_low(c); output_low(d); output_low(ca);
79
break;
case '3': output_high(a); output_high(b); output_low(c); output_low(d); output_low(ca); break;
case '4': output_low(a); output_low(b); output_high(c); output_low(d); output_low(ca); break;
case '5': output_high(a); output_low(b); output_high(c); output_low(d); output_low(ca); break;
case '6': output_low(a); output_high(b); output_high(c); output_low(d); output_low(ca); break;
case '7': output_high(a); output_high(b); output_high(c); output_low(d); output_low(ca); break;
case '8': output_low(a); output_low(b); output_low(c); output_high(d); output_low(ca); break;
case '9': output_high(a); output_low(b); output_low(c); output_high(d); output_low(ca);
80
break;
default: output_high(ponto); output_low(ca); break;
delay_ms(400); zeratudo();
D.4 Código de exemplo utilizando os leds vermelhos
para testar o funcionamento das portas
/***********************************************************************Leds.CCódigo exemplifica como acender e apagar o conjunto de leds
vermelhos utilizando qualquer porta, servindo também para testar se as portas estão funcionando. Autor: Renato Vasques Beraldo***********************************************************************/
//Bibliotecas e Configurações do kit#include <16F877A.h>#device adc=8#use delay(clock=4000000)#fuses NOWDT,XT, PUT, NOPROTECT, NODEBUG, BROWNOUT, NOLVP, NOCPD, NOWRT
/* Função para teste de funcionamento de porta através da sinalização de todos os leds*/void acendetudo(char porta);
/* Função para teste de funcionamento de porta através do desligamento de todos os leds*/void apagatudo(char porta);
void main()
setup_adc_ports(NO_ANALOGS); setup_adc(ADC_OFF);
81
setup_psp(PSP_DISABLED); setup_spi(FALSE); setup_timer_0(RTCC_INTERNAL|RTCC_DIV_64); setup_timer_1(T1_DISABLED); setup_timer_2(T2_DISABLED,0,1); setup_comparator(NC_NC_NC_NC); setup_vref(FALSE);
//Testando a porta B acendetudo('b'); delay_ms(5000); apagatudo('b');
while(true);
void acendetudo(char porta) switch(porta) case 'a': output_a(0b111111); break;
case 'b': output_b(0b11111111); break;
case 'c': output_c(0b11111111); break;
case 'd': output_d(0b11111111); break;
case 'e': output_e(0b111); break;
default: break;
void apagatudo(char porta) switch(porta) case 'a': output_a(0b000000); break;
case 'b': output_b(0b00000000); break;
82
case 'c': output_c(0b00000000); break;
case 'd': output_d(0b00000000); break;
case 'e': output_e(0b000); break;
default: break;
D.5 Código de exemplo utilizando o led verde para
demonstrar o funcionamento do PWM
/***********************************************************************PWM.CCódigo exemplifica como utilizar PWM para controlar a intensidade
de um led através da tensão aplicada.Autor: Renato Vasques Beraldo
***********************************************************************/
//Bibliotecas e Configurações do kit#include <16F877A.h>#device adc=8#use delay(clock=4000000)#fuses NOWDT,XT, PUT, NOPROTECT, NODEBUG, BROWNOUT, NOLVP, NOCPD, NOWRT
//tabela de valores do pwm/* 0 corresponde a 0 volts 5 corresponde a aproximadamente 0,09 volts 10 corresponde a aproximadamente 0,19 volts 20 corresponde a aproximadamente 0,38 volts 30 corresponde a aproximadamente 0,57 volts 40 corresponde a aproximadamente 0,72 volts 50 corresponde a aproximadamente 0,95 volts 70 corresponde a aproximadamente 1,33 volts 100 corresponde a aproximadamente 1,9 volts Esses valores foram obtidos pela formula Considerando uma saída de 5v e 256bits Temos o seguinte: 5 / 256 = 0,01953125 volts por bits Levando em conta que o led tem como voltagem máxima o valor 2 então temos:
83
256 / 5 = 51,2 => 51,2 * 2 = 102,4 Que nos dá um valor correspondente a 5 / 256 = 2 / 102,4 = 0,01953125 volts por bits. Apartir daí calculamos os valores demonstrados acima onde para um pwm igual a 10 obtemos aproximadamente uma voltagem de 0,19 como saída. */
byte const tabela[]= 0, 5, 10, 20, 30, 40, 50, 70, 100 ;
void main() long int ciclo =0;
setup_adc_ports(NO_ANALOGS); setup_adc(ADC_OFF); setup_psp(PSP_DISABLED); setup_spi(FALSE); setup_timer_0(RTCC_INTERNAL|RTCC_DIV_64); setup_timer_1(T1_DISABLED);
//Define a freqüência do pulso para 1,004kHz setup_timer_2(T2_DIV_BY_4,248,1);
//Variáveis de configuração do PWM no pino 17 = c2, setup_ccp1 (ccp_pwm); set_pwm1_duty(0); delay_ms(1000); while(true) for(ciclo = 0; ciclo <= 8; ciclo++) set_pwm1_duty (tabela[ciclo]); delay_ms(2000);
D.6 Códigos de exemplo utilizando dois ou mais
displays de 7 segmentos
D.6.1 Código de exemplo para displays de 7 segmentos anodo
comum
84
/***********************************************************************2ouMaisDisplaysAnodoComum.CCódigo exemplifica como utilizar 2 ou mais displays de 7 segmentos anodo
comum.Autor: Renato Vasques Beraldo
***********************************************************************/
//Bibliotecas e Configurações do kit#include <16F877A.h>#device adc=8#use delay(clock=4000000)#fuses NOWDT,XT, PUT, NOPROTECT, NODEBUG, BROWNOUT, NOLVP, NOCPD, NOWRT
//Pinos//Pinos de Liga e Desliga#define da pin_b4#define db pin_b5//Descomente as linhas abaixo caso esteja utilizando mais de dois displays//#define dc pin_b6//#define dd pin_b7
//Pinos de dados#define ca pin_b0#define cb pin_b1#define cc pin_b2#define cd pin_b3
/* Tabela de dados 0 => ca=0, cb=0, cc=0 e cd=0 1 => ca=1, cb=0, cc=0 e cd=0 2 => ca=0, cb=1, cc=0 e cd=0 3 => ca=1, cb=1, cc=0 e cd=0 4 => ca=0, cb=0, cc=1 e cd=0 5 => ca=1, cb=0, cc=1 e cd=0 6 => ca=0, cb=1, cc=1 e cd=0 7 => ca=1, cb=1, cc=1 e cd=0 8 => ca=0, cb=0, cc=0 e cd=1 9 => ca=1, cb=0, cc=0 e cd=1*/
//Funções//função que desliga os displaysvoid desligaDisplays();
//função que liga todos os displaysvoid ligaDisplays();
85
//função para acender digito no displayvoid acendeDigitoDisplay(int a, int b, int c, int d, int display);
void main()
setup_adc_ports(NO_ANALOGS); setup_adc(ADC_OFF); setup_psp(PSP_DISABLED); setup_spi(FALSE); setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1); setup_timer_1(T1_DISABLED); setup_timer_2(T2_DISABLED,0,1); setup_comparator(NC_NC_NC_NC); setup_vref(FALSE);
//Desliga os displays desligaDisplays();
delay_ms(1000);
while(true) //Escreve o digito 0 no display A acendeDigitoDisplay(0,0,0,0,1);
//Escreve o digito 1 no display B acendeDigitoDisplay(1,0,0,0,2);
//Funções
void desligaDisplays() output_bit(da,1); output_bit(db,1); //Descomente as linhas abaixo para mais de dois displays //output_bit(dc,1); //output_bit(dd,1);
void ligaDisplays() output_bit(da,0); output_bit(db,0); //Descomente as linhas abaixo para mais de dois displays
86
//output_bit(dc,0); //output_bit(dd,0);
void acendeDigitoDisplay(int a, int b, int c, int d, int display) switch(display) case 1: //Desliga os displays para atualização desligaDisplays(); //escreve o dado no display output_bit(ca,a); output_bit(cb,b); output_bit(cc,c); output_bit(cd,d); //habilita display A output_low(da); output_high(db); //Descomente as linhas abaixo para mais de dois displays //output_high(dc); //output_high(dd); //Atraso de Atualização delay_ms(1); break;
case 2: //Desliga os displays para atualização desligaDisplays(); //escreve o dado no display output_bit(ca,a); output_bit(cb,b); output_bit(cc,c); output_bit(cd,d); //habilita display B output_low(db); output_high(da); //Descomente as linhas abaixo para mais de dois displays //output_high(dc); //output_high(dd); //Atraso de Atualização delay_ms(1); break;
//Descomente as linhas abaixo para mais de dois displays/* case 3: //Desliga os displays para atualização desligaDisplays(); //escreve o dado no display output_bit(ca,a); output_bit(cb,b);
87
output_bit(cc,c); output_bit(cd,d); //habilita display C output_low(dc); output_high(da); output_high(db); output_high(dc); //Atraso de Atualização delay_ms(1); break;
case 4: //Desliga os displays para atualização desligaDisplays(); //escreve o dado no display output_bit(ca,a); output_bit(cb,b); output_bit(cc,c); output_bit(cd,d); //habilita display C output_low(dd); output_high(da); output_high(db); output_high(dd); //Atraso de Atualização delay_ms(1); break;*/ default: desligaDisplays(); break;
D.6.2 Código de exemplo para displays de 7 segmentos catodo
comum
/***********************************************************************2ouMaisDisplaysCatodoComum.CCódigo exemplifica como utilizar 2 ou mais displays de 7 segmentos
catodo comum.Autor: Renato Vasques Beraldo
***********************************************************************/
//Bibliotecas e Configurações do kit#include <16F877A.h>
88
#device adc=8#use delay(clock=4000000)#fuses NOWDT,XT, PUT, NOPROTECT, NODEBUG, BROWNOUT, NOLVP, NOCPD, NOWRT
//Pinos//Pinos de Liga e Desliga#define da pin_b4#define db pin_b5//Descomente as linhas abaixo caso esteja utilizando mais de dois displays//#define dc pin_b6//#define dd pin_b7
//Pinos de dados#define ca pin_b0#define cb pin_b1#define cc pin_b2#define cd pin_b3
/* Tabela de dados 0 => ca=0, cb=0, cc=0 e cd=0 1 => ca=1, cb=0, cc=0 e cd=0 2 => ca=0, cb=1, cc=0 e cd=0 3 => ca=1, cb=1, cc=0 e cd=0 4 => ca=0, cb=0, cc=1 e cd=0 5 => ca=1, cb=0, cc=1 e cd=0 6 => ca=0, cb=1, cc=1 e cd=0 7 => ca=1, cb=1, cc=1 e cd=0 8 => ca=0, cb=0, cc=0 e cd=1 9 => ca=1, cb=0, cc=0 e cd=1*/
//Funções//função que desliga os displaysvoid desligaDisplays();
//função que liga todos os displaysvoid ligaDisplays();
//função para acender digito no displayvoid acendeDigitoDisplay(int a, int b, int c, int d, int display);
void main()
setup_adc_ports(NO_ANALOGS);
89
setup_adc(ADC_OFF); setup_psp(PSP_DISABLED); setup_spi(FALSE); setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1); setup_timer_1(T1_DISABLED); setup_timer_2(T2_DISABLED,0,1); setup_comparator(NC_NC_NC_NC); setup_vref(FALSE);
//Desliga os displays desligaDisplays();
delay_ms(1000);
while(true) //Escreve o digito 0 no display A acendeDigitoDisplay(0,0,0,0,1);
//Escreve o digito 1 no display B acendeDigitoDisplay(1,0,0,0,2);
//Funções
void desligaDisplays() output_bit(da,0); output_bit(db,0); //Descomente as linhas abaixo para mais de dois displays //output_bit(dc,0); //output_bit(dd,0);
void ligaDisplays() output_bit(da,1); output_bit(db,1); //Descomente as linhas abaixo para mais de dois displays //output_bit(dc,1); //output_bit(dd,1);
void acendeDigitoDisplay(int a, int b, int c, int d, int display) switch(display)
90
case 1: //Desliga os displays para atualização desligaDisplays(); //escreve o dado no display output_bit(ca,a); output_bit(cb,b); output_bit(cc,c); output_bit(cd,d); //habilita display A output_high(da); output_low(db); //Descomente as linhas abaixo para mais de dois displays //output_low(dc); //output_low(dd); //Atraso de Atualização delay_ms(1); break;
case 2: //Desliga os displays para atualização desligaDisplays(); //escreve o dado no display output_bit(ca,a); output_bit(cb,b); output_bit(cc,c); output_bit(cd,d); //habilita display B output_high(db); output_low(da); //Descomente as linhas abaixo para mais de dois displays //output_low(dc); //output_low(dd); //Atraso de Atualização delay_ms(1); break;
//Descomente as linhas abaixo para mais de dois displays/* case 3: //Desliga os displays para atualização desligaDisplays(); //escreve o dado no display output_bit(ca,a); output_bit(cb,b); output_bit(cc,c); output_bit(cd,d); //habilita display C output_high(dc); output_low(da); output_low(db); output_low(dc); //Atraso de Atualização
91
delay_ms(1); break;
case 4: //Desliga os displays para atualização desligaDisplays(); //escreve o dado no display output_bit(ca,a); output_bit(cb,b); output_bit(cc,c); output_bit(cd,d); //habilita display C output_high(dd); output_low(da); output_low(db); output_low(dd); //Atraso de Atualização delay_ms(1); break;*/ default: desligaDisplays(); break;
D.7 Código de exemplo utilizando o led verde para
demonstrar o funcionamento do PWM, o teclado
para ajustes no nível do PWM e displays anodo
comum para mostrar o nível do PWM
/***********************************************************************Teclado+DisplayAnodo+PWM.C
Código mostra no led verde o funcionamento do PWM, o teclado para ajustes no nível do PWM e displays anodo comum para mostrar o nível do PWM
Autor: Renato Vasques Beraldo***********************************************************************/
//Bibliotecas e Configurações do kit#include <16F877A.h>#device adc=8#use delay(clock=4000000)#fuses NOWDT,XT, NOPUT, NOPROTECT, NODEBUG, BROWNOUT, NOLVP, NOCPD, NOWRT
92
/* Definições do Teclado utilizando a porta B
O teclado ficara como seguinte layout
c1 c2 c3 c4 l1 05 10 20 +5 l2 30 40 50 -5 l3 60 70 80 - l4 90 99 00 -*///Colunas#define c1 pin_b4#define c2 pin_b5#define c3 pin_b6#define c4 pin_b7
//Linhas#define l1 pin_b0#define l2 pin_b1#define l3 pin_b2#define l4 pin_b3
/* Definições do Display de 7seg utilizando a porta D*//* Tabela de dados 0 => ca=0, cb=0, cc=0 e cd=0 1 => ca=1, cb=0, cc=0 e cd=0 2 => ca=0, cb=1, cc=0 e cd=0 3 => ca=1, cb=1, cc=0 e cd=0 4 => ca=0, cb=0, cc=1 e cd=0 5 => ca=1, cb=0, cc=1 e cd=0 6 => ca=0, cb=1, cc=1 e cd=0 7 => ca=1, cb=1, cc=1 e cd=0 8 => ca=0, cb=0, cc=0 e cd=1 9 => ca=1, cb=0, cc=0 e cd=1*/
//Display7 linhas de Dados#define ca pin_d0#define cb pin_d1#define cc pin_d2#define cd pin_d3
//Display7 linha de Seleção#define da pin_d4
93
#define db pin_d5
/* Definições do PWM*///Variavel de Nivellong int ciclo =0;
//Variaveis Globaisint tecla=0;
//Funções//Função que identifica a tecla pressionadavoid varretecla();
//função que desliga os displaysvoid desligaDisplays();
//função que liga todos os displaysvoid ligaDisplays();
//função para acender digito no displayvoid acendeDigitoDisplay(int a, int b, int c, int d, int display);
//função que limpa as variaveisvoid zeraTudo();
//função que calcula o valor e envia para o displayvoid setaDigitos();
//Trata a interrupçaõ do timer0 e faz a varredura do teclado#int_timer0void trata_t0() static int conta; set_timer0(131+get_timer0()); conta++; if(conta==125) //varre a coluna 1 output_low(c1); output_high(c2); output_high(c3); output_high(c4);
if(input(l1)==0)
94
tecla = 05; else if(input(l2)==0) tecla = 30; else if(input(l3)==0) tecla = 60; else if(input(l4)==0) tecla = 90;
//varre a coluna 2 output_low(c2); output_high(c1); output_high(c3); output_high(c4);
if(input(l1)==0) tecla = 10; else if(input(l2)==0) tecla = 40; else if(input(l3)==0) tecla = 70; else if(input(l4)==0) tecla = 99; //varre a coluna 3 output_low(c3); output_high(c1); output_high(c2); output_high(c4);
if(input(l1)==0) tecla = 20; else if(input(l2)==0) tecla = 50; else if(input(l3)==0) tecla = 80; else if(input(l4)==0) tecla = 00;
//varre a coluna 4 output_low(c4); output_high(c1); output_high(c2); output_high(c3);
if(input(l1)==0) tecla = tecla + 5; if(tecla >= 100) tecla = 99;
95
else if(input(l2)==0) tecla = tecla - 5; if(tecla < 0) tecla = 0; /* else if(input(l3)==0) tecla = 00;
else if(input(l4)==0) tecla = 00; */
void main()
setup_adc_ports(NO_ANALOGS); setup_adc(ADC_OFF); setup_psp(PSP_DISABLED); setup_spi(FALSE); setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4); setup_timer_1(T1_DISABLED); setup_comparator(NC_NC_NC_NC); setup_vref(FALSE);
//Frequencia de pulso do PWM setup_timer_2(T2_DIV_BY_4,248,1);
//Variáveis de configuração do PWM no pino 17 = c2, setup_ccp1 (ccp_pwm); set_pwm1_duty(0);
//Testa displays 1 e 2 acendeDigitoDisplay(0, 0, 0, 0, 1); acendeDigitoDisplay(0, 0, 0, 0, 2); desligaDisplays();
//Zera Variaveis zeraTudo(); delay_ms(1000);
//Coloca as colunas em nivel lógico 0 output_low(c1); output_low(c2);
96
//Seta timer 0 set_timer0(131); enable_interrupts(global | int_timer0);
while(true) setaDigitos(); set_pwm1_duty(tecla);
void desligaDisplays() output_bit(da,1); output_bit(db,1); //Descomente as linhas abaixo para mais de dois displays //output_bit(dc,1); //output_bit(dd,1);
void ligaDisplays() output_bit(da,0); output_bit(db,0); //Descomente as linhas abaixo para mais de dois displays //output_bit(dc,0); //output_bit(dd,0);
void acendeDigitoDisplay(int a, int b, int c, int d, int display) switch(display) case 1: //Desliga os displays para atualização desligaDisplays(); //escreve o dado no display output_bit(ca,a); output_bit(cb,b); output_bit(cc,c); output_bit(cd,d); //habilita display A output_low(da); output_high(db); //Atraso de Atualização delay_ms(1); break;
97
case 2: //Desliga os displays para atualização desligaDisplays(); //escreve o dado no display output_bit(ca,a); output_bit(cb,b); output_bit(cc,c); output_bit(cd,d); //habilita display B output_low(db); output_high(da); //Atraso de Atualização delay_ms(1); break;
default: desligaDisplays(); break;
void zeraTudo() tecla=0;
void setaDigitos() int resto=0, resul=0; resto = tecla%10; resul = tecla/10; if(resto==0) acendeDigitoDisplay(0, 0, 0, 0, 1); else if(resto==1) acendeDigitoDisplay(1, 0, 0, 0, 1); else if(resto==2) acendeDigitoDisplay(0, 1, 0, 0, 1); else if(resto==3) acendeDigitoDisplay(1, 1, 0, 0, 1); else if(resto==4) acendeDigitoDisplay(0, 0, 1, 0, 1); else if(resto==5) acendeDigitoDisplay(1, 0, 1, 0, 1); else if(resto==6) acendeDigitoDisplay(0, 1, 1, 0, 1); else if(resto==7) acendeDigitoDisplay(1, 1, 1, 0, 1); else if(resto==8) acendeDigitoDisplay(0, 0, 0, 1, 1);
98
else acendeDigitoDisplay(1, 0, 0, 1, 1); if(resul==0) acendeDigitoDisplay(0, 0, 0, 0, 2); else if(resul==1) acendeDigitoDisplay(1, 0, 0, 0, 2); else if(resul==2) acendeDigitoDisplay(0, 1, 0, 0, 2); else if(resul==3) acendeDigitoDisplay(1, 1, 0, 0, 2); else if(resul==4) acendeDigitoDisplay(0, 0, 1, 0, 2); else if(resul==5) acendeDigitoDisplay(1, 0, 1, 0, 2); else if(resul==6) acendeDigitoDisplay(0, 1, 1, 0, 2); else if(resul==7) acendeDigitoDisplay(1, 1, 1, 0, 2); else if(resul==8) acendeDigitoDisplay(0, 0, 0, 1, 2); else acendeDigitoDisplay(1, 0, 0, 1, 2);
99
Anexo E
E.1 Código exemplificando a Transmissão e Recepção
de Dados via Comunicação Serial Padrão RS-
232
/***********************************************************************TESTA_COM_SERIAL.CTesta Comunicação Serial Padrão RS-232 entre o kit e o microcomputadorAutor: Renato Vasques Beraldo
***********************************************************************/
//Bibliotecas e Configurações do kit #include <16F877A.h>#device adc=8#use delay(clock=4000000)#fuses NOWDT,XT, PUT, NOPROTECT, NODEBUG, BROWNOUT, NOLVP, NOCPD, NOWRT
//Definição da comunicação serial#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
main()
//Declaração de Variavéischar dado[100];
//Envia dado do kit para o pcprintf(“Testando Comunicação Serial \n”);
while(true) //Pega dado enviado do pc para o kit
gets(dado);
//Reenvia o dado do kit para o pc para ter certeza do recebimento printf(“%s \n”,dado);
100
Anexo F
F.1 Código exemplificando a Gravação e Leitura de
Dados na Memória EEPROM Interna,
Mostrando os Dados Correntes em Displays de 7
Segmentos
/***********************************************************************MemoriaInternaEEPROM.CCódigo exemplifica como grava e ler dados de um determinado endereço
da memória interna do microcontrolador, mostrando o valor a ser gravado e depois o valor lido. Autor: Renato Vasques Beraldo***********************************************************************/
//Bibliotecas e Configurações do kit#include <16F877A.h>#device adc=8#use delay(clock=4000000)#fuses NOWDT,XT, PUT, NOPROTECT, NODEBUG, BROWNOUT, NOLVP, NOCPD, NOWRT
/* Definições do Display de 7seg utilizando a porta D*//* Tabela de dados 0 => ca=0, cb=0, cc=0 e cd=0 1 => ca=1, cb=0, cc=0 e cd=0 2 => ca=0, cb=1, cc=0 e cd=0 3 => ca=1, cb=1, cc=0 e cd=0 4 => ca=0, cb=0, cc=1 e cd=0 5 => ca=1, cb=0, cc=1 e cd=0 6 => ca=0, cb=1, cc=1 e cd=0 7 => ca=1, cb=1, cc=1 e cd=0 8 => ca=0, cb=0, cc=0 e cd=1 9 => ca=1, cb=0, cc=0 e cd=1*/
//Display7 linhas de Dados#define ca pin_d0#define cb pin_d1
101
#define cc pin_d2#define cd pin_d3
//Display7 linha de Seleção#define da pin_d4#define db pin_d5
//Funções
//função que liga todos os displaysvoid ligaDisplays();
//função que desliga os displaysvoid desligaDisplays();
//função para acender digito no displayvoid acendeDigitoDisplay(int a, int b, int c, int d, int display);
//função que calcula o valor e envia para o displayvoid setaDigitos();
//Variáveis Globaisint valor=0;
void main() long int i = 0, cont = 0;
setup_adc_ports(NO_ANALOGS); setup_adc(ADC_OFF); setup_psp(PSP_DISABLED); setup_spi(FALSE); setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1); setup_timer_1(T1_DISABLED); setup_timer_2(T2_DISABLED,0,1); setup_comparator(NC_NC_NC_NC); setup_vref(FALSE);
//testa os displays ligaDisplays(); //for que grava o valor da variável valor no endereço de memória i //mostrando no display o valor gravado for(i=1; i<11; i++) valor = i; write_eeprom(i, valor); //gera um atraso de 1 segundo e mantem os displays acesos com o valor escrito
102
for(cont=0; cont<400; cont++) setaDigitos(); //Mostra o fim da operação de escrita desligaDisplays();
//Atraso para realizar a leitura dos dados gravados delay_ms(2000); //for que le o valor contido no endereço de memória i //mostrando no display o valor lido for(i=1; i<11; i++) valor = read_eeprom(i); //gera um atraso de 1 segundo e mantem os displays acesos com o valor lido for(cont=0; cont<400; cont++) setaDigitos(); //Mostra o fim da operação de leitura desligaDisplays();
void desligaDisplays() output_bit(da,1); output_bit(db,1);
void ligaDisplays() output_bit(da,0); output_bit(db,0);
void acendeDigitoDisplay(int a, int b, int c, int d, int display) switch(display) case 1: //Desliga os displays para atualização desligaDisplays(); //escreve o dado no display output_bit(ca,a); output_bit(cb,b); output_bit(cc,c); output_bit(cd,d); //habilita display A output_low(da);
103
output_high(db); //Atraso de Atualização delay_ms(1); break;
case 2: //Desliga os displays para atualização desligaDisplays(); //escreve o dado no display output_bit(ca,a); output_bit(cb,b); output_bit(cc,c); output_bit(cd,d); //habilita display B output_low(db); output_high(da); //Atraso de Atualização delay_ms(1); break;
default: desligaDisplays(); break;
void setaDigitos() int resto=0, resul=0; resto = valor%10; resul = valor/10; if(resto==0) acendeDigitoDisplay(0, 0, 0, 0, 1); else if(resto==1) acendeDigitoDisplay(1, 0, 0, 0, 1); else if(resto==2) acendeDigitoDisplay(0, 1, 0, 0, 1); else if(resto==3) acendeDigitoDisplay(1, 1, 0, 0, 1); else if(resto==4) acendeDigitoDisplay(0, 0, 1, 0, 1); else if(resto==5) acendeDigitoDisplay(1, 0, 1, 0, 1); else if(resto==6) acendeDigitoDisplay(0, 1, 1, 0, 1); else if(resto==7) acendeDigitoDisplay(1, 1, 1, 0, 1); else if(resto==8) acendeDigitoDisplay(0, 0, 0, 1, 1);
104
else acendeDigitoDisplay(1, 0, 0, 1, 1); if(resul==0) acendeDigitoDisplay(0, 0, 0, 0, 2); else if(resul==1) acendeDigitoDisplay(1, 0, 0, 0, 2); else if(resul==2) acendeDigitoDisplay(0, 1, 0, 0, 2); else if(resul==3) acendeDigitoDisplay(1, 1, 0, 0, 2); else if(resul==4) acendeDigitoDisplay(0, 0, 1, 0, 2); else if(resul==5) acendeDigitoDisplay(1, 0, 1, 0, 2); else if(resul==6) acendeDigitoDisplay(0, 1, 1, 0, 2); else if(resul==7) acendeDigitoDisplay(1, 1, 1, 0, 2); else if(resul==8) acendeDigitoDisplay(0, 0, 0, 1, 2); else acendeDigitoDisplay(1, 0, 0, 1, 2);
105
Anexo G
G.1 Conjunto de Comandos para Programar o Módulo
LCD
106
G.2 Biblioteca em C para Manipulação e Programa
Fonte para Testes com Módulo LCD utilizando 4
bits
/********************************************************************BIB_MOD_LCD.CBiblioteca em C para Manipulação de Módulo LCD utilizando 4 bits e os pinosD0, D1 e D2 => para controle e D4, D5, D6 e D7 => para dados
********************************************************************/
// As definições a seguir são utilizadas para acesso aos pinos do display// caso o pino RW não seja utilizado, comente a definição lcd_rw#ifndef lcd_enable
#define lcd_enable pin_d0 // pino enable do LCD#define lcd_rs pin_d1 // pino rs do LCD
// #define lcd_rw pin_d2 // pino rw do LCD#define lcd_d4 pin_d4 // pino de dados d4 do LCD#define lcd_d5 pin_d5 // pino de dados d5 do LCD#define lcd_d6 pin_d6 // pino de dados d6 do LCD#define lcd_d7 pin_d7 // pino de dados d7 do LCD
#endif
#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 linhas do display LCD#define lcd_seg_lin 0x40 // Endereço da segunda linha na RAM do LCD
// a constante abaixo define a seqüência de inicialização do módulo LCDbyte CONST INI_LCD[4] = 0x20 | (lcd_type << 2), 0xf, 1, 6;
// lê um byte do LCD (somente com pino RW ativo)byte lcd_le_byte()
byte dado;// configura os pinos de dados como entradasinput(lcd_d4);input(lcd_d5);input(lcd_d6);input(lcd_d7);// se o pino rw for utilizado, coloca em 1#ifdef lcd_rw
output_high(lcd_rw);#endif
output_high(lcd_enable); // habilita displaydado = 0; // zera a variável de leitura// lê os quatro bits mais significativos
107
if (input(lcd_d7)) bit_set(dado,7);if (input(lcd_d6)) bit_set(dado,6);if (input(lcd_d5)) bit_set(dado,5);if (input(lcd_d4)) bit_set(dado,4);// dá um pulso na linha enableoutput_low(lcd_enable);output_high(lcd_enable);// lê os quatro bits menos significativosif (input(lcd_d7)) bit_set(dado,3);if (input(lcd_d6)) bit_set(dado,2);if (input(lcd_d5)) bit_set(dado,1);if (input(lcd_d4)) bit_set(dado,0);output_low(lcd_enable); // desabilita o displayreturn dado; // retorna o byte lido
// envia um dado de quatro bits para o displayvoid lcd_envia_nibble( byte dado )
// coloca os quatro bits nas saidasoutput_bit(lcd_d4,bit_test(dado,0));output_bit(lcd_d5,bit_test(dado,1));output_bit(lcd_d6,bit_test(dado,2));output_bit(lcd_d7,bit_test(dado,3));// dá um pulso na linha enableoutput_high(lcd_enable);output_low(lcd_enable);
void lcd_envia_byte( boolean endereco, byte dado )
// coloca a linha rs em 0output_low(lcd_rs);// aguarda o display ficar desocupado//while ( bit_test(lcd_le_byte(),7) ) ;// configura a linha rs dependendo do modo selecionadooutput_bit(lcd_rs,endereco);delay_us(100); // aguarda 100 us// caso a linha rw esteja definida, coloca em 0#ifdef lcd_rw
output_low(lcd_rw);#endif// desativa linha enableoutput_low(lcd_enable);// envia a primeira parte do bytelcd_envia_nibble(dado >> 4);// envia a segunda parte do bytelcd_envia_nibble(dado & 0x0f);
108
void lcd_ini()// rotina de inicialização do display
byte conta;output_low(lcd_d4);output_low(lcd_d5);output_low(lcd_d6);output_low(lcd_d7);output_low(lcd_rs);#ifdef lcd_rw
output_high(lcd_rw);#endifoutput_low(lcd_enable);delay_ms(15);// envia uma seqüência de 3 vezes 0x03// e depois 0x02 para configurar o módulo// para modo de 4 bitsfor(conta=1;conta<=3;++conta)
lcd_envia_nibble(3);delay_ms(5);
lcd_envia_nibble(2);// envia string de inicialização do displayfor(conta=0;conta<=3;++conta) lcd_envia_byte(0,INI_LCD[conta]);
void lcd_pos_xy( byte x, byte y) byte endereco; if(y!=1) endereco = lcd_seg_lin; else endereco = 0; endereco += x-1; lcd_envia_byte(0,0x80|endereco);
void lcd_escreve( char c)// envia caractere para o display switch (c)
case '\f': lcd_envia_byte(0,1);
delay_ms(2);break;
109
case '\n': case '\r' : lcd_pos_xy(1,2); break;
case '\b': lcd_envia_byte(0,0x10); break;
default : lcd_envia_byte(1,c); break;
// le caractere do displaychar lcd_le( byte x, byte y)
char valor;// seleciona a posição do caracterelcd_pos_xy(x,y);// ativa rsoutput_high(lcd_rs);// lê o caracterevalor = lcd_le_byte();// desativa rsoutput_low(lcd_rs);// retorna o valor do caracterereturn valor;
/********************************************************************TESTA_MOD_LCD.CPrograma que testa o módulo LCD imprimindo um caractere no display Autor: Renato Vasques Beraldo
********************************************************************///Bibliotecas#include <16f877a.h>#include <BIB_MOD_LCD.C>#use delay(clock=4000000)#fuses HS, NOWDT, PUT, NOBROWNOUT, NOLVP
main()
char dado[6] = ‘t’, ‘e’, ‘s’, ‘t’, ‘e’;int cont = 0;setup_adc_ports(no_analogs);lcd_ini();for(cont = 0; cont < 6; cont++)
lcd_escreve( dado[cont] );
Anexo H
110
H.1 Biblioteca I2C
/*****************************************************************//* I2C.C *//* Biblioteca I2C - Comunicação I2C por software com suporte *//* a memórias EEPROM (modo mestre) *//* *//* Autor: Fábio Pereira *//* *//*****************************************************************/
#ifndef scl// Definições dos pinos de comunicação#define scl pin_b1 // pino de clock#define sda pin_b0 // pino de dados#define EEPROM_SIZE 32768 // tamanho em bytes da memória EEPROM
#endif
#define seta_scl output_float(scl) // seta o pino scl#define apaga_scl output_low(scl) // apaga o pino scl#define seta_sda output_float(sda) // seta o pino sda#define apaga_sda output_low(sda) // apaga o pino sda
void I2C_start(void)// coloca o barramento na condição de start
apaga_scl; // coloca a linha de clock em nível 0seta_sda; // coloca a linha de dados em alta impedância (1)seta_scl; // coloca a linha de clock em alta impedância (1)apaga_sda; // coloca a linha de dados em nível 0apaga_scl; // coloca a linha de clock em nível 0
void I2C_stop(void)// coloca o barramento na condição de stop
apaga_scl; // coloca a linha de clock em nível 0apaga_sda; // coloca a linha de dados em nível 0seta_scl; // coloca a linha de clock em alta impedância (1)seta_sda; // coloca a linha de dados em alta impedância (1)
void i2c_ack()// coloca sinal de reconhecimento (ack) no barramento
apaga_sda; // coloca a linha de dados em nível 0seta_scl; // coloca a linha de clock em alta impedância (1)apaga_scl; // coloca a linha de clock em nível 0seta_sda; // coloca a linha de dados em alta impedância (1)
111
void i2c_nack()// coloca sinal de não reconhecimento (nack) no barramento
seta_sda; // coloca a linha de dados em alta impedância (1)seta_scl; // coloca a linha de clock em alta impedância (1)apaga_scl; // coloca a linha de clock em nível 0
boolean i2c_le_ack()// efetua a leitura do sinal de ack/nack
boolean estado;seta_sda; // coloca a linha de dados em alta impedância (1)seta_scl; // coloca a linha de clock em alta impedância (1)estado = input(sda); // lê o bit (ack/nack)apaga_scl; // coloca a linha de clock em nível 0return estado;
void I2C_escreve_byte(unsigned char dado)// envia um byte pelo barramento I2C
int conta=8;apaga_scl; // coloca SCL em 0while (conta)
// envia primeiro o MSBif (shift_left(&dado,1,0)) seta_sda; else apaga_sda;// dá um pulso em sclseta_scl;conta--;apaga_scl;
// ativa sdaseta_sda;
unsigned char I2C_le_byte()// recebe um byte pelo barramento I2C
unsigned char bytelido, conta = 8;bytelido = 0;apaga_scl;seta_sda;while (conta)
// ativa sclseta_scl;// lê o bit em sda, deslocando em bytelidoshift_left(&bytelido,1,input(sda));conta--;// desativa scl
112
apaga_scl;return bytelido;
void escreve_eeprom(byte dispositivo, long endereco, byte dado)// Escreve um dado em um endereço do dispositivo// dispositivo - é o endereço do dispositivo escravo (0 - 7)// endereco - é o endereço da memória a ser escrito// dado - é a informação a ser armazenada
if (dispositivo>7) dispositivo = 7; i2c_start(); i2c_escreve_byte(0xa0 | (dispositivo << 1)); // endereça o dispositivo i2c_le_ack(); i2c_escreve_byte(endereco >> 8); // parte alta do endereço i2c_le_ack(); i2c_escreve_byte(endereco); // parte baixa do endereço i2c_le_ack(); i2c_escreve_byte(dado); // dado a ser escrito i2c_le_ack(); i2c_stop(); delay_ms(10); // aguarda a programação da memóriabyte le_eeprom(byte dispositivo, long int endereco)// Lê um dado de um endereço especificado no dispositivo// dispositivo - é o endereço do dispositivo escravo (0 - 7)// endereco - é o endereço da memória a ser escrito byte dado;
if (dispositivo>7) dispositivo = 7; i2c_start(); i2c_escreve_byte(0xa0 | (dispositivo << 1)); // endereça o dispositivo i2c_le_ack(); i2c_escreve_byte((endereco >> 8)); // envia a parte alta do endereço i2c_le_ack(); i2c_escreve_byte(endereco); // envia a parte baixa do endereço i2c_le_ack(); i2c_start();
// envia comando de leitura i2c_escreve_byte(0xa1 | (dispositivo << 1)); i2c_le_ack(); dado = i2c_le_byte(); // lê o dado
i2c_nack(); i2c_stop(); return dado;
113
Anexo I
I.1 Biblioteca 25640.c
/////////////////////////////////////////////////////////////////////////////// Library for a MicroChip 25C640 //////// //////// init_ext_eeprom(); Call before the other functions are used //////// write_ext_eeprom(a, d); Write the byte d to the address a //////// d = read_ext_eeprom(a); Read the byte d from the address a //////// b = ext_eeprom_ready(); Returns TRUE if the eeprom is ready //////// to receive opcodes //////// //////// The main program may define EEPROM_SELECT, EEPROM_DI, EEPROM_DO //////// and EEPROM_CLK to override the defaults below. //////// //////// //////// Pin Layout //////// ----------------------------------------------- //////// | __ | //////// | 1: CS EEPROM_SELECT | 8: VCC +5V | //////// | | ____ | //////// | 2: SO EEPROM_DO | 7: HOLD +5V | //////// | __ | | //////// | 3: WP +5V | 6: SCK EEPROM_CLK | //////// | | | //////// | 4: VSS GND | 5: SI EEPROM_DI | //////// ----------------------------------------------- //////// /////////////////////////////////////////////////////////////////////////////////// (C) Copyright 1996, 2003 Custom Computer Services //////// This source code may only be used by licensed users of the CCS C //////// compiler. This source code may only be distributed to other //////// licensed users of the CCS C compiler. No other use, reproduction //////// or distribution is permitted without written permission. //////// Derivative programs created using this software in object code //////// form are not restricted in any way. ///////////////////////////////////////////////////////////////////////////////
#ifndef EEPROM_SELECT
#define EEPROM_SELECT PIN_B0#define EEPROM_CLK PIN_B1#define EEPROM_DI PIN_B2#define EEPROM_DO PIN_B4
114
#endif
#define EEPROM_ADDRESS long int#define EEPROM_SIZE 8192
void init_ext_eeprom() output_high(EEPROM_SELECT); output_low(EEPROM_DI); output_low(EEPROM_CLK);
BOOLEAN ext_eeprom_ready() BYTE cmd[1], i, data;
cmd[0] = 0x05; //rdsr opcode
output_low(EEPROM_SELECT);
for(i=1; i<=8; ++i) output_bit(EEPROM_DI, shift_left(cmd,1,0)); output_high(EEPROM_CLK); //data latches output_low(EEPROM_CLK); //back to idle
for(i=1; i<=8; ++i) output_high(EEPROM_CLK); //data latches shift_left(&data,1,input(EEPROM_DO)); output_low(EEPROM_CLK); //back to idle output_high(EEPROM_SELECT); return !bit_test(data, 0);
void write_ext_eeprom(EEPROM_ADDRESS address, BYTE data) BYTE cmd[4]; BYTE i; BYTE wren; wren=0x06; cmd[0]=data; cmd[1]=address; cmd[2]=(address>>8); cmd[3]=0x02;
// Wait until the eeprom is done with a previous write while(!ext_eeprom_ready());
output_low(EEPROM_SELECT); for(i=0; i<8; ++i)
115
output_bit(EEPROM_DI, shift_left(&wren,1,0)); output_high(EEPROM_CLK); output_low(EEPROM_CLK); output_high(EEPROM_SELECT); output_low(EEPROM_SELECT); for(i=0; i<32; ++i) output_bit(EEPROM_DI, shift_left(cmd,4,0)); output_high(EEPROM_CLK); output_low(EEPROM_CLK); output_high(EEPROM_SELECT);
BYTE read_ext_eeprom(EEPROM_ADDRESS address) BYTE cmd[3]; BYTE i,data; cmd[0]=address; cmd[1]=(address>>8); cmd[2]=0x03;
// Wait until the eeprom is done with a previous write while(!ext_eeprom_ready());
output_low(EEPROM_SELECT); for(i=0; i<24; ++i) output_bit(EEPROM_DI, shift_left(cmd,3,0)); output_high(EEPROM_CLK); output_low(EEPROM_CLK); for(i=0; i<8; ++i) shift_left(&data,1,input(EEPROM_DO)); output_high(EEPROM_CLK); output_low(EEPROM_CLK); output_high(EEPROM_SELECT); return(data);
I.2 Exemplo utilizando comunicação serial com
microcomputador e leitura / escrita em memória
EEPROM 25640
116
/********************************************************************TESTA_MEM_25640.CPrograma que efetua leitura e escrita em memória 25640 utilizando envio e recebimento de dados através de comunicação serial com o microcomp.Autor: Renato Vasques Beraldo
********************************************************************/
//Bibliotecas#include <16F877a.h>#include <input.c>#include <25640.c>
//Variáveis de Configuração#fuses HS,NOWDT,NOPROTECT,NOLVP#use delay(clock=4000000)#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
void main()
byte value,cmd; EEPROM_ADDRESS address;
init_ext_eeprom();
do do printf("\r\nRead or Write: "); cmd=getc(); cmd=toupper(cmd); putc(cmd); while ( (cmd!='R') && (cmd!='W') );
printf("\n\rLocation: ");
address = gethex();
if(cmd=='R') printf("\r\nValue: %X\r\n",READ_EXT_EEPROM( address ) );
if(cmd=='W') printf("\r\nNew value: "); value = gethex(); printf("\n\r"); WRITE_EXT_EEPROM( address, value ); while (TRUE);
117
Anexo J
J.1 Biblioteca mmc.c
// Written by Ed Waugh 2004, www.edwaugh.co.uk
// for the original source, and hundreds more examples of PIC C code, see:// http://www.microchipc.com/sourcecode/#mmc
int mmc_init();int mmc_response(unsigned char response);int mmc_read_block(unsigned long block_number);int mmc_write_block(unsigned long block_number);int mmc_get_status();
/************************** MMC Init **************************************//* Initialises the MMC into SPI mode and sets block size, returns 0 on success */
int mmc_init()int i;
SETUP_SPI(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_4 | SPI_SS_DISABLED);
*0x94 |= 0x40; // set CKE = 1 - clock idle low*0x14 &= 0xEF; // set CKP = 0 - data valid on rising edge
OUTPUT_HIGH(PIN_C2); // set SS = 1 (off)
for(i=0;i<10;i++) // initialise the MMC card into SPI mode by sending clks on SPI_WRITE(0xFF);
OUTPUT_LOW(PIN_C2); // set SS = 0 (on) tells card to go to spi mode when it receives reset
SPI_WRITE(0x40); // send reset commandSPI_WRITE(0x00); // all the arguments are 0x00 for the reset commandSPI_WRITE(0x00);SPI_WRITE(0x00);SPI_WRITE(0x00);SPI_WRITE(0x95); // precalculated checksum as we are still in MMC mode
puts("Sent go to SPI\n\r");
118
if(mmc_response(0x01)==1) return 1; // if = 1 then there was a timeout waiting for 0x01 from the mmc
puts("Got response from MMC\n\r");
i = 0;
while((i < 255) && (mmc_response(0x00)==1)) // must keep sending command if response SPI_WRITE(0x41); // send mmc command one to bring out of idle state SPI_WRITE(0x00); // all the arguments are 0x00 for command one SPI_WRITE(0x00); SPI_WRITE(0x00); SPI_WRITE(0x00); SPI_WRITE(0xFF); // checksum is no longer required but we always send 0xFF i++;if(i >= 254) return 1; // if >= 254 then there was a timeout waiting for 0x00 from the mmc
puts("Got out of idle response from MMC\n\r");
OUTPUT_HIGH(PIN_C2); // set SS = 1 (off)
SPI_WRITE(0xFF); // extra clocks to allow mmc to finish off what it is doing
OUTPUT_LOW(PIN_C2); // set SS = 0 (on)
SPI_WRITE(0x50); // send mmc command one to bring out of idle state SPI_WRITE(0x00); SPI_WRITE(0x00); SPI_WRITE(0x02); // high block length bits - 512 bytes SPI_WRITE(0x00); // low block length bits SPI_WRITE(0xFF); // checksum is no longer required but we always send 0xFF
if((mmc_response(0x00))==1) return 1;OUTPUT_HIGH(PIN_C2); // set SS = 1 (off)puts("Got set block length response from MMC\n\r");return 0;
/************************** MMC Get Status**********************************//* Get the status register of the MMC, for debugging purposes */
int mmc_get_status()
119
OUTPUT_LOW(PIN_C2); // set SS = 0 (on)
SPI_WRITE(0x58); // send mmc command one to bring out of idle state SPI_WRITE(0x00); SPI_WRITE(0x00); SPI_WRITE(0x00); // SPI_WRITE(0x00); // always zero as mulitples of 512 SPI_WRITE(0xFF); // checksum is no longer required but we always send 0xFF
OUTPUT_HIGH(PIN_C2); // set SS = 1 (off)return 0;
/************************** MMC Write Block********************************/
int mmc_write_block(unsigned long block_number)unsigned long i;unsigned long varh,varl;
varl=((block_number&0x003F)<<9);varh=((block_number&0xFFC0)>>7);
puts("Write block\n\r"); // block size has been set in mmc_init()
OUTPUT_LOW(PIN_C2); // set SS = 0 (on)
SPI_WRITE(0x58); // send mmc write block SPI_WRITE(HIGH(varh)); SPI_WRITE(LOW(varh)); SPI_WRITE(HIGH(varl)); SPI_WRITE(0x00); // always zero as mulitples of 512 SPI_WRITE(0xFF); // checksum is no longer required but we always send 0xFF
if((mmc_response(0x00))==1) return 1;puts("Got response to write block\n\r");
SPI_WRITE(0xFE); // send data token
for(i=0;i<512;i++)
SPI_WRITE(i2c_eeprom_read(HIGH(i),LOW(i))); // send data
SPI_WRITE(0xFF); // dummy CRC
120
SPI_WRITE(0xFF);
if((SPI_READ(0xFF)&0x0F)!=0x05) return 1;
puts("Got data response to write block\n\r");
OUTPUT_HIGH(PIN_C2); // set SS = 1 (off)return 0;
/************************** MMC Read Block*********************************//**** Reads a 512 Byte block from the MMC and outputs each byte to RS232 ****/
int mmc_read_block(unsigned long block_number)unsigned long i;unsigned long varh,varl;
varl=((block_number&0x003F)<<9);varh=((block_number&0xFFC0)>>7);
OUTPUT_LOW(PIN_C2); // set SS = 0 (on)
SPI_WRITE(0x51); // send mmc read single block command SPI_WRITE(HIGH(varh)); // arguments are address SPI_WRITE(LOW(varh)); SPI_WRITE(HIGH(varl)); SPI_WRITE(0x00); SPI_WRITE(0xFF); // checksum is no longer required but we always send 0xFF
if((mmc_response(0x00))==1) return 1; // if mmc_response returns 1 then we failed to get a 0x00 response (affirmative)
puts("Got response to read block command\n\r");
if((mmc_response(0xFE))==1) return 1; // wait for data token
puts("Got data token\n\r");
for(i=0;i<512;i++) putc(SPI_READ(0xFF)); // we should now receive 512 bytes
SPI_READ(0xFF); // CRC bytes that are not neededSPI_READ(0xFF);
121
OUTPUT_HIGH(PIN_C2); // set SS = 1 (off)SPI_WRITE(0xFF); // give mmc the clocks it needs to finish off
puts("\n\rEnd of read block\n\r");
return 0;
/************************** MMC get response****************************//**** Repeatedly reads the MMC until we get the response we want or timeout ****/
int mmc_response(unsigned char response) unsigned long count = 0xFFFF; // 16bit repeat, it may be possible to shrink this to 8 bit but there is not much point
while(SPI_READ(0xFF) != response && --count > 0);
if(count==0) return 1; // loop was exited due to timeout else return 0; // loop was exited before timeout
122
Anexo K
K.1 Variáveis de Configuração do Microcontrolador
PIC 16F877-A
Diretivas do Compilador
o #FUSES
Oscilador
LP => Oscilador LP (Cristal de Baixa Potência até
200kHz);
RC => Oscilador RC (RC externo com saída de clock);
XT => Oscilador XT (Cristal / Ressonador até 4MHz)
HS => Oscilador HS (Cristal / Ressonador cerâmico de
alta freqüência até 20MHz);
INTRC => Oscilador Interno
Watchdog => Circuito temporizador que provocará um reset no
programa sempre que ele produzir um timeout. Sua utilização é
indicada a locais onde o programa não pode parar de funcionar.
WDT => Watchdog habilitado
NOWDT => Watchdog desabilitado
Code Protect => Proteção do Código de Programa, habilitada
esta opção ninguém conseguirá ler o código do programa
gravado na memória do microcontrolador.
PROTECT => Proteção de código habilitada;
123
PROTECT_75% => Proteção ligada para 75% da
memória;
PROTECT_50% => Proteção ligada para 50% da
memória;
NOPROTECT => Proteção desabilitada
Power Up Timer => quando ativada, fará com que o
microcontrolador só comece a funcionar cerca de 72ms depois
que a fonte de alimentação for ligada. Isso garante que o
oscilador já estará estabilizado, evitando travamento do
microcontrolador.
PUT => Temporizador de Power-Up ligado;
NOPUT => Temporizador de Power-Up desligado;
Brown Out Detect => quando essa opção é ativada, o
microcontrolador irá resetar caso a tensão de alimentação caia
abaixo de aproximadamente 4V. Caso não esteja ativada, o
microcontrolador poderá travar com a queda de tensão.
BROWNOUT => Reset por queda de tensão ligado;
NOBROWNOUT => Reset por queda de tensão
desligado;
Low Voltage Program => Essa opção ativa a programação em
baixa voltagem. A menos que você saiba o que está fazendo,
deixe-a desabilitada. É necessário que essa opção esteja
desabilitada para que o pino RB3/PGM seja configurado como
I/O.
NOLVP => Programação em baixa tensão desabilitada;
LVP => Programação em baixa tensão habilitada;
124
K.2 Tabela com os Tipos de Dados suportados pelos
compiladores CCS
TIPOTAMANHO em
BITSINTERVALO
void 0 nenhum
short int, int1, boolean 1 0 ou 1
char 8 0 a 255
int, int8, byte 8 0 a 255
signed char 8 -128 a 127
signed int, signed byte 8 -128 a 127
unsigned char 8 0 a 255
unsigned int, unsigned 8 0 a 255
long int, int16 16 0 a 65.535
signed long int 16 -32.768 a 32.767
unsigned long int 16 -32.768 a 32.767
float 32 3.4E-38 a 3.4E+38
int32 32 0 a 4.294.967.295
signed int32 32 -2.147.483.648 a 2.147.483.647
unsigned int32 32 0 a 4.294.967.295
FONTE: (PEREIRA, 2003)
125
K.3 Tabela com as Principais Funções em Linguagem C
para compiladores CCS
FUNÇÃO RETORNO DESCRIÇÃO
abs (int8 x) int8 Retorna o valor absoluto de x
acos (float x) float Calcula o arco cosseno de x
asin (float x) float Calcula o arco seno de x
assert (cond) -Emite mensagem caso a condição (cond) seja
verdadeira
atan (float x) float Calcula o arco tangente de x
atan2 (float x, float y) float Calcula o arco tangente de y/x
atof (char x[]) float Converte a string x em um número float
atoi (char x[]) int8 Converte a string x em um número inteiro
atol (char x[]) int16 Converte a string x em um inteiro de 16 bits
atoi32 (char x[]) int32 Converte a string x em um inteiro de 32 bits
bit_clear (variável, bit) - Apaga o bit (bit) da variável (variável)
bit_set (variável, bit) - Ativa o bit (bit) da variável (variável)
bit_test (variável, bit) int1 Retorna o valor do bit (bit) da variável (variável)
ceil (float x) float Retorna o menor inteiro acima de x
cos (float x) float Calcula o cosseno de x radianos
cosh (float x) float Calcula o cosseno hiperbólico de x radianos
delay_cicles (const int8 x) - Aguarda x ciclos de máquina
delay_ms (const long int8 x) - Aguarda x milissegundos
delay_us (const long int8 x) - Aguarda x microssegundos
disable_interrupts (inter) - Desliga a interrupção especificada
enable_interrupts (inter) - Habilita a interrupção especificada
exp (float x) float Calcula e elevado a x
ext_int_edge (fonte, borda) -Configura a borda de sensibilidade da
interrupção externa
fabs (float x) float Retorna o valor absoluto de x
floor (float x) float Retorna o menor valor inteiro abaixo de x
126
FUNÇÃO RETORNO DESCRIÇÃO
fmod (float x, float y) float Retorna o resto da divisão float de x por y
frexp (float x, signed int8 *y) floatRetorna o componente exponencial e fracionário
de x
get_timerx ( ) int8 ou int16 Lê o conteúdo do timer x
getc ( ) char Lê um caractere do dispositivo de entrada padrão
fgetc ( stream ) char Lê um caractere da stream (stream)
gets ( ) &char Lê uma string do dispositivo de entrada padrão
fgets ( ) &char Lê uma string da stream (stream)
goto_address (int16 ou int32 x)
- Desvia para o endereço x
i2c_poll ( ) int1 Verifica se houve recepção na i2c
i2c_read (int1 ack) int8 Lê um dado da i2c
i2c_start ( ) - Inicia uma condição de start na i2c
i2c_stop ( ) - Insere uma condição stop na i2c
i2c_write (int8 x) int1Escreve um dado (x) na i2c e retorna um ack ou
nack
input (int8 pino) int1 Lê o estado de um pino do dispositivo
input_x ( ) int8 Lê o estado de uma porta do dispositivo
isamoung (char carac, const char[] x
int1Retorna 1 caso o caractere pertença ao conjunto
x
isalnum (char carac) int1 Testa se o argumento é uma letra ou número
isalpha (char carac) int1 Testa se o argumento é uma letra
isdigit (char carac) int1 Testa se o argumento é um número
islower (char carac) int1 Testa se o argumento é uma letra minúscula
isspace (char carac) int1 Testa se o argumento é um espaço
isupper (char carac) int1 Testa se o argumento é uma letra maiúscula
isxdigit (int8 carac) int1 Testa se o argumento é um digito hexadecimal
iscntrl (char carac) int1 Testa se o argumento é um caractere de controle
isgraph (char carac) int1 Testa se o argumento é um caractere gráfico
isprint (char carac) int1 Testa se o argumento é imprimível
ispunct (char carac) int1Testa se o argumento é um caractere de
pontuação
127
FUNÇÃO RETORNO DESCRIÇÃO
kbhit ( ) int1 Retorna se há caractere recebido na serial
label_address (rótulo)int16 ou
int32Retorna o endereço físico do rótulo especificado
labs (int16 x) int16 Retorna o valor absoluto de x
ldexp (float x, signed int8 y) float Retorna x vezes 2 elevado a y
log (float x) float Calcula o logaritmo natural de x
log10 (float x) float Calcula o logaritmo base 10 de x
make8 (int16 ou int32 val, desloc)
int8 Lê um byte especificado por (desloc) valor (val)
make16 (int8 var1, int8 var2) int16 Gera um número de 16 bits a partir de dois de 8
make32 (int8 ou int16 a, b, c, d)
int32Gera um número de 32 bits a partit de 2 ou mais
de 8 ou 16 bits
memcpy (dest, fonte, num) -Copia n bytes do ponteiro (fonte) para o ponteiro
(dest)
memset (dest, valor, n) - Seta n bytes do ponteiro (dest) com valor (valor)
modf (float x, float *y) float Retorna a parte inteira e fracionária de x
offsetof (estrutura, campo) int8Retorna o deslocamento em bytes do campo na
estrutura especificada
offsetofbit (estrutura, campo) int8Retorna o deslocamento em bits do campo na
estrutura especificada
output_bit (int8 pino, int1 valor)
-Coloca o pino especificado no nível lógico
(valor)
output_float (int8 pino) - Coloca o pino em estado de alta impedância
output_high (int8 pino) - Coloca o pino especificado em nível lógico 1
output_low (int8 pino) - Coloca o pino especificado em nível lógico 0
output_x (int8 valor) - Coloca o (valor) na porta especificada por x
perror (string) - Imprime a string erro no dispositivo STDERR
port_b_pulls (int1 valor) -Configura os resistores de pull-up internos da
porta b
pow (float x, float y) float Retorna x elevado a y
printf ( [func,] string [, valores]
- Imprime dados
fprintf( string [, valores], stream)
- Imprime dados na stream especificada
128
FUNÇÃO RETORNO DESCRIÇÃO
psp_output_full ( ) int1 Testa se a porta paralela escrava já foi lida
psp_input_full ( ) int1Testa se foi escrito um dado na porta paralela
escrava
psp_overflow ( ) int1Testa se foi sobrescrito o caractere na porta
paralela escrava
putc (int8 dado) - Escreve o dado na saída padrão
fputc (int8 dado, stream) - Escreve o dado na stream especificada
puts (string) - Escreve a string na saída padrão
fputs (string, stream) - Escreve a string na stream especificada
read_adc ( ) int8 ou int16 Lê o resultado da conversão AD
read_bank (banco, desloc) int8 Lê um registrador GPR do banco especificado
read_calibration (int8 n) int8 Lê um valor de calibração do PIC 14000
read_eeprom (int8 end) int8 Lê um endereço da memória EEPROM
read_program_eeprom (int16 ou int32 end)
int8 ou int16 Lê um endereço da memória de programa
reset_cpu ( ) - Reinicia o processador
restart_cause ( ) int8 Retorna a causa do reset do processador
restart_wdt ( ) - Reinicia a contagem do watchdog
rotate_left (var, bytes) - Rotaciona 1 bit à esquerda a variável (var)
rotate_right (var, bytes) - Rotaciona 1 bit à direita a variável (var)
set_adc_channel (canal) - Seleciona um canal do AD
set_pwmx_duty (int8 ou int16 valor)
-Configura o ciclo ativo do pwm especificado por
x
set_timerx (int8 ou int16 valor)
- Carrega um valor no timer especificado
set_tris_x (int8 valor) - Configura o registrador tris especificado
set_uart_speed (valor) - Configura a velocidade da USART
setup_adc (int8 modo) - Configura o módulo ADC interno
setup_adc_ports (valor) - Configura os pinos de entrada analógicos
setup_ccpx (modo) - Configura o módulo CCP especificado
setup_comparator (modo) -Configura o módulo comparador analógico
interno
setup_counters (modo, presc) - Configura o timer 0 e o prescaler
129
FUNÇÃO RETORNO DESCRIÇÃO
setup_psp (modo) - Configurra a porta paralela escrava
setup_spi (modo) - Configura o SSP ou MSSP para um modo SPI
setup_timer_x (modo) - Configura o timer especificado
setup_vref (modo | valor) -Configura o módulo de referência interna de
tensão
setup_wdt (modo) - Configura o watchdog
shift_left (vari, int8 bytes, int1 valor)
int1Desloca a variável (vari) à esquerda inserindo o
bit (valor)
shift_right (vari int8 bytes, int1 valor)
int1Desloca a variável (vari) à direita inserindo o bit
(valor)
sin (float x) float Retorna o seno de um ângulo de x radianos
sinh (float x) float
sleep ( ) - Coloca o PIC em modo SLEEP
spi_data_is_in ( ) int1 Retorna se há dado disponível na interface SPI
spi_read (int8 valor) int8 Lê um dado na interface SPI
spi_write (int8 dado) - Escreve um dado na interface SPI
sprintf (string, constante, valores)
- Imprime dados para uma string
sqrt (float x) float Retorna a raiz quadrada de x
strcat (s1, s2) pointer Concatena a string s2 em s1
strchr (s1, char c) pointerRetorna um ponteiro para a ocorrência do
caractere c na string s1
strrchr (s1, char c) pointerRetorna um ponteiro para a ocorrência do
caractere c na string s1, iniciando a procura pelo final da string
strcmp (s1, s2) int8 Compara a s1 com s2
strncmp (s1, s2, int n) int8 Compara os n primeiros caracteres de s1 com s2
stricmp (s1, s2) int8Compara a string s1 com s2 ignorando maiúculas
e minúsculas
strncpy (s1, s2, int n) pointer Copia n caracteres de s2 para s1
strcspn (s1, s2) int8Conta os caracteres iniciais de s1 que não
pertencem a s2
strspn (s1, s2) int8Conta os caracteres iniciais de s1 presentes em
s2
130
FUNÇÃO RETORNO DESCRIÇÃO
strlen (s1) int8 Conta o número de caracteres em s1
strlwr (s1) pointer Converte a string s1 em minúsculas
strpbkr (s1, s2) pointerProcura na string s1 pelo primeiro caractere
também presente em s2
strstr (s1, s2) pointer Procura a string s2 na string s1
strtok (s1, s2) pointerProcura a próxima ocorrência de um sinal
definido em s2 na string s1
strcpy (s1, s2) - Copia a string s2 na string s1
swap (int8 x) - Inverte os nibbles da variável x
tan (float x) float Calcula a tangente de x em radianos
tanh (float x) float Calcula a tangente hiperbólica de x em radianos
tolower (char x) char Converte o caractere x em minúsculo
toupper (char x) char Converte o caractere x em maiúsculo
write_bank (banco, desloc, valor)
-Escreve um dado num endereço de memória
RAM
write_eeprom (end, valor) - Escreve um valor na memória EEPROM
FONTE: (PEREIRA, 2003)
131
Anexo L
L.1 Planilha de Microcontroladores Selecionados
132
Anexo M
M.1 Tutorial
1. Processo de Gravação de Um Microcontrolador PIC
Para escrever e gravar programas em um microcontrolador é necessário se ter um
gravador, um software gravador, um compilador e um programa.
O programa pode ser escrito em linguagem assembler ou linguagem C e conterá as
informações de configuração do microcontrolador e a lógica do dispositivo.
Normalmente usa-se o MPLAB IDE (editor, compilador assembler e simulador), o
PCW C Compiler IDE (editor, compilador C e simulador) ou mikroC (que não será abordado
neste tutorial) para desenvolver programas para os microcontroladores. Caso o programador
assembler preferir ele poderá escrever seus programas em qualquer editor de texto e depois
compilá-lo utilizando o MPASMWIN que pode ser encontrado separado ou juntamente com o
MPLAB IDE que podem ser descarregados no sítio da Microchip Technology Inc.
(MICROCHIP, 2006), já o PCW pode ser adquirido no sítio da Custom Computer Services,
Inc. (CCS, 2006).
O software de gravação IC-PROG pode ser obtido gratuitamente no sítio (IC-PROG,
2005), este tem como principal função transmitir as informações hexadecimais geradas pelo
compilador de forma correta para o gravador.
O gravador recebe os sinais gerados pelo computador transmitindo-os para o
microcontrolador de forma que seja possível o seu armazenamento.
O diagrama 1 ilustra a seqüência de passos necessários para a programação de
microcontrolador.
133
Diagrama 1: Esquema de Gravação de Microcontroladores PIC.
A utilização de softwares próprios para edição de programas para os
microcontroladores é bem interessante, pois eles são projetados para proporcionar ao
programador um melhor aproveitamento dos recursos do microcontrolador, deixando a
disposição do programador ferramentas como, por exemplo, o debugger para simulação e
correção de erros no programa, analisador de quantidade aproximada de memória que será
utilizada para armazenamento do programa e durante a sua execução, etc.
2. Escrevendo um programa
Neste capítulo serão apresentados de forma breve dois modos de programação
(assembler e C) e suas respectivas interfaces o MPLAB IDE (versão 7.31) e o PCW C
Compiler IDE (versão 3.203). No final deste tutorial serão mostrados os dois códigos fontes,
um em assembler e um em C, estes apenas realizam uma contagem de 0 a 9 e mostram os
dígitos em um display de 7 segmentos.
2.1 Assembler e o MPLAB IDE
Antes de começar a escrever o código do programa será preciso criar um novo projeto
e definir algumas configurações iniciais.
Para criar um projeto, compilar e simular siga os seguintes passos:
134
1. Abra o MPLAB IDE (tela 1);
Tela 1: Tela inicial do MPLAB IDE
2. Clique no menu Project e depois em Project Wizard (tela 2);
Tela 2: Menu Project -> Project Wizard
135
3. Aparecerá à primeira tela do assistente de criação de projeto, clique em
Avançar ou Next, com isso será apresentada a tela de escolha de modelo de
microcontrolador (tela 3) a ser utilizado neste projeto.
Tela 3: Segunda tela do assistente de criação de projeto
4. Neste tutorial será utilizado microcontrolador PIC 16F877A para
desenvolvimento das aplicações de exemplo, feita a escolha do modelo,
novamente clicaremos em Avançar ou Next;
5. Na próxima tela é solicitada à escolha do compilador e linker que será utilizado
no projeto, como já foi descrito anteriormente o MPLAB IDE será utilizado
para desenvolvimento de aplicações em assembler, então deverá ser
selecionada na primeira caixa de seleção (Active Toolsuite) a opção Microchip
MPASM Toolsuite (tela 4) feita esta seleção, novamente clicaremos em
Avançar ou Next;
136
Tela 4: Seleção da ferramenta a ser utilizada na aplicação.
6. Nesta tela (tela 5) daremos um nome ao projeto e escolheremos onde serão
guardados os arquivos referentes ao mesmo, no caso do projeto será chamado
de display e será armazenado no diretório C:\display7, feito novamente
clicaremos em Avançar ou Next e depois em OK;
Tela 5: Escolha do nome e diretório de projeto.
7. Depois de concluídas as seis etapas anteriores vamos clicar em Avançar ou
Next até ser apresentada a tela com um resumo das opções selecionadas (tela 6)
anteriormente e confirmando que o projeto foi criado com êxito, clique no
botão de Concluir para finalizar a criação do projeto.
137
Tela 6: Conclusão de criação de projeto.
8. Depois de ser concluída a criação do projeto, criaremos um novo arquivo que
conterá o nosso programa, clique no menu File e depois em New (tela 7).
Tela 7: Criação de um novo arquivo.
9. A seguir será mostrada uma nova janela onde o programador poderá escrever o
seu programa (tela 8).
138
Tela 8: Janela de criação de programa.
10. Depois de escrito e salvo na pasta do projeto (C:\display7) temos que adicioná-
lo ao projeto, clique com o botão direito sobre a pasta Source File e depois em
Add files..., uma nova tela se abrirá onde é só escolher o arquivo salvo
anteriormente. Chegou à hora de compilarmos para ver se há ou não erros, se
não houver erros, automaticamente será criado um arquivo .hex, que
posteriormente será utilizado para exemplificar o uso do software gravador.
Para compilar o programa clique no menu Project e depois em Build All (tela
9).
Tela 9: Compilação do projeto.
11. Após o termino será exibida uma janela contendo informações sobre o
processo de compilação (tela 10), caso houver erros de compilação estes
estarão listados junto com suas respectivas informações e caso não houver
139
erros voltará para o código do programa e a mensagem BUILD SUCCEEDED
constará na lista de informações da compilação.
Tela 10: Janela com informações sobre a compilação do projeto.
12. Agora vamos dar uma olhada na ferramenta de debug do MPLAB IDE, para
habilitá-la clique no menu Debugger, depois em Select Tool marque a opção
MPLAB SIM, feito isto você poderá notar que foi acrescentada um conjunto de
botões abaixo da barra de menu (tela 11), estas são as ferramentas de execução
passo a passo do programa.
Tela 11: Conjunto de botões do debugger.
140
13. O primeiro botão da barra de ferramentas do debug denominado de run serve
para simular a execução do programa no microcontrolador; o segundo é o
botão de pause e serve para paralisar a execução da simulação; o terceiro
denominado de animate tem como função ir executando cada instrução
aportando a mesma no código do programa (facilita a visualização da
execução); o quarto, o quinto e o sexto são para fazer a simulação
manualmente; e o sétimo é o botão reset que serve para reiniciar a execução do
programa. Toda vez que estivermos realizando uma simulação e quisermos
saber o valor de uma variável do programa naquele momento é só colocar o
mouse sobre a variável e esperar, pois o seu valor será apresentado (tela 12).
Tela 12: Apresentação de valor de variável.
14. Além da ferramenta de debug temos também no menu view mais algumas
ferramentas interessantes como a Memory Usage Gauge (tela 13) que analisa o
uso de memória de programa e memória de dados.
141
Tela 13: Janela que mostra a ferramenta Memory Usage Gauge.
Finalizamos aqui a breve apresentação da interface de programação da Microchip
Technology Inc.
2.2 C e o PCW C Compiler IDE
A interface do PCW C Compiler IDE é bem amigável e os passos para o
desenvolvimento de um programa em linguagem C para microcontroladores é bem parecido
com os passos apresentados acima para o MPLAB IDE.
Vamos criar um novo projeto e compilá-lo seguindo os seguintes passos:
1. Abra o PCW C Compiler IDE (tela 14);
Tela 14: Tela inicial do PCW C Compiler IDE.
2. Clique no menu Project depois em New e em seguida em PIC Wizard (tela 15);
142
Tela 15: Menu Project -> PIC Wizard.
3. Feito isto, aparecerá uma tela pedindo para você escolher o diretório ou criar
uma pasta para salvar seus arquivos;
4. Criada a pasta e salvo o arquivo será mostrada uma nova tela (tela 16) aonde o
programador irá escolher e definir o modelo do microcontrolador e também
terá acesso a várias configurações do mesmo. A princípio devem ser mudadas
apenas a freqüência do oscilador para 4.000.000 HZ e desmarcar a opção “Low
Voltage Programming on B3(PIC16) or B5(PIC18)”;
Tela 16: Definição de modelo e configurações do microcontrolador.
143
5. Depois de definidas todas as configurações e clicarmos no botão de OK serão
criados dois arquivos um .c e um .h, o .c é o arquivo que contém o código do
programa que está sendo desenvolvido e o arquivo .h contém as configurações
que foram definidas na tela anterior. Acabado este processo será exibido um
arquivo com algumas definições (tela 17) e neste deverá ser escrito o código do
programa;
Tela 17: Janela com o arquivo que foi criado.
6. Depois de escrito o programa iremos compilá-lo, clique no botão Compile no
menu e logo em seguida clique em Compile novamente, após a compilação se
não houver erros no programa será exibida uma janela com demonstrativos do
possível uso de memória do microcontrolador em relação ao programa
compilado (tela 18), caso haja erros uma mensagem será exibida na parte
inferior da interface e a linha seguinte ao erro no código será colocada em
evidencia;
144
Tela 18: Demonstrativo da utilização de memória relativo ao projeto.
7. Depois de compilado, o arquivo .hex já estará criado e pronto para ser
gravado no microcontrolador;
8. Esta interface de programação também oferece boas ferramentas, mas uma
que chama a atenção possui a função de mostrar o código assembler gerado
a partir do código em C, esta está disponível no menu View depois clique
em C/ASM List (tela 19).
145
Tela 19: Exemplo de código assembler gerado a partir de um código C.
Finalizamos aqui a breve apresentação da interface de programação da Custom
Computer Services, Inc.
3. Gravando um programa
Neste capítulo será apresentado o software de gravação, IC-PROG (versão 1.05D),
com as suas funcionalidades. A seguir temos os passos para configurar o software e para
gravar um arquivo .hex em um microcontrolador.
1. Abra o IC-Prog (tela 20);
146
Tela 20: Janela inicial do IC-Prog
2. O IC-Prog possue interface em português, para habilitá-la, clique em Settings
no menu e depois clique em Options, na próxima janela clique na aba
Language e escolha Portuguese. Clique em no botão de OK e pronto;
3. Para usuários de Windows XP/2000/NT que querem utilizar o IC-Prog será
necessário baixar no sítio do mesmo um arquivo chamado de “icprog.sys” que
possue definições para estes sistemas operacionais. Para instalar este arquivo
basta clicar em Configuração no menu, depois clique em Opções e em seguida
clique na aba Diversos, marque a opção Ativar Driver NT/2000/XP. Clique em
no botão de OK e pronto (tela 21);
147
Tela 21: Janela de configuração do driver para Windows NT/2000/XP.
4. Agora iremos selecionar o tipo de gravador que será utilizado. Clique em
Configuração e depois em Hardware, na nova janela escolha o programador
JDM Programmer e marque em qual porta ele está instalado (tela 22).
Tela 22: Janela de configuração do hardware gravador.
5. Esta é a última parte das configurações clique em Configuração depois em
opções, na aba Programando desmarque as duas opções, pronto agora está tudo
configurado.
148
6. Vamos carregar o arquivo .hex que foi gerado em qualquer um dos softwares
de compilação. Clique em Arquivo no menu e depois em abrir. Procure o
diretório onde foi salvo o seu projeto e clique em cima do arquivo .hex depois
clique em no botão de abrir (tela 23);
Tela 23: Janela de procura e carregamento do arquivo .hex.
7. Depois de carregar o arquivo que vai ser transferido para o microcontrolador,
agora iremos efetuar a transferência, clique em Comando no menu e depois em
Limpar tudo. Feita a limpeza agora iremos clicar novamente no menu
Comando e depois em Programar tudo, clique em yes na janela de mensagem
que ira aparecer. Aguarde o término da gravação (vide tela 24) e pronto, seu
microcontrolador agora já está com o programa armazenado em sua memória.
149
Tela 24: Janela que mostra o processo de gravação.
Finalizamos aqui a breve apresentação da interface para gravação IC-Prog.
4. Conclusões
Este breve tutorial apresentou duas das principais ferramentas para desenvolvimento
de programas para microcontroladores pic e também abordou a principal ferramenta de
transferência do programa para o microcontrolador.