desenvolvimento de software e hardware embutido para um sistema

172
UNIVERSIDADE FEDERAL DO RIO DE JANEIRO ESCOLA POLITÉCNICA DEPARTAMENTO DE ELETRÔNICA E DE COMPUTAÇÃO DESENVOLVIMENTO DE SOFTWARE E HARDWARE EMBUTIDO PARA UM SISTEMA DE ESTACIONAMENTO Autor: ___________________________________________________________________ Mauricio Lopes de Oliveira Orientador:_______________________________________________________________ Prof. Manuel Lois Anido, Phd. – NCE/UFRJ Co-orientador:____________________________________________________________ Prof. José Paulo Brafman, Msc. – EP/UFRJ Avaliador:_______________________________________________________________ Prof. Carlos José Ribas D’Avila, Msc. – EP/UFRJ DEL 09/2006

Upload: vodan

Post on 10-Jan-2017

216 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: desenvolvimento de software e hardware embutido para um sistema

UNIVERSIDADE FEDERAL DO RIO DE JANEIRO

ESCOLA POLITÉCNICA

DEPARTAMENTO DE ELETRÔNICA E DE COMPUTAÇÃO

DESENVOLVIMENTO DE SOFTWARE E HARDWARE

EMBUTIDO PARA UM SISTEMA DE ESTACIONAMENTO

Autor: ___________________________________________________________________

Mauricio Lopes de Oliveira

Orientador:_______________________________________________________________

Prof. Manuel Lois Anido, Phd. – NCE/UFRJ

Co-orientador:____________________________________________________________

Prof. José Paulo Brafman, Msc. – EP/UFRJ

Avaliador:_______________________________________________________________

Prof. Carlos José Ribas D’Avila, Msc. – EP/UFRJ

DEL

09/2006

Page 2: desenvolvimento de software e hardware embutido para um sistema

ii

DEDICATÓRIA

Ao meu avô Alcides e minha avó Luzia,

que não estão ao meu lado

para compartilhar os momentos marcantes em minha vida,

como este.

Page 3: desenvolvimento de software e hardware embutido para um sistema

iii

AGRADECIMENTOS

À minha amada esposa Fabiana,

que me acolheu nas minhas angústias.

Aos meus pais por acreditarem em mim,

quando nem mesmo eu acreditava.

Ao Prof. Manuel Lois,

por sua orientação e compreensão.

Aos amigos Daniel, Raphael e Vinícius

Por suas participações

E principalmente a Deus,

por sempre me dar muito além do que eu almejava.

Page 4: desenvolvimento de software e hardware embutido para um sistema

iv

RESUMO

Este trabalho final de graduação descreve a concepção, o projeto e a implementação de um

sistema embutido baseado na linha de microcontroladores PIC, cujo hardware é testado através da

implementação de uma aplicação de um sistema de controle de estacionamento de automóveis.

Este trabalho faz uma descrição das diversas tecnologias estudadas para alcançar os objetivos

propostos e descreve o projeto e a implementação do hardware e do software empregados. Ele também

descreve a metodologia usada e todo o processo de desenvolvimento desde a concepção e projeto até a

implementação do sistema proposto.

O hardware desenvolvido é razoavelmente potente e genérico, considerando-se um sistema

embutido com microcontrolador PIC, e pode ser usado em diversas aplicações, não se limitando à

aplicação apresentada, a qual foi desenvolvida pelo autor em conjunto com alunos do curso de Ciência

da Computação da UFRJ. O sistema possibilita o controle de um estacionamento, lidando com clientes

avulsos (ou rotativos) e mensalistas e permite registrar placas, marcas, tabelas de preços e clientes

mensalistas, além de calcular o tempo de permanência e o valor a ser pago pelo usuário.

Page 5: desenvolvimento de software e hardware embutido para um sistema

v

SUMÁRIO Dedicatória .............................................................................................................................................. ii

Agradecimentos...................................................................................................................................... iii

Resumo................................................................................................................................................... iv

Sumário ................................................................................................................................................... v

Índice de figuras .................................................................................................................................... vii

Índice de tabelas ..................................................................................................................................... ix

1 Introdução ............................................................................................................................................ 1

1.1 Importância do tema................................................................................................................ 1

1.2 Objetivos do Projeto ................................................................................................................ 2

1.3 Organização do trabalho final ................................................................................................. 2

2 Revisão Bibliográfica........................................................................................................................... 3

2.1 Introdução................................................................................................................................ 3

2.2 Bibliografia revisada ............................................................................................................... 3

2.2.1 Microcontroladores analisados .................................................................................... 3

2.2.2 Artigos e produtos revisados........................................................................................ 5

2.3 Conclusões da Revisão Bibliográfica ............................................................................. 6

3 Revisão das tecnologias utilizadas no projeto...................................................................................... 7

3.1 Introdução................................................................................................................................ 7

3.2 Características gerais da família de microcontroladores PIC utilizada ................................. 10

3.2.1 Microcontroladores utilizados no projeto .................................................................. 13

3.4 Componentes externos utilizados no projeto......................................................................... 16

3.4.1 EEPROM 24C32........................................................................................................ 16

3.4.2 RAM 62256 ............................................................................................................... 17

3.4.3 MAX 232 ................................................................................................................... 18

3.4.4 PCF 8583 ................................................................................................................... 19

3.4.4 LCD............................................................................................................................ 20

Page 6: desenvolvimento de software e hardware embutido para um sistema

vi

3.3 Protocolos utilizados no projeto ............................................................................................ 21

3.3.1 Protocolo I2C ............................................................................................................. 21

3.3.2 Protocolo de comunicação para teclado PS/2 ............................................................ 22

3.4 Softwares e programadores de microcontroladores utilizados no projeto............................. 23

3.4.1 Softwares utilizados ................................................................................................... 23

3.4.2 Programador utilizado................................................................................................ 25

3.5 UML ...................................................................................................................................... 25

4 Concepção e projeto do sistema ......................................................................................................... 26

4.1 Introdução.............................................................................................................................. 26

4.2 Funções e requisitos de um sistema de estacionamento ........................................................ 26

4.3 Requisitos de hardware do sistema de estacionamento ......................................................... 30

4.4 Requisitos básicos de um S.E. para uso geral........................................................................ 31

5 Implementação e resultados ............................................................................................................... 41

5.1 Introdução.............................................................................................................................. 41

5.2 Implementação do software................................................................................................... 41

5.3 Implementação do hardware.................................................................................................. 46

5.4 Resultados ............................................................................................................................. 51

6 Conclusões ......................................................................................................................................... 54

6.1 Resumo do trabalho............................................................................................................... 54

6.2 Principais dificuldades........................................................................................................... 55

6.3 Conclusões............................................................................................................................. 56

6.4 Trabalhos futuros................................................................................................................... 57

Bibliografia utilizada............................................................................................................................. 58

Referências ............................................................................................................................................ 59

Apêndice A – Listagem do código desenvolvido.................................................................................. 62

Apêndice B – Manual de uso das Bibliotecas usadas no Hardware.................................................... 135

Apêndice C – Glossário do Sistema de Estacionamento..................................................................... 144

Apêndice D – Análise de requisitos do Sistema de Estacionamento .................................................. 148

Page 7: desenvolvimento de software e hardware embutido para um sistema

vii

ÍNDICE DE FIGURAS

Figura 1 - Níveis de abstração do processo de desenvolvimento de sistemas embutidos........... 10

Figura 2 – Um esquema simplificado do microcontrolador 16F64 ............................................ 11

Figura 3 – Pinagem do 18F452 e do 18F4620 ............................................................................ 15

Figura 4 - Pinagem da EEPROM 24C32 .................................................................................... 17

Figura 5 – Identificação da EEPROM ........................................................................................ 17

Figura 6 – Pinagem do 62256 ..................................................................................................... 18

Figura 7 – Diagrama do CI MAX232 ......................................................................................... 19

Figura 8 – Esquema de utilização do PCF 8583 ......................................................................... 19

Figura 9 – Comunicação I2C ...................................................................................................... 22

Figura 10 – Comunicação do teclado com o computador........................................................... 23

Figura 11 – Comunicação do computador com o teclado........................................................... 23

Figura 12 – Ligação do PIC com o LCD .................................................................................... 32

Figura 13 – Diagrama de tempo do ciclo de escrita do LCD...................................................... 33

Figura 14 – Ligação do PIC com o teclado PS/2 ........................................................................ 33

Figura 15 – Ligação do PIC com o 24C32 e o PCF8583............................................................ 34

Figura 16 – Diagrama de tempo dos dispositivos I2C ................................................................ 34

Figura 17 – Comunicação serial no MAX232 ............................................................................ 35

Figura 18 – Ligação do PIC com o MAX232............................................................................. 35

Figura 19 – Ligação do PIC com a memória externa 62256....................................................... 36

Figura 20 – Diagrama de tempos de leitura na memória 62256 ................................................. 36

Figura 21 – Diagrama de tempos de escrita na memória 62256 ................................................. 37

Figura 22 – Ligação do PIC com a interface paralela................................................................. 38

Figura 23 – Diagrama de tempos da interface paralela............................................................... 39

Figura 24 – Diagrama esquemático do hardware projetado........................................................ 40

Page 8: desenvolvimento de software e hardware embutido para um sistema

viii

Figura 25 – Sistema final implementado .................................................................................... 46

Figura 26 – Visão de frente do sistema....................................................................................... 47

Figura 27 – Visão lateral direita do sistema................................................................................ 48

Figura 28 – Visão frontal do sistema .......................................................................................... 49

Figura 29 – Visão lateral esquerda do sistema............................................................................ 50

Figura 30 – Disposição dos componentes na placa do sistema................................................... 51

Figura 31 – Tabela de marcas cadastradas.................................................................................. 51

Figura 32 – Tabela de preços para automóveis de classe 1......................................................... 52

Figura 33 – Ticket de entrada ..................................................................................................... 52

Figura 34 – Listagem do pátio .................................................................................................... 52

Figura 35 – Ticket de saída........................................................................................................ 53

Page 9: desenvolvimento de software e hardware embutido para um sistema

ix

ÍNDICE DE TABELAS

Tabela 1 – Características do 18F452 e 18F4620 ....................................................................... 14

Tabela 2 – Pinagem padrão do LCD........................................................................................... 20

Tabela 3 – Valores típicos do diagrama de tempo do LCD medidos em nanosegundos ............ 32

Tabela 4 – Valores dos tempos dos diagramas da memória 62256 ............................................ 37

Page 10: desenvolvimento de software e hardware embutido para um sistema

1 INTRODUÇÃO A computação está cada vez mais presente, e cada vez mais importante no nosso cotidiano.

Associada as outras tecnologias, a computação oferece uma enorme gama de produtos e serviços que

servem para melhorar a qualidade de vida das pessoas. Há inúmeros exemplos de produtos com

serviços sofisticados que só com o auxílio de computação é possível prover, como por exemplo:

eletrodomésticos e automóveis inteligentes, equipamentos médicos de última geração, etc.

Neste cenário, tem se tornado cada vez mais importante, embutir placas eletrônicas com

microcontroladores dentro dos equipamentos, a fim de dar-lhes maior capacidade para prover novas

funções, para substituir partes mecânicas ou economizar energia, entre outras coisas.

A aplicação de microcontroladores e de outros circuitos integrados dentro de equipamentos

tornou-se muito importante, tanto do ponto de vista econômico quanto estratégico, fazendo com que

muitas universidades e empresas criassem cursos, departamentos, ou áreas denominadas Sistemas

Embutidos ou Sistemas Embarcados, para estruturar melhor as pesquisas e o desenvolvimento destes

tipos de sistemas.

1.1 IMPORTÂNCIA DO TEMA Atualmente é muito comum haver pelo menos um computador pessoal nas residências. Da

mesma maneira, há diversos sistemas que ficam embutidos dentro de aparelhos facilmente

encontrados nos lares: Celulares, lavadoras, automóveis, microondas, TVs, DVD’s, etc.

Estatísticas atuais indicam que os microprocessadores usados em PC’s representam apenas 3%

do total de microprocessadores e microcontroladores fabricados no mundo [27]. Em termos de valor

de produto, os computadores e os notebooks juntos representam apenas 30% do valor do somatório de

todos os outros produtos que usam microprocessadores e microcontroladores em sistemas embutidos,

tais como máquina de lavar, microondas, automóveis e aviões [27].

Portanto, os Sistemas Embutidos são uma realidade no contexto da nova economia, que consiste

na combinação do processo da globalização e da alta tecnologia, na qual os resultados-chave e os

ativos produtivos são fundamentalmente intelectuais – informação e conhecimento – e não físicos.

Embora na nova economia se tenha dado muita atenção ao desenvolvimento de software e

telecomunicações, a nova economia, que faz uso intensivo de informação, engloba também o

desenvolvimento de sistemas embutidos.

A evolução tecnológica dos softwares de desenvolvimento e das técnicas de fabricação de CI’s

tem ocasionado uma redução nos custos de produção dos Sistemas Embutidos. Dessa forma, observa-

se uma diminuição dos preços de venda de produtos baseados em Sistemas Embutidos. Ou seja, novas

Page 11: desenvolvimento de software e hardware embutido para um sistema

2

tecnologias proporcionam preços mais baratos e fazem com que Sistemas Eletrônicos Embutidos

sejam cada vez mais utilizados dentro de produtos aos quais eles são agregados.

A facilidade de desenvolvimento e o baixo custo têm proporcionado um maior interesse por

parte das indústrias e das universidades por Sistemas Embutidos, que além de um custo cada vez mais

baixo, apresentam uma crescente flexibilidade, capaz de permitir sua utilização em uma grande gama

de aplicações.

1.2 OBJETIVOS DO PROJETO O projeto descrito neste trabalho aborda a concepção, o projeto e a implementação do hardware

de um sistema embutido com características suficientemente genéricas para poder ser utilizado em

gama razoável de aplicações. Para testar o hardware proposto, desenvolveu-se uma aplicação que

consiste num sistema para o controle de estacionamentos pequenos.

O hardware não está limitado a esta aplicação e pode ser utilizado como plataforma de

desenvolvimento de outras aplicações.

1.3 ORGANIZAÇÃO DO TRABALHO FINAL Neste item, são mencionados os capítulos descritos neste trabalho e seu conteúdo.

O capítulo 1 aborda a importância do tema, os objetivos propostos e o roteiro deste trabalho.

O capítulo 2 faz uma revisão bibliográfica, analisa as principais aplicações encontradas que

possuem alguma relação com o trabalho aqui apresentado, discute algumas famílias de

microcontroladores e justifica a escolha do microcontrolador utilizado.

O capítulo 3 discute as tecnologias relevantes utilizadas no desenvolvimento do sistema

apresentado.

O capítulo 4 apresenta a concepção e o projeto do sistema desenvolvido, mostrando as

características e necessidades de um sistema de estacionamento, apresentando e justificando as

escolhas feitas.

O capítulo 5 descreve a implementação do hardware e do software, apresentando fotos do

sistema e uma breve descrição das funções contidas nas bibliotecas desenvolvidas.

Por fim, o capítulo 6 apresenta as conclusões deste trabalho e propõe alguns temas para

evolução deste projeto.

Page 12: desenvolvimento de software e hardware embutido para um sistema

2 REVISÃO BIBLIOGRÁFICA

2.1 INTRODUÇÃO Devido à amplitude do tema Sistemas Embutidos, no qual este trabalho se insere, esta revisão

bibliográfica analisa algumas pesquisas e produtos que possuem alguma relação com o trabalho aqui

apresentado.

2.2 BIBLIOGRAFIA REVISADA

2.2.1 MICROCONTROLADORES ANALISADOS Para que os Sistemas Embutidos tenham um custo baixo e tamanho reduzido, é necessário fazer

uso de poucos componentes no circuito. Por este motivo, geralmente dá-se preferência ao uso de

microcontroladores no projeto de Sistemas Embutidos (ou sistemas embarcados), pois eles integram,

numa única pastilha, um microprocessador e vários outros dispositivos como, conversores analógico-

digitais (AD), memórias, temporizadores, interface de comunicação serial, etc. Deste modo, permitem

redução de custos e de tamanho físico, além de conferir versatilidade ao hardware. Existem várias

famílias de microcontroladores com recursos bastante variados e, por isso há diferentes escolhas

possíveis de microcontroladores, que passaremos a analisar a seguir.

Os microcontroladores 8051 [7] foram lançados pela INTEL, no início da década de 80, e são

usados em várias aplicações. A família de microcontroladores 8051, conhecida por família MCS-51, é

produzida por diversos fabricantes, tais como Intel, Philips e Siemens. Estes fabricantes têm

adicionado periféricos para o 8051, como: interfaces I2C [8], conversores analógico digitais (A/D),

modulação por largura de pulso (PWM), etc. As principais características normalmente encontradas

são: 4 portas de 8 bits, um ciclo de instrução igual a 12 ciclos de clock, 2 temporizadores/contadores

de 16 bits, 1 interface UART, entre outros. O 8051 geralmente possui poucas portas de entrada e saída

(E/S), principalmente se for usada memória externa para expansão da memória interna de dados ou de

programa, o que compromete 2 portas do 8051. Além disso, como cada ciclo de instrução ocupa 12

ciclos de clock, o 8051 necessita de um clock elevado para um ciclo de instrução considerável, o que

gera um consumo de energia mais elevado do que em outros microcontroladores. Uma outra

desvantagem da família MCS-51, em relação a outros microcontroladores como o PIC, por exemplo, é

a pouca densidade de código.

Os microcontroladores ARM [9] fazem parte de uma família de microcontroladores RISC de

normalmente 32 bits, que foi desenvolvida para ter o melhor desempenho possível dentro das

seguintes limitações: ser simples, ocupar pouca área e ter baixo consumo de energia. Apesar de

possuir um conjunto de instruções muito simples se comparado com processadores CISC, o ARM tem

instruções mais complexas do que aquelas que um processador RISC normalmente oferece. O baixo

Page 13: desenvolvimento de software e hardware embutido para um sistema

4

consumo de energia em relação a processadores CISC, como, por exemplo, o Pentium, é alcançado

através de três fatores: simplicidade do circuito, pipeline curto e um projeto que privilegia o mínimo

consumo de energia sempre que o processador não estiver em operação. Devido às suas características

de ocupar pouca área e de apresentar um baixo consumo de energia (e ao mesmo tempo apresentar um

bom desempenho), o processador ARM é muito utilizado em aplicações complexas que necessitem de

um baixo consumo de energia, como PDAs, video games (Nintendo Game Boy Advance), etc. Apesar

de ser um microcontrolador/microprocessador rápido e com baixo consumo de energia, as ferramentas

de desenvolvimento e os próprios chips custam mais caro do que o PIC ou o 8051, o que dificulta o

desenvolvimento baseado na linha ARM. Além disso, microcontroladores ARM não são facilmente

encontrados com encapsulamento DIP, o que dificulta a montagem de protótipos.

A linha de microcontroladores M68HC11 [10] é uma família de microcontroladores de 8 bits

fabricados originalmente pela Motorola e agora, produzidos pela FreeScale Semiconductor. Os

microcontroladores M68HC11 geralmente possuem 5 ports e podem operar com memória externa de

programa ou dados. Porém, quando for usada memória externa, os ports B e C são usados para

barramento de endereço e de dados respectivamente. Os microcontroladores M68HC11 possuem

geralmente: EEPROM, temporizadores, conversor A/D, clock interno de 2 MHz, gerador PWM,

interface RS-232 e SPI. Estes microcontroladores tem ferramentas de desenvolvimento

comercializadas exclusivamente pela FreeScale Semiconductor e, assim, seu uso ocasiona um alto

investimento inicial, pois não existem muitas alternativas de sistema de desenvolvimento freeware

para microcontroladores Motorola como existem por exemplo para a linha PIC. Uma outra linha de

microprocessadores recentemente criada pela FreeScale Semiconductor é o COLDFIRE, que possui

arquitetura RISC com tamanho de instruções de 16, 32 ou 48 bits, resultando numa melhor densidade

de código, quando comparado com microprocessadores RISC de 32 bits tradicionais. O COLDFIRE é

bastante usado em aplicações complexas, como PDAs, vídeo-games, etc. No entanto, além de possuir

as mesmas desvantagens da linha M68HC11 citada anteriormente, o COLDFIRE não é facilmente

encontrado com encapsulamento DIP como na linha PIC, por exemplo, dificultando a montagem de

protótipos.

Microcontroladores PIC [11] - Peripherical Interface Controller- é uma família fabricada pela

Microchip Technology com extensa variedade de modelos e periféricos internos, com arquitetura

Harvard e conjunto de instruções RISC com larguras de palavra de 12, 14 ou 16 bits. Estes

microcontroladores trabalham geralmente com velocidades de até 40 MHz usando ciclo de instrução

de quatro períodos de clock, o que permite uma velocidade de no máximo 10 MIPS Como o clock

pode variar desde 32KHz até 40MHz (conforme o modelo), pode-se estabelecer a velocidade de

acordo com a necessidade, economizando energia. Os microcontroladores PIC são encontrados em

chips de 6 a 100 pinos em diversos encapsulamentos (SOT23, DIP, SOIC, TQFP, etc). Seus principais

periféricos internos (a disponibilidade varia conforme o modelo) são: conversores A/D de 8 a 12 bits,

Page 14: desenvolvimento de software e hardware embutido para um sistema

5

temporizadores e contadores de 8 e 16 bits, comparadores analógicos, USART, controladores de

comunicação I2C, controladores PWM, watchdog timer, portas digitais com capacidade de 20mA

(fornecer ou drenar) para acionar circuitos externos e osciladores internos de 4Mhz. Existem vários

fabricantes de ferramentas de desenvolvimento para PICs e algumas são disponibilizadas

gratuitamente na Internet (apesar de terem limitações). Consequentemente é fácil e, até certo ponto,

barato obter um programador de PIC ou um compilador. Isso tornou o PIC muito popular, facilitando a

compra destes microcontroladores.

2.2.2 ARTIGOS E PRODUTOS REVISADOS O trabalho em [1] tem como objetivo implementar um sistema de automação residencial

acessível à distância pela Internet com os dispositivos da casa interligados pelo protocolo CAN. O

sistema se baseia na comunicação entre um computador servidor localizado na residência que contém

os eletrodomésticos que serão controlados e um navegador cliente com uma interface amigável que

envia pacotes ao servidor que se encarregará de tratá-los. Ao receber Estes pacotes de controle

enviados pelo cliente, o servidor se comunica através de uma interface RS-232 com um controlador

mestre, que realiza a codificação dos dados recebidos pelo servidor para o protocolo CAN e transmite

o comando para placas eletrônicas que fazem o acionamento do dispositivo. As placas eletrônicas e o

controlador mestre utilizam microcontroladores 68HC11 da Motorola.

O trabalho em [2] consiste em um sistema portátil direcionado a deficientes surdos-mudos que

converte texto em fala do idioma português do Brasil. O sistema engloba a digitação do texto, a

geração do sinal acústico correspondente à fala sintetizada, a amplificação do sinal sonoro e sua

reprodução. O projeto é composto por um microcontrolador 8031, um display LCD, uma memória

flash externa e um teclado padrão PS/2 além de circuitos para amplificação e reprodução do som. A

entrada textual é feita pelo teclado e visualizada no LCD e os fonemas correspondentes são

armazenados na memória flash. Este processo é controlado pelo microcontrolador 8031 que identifica

o texto digitado, seleciona o fonema correspondente armazenado na memória flash externa e passa o

dado digital por um conversor D/A. Enfim, a saída do conversor D/A segue para o circuito de

amplificação e reprodução do sinal sonoro.

O trabalho descrito em [3] apresenta um estudo da viabilidade de implementação de um sistema

embarcado utilizando o microcontrolador 8051. A aplicação trata de um sistema para automação do

gerenciamento de lotação e cobrança de estacionamentos pagos. Durante o projeto foi realizado o

desenvolvimento do hardware de um protótipo funcional do sistema, envolvendo a elaboração de uma

placa controladora e a programação de um firmware em Assembly para o microcontrolador 8051, a

fim de controlar as funções dos periféricos do dispositivo. Foi desenvolvido um software na

plataforma Windows para gerenciar a cobrança e a lotação do pátio, sendo possível existir mais de um

Page 15: desenvolvimento de software e hardware embutido para um sistema

6

hardware para gerenciar a entrada e saída de veículos e todos conectados por um computador através

da interface serial RS-232.

O trabalho apresentado em [4], consiste em um sistema de armazenamento, leitura,

decodificação e reprodução de arquivos de áudio no formato MP3. Este trabalho apresenta um

protótipo que armazena e reproduz arquivos de áudio MP3 utilizando componentes facilmente

encontrados no mercado, sendo o decodificador MP3 o único componente específico e, por isso, não

encontrado facilmente. O controle central do sistema é feito através de um microcontrolador

ST10F269 (microcontrolador ARM fabricado pela STMicroeletronics) e o arquivo MP3 pode estar

armazenado em um HD, em um cartão de memória CompactFlash ou um CD-ROM. A entrada de

comandos é feita usando um teclado matricial e a visualização de mensagens é feita através de um

LCD.

O trabalho descrito em [5] consiste de um sistema de acesso remoto de dispositivos elétricos. O

acesso remoto é feito através da Internet por meio de um servidor que recebe pacotes enviados por

navegadores que o acessam para controlar os dispositivos. Ao receber o comando enviado pelo

navegador, um script em PHP atualiza o banco de dados e chama uma rotina java que envia o

comando pela porta serial para uma placa contendo um PIC 16F628 que executa o comando através de

relés biestáveis que acionam o dispositivo que o usuário requisitou.

O trabalho apresentado em [6] consiste no projeto de um módulo didático para uso em cursos de

microcontroladores e teste de protótipos. O módulo é equipado com um microcontrolador 16F877 que

possui: EEPROM, conversor A/D, saída PWM, inteface serial USART e I2C. Além dos recursos

existentes no PIC, o módulo didático conta ainda com: fontes de alimentação de ±5V e ±12V, teclado

de dados matricial, LCD, 4 displays de 7 segmentos, banco de 8 LEDs, 8 chaves para entrada de

dados, motor DC, EEPROM externa e 2 relés biestáveis.

2.3 CONCLUSÕES DA REVISÃO BIBLIOGRÁFICA Após realizar uma busca em artigos, trabalhos e produtos com alguma relação com o projeto a

ser elaborado, não foram achados artigos com muita semelhança com o trabalho escolhido como tema.

Sob o ponto de vista de hardware, ele é muito simples (como é normalmente de se esperar em

um sistema embutido) e não foi necessário analisar outros esquemas.

Um outro aspecto a ressaltar na revisão bibliográfica é que os sistemas analisados não

apresentaram detalhes suficientes para uma análise aprofundada.

Page 16: desenvolvimento de software e hardware embutido para um sistema

3 REVISÃO DAS TECNOLOGIAS UTILIZADAS NO PROJETO

3.1 INTRODUÇÃO Os computadores estão completamente difundidos no nosso quotidiano. Não causa surpresa

milhões de computadores serem construídos todo ano e serem destinados a aplicações diversas. Ou

seja, estes computadores podem executar uma ampla variedade de aplicações podendo rodar

aplicações variadas como: jogos, editores de texto, planilhas eletrônicas, etc. Dentro desse grupo de

computadores encontram-se: computadores pessoais (PC’s), estações de trabalho, computadores de

grande porte e servidores. Tais sistemas podem executar uma enorme diversidade de aplicações para

suprir as necessidades do usuário.

O que passa despercebido é que milhões de sistemas computacionais são produzidos todo ano

com um propósito diferente: executar repetidamente uma função específica para o qual foram

projetados. Tais sistemas são embutidos (ou embarcados) dentro de sistemas maiores (geralmente

equipamentos eletromecânicos como automóveis, fornos de microondas, sistemas de segurança, etc),

razão pela qual são chamados Sistemas Embutidos.

Os sistemas embutidos possuem em seu núcleo um microprocessador, geralmente um

microcontrolador, que carrega dentro de si um software dedicado para executar sua função. Os

microcontroladores possuem uma grande variedade de recursos, além de entradas e saídas, tais como:

conversor A/D, EEPROM, memória flash, RTC, Timers, UART, PWM e barramentos especializados

para conectar periféricos (I2C, SPI, USB, etc). Existem diversos fabricantes de microcontroladores e

há famílias de microcontroladores com capacidades diferenciadas entre si.

Embora muitos recursos dos sistemas embutidos estejam disponíveis no interior dos

microcontroladores, pode haver a necessidade de uso de dispositivos externos, seja para estender estes

recursos, ou para suprir alguma necessidade não prevista pelo microcontrolador.

A seguir estão dois exemplos de sistemas embutidos:

1. Celulares possuem dentro de si sistemas embutidos que fazem a ligação entre o circuito

de comunicação e o usuário do celular.

2. Muitos eletrodomésticos estão agregando valor com o uso de sistemas embutidos para

criar uma interface mais amigável e confiável. Por exemplo, a programação e o controle

de um forno de microondas são feitos através de um sistema embutido. Da mesma

forma, lavadoras automáticas contêm sistemas embutidos que ampliam a gama de

opções de lavagem de roupa;

Ao contrário dos softwares projetados para computadores pessoais (PC’s), o software embutido

não pode ser transferido para outro sistema embutido sem mudanças; principalmente por causa das

Page 17: desenvolvimento de software e hardware embutido para um sistema

8

grandes diferenças de hardware, a menos que tenha sido escrito em Java e o sistema implemente uma

máquina virtual Java (JVM). Geralmente, o hardware de cada sistema embutido é confeccionado

especificamente para a aplicação em questão, com o objetivo de manter o custo baixo. Apesar disso,

os sistemas embutidos possuem algumas características comuns.

Em geral, os sistemas embutidos possuem um processador e um software. Mas para que o

software exista, deve haver um meio para armazenar o código executável e dados temporários gerados

em tempo de execução. O código geralmente é armazenado numa memória flash, que possui uma

maior velocidade de leitura que a EEPROM. Os dados temporários como passagem de parâmetros

para funções, são armazenados na memória RAM.

Entre as principais Características de Sistemas Embutidos que os diferenciam de computadores

tradicionais, podemos citar:

• Consumo de energia - Quanto maior for a freqüência de operação de um sistema, maior

será o consumo de energia, numa relação quadrática da freqüência. Como sistemas

embutidos são geralmente projetados para um fim especifico, a freqüência de operação

será somente a necessária para a execução da tarefa. Conseqüentemente, num sistema

embutido não se busca trabalhar com o maior “clock” possível. A quantidade de CI’s do

sistema também afeta o consumo de energia. Portanto, devem-se utilizar somente os

CI’s necessários para a aplicação.

• Baixo custo de produção - Para segmentos que trabalham com produção em massa de

sistemas embutidos, o custo de produção é um fator determinante e que passa pelos

projetistas do hardware e das exigências dos desenvolvedores do software contido no

sistema embutido. Ou seja: quanto maior o custo, maior será o preço do produto final. O

uso de poucos componentes proporciona uma redução das dimensões e do custo do

sistema embutido. Além disso, deve-se considerar o custo destes componentes para se

ter um custo total que seja o menor possível.

• Custo de desenvolvimento e “Time-to-Market” – Sistemas embutidos têm custo de

desenvolvimento menor que sistemas complexos feitos para PCs (jogos3D, sistemas

operacionais, etc), pois geralmente precisam de profissionais menos qualificados e as

ferramentas de desenvolvimento são mais baratas do que aquelas usadas nestes sistemas

complexos. Porém, este custo de desenvolvimento se torna pequeno no custo total caso

seja feita uma produção em massa do sistema embutido. O termo “Time-to-market” se

refere à quantidade de tempo necessária para um produto transitar da concepção até o

mercado ao qual ele é dirigido. Assim, quanto menor este tempo, menor será o custo de

desenvolvimento. O uso de ferramentas computacionais de apoio a projeto colabora

drasticamente para a redução deste tempo.

Page 18: desenvolvimento de software e hardware embutido para um sistema

9

• Quantidade produzida - A relação entre o custo de produção e o custo de

desenvolvimento é afetada pelo número de unidades a serem produzidas e vendidas. Por

essa razão, geralmente é indesejável desenvolver componentes de hardware

customizados para um baixo volume de produção. Por outro lado, para produção em

massa, pode ser útil a produção de componentes e ferramentas próprias personalizadas

para diminuir o custo de produção.

O desenvolvimento de sistemas embutidos, assim como outros sistemas, deve seguir uma

metodologia pré-estabelecida para gerar um produto com menores margens de erro e que atendam com

maior precisão seu objetivo. Uma metodologia de projeto é importante por três razões. Primeiro, ela

permite manter um registro do que deve ser realizado para garantir que todas as etapas sejam

executadas da melhor forma com menor tempo. Segundo, ela facilita a escolha de Softwares de auxílio

ao projeto, ao considerar somente uma etapa do processo. Terceiro, uma metodologia de projeto

facilita a comunicação entre os membros de uma equipe de desenvolvimento. A equipe pode

compreender mais facilmente o que deve ser feito, o que deve ser recebido de outras equipes e o que

ela deve realizar após o cumprimento da tarefa.

A figura 1 exibe as etapas de um processo de projeto para Sistemas Embutidos. No topo, há os

requisitos do sistema, onde é descrito o que o projeto deve realizar sem se especificar como. A etapa

de requisitos serve para capturar as necessidades do cliente. Após os requisitos, há a especificação do

projeto, onde é criada uma descrição mais detalhada com foco no comportamento do sistema para

compreensão da equipe de desenvolvimento. O detalhamento interno do sistema (como construir) é

iniciado no desenvolvimento da arquitetura, que fornece a estrutura do sistema em termos de

componentes. Uma vez que se conhecem os componentes necessários, pode-se projetar estes

componentes, incluindo software e algum hardware especializado que se faça necessário. Baseado

nestes componentes é realizada a integração do sistema, onde é construído o sistema completo.

Page 19: desenvolvimento de software e hardware embutido para um sistema

10

Figura 1 - Níveis de abstração do processo de desenvolvimento de sistemas embutidos

3.2 CARACTERÍSTICAS GERAIS DA FAMÍLIA DE MICROCONTROLADORES PIC UTILIZADA

Um microcontrolador é um dispositivo (single chip) que incorpora todos os componentes

básicos de um computador tradicional, em escala bastante reduzida. A principal conseqüência do

pequeno tamanho do microcontrolador é a limitação de seus recursos, se comparados com os

oferecidos por computadores tradicionais. Em termos funcionais, um microcontrolador é um

dispositivo programável que controla um processo ou sistema. Os microcontroladores são projetados

para possibilitar soluções de baixo custo e portanto, seu uso pode reduzir drasticamente o custo e o

tamanho físico de um projeto.

Os microcontroladores podem conter diversos periféricos, porém possuem algumas

características comuns. A primeira característica é uma memória não-volátil para armazenamento do

programa, sendo mais comum o uso da memória flash. Uma outra característica comum é uma

memória RAM para manipular dados em tempo de execução como vetores temporários e parâmetros.

Por fim, além dos periféricos presentes, há portas de E/S que fazem a comunicação com o meio

externo. Na figura 4 há um esquema simplificado do microcontrolador PIC 16F64 [13] que possui

interface serial, conversor A/D, temporizador, contador e watchdog timer; para ilustrar a discussão

feita até este momento.

Page 20: desenvolvimento de software e hardware embutido para um sistema

11

Figura 2 – Um esquema simplificado do microcontrolador 16F64

O desenvolvimento do software embutido para microcontroladores é realizado através de

computadores tradicionais que funcionam como plataformas de desenvolvimento onde, com os

recursos disponíveis, é possível editar, compilar e simular este software desenvolvido.

Além do desenvolvimento do software, a plataforma de desenvolvimento deve possibilitar a

programação do microcontrolador (ou carga do código objeto no microcontrolador) através de um

periférico, que é chamado de programador do dispositivo, o qual se conecta ao computador onde está o

código a ser gravado. Essa conexão pode ser feita de várias formas, porém as mais comum são o uso

das interfaces seriais RS-232 ou USB. A ligação entre o código a ser gravado e o programador que

contém o microcontrolador de destino é feita através de um software que carrega o código-objeto e

realiza a programação do dispositivo através de um protocolo estabelecido para tal. Este software é

chamado de programa de gravação do microcontrolador.

A depuração do programa carregado no microcontrolador não é tão simples, dispondo-se apenas

de impressões de variáveis no display para depurar. Existem sistemas de depuração, mas geralmente

são muito caros.

Page 21: desenvolvimento de software e hardware embutido para um sistema

12

Microcontroladores PIC - Peripherical Interface Controller- (PICmicro) é a denominação dada

à família de microcontroladores fabricados pela Microchip Technology com extensa variedade de

modelos e periféricos internos, com arquitetura Harvard e conjunto de instruções RISC. Os

microcontroladores PIC têm famílias de 12 bits, 14 bits e 16 bits de núcleo de processamento e

trabalham com velocidades desde 32KHz até 40 MHz usando ciclo de instrução de quatro períodos de

clock, o que permite uma velocidade de no máximo 10 MIPS. Os microcontroladores PIC funcionam

com tensões de alimentação de 2 a 6V, possuem de 6 a 100 pinos em diversos encapsulamentos

(SOT23, DIP, SOIC, TQFP, etc) e memória flash que pode ir de 4Kbytes à 128Kbytes.

Alguns recursos comuns em microcontroladores da linha PIC são:

• Watchdog timer - O watchdog timer consiste num contador incrementado

automaticamente quando habilitado e que, quando acontece o estouro do seu conteúdo

(passagem do mais alto valor para o mais baixo), o microcontrolador será resetado. Este

recurso é usado para evitar que o microcontrolador trave em situações não-previstas em

que o software embutido fica “preso”. Com isso, o sistema que emprega o

microcontrolador fica menos suscetível a falhas na execução do software.

• Brown-out detect - O circuito de brown-out presente em alguns modelos de

microcontroladores é utilizado para forçar um reset quando a tensão de alimentação

sofre uma pequena queda. Ele é extremamente recomendado em projetos onde é comum

o rápido desligamento e religamento da alimentação. Nestes casos, o brown-out pode

evitar problemas de reinicialização. Para que o microcontrolador execute suas

instruções com sucesso, a tensão de alimentação deve sempre ficar acima de um valor

mínimo. Quando essa tensão cai abaixo de um nível mínimo, o microcontrolador poderá

executar algumas instruções incorretamente. O resultado é uma atividade inesperada das

linhas e dados internos de controle, que pode causar perdas ou alterações nos registros e

estado das portas do microcontrolador. Para evitar estes problemas, o microcontrolador

deve ser impedido de executar suas tarefas nos períodos de tensão de alimentação

insuficiente. A melhor maneira de garantir isso é com o uso de um detector de baixa

tensão que força o microcontrolador a ficar em estado de reset enquanto a tensão não

ficar acima do mínimo desejável.

• Conversor A/D e comparador - Uma E/S analógica pode receber sinais analógicos

(geralmente níveis de tensão) e, através de periféricos internos; disponibilizar essa

informação na forma digital para uso pelo microcontrolador. Essa conversão analógico-

digital é geralmente feita através da representação digital do dado ou através da

comparação do sinal analógico com um nível de comparação estabelecido. Alguns

Page 22: desenvolvimento de software e hardware embutido para um sistema

13

microcontroladores disponibilizam saídas analógicas para controle de dispositivos que

se utilizam dessa forma de sinal.

• Periféricos para protocolos estabelecidos - Muitos microcontroladores possuem

periféricos que implementam protocolos padronizados. Assim, alguns

microcontroladores possuem recursos próprios para acessar dispositivos externos que

funcionam baseados em protocolos estabelecidos. Alguns dos protocolos encontrados

no hardware de microcontroladores são: I2C, Microwire, CAN, SPI, RS-232, RS-485,...

• Timer/Counter - Outro periférico muito comum em microcontroladores é o contador

que registra o número de vezes que ocorreu uma transição positiva ou negativa em um

pino de I/O do microcontrolador, podendo gerar uma interrupção quando ocorrer um

overflow no contador ou quando atingir um número determinado de transições. Um

timer é um contador que é incrementado ou decrementado numa taxa fixa dada pelo

circuito que gera o pulso de clock do microcontrolador, podendo gerar interrupções da

mesma forma que o contador. O timer é utilizado geralmente para contagem de tempo e

sincronismo. Em muitos microcontroladores o timer e o counter são periféricos que são

intercambiáveis, ou seja, um contador pode funcionar com timer ou vice-versa,

bastando que o mesmo seja configurado por software.

• Interrupções - Uma interrupção é um evento que suspende a operação regular do

programa enquanto o evento é atendido por um outro programa. A ocorrência de

interrupções aumenta a velocidade de resposta a eventos externos e evita a

monopolização do processador por um só processo. Os microcontroladores podem ter

diversas fontes de interrupções diferentes, que incluem: eventos externos, timer,

watchdog timer, brownout detect, etc. Quando uma interrupção é solicitada, a operação

corrente é suspensa, a interrupção é identificada e o microcontrolador executa uma

rotina de interrupção chamada ISR (interrupt service routine).

3.2.1 MICROCONTROLADORES UTILIZADOS NO PROJETO Desde o inicio dos anos 80, os fabricantes de microcontroladores têm lançado diversos

microcontroladores diferentes, com uma ampla variedade de recursos. A maioria destes

microcontroladores foi criada para atender demandas próprias dessas empresas por produtos que elas

comercializam ou são direcionados a segmentos específicos como telefonia celular, eletrodomésticos,

brinquedos, entre outros. Poucos projetos são dedicados a um uso mais geral.

A Microchip, que produz os microcontroladores PIC, se dedica ao projeto de

microcontroladores sem foco numa aplicação especifica. Por conta disso e da vasta documentação

Page 23: desenvolvimento de software e hardware embutido para um sistema

14

disponível no site da empresa (http://www.microchip.com/), várias ferramentas de desenvolvimento

para PIC’s foram produzidas e disponibilizadas gratuitamente na Internet.

• Microcontroladores 18F452 e 18F4620

O desenvolvimento deste projeto iniciou-se com o uso do PIC 18F452 [14], porém no decorrer

do projeto, o 18F452 apresentou pouca memória para acomodar todas as funções previstas no sistema

de estacionamento. Devido a isso, optou-se pelo uso do microcontrolador 18F4620 [15]. O 18F4620 é

bastante semelhante ao 18F452, sendo que, enquanto o 18F452 possui 16Kinstruções de memória de

programa, o 18F4620 possui 32Kinstruções de memória de programa. No entanto, o uso do 18F452

não foi totalmente descartado, pois o 18F452 é útil para outras aplicações que podem ser usadas no

mesmo hardware, sendo este hardware genérico o suficiente para outras aplicações. A comparação

entre estes dois PIC’s está representada na tabela 1 e na figura 3. Após isso, é feita uma descrição dos

principais recursos disponíveis nestes PIC’s.

Características PIC18F452 PIC18F4620

Freqüência máxima 40 MHz 40 MHz

Memória de programa (Bytes) 32K 64k

Memória de programa (instruções) 16384 32768

Memória de dados (Bytes) 1536 3968 EEPROM interna (Bytes) 256 1024 Portas de I/O Ports A, B, C, D, E Ports A, B, C, D, E Timers 4 4 Módulos Capture/Compare/PWM 2 2 Comunicação serial 1 USART 1USART Porta paralela escrava 1 PSP 1 PSP Módulo conversor A/D 8 canais de entrada de 10 bits 13 canais de entrada de 10 bits

Brown-out Reset programável Sim Sim Conjunto de instruções 75 instruções 83 instruções

Encapsulamento DIP com 40 pinos

PLCC com 44 pinos TQFP com 44 pinos

PDIP com 40 pinos PLCC com 44 pinos TQFP com 44 pinos

Tabela 1 – Características do 18F452 e 18F4620

Page 24: desenvolvimento de software e hardware embutido para um sistema

15

Figura 3 – Pinagem do 18F452 e do 18F4620

Alguns detalhes dos microcontroladores 18F452 e 18F4620 são:

• Configuração do oscilador - O 18F452 pode operar em oito modos diferentes de

oscilação programáveis pelo usuário e o 18F4620 em dez. São estes:

o LP: Cristal operando em baixas freqüências (32 kHz e 200 kHz)

o XT: Cristal operando em médias freqüências (1MHz e 4 MHz)

o HS: Cristal operando em altas freqüências (20 MHz e 40 Mhz)

o HS+PLL: Cristal operando junto com um PLL (phase locked-loop) interno para

multiplicar a freqüência de operação por 4 (útil para eliminar interferências

eletromagnéticas encontradas quando se fizer necessário)

o RC: Uso de um resistor e um capacitor para gerar o clock de operação

o RCIO: Uso de um resistor e um capacitor para gerar o clock de operação com

liberação do pino OSC2 do PIC para I/O digital

o EC: Clock gerado por algum circuito externo (útil para sincronizar sistemas)

o ECIO: Clock gerado por algum circuito externo com liberação do pino OSC2

para I/O digital.

o INTIO1: Clock de até 8 Mhz, gerado internamente pelo PIC (Menos preciso e

disponível apenas no 18F4620) com saída de clock em RA6 e I/O em RA7

o INTIO2: Clock de até 8 Mhz, gerado internamente pelo PIC (Menos preciso e

disponível apenas no 18F4620) com saída de clock em RA7 e I/O em RA6

• E/S - O 18F452 e o 18F4620 possuem cinco portas disponíveis. O 18F452 tem três

portas com oito bits, uma porta com seis bits e outro porta com três bits. O 18F4620 tem

quatro portas de oito bits e uma porta de quatro bits. Alguns pinos dessas portas são

Page 25: desenvolvimento de software e hardware embutido para um sistema

16

multiplexados com periféricos internos, como: I2C, USART, conversor A/D, etc. Em

geral, quando o periférico está habilitado para uso através de registradores, o pino não

pode ser usado como I/O de uso geral.

• Memória de programa flash - A memória flash, onde está o código executável, pode ser

lida, escrita e apagada durante a operação normal do 18F452 e do 18F4620. A memória

flash contida nestes microcontroladores pode ser lida byte a byte, escrita em blocos de

oito bytes e apagada em blocos de sessenta e quatro bytes. A operação de busca de

instrução é pausada enquanto a memória flash estiver sendo escrita ou apagada durante

a operação normal.

• EEPROM interna - A EEPROM interna dos dois PIC’s utilizados no projeto podem ser

lidas e escritas em operação normal e também escritas e lidas durante a programação do

dispositivo. Como observado na tabela 1, o 18F452 tem 256 bytes disponíveis na

EEPROM interna e o 18F4620 tem 1024 bytes.

• Timers/Counters - O 18F452 e o 18F4620 possuem quatro timers/counters

(temporizador/contador) que podem ser configurados com diferentes configurações. No

modo timer, o registrador associado ao timer é incrementado quando ocorrer um

determinado número de transições de clock que é determinado pelo valor do registrador

de prescale. No modo counter, o registrador é incrementado quando ocorrerem pulsos

em um pino estabelecido para este periférico.

• Módulo MSSP - O módulo MSSP (Master Synchronous Serial Port) é um periférico

presente no 18F452 e no 18F4620 útil para comunicação serial com outros dispositivos.

O módulo MSSP pode realizar essa comunicação utilizando o protocolo I2C ou o SPI.

• Módulo USART - O módulo USART (Universal Synchronous Asynchronous Receiver

Transmitter) é outro periférico destinado à comunicação serial presente no 18F452 e no

18F4620. O módulo USART pode ser configurado para realizar comunicação serial,

full-duplex e assíncrona, para enviar e receber dados de terminais e computadores

pessoais.

3.4 COMPONENTES EXTERNOS UTILIZADOS NO PROJETO

3.4.1 EEPROM 24C32 A EEPROM 24C32 [16] contém 32.768 bits organizados em 4096 palavras de 1 byte fornecidos

através do protocolo I2C. Podem ser conectados até 8 destes CIs no barramento, desde que sejam

identificados com configurações diferentes através dos pinos A0, A1 e A2.

Page 26: desenvolvimento de software e hardware embutido para um sistema

17

Na figura 4, os pinos VCC e GND fornecem a alimentação (+5V e 0V); os pinos A0, A1 e A2

fornecem uma identificação para múltiplas memórias conectadas no barramento I2C; os pinos SCL e

SDA são as linhas de clock e dados que devem ser conectado ao barramento I2C e o pino WP é a

proteção de escrita (desabilita escrita na EEPROM quando em nível “1”).

Figura 4 - Pinagem da EEPROM 24C32

A figura 5 exemplifica o endereço do 24C32. O primeiro nibble (4 bits mais significativos) é

fixo em 0x8 para identificar uma das EEPROM que podem estar conectadas ao barramento I2C. O

segundo nibble contém a identificação da EEPROM e a natureza da operação que será realizada

(leitura ou escrita).

Figura 5 – Identificação da EEPROM

Para escrita na EEPROM, o mestre do barramento deve enviar após a condição de início, o

endereço da EEPROM que será escrita com o último bit em nível “0” para identificar a operação como

escrita. Após o bit de reconhecimento da EEPROM, o mestre deve enviar dois bytes correspondentes à

posição em que o dado será escrito. Em seguida, é enviado o dado que será escrito. Caso o mestre

queira escrever dados consecutivos, basta enviar mais dados após a condição de reconhecimento, os

quais serão escritos seqüencialmente na EEPROM. Por fim, o mestre realiza uma condição de parada.

A leitura na EEPROM segue um procedimento parecido com a escrita. A diferença é o bit de

identificação da operação que é “1” para indicar uma leitura. A EEPROM envia os dados para o

mestre após o fornecimento do endereço de leitura pelo mestre. Caso o mestre deseje ler dados

seguidos na EEPROM, basta fornecer uma condição de reconhecimento. Para encerrar a leitura, ele

não executa essa condição de reconhecimento e realiza uma condição de parada.

3.4.2 RAM 62256 O CI 62256 [17] é uma memória RAM de 256KBits organizada em 32K palavras de 8 bits. De

acordo com a figura 6, além dos pinos de alimentação (VCC e VSS), a memória possui: barramento de

endereço (A0 à A13); barramento de dados (IO1 à IO8); habilitação de saída (OE); habilitação de

escrita (WE) e habilitação do CI (CE).

Page 27: desenvolvimento de software e hardware embutido para um sistema

18

Figura 6 – Pinagem do 62256

3.4.3 MAX 232 O RS-232 é uma interface definida pela EIA (Electrical Industries Association) e equivalente ao

CCITT-V24 para comunicação serial em que os níveis de tensão dos sinais transmitidos e recebidos

diferem do padrão TTL. O nível lógico 0 é definido como uma tensão de +3V à +12 V e o nível lógico

1 é definido como uma tensão entre -3V à -12V para dados. Para sinais de controle, uma tensão entre

+3V e +12V representa o nível lógico “1” e uma tensão entre –3V e –12V representa o nível lógico

“0”.

Uma interface de comunicação que segue o padrão RS-232 é importante para um sistema

microcontrolado porque seu uso é muito comum em computadores pessoais e sua utilização nestes

sistemas possibilita uma comunicação com estes computadores. No entanto, a grande maioria dos

sistemas microcontrolados segue padrões TTL, de forma que para se trabalhar com o padrão RS-232

deve ser usado um circuito que faça a conversão entre os padrões RS-232 e TTL. Tal circuito consiste

no MAX232, o qual transforma a fonte positiva de +5V em +5V e –5V, através de um oscilador e de

circuitos de chaveamento e é ilustrado na figura 7..

Page 28: desenvolvimento de software e hardware embutido para um sistema

19

Figura 7 – Diagrama do CI MAX232

3.4.4 PCF 8583 O PCF 8583 [18] é um chip RTC (Real-time clock) que armazena e atualiza a hora e a data com

base na oscilação de um cristal de 32.768 KHz. A escolha deste RTC produzido pela Philips, Inc

deveu-se ao fato de o PCF8583 usar o protocolo I2C para receber dados referentes a hora e a data e

fornecer a hora e a data atuais. Assim, é feita uma economia dos pinos usados no microcontrolador.

Um esquema prático de utilização do PCF8583 está na figura 8. Quando o circuito estiver

ligado, o PCF8583 é alimentado pela fonte deste circuito. Porém quando o circuito é desligado, a

alimentação é fornecida pela bateria BT1. Este chaveamento é feito pelos diodos D1 e D2. Além dos

pinos para o cristal oscilador (OSCI e OSCO), dos pinos de alimentação (VCC e GND) e dos pinos

referentes ao barramento I2C (SDA e SCL), há o pino INT que é ativo caso uma hora e uma data

programada estiver sido alcançada.

Caso a bateria no circuito da figura 8 acabe, deve se configurar a hora e a data todas as vezes

que se ligar o circuito, pois a memória RAM contida no PCF8583 apagará no desligamento do

sistema. Isso acontece até que a bateria seja trocada por uma nova.

Figura 8 – Esquema de utilização do PCF 8583

Page 29: desenvolvimento de software e hardware embutido para um sistema

20

3.4.4 LCD O visor LCD empregado é da Hitachi e apresenta uma interface de saída muito utilizada em

sistemas microcontrolados. Visores LCD são especificados pelo número de linhas e colunas que eles

possuem, havendo LCD’s com várias linhas e colunas. O visor utilizado apresenta 2 linhas por 40

colunas.

Os módulos podem ser encontrados com LED backlight (com uma iluminação de fundo) para

facilitar sua leitura. Neste caso, a alimentação deste LED faz-se normalmente pelos pinos 15 e 16. A

corrente de alimentação deste LED varia de 100 a 200mA, dependendo do modelo.

Estes módulos utilizam um controlador próprio chamado HD44780 [19]. Este controlador

estabelece uma comunicação com o sistema microcontrolado e executa a ação requerida no LCD

propriamente dito. A tabela 2 fornece uma descrição da pinagem padrão do LCD.

Pino Função Descrição

1 Alimentação Terra ou GND 2 Alimentação VCC (+5 v) 3 V0 Tensão para ajuste de contraste através de um potenciômetro

ligado a este pino. 4 RS Seleção: 1 - Dado, 0 - Instrução 5 R/W Seleção: 1 - Leitura, 0 - Escrita 6 E Chip select 1 - Habilita, 0 - Desabilitado 7 B0 LSB 8 B1

9 B2

10 B3

11 B4

12 B5

13 B6

14 B7 MSB

Barramento de Dados

15 A (qdo existir) Anodo p/LED backlight 16 K (qdo existir) Catodo p/LED backlight

Tabela 2 – Pinagem padrão do LCD

Comandos são enviados para o controlador HD44780 através do barramento de dados. Esta

comunicação pode ser feita byte a byte ou nible (4 bits) a nible. Caso seja usada a comunicação nible a

nible, utilizam-se somente os pinos 7 ao pino 10 do barramento, havendo uma economia de pinos de

E/S do microcontrolador.

Page 30: desenvolvimento de software e hardware embutido para um sistema

21

3.3 PROTOCOLOS UTILIZADOS NO PROJETO

3.3.1 PROTOCOLO I2C O I2C é um protocolo síncrono de duas linhas, sendo uma linha de clock (chamada SCL) e outra

linha de dados (chamada de SDA). Graças à especificação das saídas em coletor (ou dreno) aberto, o

protocolo permite a ligação de diversos componentes nas mesmas linhas, formando uma rede de

comunicação de dispositivos. A quantidade de dispositivos que podem ser conectados no barramento é

limitada apenas pela capacitância máxima admitida que é de 400pF segundo a especificação. Como

todos os dispositivos conectados ao barramento estão em paralelo, cada um deles adiciona uma

capacitância definida pelo seu circuito.

O I2C é um protocolo síncrono do tipo mestre-escravo, mas também suporta multi-mastering,

ou seja, a presença de diversos mestres presentes no barramento, sendo que somente um pode estar

ativo por vez.

Os princípios de funcionamento do I2C são:

• A informação presente na linha de dados (SDA) somente é lida durante a fase alta da

linha de clock (SCL);

• Somente é permitido alterar o nível da linha de dados (SDA) durante a fase baixa da

linha de clock (SCL);

• Quando o barramento não está em uso, ambas as linhas permanecem desligadas e são

forçadas em nível “1” pelos resistores de pull-up.

No início da transmissão, o dispositivo força a linha SDA de “1” para “0”, durante a fase alta da

linha SCL, indicando a todos os componentes presentes no barramento que uma transmissão terá

início. Este processo é chamado de condição de início. O fim da transmissão (condição de parada)

consiste na transição de “0” para “1” da linha SDA durante a fase alta da linha SCL.

Após a condição se início, são transmitidos oito bits de dados, iniciando pelo MSB. Após o

último bit (LSB) o receptor deve gerar uma condição de reconhecimento, o que é feito colocando a

linha SDA em “0” antes do nono pulso de clock da linha SCL. Caso o receptor não reconheça o dado,

mantendo a linha SDA em “1” após o nono pulso, o transmissor deve gerar uma condição de parada e

reiniciar a transmissão.

Para a coexistência de diversos dispositivos em um mesmo barramento, é necessário que cada

um possua uma identificação. O formato básico de uma identificação I2C é constituída por 7 bits de

endereço, utilizados para especificar o dispositivo escravo a ser acessado e, após essa identificação

segue-se um bit identificador de leitura ou escrita.

Page 31: desenvolvimento de software e hardware embutido para um sistema

22

Dessa forma, após o envio da identificação do escravo pelo mestre e da condição de

reconhecimento pelo escravo, o mestre pode enviar e receber dados do escravo. Terminada a

comunicação, segue-se uma condição de parada. Este processo é demonstrado na figura 9.

Figura 9 – Comunicação I2C

3.3.2 PROTOCOLO DE COMUNICAÇÃO PARA TECLADO PS/2 O protocolo para comunicação com o teclado PS/2 é um protocolo serial, síncrono e

bidirecional. Ou seja, o teclado pode enviar informações para o computador e o computador pode

enviar informações para o teclado serialmente através de uma linha de dados, a qual é chamada de

KBD_DATA. O sincronismo é feito através de uma linha de clock, que é chamada de KBD_CLOCK.

Ambas as linhas são conectadas a resistores de pull-up.

A alimentação para o teclado é provida pelo conector, de forma que além das linhas

KBD_DATA e KBD_CLOCK, o conector tem duas linhas para alimentação (+5V e terra), que é

fornecida pelo computador.

O teclado pode enviar informações para o computador sempre que as linhas KBD_CLOCK e

KBD_DATA estiverem em nível “1” pelos resistores de pull-up. Caso o computador coloque a linha

KBD_CLOCK em nível “0”, o teclado cria um buffer com as informações que devem ser enviadas ao

computador até que o mesmo termine de enviar. Isso acontece porque o computador tem prioridade na

comunicação.

De acordo com a figura 10, a transmissão de informações do teclado para o computador é

realizada através de 11 bits transmitidos pela linha KBD_DATA e sincronizados por KBD_CLOCK

numa freqüência de 20 kHz a 30 kHz estabelecida pelo teclado. O primeiro bit transmitido pelo

teclado é o bit de início (nível “0”), seguido por 8 bits de dados ou comandos (do LSB até o MSB).

Após os dados, segue-se um bit de paridade (paridade impar) e um bit de parada em nível “1”. Cada

bit é lido pelo computador na transição de descida do clock gerado pela linha KBD_CLOCK.

Page 32: desenvolvimento de software e hardware embutido para um sistema

23

Figura 10 – Comunicação do teclado com o computador

De acordo com a figura 11, quando o computador precisa enviar comandos para o teclado, ele

coloca a linha KBD_CLOCK em nível “0” por aproximadamente 60us. Após isso, o computador

coloca a linha KBD_DATA em nível “0” e libera a linha KBD_CLOCK para que o teclado gere o

clock. Após a primeira transição de descida do clock, o computador envia os 8 bits de comando (do

LSB até o MSB) seguido pelo bit de paridade (paridade ímpar). Após o bit de paridade, o computador

libera a linha KBD_DATA e aguarda o bit de reconhecimento do comando provido pelo teclado na

próxima transição de descida.

Figura 11 – Comunicação do computador com o teclado

Dentre os comandos enviados para o teclado estão: acender ou apagar LED’s de status do

teclado (NUM LOCK, CAPS LOCK e SCROLL LOCK), estabelecer taxa de repetição da digitação do

teclado, habilitar ou desabilitar o teclado e reiniciar o teclado.

Além dos códigos das teclas pressionadas ou soltas, o teclado pode enviar comandos para

indicar certas situações para o computador como: reconhecimento de comandos, erro ou estouro de

buffer e pedido de reenvio de comando.

3.4 SOFTWARES E PROGRAMADORES DE MICROCONTROLADORES UTILIZADOS NO PROJETO

3.4.1 SOFTWARES UTILIZADOS O aumento do poder de processamento dos computadores e a criação de linguagens de alto nível

têm proporcionado a criação de sofwares cada vez mais rápidos e sofisticados. Estes fatores

ocasionaram uma maior difusão de softwares produzidos com o intuito de auxiliar projetos.

Page 33: desenvolvimento de software e hardware embutido para um sistema

24

Os softwares utilizados neste trabalho consistem de:

• Compilador CCS [20] – Este compilador foi utilizado inicialmente no

desenvolvimento do sistema e oferece algumas vantagens em relação ao compilador

HITECH PICC-18 descrito a seguir, como por exemplo, possuir algumas bibliotecas

para LCD, para EEPROM, RTC, etc. No entanto, ele não é um compilador ANSI-C.

Além disso, ele se mostrou ineficaz na geração de algumas funções. Por exemplo, a

função delay_ms() é implementada in-line em vez de chamar uma rotina, gerando um

enorme número de NOPS para atrasos grandes, e gastando memória

desnecessariamente.

• Compilador HITECH PICC-18 [21] – Este é um compilador C para

microcontroladores da linha PIC pertencentes a família PIC18. O HITECH PICC-18

Compiler é um compilador ANSI-C que possui integração com o MPLAB, que é um

ambiente de desenvolvimento integrado (IDE) fornecido pela Microchip. Este

compilador se mostrou mais eficiente que o CCS.

• Simulador ISIS Proteus [22] – Para a construção do esquemático e a simulação inicial

do sistema foi utilizada a ferramenta ISIS Proteus. Este software possui bibliotecas

com microcontroladores PIC, LCD’s, EEPROM’s, RTC’s, etc; disponíveis para projeto

e simulação, sendo possível carregar o código gerado pelo compilador no componente

do microcontrolador no ISIS Proteus e simular sua iteração com os outros

componentes. Além disso, o ISIS Proteus permite depurar o código, acompanhando

passo-a-passo como o código interage com o microcontrolador e outros componentes

do projeto. O ISIS PROTEUS foi usado no início do projeto e, posteriormente, não foi

mais possível usá-lo porque ele não simulava todos os componentes empregados.

• IDE MPLAB [23] - O MPLAB é um ambiente de desenvolvimento integrado para

compiladores baseados em microcontroladores PIC. O MPLAB é desenvolvido pela

Microchip e possui compatibilidade com o compilador HITECH PICC 18, facilitando

sua utilização. O MPLAB possui um editor de códigos e permite depurar o código

gerado, além de permitir programação direta do PIC.

• Programador ASIX UP [24] – O software de programação ASIX UP faz a

comunicação com o programador Presto que está conectado ao microcontrolador PIC e

conecta-se ao computador através da interface USB. Este software permite carregar o

código-objeto gerado pelo compilador e enviá-lo ao programador do microcontrolador,

o qual realiza a gravação deste código nele.

Page 34: desenvolvimento de software e hardware embutido para um sistema

25

3.4.2 PROGRAMADOR UTILIZADO Para realizar a programação dos microcontroladores utilizados no projeto foram necessários

dispositivos que fizessem a gravação do programa a ser executado nos microcontroladores. Estes

dispositivos consistem nos programadores.

O programador utilizado no início do projeto foi o McFlash desenvolvido pela Mosaico

Engenharia, Ltda. Este programador não abrange uma grande gama de PIC’s, porém programa o

18F452, que foi o primeiro PIC utilizado no projeto. No entanto, ao se optar pelo PIC 18F4620, o

McFlash teve que ser substituído pelo programador PRESTO, que é comercializado pela ASIX, Inc. O

Presto é um dispositivo de gravação via USB e dentro da gama de componentes que o Presto pode

gravar, encontram-se: Microcontroladores PIC, ATMEL e AVR, além de EEPROMs seriais (24LCxx,

93LCxx e 25Cxx). A gama de microcontroladores PIC com que este programador trabalha é bem

maior que a do McFlash e abrange o 18F4620. Além disso, este programador permite a gravação In-

Circuit, eliminando a necessidade de retirada do circuito para programação do microcontrolador.

3.5 UML A UML é a linguagem padrão para especificar, visualizar, documentar e construir artefatos de

um sistema e pode ser utilizada com todos os processos ao longo do ciclo de desenvolvimento e

através de diferentes tecnologias de implementação [25].

A UML disponibiliza uma forma padrão de modelagem de projetos de Sistemas, incluindo seus

aspectos conceituais, tais como: processos de negócios e funções do sistema, além de itens concretos

como as classes escritas em determinada linguagem de programação, processos de banco de dados e

componentes de software reutilizáveis.

Dentro da especificação UML foi utilizada no projeto a análise de requisitos, onde se capturam

as intenções e necessidades dos usuários do sistema a ser desenvolvido. A análise de requisitos

descreve as necessidades e desejos de um determinado sistema. O princípio básico da análise de

requisitos é identificar e documentar o que é realmente necessário, desta forma comunicando a todos

os envolvidos no projeto, da forma mais clara possível, de maneira não-ambígua os requisitos de modo

que os possíveis riscos sejam identificados. Um exemplo de parte da descrição do sistema utilizando a

análise de requisitos é apresentado no capítulo 4

Page 35: desenvolvimento de software e hardware embutido para um sistema

4 CONCEPÇÃO E PROJETO DO SISTEMA

4.1 INTRODUÇÃO Este capítulo apresenta a concepção e o projeto do sistema como um todo (software+hardware),

iniciando pela apresentação e descrição das funções operacionais e dos requisitos de um sistema de

estacionamento. O sistema de estacionamento foi desenvolvido pela equipe do grupo de pesquisa em

Sistemas Embutidos do NCE/UFRJ, do qual também participaram os alunos do curso de ciência da

computação: Daniel da Cunha Schmidt, Raphael Azevedo Silva e Vinicius Santos Silva. O nosso

papel no software foi participar na elaboração do documento de especificação de requisitos em UML e

prover todas as funções básicas de entrada e saída do sistema. Esta aplicação foi escolhida por ser

razoavelmente complexa para testar o hardware apresentado, incluindo a implementação de um

sistema de arquivos tipo FAT baseado numa implementação feita para o Zilog [26].

4.2 FUNÇÕES E REQUISITOS DE UM SISTEMA DE ESTACIONAMENTO A etapa inicial na concepção do sistema de estacionamento consistiu em analisar as

funcionalidades que devem ser executadas por um sistema de estacionamento e, através dessas

funcionalidades, realizar uma análise mais profunda delas, onde são gerados o fluxo normal e as

exceções da função, ou seja, os possíveis fluxos diferentes do fluxo normal de execução da função

analisada. Este processo é chamado de Análise de Requisitos e foi desenvolvido através de reuniões,

onde a equipe envolvida no projeto do estacionamento discutia e executava essa etapa inicial.

Paralelamente a este processo, surgiram termos que, para evitar ambigüidade, foram definidos em um

glossário para posterior consulta. Este glossário encontra-se no apêndice C e seu uso é importante para

entendimento das funções e dos requisitos gerados. A seguir, está a lista dos requisitos analisados, os

quais foram implementados no sistema de estacionamento.

Requisitos sucintos que o sistema deve atender:

1. Operador do terminal libera a entrada de um cliente do estacionamento no pátio.

2. Operador do terminal libera a saída de um cliente do estacionamento.

3. Operador do terminal realiza abertura de caixa.

4. Operador do terminal realiza entrada de caixa.

5. Operador do terminal realiza saída de caixa.

6. Operador do terminal lista os automóveis presentes no pátio.

7. Operador do terminal lista a tabela de preços.

8. Operador do terminal troca o nível de acesso (operador/gerente/root).

Page 36: desenvolvimento de software e hardware embutido para um sistema

27

9. Operador do terminal imprime a tabela com códigos das marcas.

10. Gerente inclui itens na tabela de marcas.

11. Gerente remove itens na tabela de marcas.

12. Gerente edita itens na tabela de marcas.

13. Gerente inclui novos clientes mensalistas no sistema.

14. Gerente remove clientes mensalistas do sistema.

15. Gerente edita cadastro de clientes mensalistas.

16. Gerente configura a tabela de preços.

17. Gerente configura o cabeçalho e o rodapé dos tickets de entrada, saída e recibo.

18. Gerente configura a data e a hora do Sistema.

19. Gerente inclui operadores no sistema.

20. Gerente edita o cadastro de operadores do sistema.

21. Gerente remove operadores do sistema.

Requisitos detalhados:

Para ilustrar o detalhamento existente no documento de requisitos, que se encontra no apêndice

D, segue-se a descrição dos requisitos 2 e 18.

• Requisito2:

Fluxo normal:

o O display exibe:

Entrada:

Placa: Cod.Marca:

o O operador digita a placa do automóvel e pressiona “enter”;

o O operador digita o código de 3 dígitos associado a marca do automóvel;

o Assim que o operador digita o código de 3 dígitos da marca do automóvel o sistema

exibe, após o código digitado, a marca associada;

o O operador verifica que a marca do automóvel está correta e pressiona “enter”;

o O sistema imprime o ticket de entrada;

Page 37: desenvolvimento de software e hardware embutido para um sistema

28

Exceções:

o A placa digitada pelo operador é incorreta.

Ação: o campo Placa no display é limpo e o sistema fica esperando o operador

digitar uma nova placa.

o O código de marca digitado pelo operador é incorreto, i.e., o código digitado não está

cadastrado na tabela de marcas.

Ação: o sistema exibe logo à frente o campo Marca a mensagem Código Inválido e

fica esperando o operador digitar um novo código.

o O operador verifica que o código digitado não confere com a marca exibida no display

pelo sistema.

Ação: operador pressiona “Backspace“. O sistema limpa o campo Marca. O

operador digita um novo código de marca e pressiona “enter”.

o O operador tenta dar entrada em um automóvel que já está no pátio.

Ação: O sistema exibe a mensagem: Automóvel já no estacionamento; O operador

pressiona “enter” ou “backspace”; Sistema apaga os campos Placa e Marca e espera

o operador digitar uma nova Placa e Marca.

o O operador digita um Código de Mensalista no campo Placa.

Ação: O sistema exibe a mensagem: Mensalista? (S/N)

O operador digita S ou s.

Ação: O sistema associa o código à placa da tabela de mensalistas, dá entrada e

imprime o ticket de entrada.

O operador digita N ou n.

Ação: O sistema apaga os campos Placa e Marca e espera o operador digitar uma

nova Placa e Marca.

Observações:

o Como entrada para o campo placa o sistema aceita apenas uma seqüência de no

mínimo 2 (automóveis antigos) e no máximo 3 letras seguida por 4 algarismos ou

apenas 4 algarismos (entrada pelo código do mensalista).

o Como entrada para o campo Cod.Marca o sistema aceita apenas uma seqüência de 3

algarismos.

o Modelo de relatório de Ticket de Entrada: ver Glossário

Page 38: desenvolvimento de software e hardware embutido para um sistema

29

• Requisito 18:

− O sistema permite um máximo de 5 linhas de cabeçalho e 3 linhas de rodapé. A fonte pode

ser impressa em tamanho normal (padrão da impressora, máximo de 40 caracteres).

Fluxo Normal:

o O display exibe:

Cabeçalho 1:

o O gerente digita o texto para o cabeçalho 1 e pressiona “enter”;

o O display exibe:

Cabeçalho 2:

o O gerente digita o texto para o cabeçalho 2 e pressiona “enter”;

o O display exibe:

Cabeçalho 3:

O gerente digita o texto para o cabeçalho 3 e pressiona “enter”;

o O display exibe:

Cabeçalho 4:

O gerente digita o texto para o cabeçalho 4 e pressiona “enter”;

o O display exibe:

Cabeçalho 5:

O gerente digita o texto para o cabeçalho 5 e pressiona “enter”;

o O display exibe:

Rodapé 1:

O gerente digita o texto para o rodapé 1 e pressiona “enter”;

o O display exibe:

Rodapé 2:

O gerente digita o texto para o rodapé 2 e pressiona “enter”;

o O display exibe:

Rodapé 3:

O gerente digita o texto para o rodapé 3 e pressiona “enter”;

− Durante a digitação dos campos Cabeçalho1-5 e Rodapé1-3, o sistema aceita apenas

seqüências alfanuméricas de pelo menos 3 caracteres.

Page 39: desenvolvimento de software e hardware embutido para um sistema

30

4.3 REQUISITOS DE HARDWARE DO SISTEMA DE ESTACIONAMENTO Com um entendimento inicial do sistema pronto e tendo as especificações do projeto, pode-se

iniciar a seleção dos componentes de hardware que devem ser utilizados para suprir as necessidades

do projeto e prever aplicações mais complexas, de forma que o hardware proposto possa também ser

usado em outras aplicações.

Os componentes de hardware necessários para atender o sistema de estacionamento são:

EEPROM: Pela análise dos requisitos, conclui-se que o hardware deve possuir um meio de

armazenamento permanente para guardar informações sobre: operadores, gerentes, carros no pátio, etc.

Para essa finalidade, foi escolhida a EEPROM serial 24C32 que, como discutido anteriormente,

funciona sob o protocolo I2C e tem capacidade de armazenar 4Kbytes de dados. Essa memória por ser

serial, possui a vantagem de economizar pinos de E/S para uso futuro e, funcionando sob o protocolo

I2C, pode ter outros componentes conectados nos mesmos pinos de E/S.

Teclado PS/2: O teclado PS/2 é utilizado para realizar entrada de dados, como por exemplo, a

placa do automóvel que está entrando no pátio. Seu uso, comparado a um teclado matricial, é mais

eficaz, pois todos os caracteres alfanuméricos já estão no teclado PS/2 e a construção de um teclado

matricial com todos estes caracteres seria bastante dispendiosa. Além disso, teclados compatíveis com

teclados de PC têm custo muito baixo hoje em dia.

LCD: O LCD é usado para exibição de mensagens direcionadas pelo PIC. Sua utilidade aplica-

se a visualização de informações, como a hora e a data registrada no RTC. O LCD possui um

controlador especializado chamado HD44780, que controla todas as funções a serem executadas pelo

LCD, dando um maior controle e inteligência ao seu uso, se comparado com outros visores de baixo

custo, como por exemplo, um vetor de displays de 7 segmentos.

Interface paralela: A interface paralela serve para impressão de relatórios e dos tickets

necessários ao sistema de estacionamento, como por exemplo, o ticket de entrada que o cliente recebe

do operador. A opção da interface paralela para impressão deve-se a facilidade de se achar impressoras

que funcionam sob este barramento.

RTC PCF8583: O RTC serve para armazenar e atualizar a hora e a data a serem utilizadas no

sistema de estacionamento. A hora e a data atual são informações úteis para cálculo do tempo de

permanência do cliente no estacionamento. O chip escolhido para essa função é o PCF8583 e suas

vantagens são as mesmas discutidas no componente 24C32 (economia de E/S).

Page 40: desenvolvimento de software e hardware embutido para um sistema

31

4.4 REQUISITOS BÁSICOS DE UM S.E. PARA USO GERAL A criação de um S.E. de uso geral deve levar em conta algumas das considerações já feitas

sobre sistemas embutidos, como baixo consumo e tamanho reduzido e, ao mesmo tempo, ter

capacidade de memória flash, EEPROM, RAM e diferentes interfaces de E/S. Observa-se que um

sistema de uso geral normalmente possui muitas interfaces para atender diferentes aplicações. Por

outro lado, o uso de várias interfaces contrasta com as considerações já feitas sobre sistemas

embutidos. Em vista disso, este projeto usa os componentes externos que se mostraram necessários

para atender a aplicação escolhida.

Um sistema de uso geral normalmente possui entradas e saídas e meios de armazenamento

permanente. Para o sistema proposto, foram implementados os seguintes recursos:

• LCD

A figura 12 ilustra a ligação elétrica feita do LCD com o PIC. O resistor R4, ligado entre VCC e

o pino RA4 é um resistor de pull-up e, seu uso é necessário porque o pino fica em dreno aberto quando

configurado como I/O digital. O potenciômetro serve para regulagem de contraste que é feita

variando-se a tensão no pino 3 do LCD. Além disso, são usados somente os pinos D4, D5, D6 e D7 no

barramento de dados/comando do LCD, significando que a comunicação do LCD com o PIC é feita

nibble a nibble para proporcionar economia E/S no PIC.

Os sinais de controle do LCD são: RS, R/W e E. O sinal RS é usado para diferenciação entre

dado ou comando transmitido (1 - Dado, 0 – Instrução); o sinal R/W seleciona entre escrita ou leitura

(1 - Leitura, 0 – Escrita) e o sinal E (Enable) habilita ou desabilita o LCD (1 ou 1 → 0 - Habilita, 0 –

Desabilita).

A figura 13 ilustra o diagrama de tempo do ciclo de escrita do LCD. Caso o LCD esteja

configurado para comunicação usando somente os pinos D4 à D7, serão necessários 2 ciclos de escrita

ou leitura para transmissão ou recebimento de dados e comandos. Um ciclo de leitura é realizado da

mesma forma que o ciclo de escrita, mas com o sinal R/W em nível “1” na transição do nível “1” para

o nível “0” do enable. Os valores dos tempos na figura 13 encontram-se na tabela 3.

Page 41: desenvolvimento de software e hardware embutido para um sistema

32

Parâmetro Símbolo Min Max Enable Cycle Time tc 500 - Enable Pulse Width (High) tw 230 -

Enable Rise/Fall Time tr,tf - 20 Address Setup Time tas 40 - Address Hold Time tah 10 - Data Setup Time tds 80 Data Hold Time th 10 -

Tabela 3 – Valores típicos do diagrama de tempo do LCD medidos em nanosegundos

Figura 12 – Ligação do PIC com o LCD

Page 42: desenvolvimento de software e hardware embutido para um sistema

33

Figura 13 – Diagrama de tempo do ciclo de escrita do LCD

• Teclado PS/2

A figura 14 ilustra a ligação elétrica feita entre o conector do teclado PS/2 com o PIC. Segundo

a especificação do protocolo, é recomendável que os pinos KBD_CLOCK e KBD_DATA possuam

resistores de pull-up por causa de alguns teclados que possuem essas linhas em coletor aberto. Além

da linha de dado (KBD_DATA) e a linha de clock (KBD_CLOCK), o pino de conexão do teclado

possui alimentação que deve ser fornecida pelo circuito externo para funcionamento do teclado. O

diagrama de tempo da comunicação do computador com o teclado encontra-se na figura 11 e o

diagrama de tempo da comunicação do teclado com o computador está na figura 10.

Figura 14 – Ligação do PIC com o teclado PS/2

Page 43: desenvolvimento de software e hardware embutido para um sistema

34

• 24C32 e PCF8583

A figura 15 ilustra a ligação elétrica entre o PIC e os CIs 24C32 (EEPROM) e PCF8583 (RTC).

Estes dois CI’s funcionam sob o barramento I2C, razão pela qual possuem a linha de dado e de clock

em comum (SCL e SDA). Além disso, são necessários resistores de pull-up nas linhas SCL e SDA,

porque os dois CI’s estão em coletor aberto, segundo a especificação do protocolo I2C.

Os endereços I2C padrão do 24C32 é 0x51 para leitura e 0x50 para escrita (O LSB identifica a

operação como sendo de leitura ou de escrita), que são os mesmos endereços I2C do PCF8583. Este

problema foi resolvido colocando-se o pino A0 do 24C32 em nível “1” para que ele possua endereço

0x52 para leitura e 0x51 para escrita. Os pinos A0, A1 e A2 do 24C32 possuem pull-down interno, de

forma que não é necessário ligar os pinos A2 e A3 ao terra.

O diagrama de tempo dos dispositivos I2C está na figura 16. A freqüência máxima especificada

nos manuais do 24C32 e no PCF8583 para a freqüência no barramento é 100 khz.

Figura 15 – Ligação do PIC com o 24C32 e o PCF8583

Figura 16 – Diagrama de tempo dos dispositivos I2C

Page 44: desenvolvimento de software e hardware embutido para um sistema

35

• MAX 232

A figura 17 demonstra a comunicação feita entre o PIC e um dispositivo externo usando o

conversor MAX232. Através da figura, verifica-se a existência de um bit de início (start bit), que é

seguido por 8 bits (do LSB ao MSB) e, por fim, a comunicação encerra-se com o bit de parada (stop

bit).

A figura 18 ilustra a ligação elétrica do MAX232 com o PIC. O MAX232 está localizado entre

o PIC e o conector DB-9 para fazer a conversão dos níveis de tensão do padrão TTL para o padrão RS-

232 e vice-versa.

Figura 17 – Comunicação serial no MAX232

Figura 18 – Ligação do PIC com o MAX232

• Memória 62256

A figura 19 ilustra a ligação elétrica da memória RAM externa 62256 com o PIC. Para

endereçar 32 Kbytes (que correspondem a 256Kbits) é necessário um barramento de endereço de 15

bits, conforme consta no CI 62256 na figura 6 e na figura 19. Como o barramento de dados possui 8

bits, teriam de ser usados 23 pinos do PIC para acrescentar a memória RAM externa. Este problema é

contornado usando latchs 74LS373 para multiplexar o barramento de dados, os 8 bits menos

significativos do barramento de endereço e os 7 bits mais significativos do barramento de endereço.

Assim, é usado o port D tanto para o barramento de dados como para o barramento de endereço. O

Page 45: desenvolvimento de software e hardware embutido para um sistema

36

pino LE_L habilita o latch que conterá os 8 bits menos significativos do barramento de endereço e o

pino LE_H habilita o latch que conterá os 7 bits mais significativos do barramento de endereço.

A figura 20 ilustra o diagrama de tempo de leitura da memória 62256 e a figura 21 ilustra o

diagrama de escrita. Os tempos destes diagramas estão descriminados na tabela 4.

Figura 19 – Ligação do PIC com a memória externa 62256

Figura 20 – Diagrama de tempos de leitura na memória 62256

Page 46: desenvolvimento de software e hardware embutido para um sistema

37

Figura 21 – Diagrama de tempos de escrita na memória 62256

Parâmetro Símbolo Min Max Read cycle time tRC 70 -

Address access time tAA - 70

Chip select to output tCO - 70

Output enable to valid output tOE - 35

Chip select to low-Z output tLZ 10 -

Output enable to low-Z output tOLZ 5 -

Chip disable to high-Z output tHZ 0 30

Output disable to high-Z output tOHZ 0 30

Leitura

Output hold from address change tOH 5 -

Write cycle time tWC 70 -

Chip select to end of write tCW 60 -

Address set-up time tAS 0 -

Address valid to end of write tAW 60 -

Write pulse width tWP 50 -

Write recovery time tWR 0 -

Write to output high-Z tWHZ 0 25

Data to write time overlap tDW 30 -

Data hold from write time tDH 0 -

Escrita

End write to output low-Z tOW 5 -

Tabela 4 – Valores dos tempos dos diagramas da memória 62256

• Interface paralela

A ligação do PIC com a interface paralela está ilustrada na figura 22. A interface paralela, que é

usada pra conectar uma impressora no hardware, possui um barramento de dados (D0 à D7) e sinais de

controle (BUSY e strobe). Apesar de haver outros sinais de controle disponíveis na interface paralela

Page 47: desenvolvimento de software e hardware embutido para um sistema

38

Centronics, somente estes sinais de controle são usados para se ter um controle econômico da

impressora.

De acordo com o diagrama de tempos da figura 23, o PIC lê o estado da linha BUSY para

verificar se a impressora está com seu buffer cheio. Caso não esteja, o PIC escreve um dado no

barramento de endereço e aplica um pulso de duração não inferior a 1uS em STROBE. Depois,

verifica novamente o estado da linha BUSY.

Figura 22 – Ligação do PIC com a interface paralela

Page 48: desenvolvimento de software e hardware embutido para um sistema

39

Figura 23 – Diagrama de tempos da interface paralela

Os componentes e suas ligações descritas acima formam o sistema aqui concebido e projetado

que está ilustrado na figura 24. Além das ligações dos componentes externos, o PIC possui um botão

de reset realizado pelo pino 1 do PIC (MCLR), além da conexão de um cristal para o oscilador interno

do PIC.

Page 49: desenvolvimento de software e hardware embutido para um sistema

40

Figura 24 – Diagrama esquemático do hardware projetado

Page 50: desenvolvimento de software e hardware embutido para um sistema

5 IMPLEMENTAÇÃO E RESULTADOS

5.1 INTRODUÇÃO Este capítulo apresenta uma descrição da implementação do hardware do sistema, mostrando a

construção da placa lógica com tecnologia wire-wrapp, descrevendo as interconexões dos principais

módulos e o empacotamento utilizado.

Além da implementação do hardware, este capítulo descreve a implementação do software da

aplicação escolhida, a qual foi realizada no laboratório de Sistemas Embutidos do NCE/UFRJ e que

consiste num sistema de estacionamento.

5.2 IMPLEMENTAÇÃO DO SOFTWARE Para dar suporte ao hardware foram desenvolvidas bibliotecas com funções definidas para

manipular os componentes eletrônicos explicados anteriormente. Desta forma, cada componente terá

uma biblioteca associada a ele que realizará a sua manipulação pelo PIC. O apêndice A contém a

listagem destes arquivos com as funções pertinentes.

Para facilitar o desenvolvimento foi feito um manual de uso das bibliotecas dos componentes de

E/S cuja descrição se encontra no apêndice B. A seguir será feita uma descrição resumida das funções

de software implementadas para o sistema de estacionamento. Podem ser encontrados maiores

detalhes no manual apresentado no apêndice B.

Timer 0 (DELAY_TIMER.C)

Para contagem de tempo foi usado o TIMER0 do PIC, que consiste num temporizador de 16

bits. A listagem deste arquivo está no apêndice A e contém as seguintes funções.

• void init_tmr0(int value): A função init_tmr0 inicializa o timer0. A variável Value

recebe o valor do prescale para o timer0.

• void delay_tmr0(int value): Atribui 65536-value para o TMR0, inicia a contagem do

timer0 e aguarda o overflow. Ou seja, a função realiza uma contagem definida pela

variável value e pelo prescale.

Display de Cristal Líquido (LCD.C)

A manipulação o LCD é implementada pelo arquivo lcd.c, que contém as funções que enviam

comandos para o LCD executar. A listagem deste arquivo está no apêndice A e contém as seguintes

funções:

• void lcd_init(void): Inicializa o LCD.

Page 51: desenvolvimento de software e hardware embutido para um sistema

42

• void lcd_cursor(lcd_cursor_type): Muda o cursor do LCD. O tipo lcd_cursor_type é

composto dos seguintes valores: lcd_cursor_on, lcd_cursor_off, lcd_cursor_blink,

lcd_cursor_alternate.

• void lcd_gotoxy( byte x,byte y): Posiciona o cursor na coluna x e linha y no LCD.

• void lcd_erase(lcd_direction dir,byte n): Apaga n bytes na direção dir (right ou left são

os valores possíveis para o tipo lcd_direction).

• void lcd_erase_all(void): Apaga todo o conteúdo do visor do LCD.

• byte lcd_getc(byte x,byte y): Obtém o caracter que se encontra na coluna x, linha y do

LCD.

• void lcd_moven(lcd_direction direc,char n): Move o cursor n vezes numa direção.

• void lcd_putch(unsigned char): Imprime um caracter no visor do LCD.

Teclado PS/2 (KEYBOARD.C)

O protocolo de comunicação com o teclado PS/2 é implementado no arquivo keyboard.c, que

fornece as funções básicas para entrada de dados pelo teclado. A listagem deste arquivo está no

apêndice A, e contém a s seguintes funções:

• unsigned char kbd_getc(): Retorna um caracter pela entrada do teclado. Sendo válidos

números, letras e teclado de funções.

• void kbd_gets(char string[], unsigned char lenght): Retorna um vetor de char chamado

string com tamanho máxino length pelo teclado, exibindo os caracteres no LCD.

Memória RAM externa (62256.C)

O acesso à memória RAM externa é feita através do arquivo 62256.c. Esta biblioteca realiza as

funções para escrita e leitura na memória RAM externa. A listagem deste arquivo está no apêndice A e

contém as seguintes funções:

• void ram_Init(void): Incializa a RAM. Este comando deve ser usado antes de qualquer

instrução de utilização da RAM.

• void ram_Cursor(unsigned int address): Coloca addres no barramento de endereço da

RAM.

• unsigned char ram_ReadByte(unsigned int address): Retorna um byte lido no endereço

address.

• void ram_WriteByte(unsigned char value,unsigned int address): Grava um byte value

no endereço address.

Page 52: desenvolvimento de software e hardware embutido para um sistema

43

• void ram_SequentialWrite(char *val,unsigned int initial_address): Realiza uma escrita

sequencial do vetor de char val iniciando em initial_address.

• void ram_SequentialRead(char *val,unsigned int initial_address,unsigned int size):

Realiza uma leitura sequencial colocando no vetor de char val de initial_address até

initial_address+size.

Interface I2C (I2C_MASTER.C)

O arquivo i2c_mater.c possui funções para configurar o módulo MSSP (Master Synchronous

Serial Port) para o protocolo I2C no modo mestre e funções de leitura e escrita dos registradores do

módulo MSSP. A listagem deste arquivo está no apêndice A e contém as seguintes funções:

• void i2c_init(unsigned char ssp_add): Esta função configura o módulo MSSP para o

protocolo I2C no modo mestre e especifica a freqüência do pino SCL pelo parâmetro da

função ssp_add.

• char i2c_start(unsigned char i2c_address): Executa uma condição de início no

barramento I2C e envia o endereço do dispositivo cujo acesso este sendo solicitado e

designado pelo parâmetro address (endereço do dispositivo). Caso o dispositivo

responda, a função retona verdadeiro, caso contrário retona falso.

• char i2c_restart(unsigned char i2c_address): Inicia a repetição da condição de início do

barramento I2C e envia o endereço do dispositivo cujo acesso este sendo solicitado e

designado pelo parâmetro address (endereço do dispositivo). Caso o dispositivo

responda, a função retona verdadeiro, caso contrário retona falso.

• char i2c_read(unsigned char ack): Executa uma leitura do dispositivo selecionado

através da função i2c_start ou i2c_restart e retorna a leitura realizada. Após executar a

leitura executa a condição de reconhecimento dada pelo parâmetro ack (1 ou 0).

• char i2c_write( unsigned char i2cWriteData): Executa uma escrita no dispositivo

selecionado através da função i2c_start ou i2c_restart. Após executar a escrita a função

retona o reconhecimento da escrita do dispositivo acessado (1-Dispositivo reconhece a

transmissão; 0-Dispositivo não reconhece a transmissão).

• void i2c_stop(): Executa uma condição de parada no barramento I2C.

Page 53: desenvolvimento de software e hardware embutido para um sistema

44

EEPROM 24C32 (24CXX.C)

As funções direcionadas à EEPROM 24C32 estão no arquivo 24cxx.c. Essa biblioteca faz uso

da biblioteca i2c_master.h que contém as funções para manipulação da interface I2C do PIC. A

listagem deste arquivo está no apêndice A e contém as seguintes funções:

• void i2c_eepromWrite(char device,int address, char data): Escreve o caracter data no

endereço address no dispositivo device, onde device é um identificador da memória no

caso de uso de múltiplas memórias do mesmo tipo.

• char i2c_eepromReadCurrent(char device): Retorna um byte lido no endereço currente

no dispositivo device.

• void i2c_eepromCursor(char device,int i2c_address): Posiona o cursor de endereço do

dispositivo device no endereço i2c_address.

• void i2c_eepromPageWrite(char device,int address, char *data,unsigned char size_str):

Escreve um vetor de char que tenha no máximo 12 posições iniciando no endereço

address, no dispositivo device com tamanho size_str.

RTC PCF8583 (PCF8583.C):

O arquivo pcf8583.c contém o código usado para manipular o RTC PCF8583. Essa biblioteca

faz uso da biblioteca i2c_master.h que contém as funções para manipulação da interface I2C do PIC.

A listagem deste código está no apêndice A e contém as seguintes funções:

• void write8583_rtc(struct Time *t, struct Date *d, BYTE address_reg): Ajusta a hora e

a data do RTC ou o alarme do mesmo através das estruturas Time e Date.

• void read8583_rtc(struct Time *t, struct Date *d, BYTE address_reg): Lê a data e a

hora do RTC ou o alarme do mesmo através de Date e Time.

• void configure8583_control_reg(BYTE control_reg): Configura o reg. de controle do

RTC.

• void configure8583_alarm_reg(BYTE alarm_reg): Configura o registrador de alarme do

RTC.

Impressora matricial (PRINTER.C):

O arquivo printer.c contém as funções para uso da impressora matricial. A listagem deste código

está no apêndice A e contém as seguintes funções:.

• void printer(unsigned char c): Esta função imprime um caracter pela impressora

matricial.

Page 54: desenvolvimento de software e hardware embutido para um sistema

45

• void prn_printf(const char *str): Esta função imprime uma string pela impressora

matricial.

Sistema de Arquivos FAT para EEPROM (FILE.C, FILEINIT.C e FILECONF.H):

Os arquivos file.c, fileinit.c e fileconf.h contêm as funções necessárias para implementar uma

versão compacta do sistema de arquivos FAT para a EEPROM. O uso dessa biblioteca faz com que a

EEPROM fique transparente, sendo necessário somente criar, abrir, ler, escrever e fechar arquivos

usando as funções implementadas para o sistema de arquivos. A listagem destes códigos está no

apêndice A. e contém as seguintes funções:

• char fcreate(char name[], char tag): Esta função cria um novo arquivo na EEPROM,

tendo como parâmetro o nome do arquivo a ser criado, onde o tamanho máximo é de até

8 caracteres. Um campo tag indica se o arquivo será seqüencial ou será um arquivo de

registros (0-Arquivo sequencial ; N-Arquivo de registros, onde N é o tamanho de cada

registro). O arquivo de registros, ao contrário do arquivo seqüencial, possui campos de

tamanho fixo.

• char ferase(char name[]) : Apaga o arquivo da EEPROM. Retorna “1” caso o arquivo

não exista e “0” em caso de sucesso.

• int fexist(char name[]) : Procura pelo arquivo na tabela de arquivos da EEPROM.

Retorna “1” se o arquivo não for encontrado e, caso o arquivo exista, retorna o índice do

arquivo na tabela.

• FILE* fopen(char name[], char mode): Abre um arquivo na EEPROM. Retorna 0 caso

nenhum arquivo seja encontrado ou se não houver mais espaço na tabela de arquivo. Se

o arquivo for encontrado, retorna sua entrada na tabela de arquivos aberta. O arquivo

pode ser aberto nos seguintes modos através do parâmetro mode: FM_APPEND –

Insere dados no fim do arquivo e FM_RDWR – Lê ou escreve no início do arquivo.

• int fclose(FILE *pf): Fecha um arquivo previamente aberto e retorna “0” se a operação

for bem-sucedida ou “1” caso contrário. O parâmetro pf é um ponteiro para o arquivo

aberto.

• int fread(void bfr[],int size, FILE *pf): Executa uma leitura de um arquivo aberto. O

parâmetro bfr é uma variável que recebe os dados lidos, size é o número de bytes a

serem lidos e pf é um ponteiro para o arquivo a ser lido.

• int fwrite(char bfr[],int size,FILE *pf): Executa uma escrita em um arquivo aberto. O

parâmetro bfr é uma variável que recebe os dados a serem escritos, size é o número de

bytes a serem escritos e pf é um ponteiro para o arquivo.

Page 55: desenvolvimento de software e hardware embutido para um sistema

46

Programa principal (ESTACIONAMENTO.C e MENUS.C)

O arquivo estacionamento.c é o código principal executado pelo PIC. Este código contem as

inicializações dos componentes externos utilizados e após isso faz chamada a rotina menus(), que está

no arquivo menus.c. O arquivo menus.c possui as rotinas com a estrutura dos menus exibidas no LCD

e a implementação dos requisitos já discutidos. A listagem desses arquivos encontra-se no apêndice A.

5.3 IMPLEMENTAÇÃO DO HARDWARE Para que fosse portátil, buscou-se construir o sistema numa embalagem bem pequena e leve, o

que foi conseguido com uma caixa de plástico com dimensões 12 cm x 12 cm x 7 cm, A versão final

ideal será um teclado pequeno, como o de um notebook com um display junto às teclas de função e a

placa eletrônica sob o teclado.

A figura 25 mostra o sistema dentro da caixa de plástico com a impressora, teclado PS/2 e o

programador Presto conectados. A ligação destes periféricos com a placa desenvolvida compõe o

sistema proposto neste relatório com todas as exigências discutidas para atender a implementação de

um sistema de controle de estacionamento.

Figura 25 – Sistema final implementado

A figura 26 mostra a visão de frente do compartimento do projeto com conectores para porta

serial, porta paralela, teclado PS/2, potenciômetro para ajuste do contraste do LCD e botão de reset.

Page 56: desenvolvimento de software e hardware embutido para um sistema

47

Figura 26 – Visão de frente do sistema

A figura 27 mostra a visão lateral direita do sistema com indicações do conector do Power LED

da placa que se liga a um cabo com LED na outra ponta localizado no painel frontal. A figura 26

também indica o conector do programador do PIC que se liga ao Presto na outra ponta.

Page 57: desenvolvimento de software e hardware embutido para um sistema

48

Figura 27 – Visão lateral direita do sistema

A figura 28 ilustra a visão frontal do sistema com as seguintes conexões:

• Conector da porta paralela em que é ligado um cabo cuja outra ponta é conectada a

porta paralela localizada no painel do sistema.

• Conector para LCD, onde é ligado um cabo conectado a um LCD na outra ponta.

• Conector da porta serial, onde é ligado um cabo conectado a um conector DB-9.

Page 58: desenvolvimento de software e hardware embutido para um sistema

49

Figura 28 – Visão frontal do sistema

A figura 29 ilustra a visão lateral esquerda do sistema com as seguintes conexões:

• Conector do teclado PS/2 que se liga a um cabo cuja outra ponta está localizada no

painel frontal onde é conectado o teclado PS/2

• Conector do potenciômetro para ajuste do contraste do LCD que se liga a um cabo com

um potenciômetro na outra ponta

• Conector de alimentação que se liga a um cabo cuja outra ponta está localizada no

painel frontal e recebe a alimentação provida por uma fonte.

• Conector do botão de reset da placa que se liga a um cabo cuja outra ponta está ligado o

botão de reset localizado no painel frontal

Page 59: desenvolvimento de software e hardware embutido para um sistema

50

Figura 29 – Visão lateral esquerda do sistema

A figura 30 ilustra a disposição dos componentes na placa eletrônica do sistema. Os

componentes mostrados na figura são:

• PIC 18F4620 para controle do sistema

• 2 CIs 74LS244 usados para isolar a porta paralela do 18F4620, protegendo o PIC.

• 2 CIs 74LS373 para uso da memória RAM 62256 conforme discutido anteriormente

• MAX232 para conversão do nível TTL para o RS232

• RTC PCF8583 para manipulações da data e da hora

• EEPROM 24C32 para armazenamento de dados

• Bateria de Lítio para preservação da hora e da data do PCF8583

• Cristal oscilador para geração do clock do 18F4620

• Banco dos resistores usados no sistema

• Cristal de 32,768 KHz usado pelo RTC

• LM7805 usado para regulação da alimentação

• Banco de capacitores usados pelo MAX232

• Conectores para ligação dos periféricos

Page 60: desenvolvimento de software e hardware embutido para um sistema

51

Figura 30 – Disposição dos componentes na placa do sistema

5.4 RESULTADOS Nesta seção são demonstradas algumas das listagens obtidas com o sistema implementado.

A figura 31 mostra uma listagem de marcas cadastradas no sistema de estacionamento. Essa

listagem possui: O código da marca, a classe do automóvel e a descrição deste.

Figura 31 – Tabela de marcas cadastradas

Page 61: desenvolvimento de software e hardware embutido para um sistema

52

A figura 32 mostra uma tabela de preços configurada no sistema para automóveis de classe 1,

relacionando o preço de acordo com o tempo de permanência do cliente no estacionamento.

Figura 32 – Tabela de preços para automóveis de classe 1

A figura 33 ilustra um ticket de entrada no estacionamento com a hora e a data de entrada, a

marca do automóvel que entrou e sua placa, bem como o cabeçalho e o rodapé previamente

configurados no sistema.

Figura 33 – Ticket de entrada

A figura 34 mostra a listagem dos automóveis presentes no pátio do estacionamento numa

determinada hora e data. A listagem do pátio contém a placa, o tipo do cliente (A-Avulso, M-

Mensalista), o código da marca, a hora e a data de entrada no pátio.

Figura 34 – Listagem do pátio

Page 62: desenvolvimento de software e hardware embutido para um sistema

53

A figura 35 mostra o ticket de saída do estacionamento com a hora e a data de saída, tempo de

permanência e o valor pago, além do cabeçalho e do rodapé previamente configurados. No caso em

questão, o cliente ficou no pátio tempo menos que o tempo de desistência, não pagando nada.

Figura 35 – Ticket de saída

Page 63: desenvolvimento de software e hardware embutido para um sistema

6 CONCLUSÕES

6.1 RESUMO DO TRABALHO Este trabalho final de graduação apresentou a concepção, projeto e implementação de um

sistema embutido com hardware suficientemente genérico para ser usado em diversas aplicações. Para

testar o hardware foi desenvolvida uma aplicação que consiste em um sistema de controle de

estacionamento, que é razoavelmente complexa para avaliar os diversos componentes do circuito. O

projeto descrito é uma contribuição ao desenvolvimento de outros Sistemas Embutidos, uma vez que

foram apresentadas as diversas etapas do projeto, desde a concepção inicial até a implementação final

do sistema.

O desenvolvimento deste trabalho envolveu o estudo de diversas tecnologias, tais como:

• Análise de requisitos em UML;

• Estudo de Sistemas embutidos de uma forma geral;

• Microcontroladores PIC;

• Programação em linguagem C e ambientes de desenvolvimento para PIC;

• Protocolos de entrada e saída como I2C, teclado PS/2, protocolo LCD, protocolo RS-

232;

• Gravação de PICs com vários programadores;

• Conexão de EEPROM e “Real-time Clock” (RTC) a microcontrolador PIC;

• Construção de hardware usando “Wire-wrapp”.

O sistema descrito neste trabalho possibilita:

• Comunicação serial com outro computador;

• Impressão usando a interface paralela Centronics;

• Manipulação de um LCD de 2 linhas e 40 colunas;

• Manipulação de um teclado PS/2;

• Ajuste e atualização automática da data e da hora usando o RTC PCF8583;

• Manipulação de uma RAM externa de 256KBits (62256);

• Manipulação de uma EEPROM externa de 32KBits (24C32).

O software descrito neste trabalho é composto de 2 camadas que são as rotinas básicas e a

aplicação. As rotinas básicas fazem parte deste trabalho e consistem de:

Page 64: desenvolvimento de software e hardware embutido para um sistema

55

• Rotinas para o teclado;

• Rotinas para impressão;

• Rotinas para LCD;

• Rotinas para EEPROM;

• Rotinas para RTC;

• Rotinas para porta serial;

• Rotinas para I2C.

A aplicação desenvolvida consiste de um sistema para controle de estacionamento e permite,

entre outras coisas:

• Gerenciar clientes mensalistas;

• Cadastrar usuários do sistema;

• Cadastrar cabeçalho e rodapé do ticket.

• Cadastrar a entrada no pátio;

• Liberar a saída do pátio fornecendo ticket de saída e recibo caso seja solicitado;

• Listar os automóveis presentes no pátio;

• Gerenciar as marcas dos automóveis;

• Gerenciar a tabela de preços;

• Gerenciar a hora e a data do sistema;

6.2 PRINCIPAIS DIFICULDADES Durante o andamento deste trabalho foram encontradas várias dificuldades decorrentes da

escolhas de tecnologias que mais tarde se mostraram ineficazes para se alcançar o objetivo proposto

neste trabalho. As principais foram:

• A escolha do compilador CCS, que se mostrou ineficiente para códigos com tamanho

considerável, pois não executava uma boa otimização e não atendia ao padrão ANSI-C.

Um exemplo disto foi a rotina de delay_ms, em que o CCS expandia “in-line” ao invés

de usar loop. Este problema foi solucionado com a escolha do compilador HITECH-

PICC18 Compiler, após análise de compiladores para microcontroladores PIC.

Page 65: desenvolvimento de software e hardware embutido para um sistema

56

• Com o crescimento do código, o microcontrolador 18F452 se mostrou incapaz de

armazenar o código necessário ao sistema, tendo que ser feita uma busca de

microcontroladores PIC semelhantes ao 18F452, mas com maior memória. A opção

escolhida foi o PIC 18F4620.

• A escolha do 18F4620 trouxe dois problemas: O compilador e o programador. O

compilador escolhido (HITECH-PICC18) não tinha suporte para o 18F4620 por ser a

versão 8.30, sendo substituída pela versão 8.35 do compilador que dava suporte ao

18F4620. O programador McFlash também teve que ser trocado pelo Presto por não

dar suporte ao 18F4620.

• Adicionalmente, o programador Presto solucionou um problema do programador

McFlash, pois o Presto, ao contrário do McFlash, possibilita a gravação do PIC In-

Circuit. Assim, ele diminui o risco de quebra dos pinos do PIC e da maior eficiência ao

desenvolvimento, pois não há mais a perda de tempo ocasionada pela retirada e

colocação do PIC na placa.

• Tentou-se usar um PIC com mais memórias flash e RAM que o 18F4620, que foi o

18F6420. Porém, este PIC possui um encapsulamento PLCC, que dificultava seu uso e,

além disso, o programador não suportava este PIC.

6.3 CONCLUSÕES Os principais objetivos estabelecidos no início deste trabalho foram plenamente atingidos,

sendo o principal deles a disponibilização de um sistema embutido de uso geral validado por uma

aplicação de controle de estacionamento.

As principais conclusões do sistema que podem ser tiradas deste trabalho são:

• Sistemas Embutidos simples podem ser utilizados para resolver problemas

razoavelmente complexos utilizando eletrônica barata e normalmente mais confiável

que computadores tradicionais. O fato de geralmente não possuírem dispositivos com

partes móveis, como por exemplo, discos rígidos, aumenta muito a confiabilidade destes

sistemas.

• O sistema projetado pode ser perfeitamente utilizado em um sistema móvel, devido ao

seu tamanho reduzido e ao seu baixo consumo de energia.

• Programar Sistemas Embutidos em uma linguagem de alto nível como C, aumenta

muito a produtividade e torna mais fácil uma migração para outro sistema, caso seja

necessário.

Page 66: desenvolvimento de software e hardware embutido para um sistema

57

• O custo de ferramentas de desenvolvimento, como compiladores e simuladores ainda é

elevado, principalmente em se tratando das boas ferramentas.

• O sistema ISIS-PROTEUS mostrou-se bastante útil nas etapas iniciais do trabalho, pois

ele permitiu simular o processador PIC em conjunto com alguns periféricos. Com o

aumento da complexidade do sistema, o ISIS-PROTEUS não dispunha de plugins para

simular os novos componentes, como por exemplo, o teclado PS/2.

• O projeto foi extremamente importante na minha formação, pois me permitiu trabalhar

com software de alto nível e um hardware, ampliando substancialmente minhas chances

de empregabilidade e, ao mesmo tempo, me dando uma boa visão do que eu poderia

fazer como micro-empresário.

6.4 TRABALHOS FUTUROS Como desdobramento em trabalhos futuros, sugere-se que sejam adicionados alguns novos

requisitos e expandidos requisitos existentes. Um exemplo de requisito que pode ser expandido é em

relação aos clientes mensalistas, que podem ter uma data limite de pagamento cadastrada no sistema e,

caso não quitassem suas dívidas até a data limite, sua entrada no estacionamento não seria permitida.

A expansão deste requisito criaria outros requisitos, como a impressão da listagem dos mensalistas

inadimplentes.

Além disso, sugere-se a adição de novos componentes no hardware. Tais como:

1. A inclusão de uma interface IRDA para comunicação sem-fio com outros sistemas;

2. A inclusão de uma interface USB seria útil para comunicação com outros sistemas que

possuem essa interface que esta se tornando extremamente popular;

3. Interface ZigBee 802.15.4 e protocolos;

4. Interface de rede Ethernet via conector RJ-45.

Page 67: desenvolvimento de software e hardware embutido para um sistema

58

BIBLIOGRAFIA UTILIZADA

BOOCH, G.; RUMBAUGH, J. & JACOBSON, I. UML: Guia do usuário. Rio de Janeiro: Campus, 2000.

PALTOR, I.; LILUS, J. A case study on designing embedded systems using the UML notation. Finland: Turku

Centre for Computer Science, 1999.

CHAPMAN, M. The final word on the 8051. London: E-book gratuito, 1994.

PEREIRA, F. PIC: Programação em C. São Paulo: Érica, 2003.

SOUZA, D. Desbravando o PIC. São Paulo: Érica, 2000.

PREDKO, M. Programming and customizing PICmicro microcontrollers. Toronto, Canadá: M. books, 1999.

ZELENOVSKY, R.; MENDONÇA, A. PC: um guia prático de Hardware e Interfaceamento. Rio de Janeiro:

MZ Editora, 1999.

Page 68: desenvolvimento de software e hardware embutido para um sistema

59

REFERÊNCIAS

[1] AMORY, A. PETRINI, J. Sistema integrado e multiplataforma para controle remoto de

residências. PUC-RS. Projeto final de curso. Disponível por WWW em., consultado em Agosto de

2006.

[2] FRIEDRICH, E. Sistema de Síntese de Voz Microcontrolado Portátil. UNICENP. Projeto

final de curso. Disponível por WWW em http://www.

http://engcomp.unicenp.br/engcomp/UserFiles/File/ProjFinais/2004_SinteseVoz_Elcio.pdf,

consultado em Agosto de 2006.

[3] ADÁRIO, A. M. S. ; BOGO, R. C. ; GRACIOLLI, T. G. . Implementação de um Sistema

Embarcado para Automação de Estacionamentos Utilizando o Microcontrolador 8051. In:

Salão de Iniciação Científica da UFRGS, 2003, Porto Alegre. Anais do XV Salão de Iniciação

Científica da UFRGS. Porto Alegre : UFRGS, 2003. p. 114.

[4] LATREILLE, G. Uma implementação de Sistema Microcontrolado para Aparelho de

Áudio MP3.UNOESC. Projeto final de graduação. Disponível por WWW em

http://www.geocities.com/gilvanl. Consultado em Agosto de 2006.

[5] FERREIRA, E. F.; ARNOLD, F. J. Alarme Residencial microcontrolado. CESET-

UNICAMP. Projeto de iniciação científica. Disponível por WWW em

http://scholar.google.com.br/url?sa=U&q=http://www.prp.unicamp.br/pibic/congressos/xiiicongres

so/paineis/023603.pdf. Consultado em Agosto de 2006.

[7] INTEL, INC. MCS-51 Microcontrollers Classic. Disponível por WWW em

http://www.intel.com/design/mcs51/docs_mcs51.htm. Consultado em Agosto de 2006.

[8] PHILIPS, INC. The I2C-Bus specification. . Disponível por WWW em http://www.semiconductors.philips.com/acrobat_download/literature/9398/39340011.pdf#search=%22I2C%20specification%22 . Consultado em Agosto de 2006.

[9] ARM, INC. MCS-51 Microcontrollers Classic. Disponível por WWW em

http://www.arm.com/documentation/books/1183.html . ARM Architecture reference manual.

Consultado em Agosto de 2006.

Page 69: desenvolvimento de software e hardware embutido para um sistema

60

[10] FREESCALE SEMICONDUCTORS, INC. M68HC11 Reference manual. Disponível por

WWW em

http://www.freescale.com/files/microcontrollers/doc/ref_manual/M68HC11RM.pdf#search=%22M

68HC11%20reference%20manual%22 .Consultado em Agosto de 2006.

[11] MICROCHIP TECHNOLOGY, INC. Getting started with PIC microcontrollers. Disponível

por WWW em

http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2551 .Consultado

em Agosto de 2006.

[12] BOSCH, INC. Controller Area Network. Disponível por WWW em

http://www.semiconductors.bosch.de/en/20/can/index.asp .Consultado em Agosto de 2006.

[13] MICROCHIP TECHNOLOGY, INC. PIC16F84. Disponível por WWW em

http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1335&dDocNam

e=en010229.Consultado em Agosto de 2006.

[14] MICROCHIP TECHNOLOGY, INC. PIC18F452. Disponível por WWW em

http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1335&dDocNam

e=en010296 .Consultado em Agosto de 2006.

[15] MICROCHIP TECHNOLOGY, INC. PIC18F4620. Disponível por WWW em

http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1335&dDocNam

e=en010304.Consultado em Agosto de 2006.

[16] ATMEL CORPORATION, INC. AT24C32. Disponível por WWW em

http://www.atmel.com/dyn/products/product_card.asp?part_id=3792. Consultado em Agosto de

2006.

[17] DATASHEETARCHIVE. Datasheet do 62256 Disponível por WWW em

http://www.datasheetarchive.com/search.php?q=62256&sType=part&ExactDS=Starts . Consultado

em Agosto de 2006.

Page 70: desenvolvimento de software e hardware embutido para um sistema

61

[18] Philips, Inc. Datasheet do RTC PCF8583. Disponível por WWW em

http://www.semiconductors.philips.com/pip/PCF8583_5.html . Consultado em Agosto de 2006.

[19] Spark fun Electronics, Inc. Datasheet do processadro HD44780. Disponível por WWW em

http://www.sparkfun.com/datasheets/LCD/HD44780.pdf . Consultado em Agosto de 2006.

[20] CCS ,Inc. CCS PIC-C Compiler. Disponível por WWW em

http://www.ccsinfo.com/product_info.php?cPath=Store&products_id=PCH_full. Consultado em

Agosto de 2006.

[21] HI-TECH Software ,Inc. HI-TECH PICC-18 Compiler. Disponível por WWW em

http://www.htsoft.com/products/pic18ccompiler.php . Consultado em Agosto de 2006.

[22] LABCENTER Electronics, Inc. Simulador PROTEUS. Disponível por WWW em

http://www.labcenter.co.uk/index_uk.htm . Consultado em Agosto de 2006.

[23] MICROCHIP TECHNOLOGY, Inc. MPLAB Quick start guide. Disponível por WWW em

http://ww1.microchip.com/downloads/en/DeviceDoc/51281F.pdf . Consultado em Agosto de 2006.

[24] ASIX PIC-TOOLS, Inc. PRESTO USB Programmer. Disponível por WWW em

http://www.pic-tools.com/prg_presto.htm . Consultado em Agosto de 2006.

[25] FURLAN, J. DAVI. Modelagem de objetos através da UML. São Paulo, Makron Books:

1998.

[26] ELECTRONICS ENGINEERING TIMES. Using na eZ80 Memory File System. Disponível

por WWW em http://www.eetasia.com/ART_8800336573_499486_7ba16f96200405.HTM

. Consultado em Agosto de 2006.

[27] TURLEY, JIM. The two percent solution. Embedded.com - Thinking inside the box.

Disponível por WWW em

http://www.eetasia.com/ART_8800336573_499486_7ba16f96200405.HTM . Consultado

em Agosto de 2006.

Page 71: desenvolvimento de software e hardware embutido para um sistema

62

APÊNDICE A – LISTAGEM DO CÓDIGO DESENVOLVIDO

DELAY_TIMER.C:

/* Routines for delay using Timer 0 Developed by NCE/UFRJ Registers and flags used in delay_timer T0CON: The T0CON register is a readable and writable register that controls all the aspects of Timer0, including the prescale selection. bit 7 TMR0ON: Timer0 On/Off Control bit 1 = Enables Timer0 0 = Stops Timer0 bit 6 T08BIT: Timer0 8-bit/16-bit Control bit 1 = Timer0 is configured as an 8-bit timer/counter 0 = Timer0 is configured as a 16-bit timer/counter bit 5 T0CS: Timer0 Clock Source Select bit 1 = Transition on T0CKI pin 0 = Internal instruction cycle clock (CLKO) bit 4 T0SE: Timer0 Source Edge Select bit 1 = Increment on high-to-low transition on T0CKI pin 0 = Increment on low-to-high transition on T0CKI pin bit 3 PSA: Timer0 Prescaler Assignment bit 1 = TImer0 prescaler is NOT assigned. Timer0 clock input bypasses prescaler. 0 = Timer0 prescaler is assigned. Timer0 clock input comes from prescaler output. bit 2-0 T0PS2:T0PS0: Timer0 Prescaler Select bits 111 = 1:256 prescale value 110 = 1:128 prescale value 101 = 1:64 prescale value 100 = 1:32 prescale value 011 = 1:16 prescale value 010 = 1:8 prescale value 001 = 1:4 prescale value 000 = 1:2 prescale value TMR0IE: TMR0 Overflow Interrupt Enable bit. TMR0IE is the bit 5 of the INTCON Refister. The INTCON register configures the interrupts. 1 = Enables the TMR0 overflow interrupt 0 = Disables the TMR0 overflow interrupt TMR0L: Timer 0 Register Low Byte TMR0IF: TMR0 Overflow Interrupt Flag bit. Bit 2 of the INTCON register. 1 = TMR0 register has overflowed (must be cleared in software) 0 = TMR0 register did not overflow */ #ifndef _DELAY_TIMER_H #define _DELAY_TIMER_H #endif #define PRE_SCALE_2 0x00 #define PRE_SCALE_4 0x01 #define PRE_SCALE_8 0x02 #define PRE_SCALE_16 0x03 #define PRE_SCALE_32 0x04 #define PRE_SCALE_64 0x05 #define PRE_SCALE_128 0x06 #define PRE_SCALE_256 0x07 #define NO_SCALE 0x08

Page 72: desenvolvimento de software e hardware embutido para um sistema

63

void init_tmr0(unsigned char); void delay_tmr0(unsigned int); void init_tmr0(unsigned char value) { T0CON=value; TMR0IE=1; } void delay_tmr0(unsigned int value) { unsigned int temp; temp=65536-value; TMR0H=temp>>8; TMR0L=temp&0x0F; TMR0IF=0; TMR0ON=1; while (!TMR0IF); TMR0ON=0; TMR0IF=0; } #define delay_tmr0_inline(value) \ int temp;\ temp=65536-value; \ TMR0H=temp>>8;\ TMR0L=temp&0x0F;\ TMR0IF=0;\ TMR0ON=1;\ while (!TMR0IF);\ TMR0ON=0;\ TMR0IF=0;\ #endif

LCD.C:

#ifndef _LCD_H #define _LCD_H #ifndef BITNUM #define BITNUM(adr, bit) ((unsigned)(&adr)*8+(bit)) #endif #ifndef BITTEST # define BITTEST(var,bit) ((var & (1<<bit)) != 0) #endif typedef unsigned char byte; typedef enum {lcd_cursor_on,lcd_cursor_off,lcd_cursor_blink,lcd_cursor_alternate} lcd_cursor_type; typedef enum {left,right} lcd_direction; // 0=5x7 1=5x10 2=2lines #ifndef LCD_TYPE #define LCD_TYPE 2 #endif #ifdef USE_NO_PORT_LCD #ifndef LCD_EN #error LCD_EN not defined #endif #ifndef LCD_RS #error LCD_RS not defined #endif #ifndef LCD_RW #error LCD_RW not defined #endif #ifndef LCD_D4 #error LCD_D4 not defined #endif #ifndef LCD_D5 #error LCD_D5 not defined

Page 73: desenvolvimento de software e hardware embutido para um sistema

64

#endif #ifndef LCD_D6 #error LCD_D6 not defined #endif #ifndef LCD_D7 #error PIN_D7 not defined #endif #define PIN_EN LAT##LCD_EN #define TRIS_EN TRIS##LCD_EN #define PIN_RS LAT##LCD_RS #define TRIS_RS TRIS##LCD_RS #define PIN_RW LAT##LCD_RW #define TRIS_RW TRIS##LCD_RW #define PIN_D4 LAT##LCD_D4 #define TRIS_D4 TRIS##LCD_D4 #define PIN_D5 LAT##LCD_D5 #define TRIS_D5 TRIS##LCD_D5 #define PIN_D6 LAT##LCD_D6 #define TRIS_D6 TRIS##LCD_D6 #define PIN_D7 R##LCD_D7 #define TRIS_D7 TRIS##LCD_D7 #define P_INPUT 1 #define P_OUTPUT 0 #else #define LCD_READ 0xE0 #define LCD_WRITE 0x00 #ifdef USE_PORTA_LCD #define PORT_LCD PORTA #define TRIS_LCD TRISA #endif #ifdef USE_PORTB_LCD #define PORT_LCD PORTB #define TRIS_LCD TRISB #endif #ifdef USE_PORTC_LCD #define PORT_LCD PORTC #define TRIS_LCD TRISC #endif #ifdef USE_PORTD_LCD #define PORT_LCD PORTD #define TRIS_LCD TRISD #endif #ifndef PORT_LCD #error USE_PORTx_LCD not defined #endif static volatile near bit PIN_EN @ ((unsigned)&PORT_LCD*8)+0; static volatile near bit PIN_RS @ ((unsigned)&PORT_LCD*8)+1; static volatile near bit PIN_RW @ ((unsigned)&PORT_LCD*8)+2; static volatile near bit PIN_D4 @ ((unsigned)&PORT_LCD*8)+3; static volatile near bit PIN_D5 @ ((unsigned)&PORT_LCD*8)+4; static volatile near bit PIN_D6 @ ((unsigned)&PORT_LCD*8)+5; static volatile near bit PIN_D7 @ ((unsigned)&PORT_LCD*8)+6; #endif /*These bytes need to be sent to the LCD to start it up*/ const char LCD_INIT_STRING[4]={0x20 | (LCD_TYPE <<2),0xC,1,6}; #define LCD_LINE_TWO 0x40 // LCD RAM address for the second line static volatile bit RS; /*Prototypes*/ void lcd_delay(void); void lcd_send_nibble(byte); void lcd_send_byte(byte); byte lcd_read_byte(void); void lcd_init(void); void lcd_cursor(lcd_cursor_type); void lcd_gotoxy( byte,byte); void lcd_build_char(byte,byte[7]); void lcd_use_build_char(byte); void lcd_erase(lcd_direction,byte); void lcd_erase_all(void); byte lcd_getc(byte,byte); void lcd_moven(lcd_direction,char); void lcd_putch(unsigned char); /*Functions*/

Page 74: desenvolvimento de software e hardware embutido para um sistema

65

void lcd_delay(void) { unsigned char cont; cont=10; while(cont--); } void lcd_send_nibble(byte n){ PIN_D4=BITTEST(n,0); PIN_D5=BITTEST(n,1); PIN_D6=BITTEST(n,2); PIN_D7=BITTEST(n,3); PIN_EN=1; lcd_delay(); PIN_EN=0; lcd_delay(); } void lcd_send_byte(byte n){ PIN_RS=0; lcd_delay(); while(BITTEST(lcd_read_byte(),7)); PIN_RS=RS; lcd_delay(); PIN_RW=0; lcd_delay(); PIN_EN=0; lcd_send_nibble(n>>4); lcd_send_nibble(n & 0x0f); } byte lcd_read_byte() { byte low,high; low=0;high=0; #ifndef USE_NO_PORT_LCD TRIS_LCD=LCD_READ; #else TRIS_EN=0;TRIS_RS=0;TRIS_RW=0; TRIS_D4=1;TRIS_D5=1;TRIS_D6=1;TRIS_D7=1; #endif PIN_RW=1; lcd_delay(); PIN_EN=1; lcd_delay(); if (PIN_D7) high |= (1<<3); if (PIN_D6) high |= (1<<2); if (PIN_D5) high |= (1<<1); if (PIN_D4) high |= 1; PIN_EN=0; lcd_delay(); PIN_EN=1; lcd_delay(); if (PIN_D7) low |= (1<<3); if (PIN_D6) low |= (1<<2); if (PIN_D5) low |= (1<<1); if (PIN_D4) low |= 1; PIN_EN=0; lcd_delay(); #ifndef USE_NO_PORT_LCD TRIS_LCD=LCD_WRITE; #else TRIS_EN=0;TRIS_RS=0;TRIS_RW=0;TRIS_D4=0;TRIS_D5=0;TRIS_D6=0;TRIS_D7=0; #endif return ( (high<<4) | low); } void lcd_init() { byte i; #ifndef USE_NO_PORT_LCD TRIS_LCD=LCD_WRITE; #else TRIS_EN=0;TRIS_RS=0;TRIS_RW=0;TRIS_D4=0;TRIS_D5=0;TRIS_D6=0;TRIS_D7=0; #endif lcd_delay(); PIN_RS=0; lcd_delay(); PIN_RW=0; lcd_delay(); PIN_EN=0; lcd_delay(); for (i=1;i<=3;++i) {

Page 75: desenvolvimento de software e hardware embutido para um sistema

66

lcd_send_nibble(3); lcd_delay(); } lcd_send_nibble(2); PIN_RS=RS==1?1:0; for (i=0;i<=3;++i) lcd_send_byte(LCD_INIT_STRING[i]); lcd_delay(); } void lcd_erase_all() { RS=0; lcd_send_byte(0x1); lcd_gotoxy(1,1); } void lcd_gotoxy(byte x,byte y) { byte address; if(y!=1) address=LCD_LINE_TWO; else address=0; address+=x-1; RS=0; lcd_send_byte(0x80|address); } void lcd_cursor(lcd_cursor_type lcdtype) { RS=0; switch (lcdtype) { case lcd_cursor_on: lcd_send_byte(0x0E); break; case lcd_cursor_off: lcd_send_byte(0x0C); break; case lcd_cursor_blink: lcd_send_byte(0x0D); break; case lcd_cursor_alternate: lcd_send_byte(0x0F); break; } } void lcd_build_char(unsigned char address,unsigned char map[]) { unsigned char Count; for (Count=0;Count<=7;Count++) { RS=0; lcd_send_byte(address+Count); RS=1; lcd_send_byte(map[Count]); } } void lcd_use_build_char(byte number) { RS=1; lcd_send_byte(number); } void lcd_erase(lcd_direction dir,byte n) { while(n--) { RS=0; lcd_send_byte(0x10+dir*4); lcd_putch(' '); RS=0; lcd_send_byte(0x10); } } char lcd_getc(char x,char y) { byte value; lcd_gotoxy(x,y); while(BITTEST(lcd_read_byte(),7)); RS=1;

Page 76: desenvolvimento de software e hardware embutido para um sistema

67

value=lcd_read_byte(); RS=0; return value; } void lcd_moven(lcd_direction dir,char n) { RS=0; while(n--) if (dir) lcd_send_byte(0x14); else lcd_send_byte(0x10); } void lcd_putch(unsigned char c) { RS=0; switch(c){ case '\f': lcd_send_byte(0x1); break; case '\n': lcd_gotoxy(1,2); break; case '\b': lcd_send_byte(0x10); break; default : RS=1; lcd_send_byte(c); break; } } #endif

KEYBOARD.C

// Design by Eng. Mauricio Lopes de Oliveira /* The KEYB_CLOCK and KEYB_DATA pins should be connected to the keyboard corresponded pins with an 4K7 Pullup. The keyboard alse needs GND and +5V*/ #ifndef KEYB_DATA #error KEYB_DATA pin not defined. Use #define KEYB_DATA PIN_XX #endif #ifndef KEYB_CLOCK #error KEYB_CLOCK pin not defined. Use #define KEYB_CLOCK PIN_XX #endif #define PIN_KEYB_DATA R##KEYB_DATA #define TRIS_KEYB_DATA TRIS##KEYB_DATA #define PIN_KEYB_CLOCK R##KEYB_CLOCK #define TRIS_KEYB_CLOCK TRIS##KEYB_CLOCK #define PIN_INPUT 0x01 #define PIN_OUTPUT 0x00 #define true 1 #define false 0 #define bit_clear(nvar,nbit) (nvar &= ~(1<<nbit)) #define bit_set(nvar,nbit) (nvar |= (1<<nbit)) //functions prototypes void kbd_init(void); unsigned char kbd_rcv(void); unsigned char kbd_getc(void); void kbd_init(void){ TRIS_KEYB_CLOCK=PIN_INPUT; TRIS_KEYB_DATA=PIN_INPUT; }

Page 77: desenvolvimento de software e hardware embutido para um sistema

68

void kbd_gets(char[] , unsigned char ); // ***** Keyboard Functions ***** /*********************************** kbd_rcv(): Receives bytes from keyboard Return the byte received ***********************************/ unsigned char kbd_rcv(void) { unsigned char cmd=0,cont; for(cont=1;cont<12;cont++) { while(PIN_KEYB_CLOCK); if ((cont>=2)&&(cont<=9)&&(PIN_KEYB_DATA)) cmd|=(1<<(cont-2)); while (!PIN_KEYB_CLOCK); } return cmd; } // Functions keypad #define KBD_F1 0x81 #define KBD_F2 0x82 #define KBD_F3 0x83 #define KBD_F4 0x84 #define KBD_F5 0x85 #define KBD_F6 0x86 #define KBD_F7 0x87 #define KBD_F8 0x88 #define KBD_F9 0x89 #define KBD_F10 0x8A #define KBD_F11 0x8B #define KBD_F12 0x8C #define KBD_UP 0x92 #define KBD_DOWN 0x8C #define KBD_LEFT 0x8E #define KBD_RIGHT 0x90 #define KBD_HOME 0X91 __EEPROM_DATA(0x1C,0x32,0x21,0x23,0x24,0x2B,0x34,0x33); __EEPROM_DATA(0x43,0x3B,0x42,0x4B,0x3A,0x31,0x44,0x4D); __EEPROM_DATA(0x15,0x2D,0x1B,0x2C,0x3C,0x2A,0x1D,0x22); __EEPROM_DATA(0x35,0x1A,0x45,0x16,0x1E,0x26,0x25,0x2E); __EEPROM_DATA(0x36,0x3D,0x3E,0x46,0x70,0x69,0x72,0x7A); __EEPROM_DATA(0x6B,0x73,0x74,0x6C,0x75,0x7D,0x05,0x06); __EEPROM_DATA(0x04,0x0C,0x03,0x0B,0x83,0x0A,0x01,0x09); __EEPROM_DATA(0x78,0x07,0x75,0x72,0x00,0x00,0x00,0x00); unsigned char kbd_getc() { unsigned char rcv,cont; char keypad; loop: rcv=kbd_rcv(); if (rcv==0xE0) { keypad=true; rcv=kbd_rcv(); } else keypad=false; if (rcv==0xF0) { kbd_rcv(); goto loop; } cont=0; while ((eeprom_read(cont)!=rcv)&&(cont<59)) cont++; cont++; if (cont<=26) rcv=64+cont;//A-Z else if ((cont>26)&&(cont<=36)) rcv=21+cont;//0-9 else if ((cont>36)&&(cont<=46)) //0-9 Keypad {

Page 78: desenvolvimento de software e hardware embutido para um sistema

69

rcv=11+cont; if (keypad) rcv=rcv+90; } else if (rcv==0x29) rcv=32; //espaço else if (rcv==0x1B) rcv=27; // esc else if (rcv==0x5A) rcv=13; //carriage return else if (rcv==0x66) rcv=8; //backspace else if ((cont>46)&&(cont<=58)) rcv=cont+82;//Functions Keypad else goto loop;//rcv='\0'; return rcv; } void kbd_gets(char string[], unsigned char lenght) { char rec=0; char pos=0; //Números de Caracteres char cont=0; //posição do cursor do { rec = kbd_getc(); if ( ((rec<KBD_F1)||(rec>KBD_F12))&&rec!=0&&rec!=13&&((rec<129)||(rec>140))) { if ((rec!=KBD_LEFT)&&(rec!=KBD_RIGHT)&&(rec!=KBD_UP)&&(rec!=KBD_DOWN)&&(rec!=8)&&(pos<lenght)) { printf("%c",rec); string[cont]=rec; if (pos==cont) pos++; cont++; } if ((rec==8)&&(cont!=0)) { if (cont==pos) pos--; else string[cont-1]=' '; cont--; lcd_erase(left,1); } if ((rec==KBD_LEFT)&&(cont!=0)) { cont--; lcd_moven(left,1); } if ((rec==KBD_HOME)&&(cont!=0)) { lcd_moven(left,cont); cont=0; } if ((rec==KBD_RIGHT)&&(cont!=pos)) { cont++; lcd_moven(right,1); } } } while (rec!=13); string[pos]='\0'; }

24CXX.C:

#ifndef _24CXX_H #define _24CXX_H #ifndef _I2C_MASTER_H #error i2c_master.h not included #endif #define I2C_EEPROM (0xA0) #define I2C_EEPROM_A0 (0xA0 | 0x02) #define I2C_EEPROM_A1 (0xA0 | 0x04) #define I2C_EEPROM_A1_A0 (0xA0 | 0x06)

Page 79: desenvolvimento de software e hardware embutido para um sistema

70

#define I2C_EEPROM_A2 (0xA0 | 0x08) #define I2C_EEPROM_A0_A2 (0xA0 | 0x0A) #define I2C_EEPROM_A1_A2 (0xA0 | 0x0C) #define I2C_EEPROM_A0_A1_A2 (0xA0 | 0x0E) char i2c_eepromReady(char); void i2c_eepromWrite(char,int, char); char i2c_eepromRead(char,int); char i2c_eepromReadCurrent(char); void i2c_eepromCursor(char,int); void i2c_eepromSequentialRead(char ,int ,char *,unsigned char ); void i2c_eepromTextWrite(char ,int , char *); char i2c_eepromReady(char device) { char ack; ack=i2c_start(device); i2c_stop(); return ack; } void i2c_eepromWrite(char device,int address, char data) { i2c_eepromCursor(device,address); i2c_write(data); i2c_stop(); } char i2c_eepromReadCurrent(char device) { char data; i2c_restart(device | 0x01); data=i2c_read(0); i2c_stop(device); return(data); } char i2c_eepromRead(char device,int address) { i2c_eepromCursor(device,address); return(i2c_eepromReadCurrent(device)); } void i2c_eepromCursor(char device,int i2c_address) { while(!i2c_eepromReady(device)); i2c_start(device); i2c_write(i2c_address>>8); i2c_write(i2c_address); } void i2c_eepromSequentialRead(char device,int address,char *data,unsigned char size_str) { unsigned char cont; i2c_eepromCursor(device,address); i2c_restart(device | 0x01); for(cont=0;cont<(size_str-1);cont++) data[cont]=i2c_read(1); data[size_str-1]=i2c_read(0); data[size_str]='\0'; i2c_stop(device); } void i2c_eepromTextWrite(char device,int address, char *data) { unsigned char cont2; int cont1,cont3; cont1=0; cont2=address; cont3=0; while(data[cont1]!='\0') { while(!i2c_eepromReady(device)); i2c_start(device); i2c_write(cont2>>8); i2c_write(cont2); for (cont3=0;cont3<16;cont3++) { i2c_write(data[cont1++]); if(data[cont1]=='\0') break; } i2c_stop(); cont2+=16; } } #endif

Page 80: desenvolvimento de software e hardware embutido para um sistema

71

62256.C:

#ifndef _62256_H #define _62256_H #ifndef RAM_LE_H #error RAM_LE_H not defined #endif #ifndef RAM_LE_L #error RAM_LE_L not defined #endif #ifndef PORT_RAM #error PORT_RAM not defined #endif #ifndef RAM_OE #error RAM_OE not defined #endif #ifndef RAM_WE #error RAM_WE not defined #endif #define PORT_INPUT 0xFF #define PORT_OUTPUT 0x00 #define PIN_INPUT 0x01 #define PIN_OUTPUT 0x00 #define T_RAM_LE_H TRIS##RAM_LE_H #define P_RAM_LE_H LAT##RAM_LE_H #define T_RAM_LE_L TRIS##RAM_LE_L #define P_RAM_LE_L LAT##RAM_LE_L #define T_RAM TRIS##PORT_RAM #define L_RAM LAT##PORT_RAM #define T_OE TRIS##RAM_OE #define P_OE LAT##RAM_OE #define T_WE TRIS##RAM_WE #define P_WE LAT##RAM_WE #define P_RAM PORT##PORT_RAM void ram_Init(void); void ram_Cursor(unsigned int); unsigned char ram_ReadByte(unsigned int); void ram_WriteByte(unsigned char,unsigned int); void ram_SequentialWrite(char *,unsigned int); void ram_SequentialRead(char *,unsigned int,unsigned int); void ram_Init(void){ T_RAM_LE_L=T_RAM_LE_H=PIN_OUTPUT; T_WE=PIN_OUTPUT; T_OE=PIN_OUTPUT; P_WE=1; P_OE=1; } void ram_Cursor(unsigned int address){ P_RAM_LE_H=0; P_RAM_LE_L=0; T_RAM=PORT_OUTPUT; P_RAM=(unsigned char)(address>>8); P_RAM_LE_H=1; P_RAM_LE_H=0; P_RAM=(unsigned char)(address&0xFF); P_RAM_LE_L=1; P_RAM_LE_L=0; } unsigned char ram_ReadByte(unsigned int address){ unsigned char ret; ram_Cursor(address); P_OE=0; T_RAM=PORT_INPUT; ret=P_RAM; P_OE=1; return ret;

Page 81: desenvolvimento de software e hardware embutido para um sistema

72

} void ram_WriteByte(unsigned char value,unsigned int address){ T_RAM=PORT_OUTPUT; ram_Cursor(address); L_RAM=value; P_WE=0; P_WE=1; T_RAM=PORT_INPUT; } void ram_SequentialWrite(char *val,unsigned int initial_address){ int cont=0; while(val[cont++]!='\0') ram_WriteByte(val[cont-1],initial_address+cont-1); } void ram_SequentialRead(char *val,unsigned int initial_address,unsigned int size){ int cont=0; while(cont++!=size)val[cont-1]=ram_ReadByte(initial_address+cont-1); val[cont-1]='\0'; } #endif

PCF8583.C:

/*********************************************************************/ /* PCF8583.h */ /* Header file for the control of the PCF8583 */ /* of Fernando Heitor (2003) */ /* UPADATE: June 2004 */ /* http://www.fernando-heitor.de */ /* The following routines are here integrated: */ /* DectoHex() - dec. in Hex. changes over */ /* HextoDec() - wandelt Hex. in Dez. um */ /* write8583_rtc() - Function writes the indicated byte with */ /* address into the PCF8583 */ /* read8583_rtc() - Function reads in the indicated */ /* address of PCF8583 */ /* */ /*********************************************************************/ #ifndef _PCF_8583_H #define _PCF_8583_H #define BYTE unsigned char #ifndef _I2C_MASTER_H #error i2c_master.h not included #endif struct Time { BYTE hour; BYTE minute; BYTE seconds; }; struct Date { BYTE year; BYTE month; BYTE day; BYTE weekday; }; struct Counter { BYTE thousand; BYTE hundred; BYTE one; }; BYTE sec_before; // Artificial variable for the second examination /********************************************* Definitions for A0 pin

Page 82: desenvolvimento de software e hardware embutido para um sistema

73

**********************************************/ #ifndef RTC_A0_HIGH #define ADDRESS_WRITE 0xA0 // The address A0 for letters, if pin A0 is because of the PCF8583 on GND #define ADDRESS_READ 0xA1 // The address A1 for vintages, if pin A0 at the PCF8583 on GND leigt #else #define ADDRESS_WRITE 0xA2 // The address A0 for letters, if pin A0 is because of the PCF8583 on GND #define ADDRESS_READ 0xA3 // The address A1 for vintages, if pin A0 at the PCF8583 on GND leigt #endif /******************************************** Definitions for the PCF8583 ********************************************/ //Used in write8583_rtc #define SET_DATE_TIME 0x01 // Start address in the PCF8583 register for describing #define SET_ALARM 0x09 // With this address setting the alarm time begins //Used in read8583_rtc #define GET_DATE_TIME 0x02 // Start address in the PCF8583 register for reading #define GET_ALARM 0x0A // The alarm time can be queried by this address /**********************************************************/ /*** different adjustment possibilities for the PCF8583 ***/ /**********************************************************/ // Configurations for the control/status register //Used in configure8583_control #define alarm_enable 0x04 // Here the alarm function is activated #define clock_mode32khz 0x00 // Clock frequency of the PCF8583 32,768 kHz #define clock_mode50hz 0x10 // Clock frequency of the PCF8583 50 Hz #define eventcounter_mode 0x20 // Event-Counter Mode #define hold_last_count_f 0x40 //Configurations for alarm the control register //Used in configure8583_alarm_reg #define timer_hundsek 0x01 // Timer function: Timer is released in the 100stel seconds #define timer_seconds 0x02 // Timer function: Timer is released in the 1-second pulse #define timer_minutes 0x03 // Timer function: Timer is released in the minutes pulse #define timer_hours 0x04 // Timer function: Timer is released once per hour #define timer_days 0x05 // Timer function: Timer is daily released #define timer_int_enable 0x08 // Here the timer interrupt is activated #define daily_alarm 0x10 // Clock alarm function DAILY alarm #define weekday_alarm 0x20 // Clock alarm function weekday alarm #define dated_alarm 0x30 // Clock alarm function dated alarm #define timer_alarm_enable 0x40 // Here the timer alarm is switched on #define alarm_int_enable 0x80 // Here the alarm interrupt is switched on //further configuration options for the hour register address 0x04 #define STD_Anzeige_12h 0x80 #define STD_AM_Flag 0x00 #define STD_PM_Flag 0x40 // Transformation from decimal to BCD BYTE DectoBCD( BYTE value) { return ( value%10 + 16 * (value/10)); } // Transformation of BCD to decimal BYTE BCDtoDec( BYTE value) { return ( value%16 + 10 * (value/16));

Page 83: desenvolvimento de software e hardware embutido para um sistema

74

} BYTE DectoHex( BYTE value) { return ( value%10 + 16 * (value/10)); } /* Transformation of hexadecimal (BCD) to decimal */ BYTE HextoDec( BYTE value) { return ( value%16 + 10 * (value/16)); } void write8583_rtc(struct Time *t, struct Date *d, BYTE address_reg) { BYTE rtc_temp; i2c_start(ADDRESS_WRITE); i2c_write(address_reg); i2c_write(0x00); // Hundreds of seconds are set here to 0 i2c_write(DectoBCD(t->seconds));//Seconds are stored in address 0x02 i2c_write(DectoBCD(t->minute)); // Minutes are stored in address 0x03 i2c_write(DectoBCD(t->hour)); // Hours are stored in address 0x04 rtc_temp = (DectoBCD(d->day) ) & 0x3F; i2c_write( rtc_temp | ( (d->year & 0x03) << 6) );// Year and day are stored in address 0x05 rtc_temp = DectoBCD(d->month); i2c_write( d->weekday<<5 | rtc_temp);//Here month and weekday are summarized and written i2c_stop(); } void read8583_rtc(struct Time *t, struct Date *d, BYTE address_reg) { BYTE rtc_temp; i2c_start(ADDRESS_WRITE); i2c_write(address_reg); i2c_restart(ADDRESS_READ); t->seconds = BCDtoDec(i2c_read(1) & 0x7f);// Seconds in address 0x02 one selects t->minute = BCDtoDec(i2c_read(1));//Minutes in address 0x03 one selects t->hour = BCDtoDec(i2c_read(1) & 0x3f);//Hours in address 0x04 one selects //Year and day in the address 0x05 are picked out rtc_temp = i2c_read(1); d->year = (rtc_temp >> 6 ) & 0x03; d->day = BCDtoDec(rtc_temp & 0x3f); //Weekday and month are picked out in the address 0x06 rtc_temp = i2c_read(0); d->weekday = rtc_temp >> 5; d->month = BCDtoDec(rtc_temp & 0x1f); i2c_stop(); } // By the function the register one configures to control/status void configure8583_control_reg(BYTE control_reg) { i2c_start(ADDRESS_WRITE); i2c_write(0x00); i2c_write(control_reg); i2c_stop(); } // By the function one configures to alarm control register void configure8583_alarm_reg(BYTE alarm_reg) { i2c_start(ADDRESS_WRITE); i2c_write(0x08); i2c_write(alarm_reg); i2c_stop(); } // Material time Clock is set to 0, if timer mode is used void write8583_zeroclock() { i2c_start(ADDRESS_WRITE); i2c_write(0x01); i2c_write(0x00); i2c_write(0x00); i2c_write(0x00);

Page 84: desenvolvimento de software e hardware embutido para um sistema

75

i2c_write(0x00); i2c_stop(); } //Timer value is set in address 0x0F void write8583_timer(BYTE alarm_timer) { i2c_start(ADDRESS_WRITE); i2c_write(0x07); i2c_write(0x00); i2c_stop(); i2c_restart(ADDRESS_WRITE); i2c_write(0x0f); i2c_write(DectoHex(alarm_timer)); i2c_stop(); } // With this function PCF8583 in the Event Counter mode with the number of Events is initialized void write8583_eventcounter(struct Counter *c) { i2c_start(ADDRESS_WRITE); i2c_write(0x01); i2c_write(c->one); i2c_write(c->hundred); i2c_write(c->thousand); i2c_stop(); } //PCF8583 in the Event Counter mode is initialized by this function with the number of Events around the alarm to release void write8583_eventalarm(struct Counter *c) { i2c_start(ADDRESS_WRITE); i2c_write(0x09); // address of first write i2c_write(c->one); i2c_write(c->hundred); i2c_write(c->thousand); i2c_stop(); } // Here the Event Counter is read, i.e. the current number of Events. void read8583_eventcounter(struct Counter *c) { BYTE var; i2c_start(ADDRESS_WRITE); i2c_write(0x01); i2c_start(ADDRESS_READ); var = i2c_read(1); c->one = HextoDec(var); var = i2c_read(1); c->hundred = HextoDec(var); var = i2c_read(0); c->thousand = HextoDec(var); i2c_stop(); } // Here the Event alarm is picked out tons of the releases i.e. the NUMBERS OF Events around at alarm. void read8583_event_alarm(struct Counter *c) { BYTE var; i2c_start(ADDRESS_WRITE); i2c_write(0x09); i2c_restart(ADDRESS_READ); var = i2c_read(1); c->one = HextoDec(var); var = i2c_read(1); c->hundred = HextoDec(var); var = i2c_read(0); c->thousand = HextoDec(var); i2c_stop(); } #endif

Page 85: desenvolvimento de software e hardware embutido para um sistema

76

PRINTER.C:

#ifndef _PRINTER_H #define _PRINTER_H #define BUSY C0 #define STROBE C1 #define HPRINT B7 #define PPRINT D #define PORT_INPUT 0xFF #define PORT_OUTPUT 0x00 #define PIN_INPUT 0x01 #define PIN_OUTPUT 0x00 #define L_HPRINT LAT##HPRINT #define T_HPRINT TRIS##HPRINT #define T_BUSY TRIS##BUSY #define R_BUSY R##BUSY #define T_STROBE TRIS##STROBE #define L_STROBE LAT##STROBE #define T_PRINT TRIS##PPRINT #define L_PRINT LAT##PPRINT void printer(unsigned const char); void prn_printf(unsigned const char[]); void printer(unsigned const char c){ T_HPRINT=PIN_OUTPUT; T_STROBE=PIN_OUTPUT; T_PRINT=PORT_OUTPUT; T_BUSY=PIN_INPUT; L_HPRINT=0; while (R_BUSY); L_PRINT=c; L_STROBE=0; L_STROBE=1; T_STROBE=PIN_INPUT; T_HPRINT=PIN_INPUT; } void prn_printf(unsigned const char str[] ){ unsigned int cont=0; while(str[cont]!='\0'){ printer(str[cont]); cont++; } } #endif

I2C_MASTER.C:

/***************************************************************************************** Hardware I2C single master routines for PIC18Fxxx and 18Fxxxx for HI-TEC PIC C COMPILER. i2c_init - initialize I2C functions i2c_start - issue Start condition i2c_repStart- issue Repeated Start condition i2c_stop - issue Stop condition i2c_read(x) - receive unsigned char - x=0, don't acknowledge - x=1, acknowledge i2c_write - write unsigned char - returns ACK by

Page 86: desenvolvimento de software e hardware embutido para um sistema

77

Mauricio Oliveira E-mail [email protected] REGISTERS AND FLAGS SSPIF: (Peripheral Interrupt Request Register 1 - PIR1 - Bit 3) SSP Interrupt flag, is set in the following events: Start condition, Stop condition, Data transfer byte transmitted/receive Acknowledge transmit, repeated Start SSPBUF: (SYNCHRONOUS SERIAL PORT) Receive Buffer/Transmit Register SSPBUF is the buffer register to which data bytes are written to or read from. RCEN: SSPCON2 (MSSP CONTROL REGISTER 2 -I2C MODE) bit 3 1 = Enables Receive mode for I2C operation 0 = Receive Idle ACKDT: SSPCON2 bit5 - Acknowledge Data bit (Master Receive mode only) 1 = Not Acknowledge 0 = Acknowledge ACKEN: SSPCON2 bit 4 - Acknowledge Sequence Enable bit 1 = Initiate Acknowledge sequence on SDA and SCL pins and transmit ACKDT data bit. Automatically cleared by hardware. 0 = Acknowledge sequence Idle SEN: SSPCON2 bit 0 - Start Condition Enable 1 = Initiate Start condition on SDA and SCL pins. Automatically cleared by hardware. 0 = Start condition Idle ACKSTAT: SSPCON2 bit 6 - Acknowledge Status bit 1 = Acknowledge was not received from slave 0 = Acknowledge was received from slave RSEN: SSPCON2 bit 1 - Repeated Start Condition Enable bit 1 = Initiate Repeated Start condition on SDA and SCL pins. Automatically cleared by hardware. 0 = Repeated Start condition Idle PEN: SSPCON2 bit 2 - Stop Condition Enable bit 1 = Initiate Stop condition on SDA and SCL pins. Automatically cleared by hardware. 0 = Stop condition Idle **********************************************************************************************************/ #ifndef _I2C_MASTER_H #define _I2C_MASTER_H void i2c_init(unsigned char); void i2c_waitForIdle(void); char i2c_start(unsigned char); char i2c_restart(unsigned char); void i2c_stop(); unsigned char i2c_write( unsigned char); unsigned char i2c_read( unsigned char); void i2c_init(unsigned char ssp_add) { SSPCON1 = 0x38; // set I2C master mode SSPCON2 = 0x00; /* clock = FOSC / (4 * (SSPADD+1)) - Max Clock - 100k*/ SSPADD = ssp_add; // 100k at 4Mhz clock CKE=1; // use I2C levels worked also with '0' SMP=1; // disable slew rate control worked also with '0' } void i2c_waitForIdle() { while ((SSPCON2 & 0x1F) || RW ) {}; // wait for idle and not writing } char i2c_start(unsigned char i2c_address) { i2c_waitForIdle(); SEN=1; return (i2c_write(i2c_address)); }

Page 87: desenvolvimento de software e hardware embutido para um sistema

78

char i2c_restart(unsigned char i2c_address) { i2c_waitForIdle(); RSEN=1; return (i2c_write(i2c_address)); } void i2c_stop() { i2c_waitForIdle(); PEN=1; } unsigned char i2c_read( unsigned char ack ) { char i2cReadData; i2c_waitForIdle(); RCEN=1; i2c_waitForIdle(); i2cReadData = SSPBUF; i2c_waitForIdle(); if ( ack ) ACKDT=0; else ACKDT=1; ACKEN=1; // send acknowledge sequence return( i2cReadData ); } unsigned char i2c_write( unsigned char i2cWriteData ) { i2c_waitForIdle(); SSPBUF = i2cWriteData; i2c_waitForIdle(); return ( ! ACKSTAT ); // function returns '1' if transmission is acknowledged } #endif

FILE.C:

/******************************************************************* * Arquivo: file1.c * Descrição:Funcoes Basicas do Sistema de Arquivos * * * Equipe de Sistemas Embutidos - NCE/UFRJ - 2005/2006 * Autores: Daniel da Cunha Schmidt * Vinicius dos Santos Silva * * Baseado no codigo para o Sistema de Arquivos ZiLOG * para o eZ80 ********************************************************************/ #include "..\includes\fileinit.c" int file_allocate_sector() { int blk = 0; //Procura por um setor vazio na tabela while(sector_table[blk] != 0xFFFF) { blk++; // Se nao achar setor vazio, retorna '-1' if(blk >= NSECTORS) return -1;

Page 88: desenvolvimento de software e hardware embutido para um sistema

79

} //Retorna o indice do primeiro setor vazio na tabela return blk; } /* Cria novo arquivo na EEPROM Retorna -1 se o arquivo ja existe ou se nao existe espaco. Retorna 0 em caso de sucesso. name[] Nome do arquivo a ser criado. tag 0 - Arquivo Sequencial n - Arquivo de Registros, onde n eh o tamanho de cada registro. */ char fcreate(char name[], char tag) { int idx, blk, end_st; char i; //Procura o arquivo pra ver se ele ja existe idx = fexists(name); //Se ja existir... if (idx >= 0) { return (char)-1; } //Se nao existir, zera 'idx' idx = 0; //Procura entrada vazia na tabela de arquivos while(file_table[idx].name[0] != 0xFF) { idx++; //Se nao existirem mais entradas vazias... if(idx >= NFENTRIES) { return (char)0xFF; } } //Procura por um setor vazio para alocar o inicio do arquivo blk = file_allocate_sector(); //Se nao existir setor vazio... if (blk < 0) { return (char)0xFF; } //Escreve o nome do novo arquivo strcpy(file_table[idx].name, name); for (i=0; i<TAM_STRING; i++) i2c_eepromWrite(I2C_EEPROM_A0, ft_logictophysical(idx,FTNAME)+i, name[i]); //Escreve o numero do primeiro setor do novo arquivo file_table[idx].start = blk; write_eeprom_int(ft_logictophysical(idx,FTSTART), blk, EEPROM_EXT); //Cria uma 'tag' pro arquivo end_st = FS_ADDRESS + blk * SECTORSIZE; // <======== acertar endereco (end_st) i2c_eepromWrite(I2C_EEPROM_A0, end_st, tag); //O tamanho do arquivo eh 1 (apenas a tag) file_table[idx].size = 1; write_eeprom_int(ft_logictophysical(idx,FTSIZE), 1, EEPROM_EXT); //Sector_table[blk] recebe o numero do proximo setor ocupado pelo arquivo //Neste caso, o proprio setor (o unico! - por enquanto) sector_table[blk] = blk; write_eeprom_int(st_logictophysical(blk), blk, EEPROM_INT);

Page 89: desenvolvimento de software e hardware embutido para um sistema

80

temp = create_int(st_logictophysical(blk), EEPROM_INT); return (char)0; } /* Apaga o arquivo da EEPROM Retorna -1 se o arquivo nao existir Retorna 0 em caso de sucesso */ char ferase(char name[]) { int idx, blk, blk1; /* DEBUG char lido1[], lido2[]; */ // procura o nome do arquivo para ver se ele existe idx = fexists(name); //Se arquivo nao existir... if(idx < 0) { return (char) 0xFF; } //'blk' recebe o numero do primeiro setor do arquivo blk = file_table[idx].start; //Libera todos os setores do arquivo while(sector_table[blk] != 0xFFFF) { //'blk1' guarda o indice do proximo setor do arquivo blk1 = sector_table[blk]; i2c_eepromSequentialRead (I2C_EEPROM_A0, st_logictophysical(blk), lido1, 0x02); //O indice eh apagado sector_table[blk] = 0xFF; write_eeprom_int (st_logictophysical(blk), 0xFF, EEPROM_INT); /* DEBUG i2c_eepromSequentialRead(I2C_EEPROM_A0, st_logictophysical(blk), lido2, 0x02); blk = blk1; } i2c_eepromSequentialRead(I2C_EEPROM_A0, ft_logictophysical(idx, FTSTART), lido1, 0x02); //Apaga o setor inicial do arquivo na tabela file_table[idx].start = 0xFF; write_eeprom_int (ft_logictophysical(idx, FTSTART), 0xFF, EEPROM_EXT); // apaga o tamanho do arquivo na tabela file_table[idx].size = (int)0xFF; i2c_eepromPageWrite (I2C_EEPROM_A0, ft_logictophysical(idx, FTSIZE), (char*)0xFF, sizeof (int) ); // apaga o nome do arquivo na tabela (apaga so a primeira letra) file_table[idx].name[0] = (char)0xFF; i2c_eepromPageWrite(I2C_EEPROM_A0, ft_logictophysical(idx, FTNAME), (char*)0xFF, 1); return (char)0; } /* Procura pelo arquivo na tabela de arquivos Retorna -1 se o arquivo nao for encontrado se for emcontrado, retorna o indice do arquivo na tabela */ int fexists(char name[]) { int idx = 0;

Page 90: desenvolvimento de software e hardware embutido para um sistema

81

while(idx < NFENTRIES) { strcpy(name_temp, file_table[idx].name); strcpy(buf, file_table[idx].name); if(strcmp(file_table[idx].name, name) == 0) return idx; idx ++; } return -1; } /* Abre um arquivo. Retorna 0 se nenhum arquivo com o nome apontado por name[] for encontrado ou se nao ha mais espaco na tabela de arquivos abertos. Se o arquivo for encontrado, sua entrada na tabela de arquivos abertos eh retornada. name[]: Nome do arquivo a ser aberto. modos: FM_APPEND - Insere dados no fim do arquivo FM_RDWR - Le ou escreve no inicio do arquivo Se algum outro valor diferente de FM_APPEND eh fornecido, o modo default ed FM_RDWR. */ FILE* fopen(char name[], char mode) { int idx, ind; char outro_nome[9], buf[20]; ind = -1; for (idx = NFHANDLES-1; idx >= 0; idx--) { strcpy(outro_nome, file_handle_table[idx].pfile->name); if (strcmp(outro_nome, name) == 0) { return NULL; } if (file_handle_table[idx].pfile == (file_entry *)0) ind = idx; } if (ind < 0) { return NULL; } idx = fexists(name); if (idx < 0) { return NULL; } //Associa a entrada do arquivo a 'tabela de arquivos abertos' file_handle_table[ind].pfile = &file_table[idx]; file_handle_table[ind].tag = i2c_eepromRead(I2C_EEPROM_A0, FS_ADDRESS + (file_handle_table[ind].pfile->start)* SECTORSIZE ); //Seta o valor de 'offset' if (mode) { file_handle_table[ind].offset = file_handle_table[ind].pfile->size; file_handle_table[ind].offset, EEPROM_INT); } else { //Se for FM_RDWR, escreve/le no inicio do arquivo //pf-> offset = 0; file_handle_table[ind].offset = 0;

Page 91: desenvolvimento de software e hardware embutido para um sistema

82

} return &file_handle_table[ind]; } /* Fecha um arquivo previamente aberto. Retorna 0 se bem sucedido ou -1 caso contrario. pf: Ponteiro para o arquivo aberto (retornado por fopen) */ int fclose(FILE* pf) { int idx; for (idx = 0; idx < NFHANDLES; idx++) if (pf == &file_handle_table[idx]) { pf-> pfile = NULL; // zera o 'offset' pf-> offset = 0; return 0; } return -1; } /* Le de um arquivo. bfr[]: Buffer parar receber os dados lidos size: Numero de bytes a serem lidos pf: Ponteiro para o arquivo */ int fread (void bfr[], int size, FILE *pf) { int rdsize, rdsize0, restdata, abssecoffs; int csec, secoffs; // verifica se o tamanho do arquivo eh valido if (size < 1) return EOF; // numero de bytes a serem lidos rdsize0 = size; if(rdsize0 < 1) return EOF; rdsize = rdsize0; // 'bptr' recebe o endereco do buffer apontado por 'bfr' //bptr = bfr; // fisrt sector with file data csec = pf->pfile->start; secoffs = 0; // go through all sectors of the file while( csec != 0xFFFF ) { // restdata is the length of the data in this sector // after the file offset //pf->offset = 0; // <======================== restdata = secoffs + SECTORSIZE - pf->offset; // <=================== verificar pf->offset!!!! if( restdata > 0 ) { // compute absolute address in memory // 14.10.2003 14:09 the explicit conversion of csec to (int) is necessary abssecoffs = FS_ADDRESS + (int)csec * SECTORSIZE + pf->offset - secoffs; // lcd_erase_all(); // if the rest is more then data requested // then in this sector read last time if( restdata >= rdsize ) { // copy records into the destination buffer

Page 92: desenvolvimento de software e hardware embutido para um sistema

83

i2c_eepromSequentialRead(I2C_EEPROM_A0, abssecoffs, bfr, size); pf->offset += rdsize; // <=========== mudar pf->offset para outra variavel // read n records, stop // or if end of file, stop return rdsize0; } else // else read till the end of this sector // and continue in the next sector { i2c_eepromSequentialRead(I2C_EEPROM_A0, abssecoffs, bfr, size); bfr += restdata; pf->offset += restdata; // <=========== mudar pf->offset para outra variavel rdsize -= restdata; rdsize); } } // move to next sector csec = sector_table[csec]; secoffs += SECTORSIZE; } return EOF; } /* Escreve em um arquivo bfr[]: Buffer que contem os dados a serem escritos pf: Ponteiro para o arquivo */ int fwrite (char bfr[], int size, FILE *pf) // <==== Retirar size como parametro!!!! { int wrsize, wrsize0, restdata, abssecoffs; int nsec, csec, secoffs; int i; //char bptr[]; // pointer to the actual file data on the disk //void *fptr; // verifica se o tamanho do arquivo eh valido if (size < 1) return EOF; // the total size of data to write wrsize0 = size; // the current amount of data left for writing wrsize = wrsize0; // fisrt sector with file data csec = pf->pfile->start; // sector offset secoffs = 0; // go through all sectors of the file while( csec != 0xFFFF ) { // restdata is the space available for writing // in this sector after the file offset pointer // 'restdata' eh o espaco disponivel para escrita no setor restdata = secoffs + SECTORSIZE - pf->offset; // if the sector contains the offset, then // the restdata more than 0, can write here // se 'restdata'>0, podemos escrever aqui if( restdata > 0 ) { // compute absolute address in memory // 14.10.2003 14:09 the explicit conversion of csec to (int) is necessary abssecoffs = FS_ADDRESS + (int)csec * SECTORSIZE + pf->offset - secoffs; if( restdata >= wrsize ) { // copy records into the destination buffer

Page 93: desenvolvimento de software e hardware embutido para um sistema

84

//i2c_eepromPageWrite(I2C_EEPROM_A0, abssecoffs, bfr, wrsize); for (i=0; i<wrsize; i++) i2c_eepromWrite(I2C_EEPROM_A0, abssecoffs+i, bfr[i]); // adjust the pointer pf->offset += wrsize; /* // adjust the size of the file pf->pfile->size = pf->offset; // mapeia 'pf->pfile->size' para end. fisico idx = (pf->pfile - file_table)/sizeof(file_entry); printf("\nidx = %d pf->offset = %d", idx, pf->offset); delay_tmr0(31250); write_eeprom_int(ft_logictophysical(idx,FTSIZE), pf->offset, EEPROM_EXT); return wrsize0; } else { // copy records into the destination buffer for (i=0; i<restdata; i++) i2c_eepromWrite(I2C_EEPROM_A0, abssecoffs+i, bfr[i]); // move the buffer pointer bfr += restdata; // adjust the pointer pf->offset += restdata; /* // adjust the size of the file pf->pfile->size = pf->offset; // mapeia 'pf->pfile->size' para end. fisico idx = (pf->pfile - file_table)/sizeof(file_entry); write_eeprom_int(ft_logictophysical(idx,FTSIZE), pf->offset, EEPROM_EXT); wrsize -= restdata; } } nsec = sector_table[csec]; if( nsec == csec ) { // allocate a new sector nsec = file_allocate_sector( ); // cannot allocate? if( nsec == -1 ) { puts("ERRO: Tabela de setores cheia!!"); kbd_getc(); return EOF;//(wrsize0 - restdata); } // bind the new sector as a next in the file chain sector_table[csec] = nsec; write_eeprom_int(st_logictophysical(csec), nsec, EEPROM_INT); sector_table[nsec] = nsec; write_eeprom_int(st_logictophysical(nsec), nsec, EEPROM_INT); } csec = nsec; secoffs += SECTORSIZE; } return EOF; }

Page 94: desenvolvimento de software e hardware embutido para um sistema

85

FILEINIT.C:

/******************************************************************* * Arquivo: fileinit.c * Descrição:Inicializa o sistema de arquivos * * * Equipe de Sistemas Embutidos - NCE/UFRJ - 2005/2006 * Autores: Daniel da Cunha Schmidt * Vinicius dos Santos Silva * * Baseado no codigo para o Sistema de Arquivos ZiLOG * para o eZ80 ********************************************************************/ /* Inicializa o sistema de arquivos. Inicializa = Grava 0xFF em todas as posicoes das tabelas de setores, arquivos abertos arquivos e na area de dados (eeprom externa). */ void init_file_system() { int addr, i; char senha1[9] = "OPERADOR"; char senha2[9] = "GERENTE"; char senha3[9] = "ROOT"; char senha4[9] = "SISTEMA"; addr = SECTABLE_ADDRESS; //Inicializa a tabela de setores (EEPROM INTERNA) for (i = 0 ; i < (int)SECTABLE_SIZE ; i++) eeprom_write(addr++, 0xFF); addr = FHANDTABLE_ADDRESS; //Inicializa a tabela de arquivos abertos (EEPROM INTERNA) for (i = 0 ; i < (int)FHANDTABLE_SIZE ; i++) eeprom_write(addr++, 0x00); addr = FTABLE_ADDRESS; //Inicializa a tabela de arquivos (EEPROM EXTERNA) for (i = 0 ; i < (int)FTABLE_SIZE ; i++) i2c_eepromWrite(I2C_EEPROM_A0, addr++, 0xFF); addr = FS_ADDRESS; //Inicializa o sistema de arquivos (EEPROM EXTERNA) for ( i = 0 ; i < (int)FS_SIZE ; i++) i2c_eepromWrite(I2C_EEPROM_A0, addr++, 0xFF); // Escreve as senhas padrao na EEPROM externa addr = 0x1FA0; for (i = 0; i < 10; i++) i2c_eepromWrite(I2C_EEPROM_A0, addr++, senha1[i]); //addr = 0x3E5; for (i = 0; i < 10; i++) i2c_eepromWrite(I2C_EEPROM_A0, addr++, senha2[i]); //addr = 0x3EE; for (i = 0; i < 10; i++) i2c_eepromWrite(I2C_EEPROM_A0, addr++, senha3[i]); //addr = 0x3F7; for (i = 0; i < 10; i++) i2c_eepromWrite(I2C_EEPROM_A0, addr++, senha4[i]); printf("\nSistema de Arquivos inicializado..."); }

Page 95: desenvolvimento de software e hardware embutido para um sistema

86

FILECONF.H: /******************************************************************* * Arquivo: fileconf.h * Descrição:Parametros basicos do Sistema de Arquivos * * * Equipe de Sistemas Embutidos - NCE/UFRJ - 2005/2006 * Autores: Daniel da Cunha Schmidt * Vinicius dos Santos Silva * * Baseado no codigo para o Sistema de Arquivos ZiLOG * para o eZ80 ********************************************************************/ #ifndef __FILECONF_H_ #define __FILECONF_H_ /* Numero de entradas na tabela de arquivos */ #define NFENTRIES 32 /* Numero maximo de arquivos abertos */ #define NFHANDLES 10 /* Numero de setores na EEPROM */ #define NSECTORS 60 // 8 Kb FS /* Tamanho(bytes) de um setor na EEPROM */ #define SECTORSIZE 128 /* Tamanho(bytes) da EEPROM externa */ #define EXT_EEPROM_SIZE 8192 // <===== sobram 96 bytes //Tamanho(bytes) da EEPROM interna // ja esta definido!!! //#define EEPROM_SIZE 256 // <===== sobram 22 bytes /* Tamanho(bytes) da tabela de arquivos (file table) */ #define FTABLE_SIZE (sizeof(file_entry)*NFENTRIES) //416 bytes /* Tamanho(bytes) da tabela de arquivos abertos (file handle table) */ #define FHANDTABLE_SIZE (sizeof(file_handle)*NFHANDLES) //50 bytes /* Tamanho(bytes) da tabela de setores */ #define SECTABLE_SIZE (sizeof(int)*NSECTORS) //120 bytes /* Tamanho do sistema de arquivos */ #define FS_SIZE (EXT_EEPROM_SIZE - FTABLE_SIZE) //7776 bytes /* Endereco fisico inicial da tabela de arquivos (EEPROM EXTERNA) */ #define FTABLE_ADDRESS 0x00 //Endereco fisico inicial da tabela de setores (EEPROM INTERNA) #define SECTABLE_ADDRESS 0x40 // Comeca apos o espaco utilixado pela biblioteca do teclado (64 bytes) /* Endereco fisico inicial da tabela de arquivos abertos (EEPROM INTERNA) */ #define FHANDTABLE_ADDRESS (SECTABLE_ADDRESS + SECTABLE_SIZE) //0xB8(184) /* Endereco fisico inicial do sistema de arquivos (EEPROM EXTERNA) */ #define FS_ADDRESS (FTABLE_ADDRESS + FTABLE_SIZE) //0x1A0(416) /* Tamanho padrao da string em 'file_table[i].name' (8 caracteres + '\0') */ #define TAM_STRING 9 #endif

Page 96: desenvolvimento de software e hardware embutido para um sistema

87

ESTACIONAMENTO.C: #include <pic18.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> /* Inicializacao - Faca as coisas nessa ordem: */ /* Inicializacao dos dados da biblioteca de teclado */ #include "..\includes\keyboard_eeprom.h" /* Inicializacao do LCD */ #define lcd_type 2 #define LCD_EN A2 #define LCD_RS A0 #define LCD_RW A1 #define LCD_D4 A3 #define LCD_D5 A4 #define LCD_D6 A5 #define LCD_D7 B3 #define USE_NO_PORT_LCD #include "..\includes\lcd.h" void putch(unsigned char c); void putch(unsigned char c) { lcd_putch(c); } /* Inicialização do teclado */ #define KEYB_DATA E1 #define KEYB_CLOCK E0 #include "..\includes\keyboard.h" /* Inicializacao da impressora */ #include "..\includes\printer.h" //Comentado por falta de memoria!! /* Inicializacao do I2C */ #include "..\includes\i2c_master.h" /* Inicializacao do PCF8583 (RTC) */ #include "..\includes\pcf8583.h" /*Inicializacao da EEPROM I2C */ #include "..\includes\24Cxx.h" #define I2C_MEMORY I2C_EEPROM_A0 /*Inicializacao do timer */ #include "..\includes\delay_timer.h" /* Inicializacao do Sitema de Arquivos */ #include "..\includes\fileconf.h" /* Definicoes Básicas e Prototipos de Funcoes do Sistema de Arquivo */ #include "..\includes\file.h" /* Funcoes de Acesso a memoria */ #include "..\includes\memoria.c" // Variavel usada com 'sprintf' char buf[80]; /* Funcoes Basicas do Sistema de Arquivo */ #include "..\includes\file1.c" #include "..\includes\fase2.c" typedef enum {operador, gerente, root, sistema} nivel_acesso; // NOVO NIVEL: SISTEMA -> == root, mas senha NAO pode ser alterada // sempre que o hardware eh iniciado, nivel de acesso == operador nivel_acesso nivel_operador = 1; char codigo_operador[3] = "00"; typedef struct { int inteiro; int frac; } st_float; #include "..\requisitos\Menus.c" void main() { struct Date d; int dias; long int D; char c; char buffer[20]; float val; FILE* teste; // inicializacao dos dispositivos de hardware init_tmr0(PRE_SCALE_256); lcd_init();

Page 97: desenvolvimento de software e hardware embutido para um sistema

88

lcd_cursor(lcd_cursor_blink); i2c_init(0x45); kbd_init(); ADCON1=0x0F; //Port usado pelo teclado para TTL lcd_erase_all(); init_file_system(); load_sector_table(); load_file_table(); rtc_start(); while(1) { menu(); } }

MENUS.C: #define SemPermissao "Voce nao tem permissao para acessar \neste menu!" #define DataInvalida "Dava Invalida.\nTente novamente." #define HoraInvalida "Hora Invalida.\nTente novamente." #define mOperacoes_L1 "Ent.cx. Sai.cx. trocaOp. Fecha. atRaso\n" #define mOperacoes_L2 "oP.espec. rec.Mensal. Tab.prec. pAtio" #define mOpEspeciais_L1 "Mensal. Relog. Senhas Param.\n" #define mOpEspeciais_L2 "Tab.prec. cp.Inic. Operador" #define mMensalistas_L1 "Incluir Alterar Excluir Listar\n" #define mMensalistas_L2 "Pagamento Datalimite" #define mPatio_L1 "Entrada Saida Listar\n" #define mParametros_L1 "Cabecalho cOres Marcas" #define mManterInfo_L1 "Incluir Alterar Excluir Listar" #define EVER ;; #define ENTRADA 0 #define SAIDA 1 #define PLC_MAX 8 #define COD_MAX 4 #define NOME_MAX 21 #define TRUE 1 #define FALSE 0 #define ENTER 13 #define ESC 27 #define BACKSPACE 8 //Prototipos void menu (void); void menu_op_especiais (void); void menu_param_sistema (void); void menu_marcas (void); void menu_operadores (void); void menu_patio (void); int entrada_patio (void); int saida_patio (void); void listar_patio (void); void menu_mensal (void); int incluir_mensalista (void); int excluir_mensalista (void); int alterar_mensalista (void); int listar_mensalista (void); void abertura_caixa (void); int entrada_caixa (void); int saida_caixa (void); void imprime_mov_caixa (char mov, char valor[]); void fechamento_caixa (void); void incluir_marcas (void); int alterar_marcas (void); int excluir_marcas (void);

Page 98: desenvolvimento de software e hardware embutido para um sistema

89

int listar_marcas (void); void altera_relogio (void); int altera_senhas (void); int troca_nivel_acesso (void); void incluir_operadores (void); int alterar_operadores (void); int excluir_operadores (void); int listar_operadores (void); int troca_operadores (void); void configura_cabecalho (void); void configura_tab_preco (void); void listar_tab_preco (void); int imprime_entrada (char[], char[], int, int); void configura_pgto_mensalista (void); void configura_data_mensalista (void); void ler_ano(void); void grava_ano(void); long int calcula_dias_corridos(struct Date *d1, struct Date *d2); //ouraiti! long int calcula_permanencia (struct Time *t1, struct Date *d1, struct Time *t2, struct Date *d2); //OK st_float* calcula_valor (int hora_perm, int min_perm, char nome_tab[]); void inicia_display_patio (void); void pega_codMarca (char[]); void cursor_placa_patio (void); void inicia_display_mensal (void); char pega_nome (char[], int altera_nome); // altera_nome = 1: alteração do nome; altera_nome = 0: incluindo primeira vez char pega_classe (char[], int altera_classe); // altera_classe = 1: alteração da classe; altera_classe = 0: incluindo primeira vez void cursor_placa_mensal (void); char pega_placa (char[], int placa2, int altera_placa, int placa_patio); // altera_placa = 1: alteração da placa; altera_placa = 0: incluindo primeira vez void pega_num (char cod_len, int inicio, int fim, char codigo[]); void pega_valor (char val_len, char valor[]); //*********************************************************************************** // void menu() // //*********************************************************************************** void menu() { char opcao, buf; char nome[9]; lcd_erase_all(); puts(mOperacoes_L1); puts(mOperacoes_L2); opcao = kbd_getc(SOLETRA); switch(opcao) // testar com 'else if' { case 'E': troca_nivel_acesso (); break; case 'S': lcd_erase_all(); sprintf(buf, "nivel de acesso: %d", nivel_operador); puts(buf); delay_tmr0(62000); break; case 'O': troca_operadores (); break; case 'F': break; case 'R': lcd_erase_all(); strcpy(nome, file_table[0].name); puts(nome); strcpy(nome, file_table[1].name); puts("\n");

Page 99: desenvolvimento de software e hardware embutido para um sistema

90

puts(nome); kbd_getc(LETRAENUMERO); break; case 'P': if (nivel_operador) menu_op_especiais(); else { lcd_erase_all(); puts(SemPermissao); } break; case 'M': break; case 'T': configura_tab_preco (); break; case 'A': menu_patio(); break; } } //*********************************************************************************** // void menu_op_especiais() // //*********************************************************************************** void menu_op_especiais() { char opcao; lcd_erase_all(); puts(mOpEspeciais_L1); puts(mOpEspeciais_L2); opcao = kbd_getc(SOLETRA); switch(opcao) { case 'M': menu_mensal(); break; case 'R': if (nivel_operador >= 1) altera_relogio(); break; case 'S': if (nivel_operador > 1) altera_senhas(); break; case 'P': menu_param_sistema(); break; case 'T': listar_tab_preco(); break; case 'I': imprime_entrada(); break; case 'O': menu_operadores(); break; } } //*********************************************************************************** // void menu_parametros_sistema()

Page 100: desenvolvimento de software e hardware embutido para um sistema

91

// //*********************************************************************************** void menu_param_sistema() { char opcao; lcd_erase_all(); puts(mParametros_L1); opcao = kbd_getc(SOLETRA); switch(opcao) { case 'C': configura_cabecalho (); break; case 'O': //menu_cores(); break; case 'M': menu_marcas(); break; } } //*********************************************************************************** // void menu_marcas() // //*********************************************************************************** void menu_marcas() { char opcao; lcd_erase_all(); puts(mManterInfo_L1); opcao = kbd_getc(SOLETRA); switch(opcao) { case 'I': incluir_marcas(); break; case 'A': alterar_marcas(); break; case 'E': excluir_marcas(); break; case 'L': listar_marcas(); break; } } //*********************************************************************************** // void menu_operadores() // //*********************************************************************************** void menu_operadores() { char opcao; lcd_erase_all(); puts(mManterInfo_L1); opcao = kbd_getc(SOLETRA); switch(opcao) { case 'I':

Page 101: desenvolvimento de software e hardware embutido para um sistema

92

incluir_operadores(); break; case 'A': alterar_operadores(); break; case 'E': excluir_operadores(); break; case 'L': listar_operadores (); break; } } //*********************************************************************************** // void menu_patio() // //*********************************************************************************** void menu_patio() { char opcao; lcd_erase_all(); puts(mPatio_L1); opcao = kbd_getc(SOLETRA); switch(opcao) // testar com 'else if' { case 'E': entrada_patio(); break; case 'S': saida_patio(); break; case 'L': listar_patio(); break; } } //*********************************************************************************** // void menu_mensal() // //*********************************************************************************** void menu_mensal() { char opcao; lcd_erase_all(); puts(mMensalistas_L1); puts(mMensalistas_L2); opcao = kbd_getc(SOLETRA); switch(opcao) // testar com 'else if' { case 'I': incluir_mensalista(); break; case 'A': alterar_mensalista (); break; case 'E': excluir_mensalista(); break; case 'L':

Page 102: desenvolvimento de software e hardware embutido para um sistema

93

listar_mensalista(); break; case 'P': pagamento_mensalista(); break; case 'D': data_limite(); break; } } //***********************************************************************************/ // void altera_relogio () // //*********************************************************************************** void altera_relogio () { static int xpos, ypos; char lido_temp[3], op, temp1[3], temp2[3], temp3[3], temp4[3]; int ano_padrao; struct Time t0; struct Date d0; struct Date tempd0; static FILE *relogio; int num; relogio = fopen("relogio", FM_RDWR); relogio->offset = 1; fread (buf_ano_padrao, 2, relogio); buf_ano_padrao[2] = '\0'; num = atoi (buf_ano_padrao); for(EVER) { read8583_rtc(&t0, &d0, GET_DATE_TIME); lcd_erase_all(); if (d0.day < 10) { strcpy (temp4,itoa(d0.day)); sprintf(temp1, "0%s", temp4); } else strcpy (temp1, itoa(d0.day)); if (d0.month < 10) { strcpy (temp4,itoa(d0.month)); sprintf(temp2, "0%s", temp4); } else strcpy (temp2, itoa(d0.month)); if ((d0.year + num) < 10) { strcpy (temp4, (itoa(d0.year + num))); sprintf(temp3, "0%s", temp4); } else strcpy (temp3, itoa(num)); sprintf(buf, "Data Atual: %s/%s/%s\n", temp1, temp2, temp3); puts(buf); puts("Nova Data : / / "); xpos=13; ypos=2; lcd_gotoxy(xpos, ypos); kbd_gets(lido_temp, 2, 1,SONUMERO); d0.day = atoi(lido_temp); xpos += 3; lcd_gotoxy(xpos, ypos); kbd_gets(lido_temp, 2, 1,SONUMERO); d0.month = atoi(lido_temp);

Page 103: desenvolvimento de software e hardware embutido para um sistema

94

xpos += 3; lcd_gotoxy(xpos, ypos); kbd_gets(lido_temp, 4, 1,SONUMERO); d0.year = atoi(lido_temp); lcd_erase_all(); printf("%d\n", d0.year); printf("%d", num + 4); kbd_getc(LETRAENUMERO); if ((d0.year >= (num+4))) { relogio->offset = 1; strcpy (buf_ano_padrao, itoa(d0.year)); fwrite (buf_ano_padrao, 2, relogio); } xpos = 12; if ( ( (d0.day >= 1) && (d0.day <= 31) ) && ( (d0.month >= 1) && (d0.month <=12) ) ) //Falta restrição p/ ano. Bissexto: mod 4 != 100, exceto 400, e != 3300 if (!( ( (d0.day >= 30) && (d0.month == 2) ) || ( (d0.day == 31) && ( (d0.month == 4) || (d0.month == 6) || (d0.month == 9) || (d0.month == 11) ) ) ) ) if (!( ((d0.day == 29) && (d0.month == 2)) && (d0.year % 4) ) ) { //write8583_rtc(&t0,&d0,SET_DATE_TIME); tempd0 = d0; break; } } for(EVER) { lcd_erase_all(); if (t0.hour < 10) { strcpy (temp4,itoa(t0.hour)); sprintf(temp1, "0%s", temp4); } else strcpy (temp1, itoa(t0.hour)); if (t0.minute < 10) { strcpy (temp4,itoa(t0.minute)); sprintf(temp2, "0%s", temp4); } else strcpy (temp2, itoa(t0.minute)); if (t0.seconds < 10) { strcpy (temp4,itoa(t0.seconds)); sprintf(temp3, "0%s", temp4); } else strcpy (temp3, itoa(t0.seconds)); sprintf(buf, "Hora Atual: %s:%s:%s\n", temp1, temp2, temp3); puts(buf); puts("Nova Hora : : : "); xpos=13; ypos=2; lcd_gotoxy(xpos, ypos); kbd_gets(lido_temp, 2, 1,SONUMERO); t0.hour = atoi(lido_temp); xpos += 3; lcd_gotoxy(xpos, ypos); kbd_gets(lido_temp, 2, 1,SONUMERO); t0.minute = atoi(lido_temp); xpos += 3; lcd_gotoxy(xpos, ypos); kbd_gets(lido_temp, 4, 1,SONUMERO); t0.seconds = atoi(lido_temp); xpos = 12; if ( ( (t0.hour >=0) && (t0.hour < 24) ) && ( (t0.minute >=0) && (t0.minute < 60) ) && ( (t0.seconds >= 0) && (t0.seconds < 60) ) ) break; } write8583_rtc(&t0,&tempd0,SET_DATE_TIME); fclose(relogio);

Page 104: desenvolvimento de software e hardware embutido para um sistema

95

} //*********************************************************************************** // void abertura_caixa () // //*********************************************************************************** void abertura_caixa () { char nome_arq[9] = "caixa", valor[7]; int num; FILE* caixa; num = fexists(nome_arq); if (num < 0) fcreate(nome_arq, 0); caixa = fopen(nome_arq, FM_RDWR); lcd_erase_all(); puts("Valor (R$xxx.xx): "); lcd_gotoxy(19, 1); pega_valor (6, valor); insere_seq(valor, 7, caixa, 1); fclose(caixa); } //*********************************************************************************** // int entrada_caixa () // //*********************************************************************************** int entrada_caixa () { char nome_arq[6] = "caixa", valor[7], valor_caixa[8]; int inteiro = 0, frac = 0, temp, temp2; FILE* caixa; if (strcmp(codigo_operador, "00") == 0) { lcd_erase_all(); puts ("ERRO: Nao existe operador logado no\nsistema!"); kbd_getc(LETRAENUMERO); return -1; } if(fexists(nome_arq) < 0) { lcd_erase_all(); puts ("ERRO: Abertura de Caixa nao realizada!"); kbd_getc(LETRAENUMERO); return -1; } caixa = fopen(nome_arq, FM_RDWR); lcd_erase_all(); puts("Valor (R$xxx.xx): "); lcd_gotoxy(19, 1); pega_valor (6, valor); consulta(0, valor_caixa, caixa); // Passa a parte fracionaria de 'valor' para a var. 'frac' temp2 = strlen(valor); strncpy(buf, &valor[temp2 - 3], 2); buf[2] = '\0'; frac = atoi(buf); // Passa a parte fracionaria de 'valor_caixa' para a var. 'temp' temp2 = strlen(valor_caixa); strncpy(buf, &valor_caixa[temp2 - 3], 2); buf[2] = '\0'; temp = atoi(buf); // Soma a parte fracionaria frac += temp; if (frac >= 100) { frac -= 100; inteiro++; } // Passa a parte inteira de 'valor' para a var. 'inteiro' temp2 = strlen(valor); strncpy(buf, valor, temp2 - 3); buf[temp2 - 3] = '\0'; inteiro = atoi(buf); // Passa a parte inteira de 'valor_caixa' para a var. 'temp' temp2 = strlen(valor_caixa); strncpy(buf, valor_caixa, temp2 - 3); buf[temp2 - 3] = '\0'; temp = atoi(buf);

Page 105: desenvolvimento de software e hardware embutido para um sistema

96

// Soma a parte inteira inteiro += temp; // Transforma o result em string strcpy(valor_caixa, itoa(inteiro)); strcat(valor_caixa, "."); strcat(valor_caixa, itoa(frac)); temp2 = strlen(valor_caixa) + 1; insere_seq(valor_caixa, temp2, caixa, 1); puts("\nValor total do caixa: "); lcd_gotoxy(23, 1); puts(valor_caixa); kbd_getc(LETRAENUMERO); fclose(caixa); imprime_mov_caixa (ENTRADA, valor_caixa); return 0; } //*********************************************************************************** // int saida_caixa () // //*********************************************************************************** int saida_caixa () { char nome_arq[6] = "caixa", valor[7], valor_caixa[8]; int inteiro = 0, frac = 0, temp, temp2; FILE* caixa; // Verifica se ha operador logado no sistema if (strcmp(codigo_operador, "00") == 0) { lcd_erase_all(); puts ("ERRO: Nao existe operador logado no\nsistema!"); kbd_getc(LETRAENUMERO); return -1; } // Verifica se o arq 'caixa' existe if(fexists(nome_arq) < 0) { lcd_erase_all(); puts ("ERRO: Abertura de Caixa nao realizada!"); kbd_getc(LETRAENUMERO); return -1; } caixa = fopen(nome_arq, FM_RDWR); lcd_erase_all(); puts("Valor (R$xxx.xx): "); lcd_gotoxy(19, 1); pega_valor (6, valor); consulta(0, valor_caixa, caixa); // Passa a parte inteira de 'valor' para a var. 'temp' temp2 = strlen(valor); strncpy(buf, valor, temp2 - 3); buf[temp2 - 3] = '\0'; temp = atoi(buf); // Passa a parte inteira de 'valor_caixa' para a var. 'inteiro' temp2 = strlen(valor_caixa); strncpy(buf, valor_caixa, temp2 - 3); buf[temp2 - 3] = '\0'; inteiro = atoi(buf); // Diminui a parte inteira inteiro -= temp; // Passa a parte fracionaria de 'valor' para a var. 'temp' temp2 = strlen(valor); strncpy(buf, &valor[temp2 - 3], 2); buf[2] = '\0'; temp = atoi(buf); // Passa a parte fracionaria de 'valor_caixa' para a var. 'frac' temp2 = strlen(valor_caixa); strncpy(buf, &valor_caixa[temp2 - 3], 2); buf[2] = '\0'; frac = atoi(buf); // Diminui a parte fracionaria frac -= temp; if (frac < 0) { frac *= -1;

Page 106: desenvolvimento de software e hardware embutido para um sistema

97

inteiro--; } if (inteiro < 0) { lcd_erase_all(); puts("ERRO: Dinheiro insuficiente em caixa!!"); puts("\nValor total do caixa: "); lcd_gotoxy(23, 2); puts(valor_caixa); kbd_getc(LETRAENUMERO); fclose(caixa); return -1; } // Transforma o result em string strcpy(valor_caixa, itoa(inteiro)); strcat(valor_caixa, "."); strcat(valor_caixa, itoa(frac)); temp2 = strlen(valor_caixa) + 1; insere_seq(valor_caixa, temp2, caixa, 1); //lcd_erase_all(); puts("\nValor total do caixa: "); lcd_gotoxy(23, 1); puts(valor_caixa); kbd_getc(LETRAENUMERO); fclose(caixa); imprime_mov_caixa (SAIDA, valor_caixa); return 0; } //*********************************************************************************** // void imprime_mov_caixa (char mov, char valor[]) // //*********************************************************************************** void imprime_mov_caixa (char mov, char valor[]) { struct Time t0; struct Date d0; int temp; strcpy(buf,"\n\n === ENTRADA DE CAIXA ==="); if (mov) strcpy(buf,"\n\n === SAIDA DE CAIXA ==="); prn_printf(buf); prn_printf("\n\n"); prn_printf("\tCodigo do Oper.: "); prn_printf(codigo_operador); prn_printf("\n"); prn_printf("\tValor da Oper..: "); prn_printf(valor); prn_printf("\n"); read8583_rtc(&t0, &d0, GET_DATE_TIME); strcpy(buf, "\0"); if (strlen(itoa(d0.day)) == 1) strcat(buf, "0"); strcat(buf, itoa(d0.day)); strcat(buf, "/"); if (strlen(itoa(d0.month)) == 1) strcat(buf, "0"); strcat(buf, itoa(d0.month)); strcat(buf, "/"); temp = descobre_ano() + d0.year; strcat(buf, itoa(temp)); strcat(buf, " - "); if (strlen(itoa(t0.hour)) == 1) strcat(buf, "0"); strcat(buf, itoa(t0.hour)); strcat(buf, ";"); if (strlen(itoa(t0.minute)) == 1) strcat(buf, "0"); strcat(buf, itoa(t0.minute)); strcat(buf, ":"); if (strlen(itoa(t0.seconds)) == 1) strcat(buf, "0");

Page 107: desenvolvimento de software e hardware embutido para um sistema

98

strcat(buf, itoa(t0.seconds)); prn_printf("\t"); prn_printf(buf); prn_printf("\n\n\n\n\n"); } //*********************************************************************************** // incluir_marcas () // //*********************************************************************************** void incluir_marcas () { char marca[11], buffer[15]="\0", nome_arq[6] = "marca"; FILE* tab_marca; int cod, num; // Se nao existir, cria o arquivo 'marca'. O arquivo eh aberto para uso. num = fexists(nome_arq); if (num < 0) fcreate(nome_arq, 15); tab_marca = fopen(nome_arq, FM_RDWR); // Calcula o numero do codigo num = prox_vazio(tab_marca); cod = ( (num - 1) / tab_marca->tag ) + 1 ; // Completa o campo 'cod_marca' para que tenha 3 caracteres if (cod < 10) strcpy(buffer, "00"); else if (cod > 9 && cod < 100) strcpy(buffer, "0"); // Faz interface com usuario e recolhe os dados strcat(buffer, itoa(cod)); lcd_erase_all(); sprintf(buf, "Cod.Marca: %s\nMarca: ", buffer); puts(buf); lcd_gotoxy(8, 2); kbd_gets(marca, 10, 0,LETRAENUMERO); lcd_gotoxy(25, 2); puts("Classe(1-6): "); lcd_gotoxy(38, 2); pega_num (1, 1, 6, &buffer[3]); // Copia os campos em 'buffer' e insere o registro: COD | CLASSE | MARCA strcat(buffer, marca); insere(buffer, tab_marca); // Fecha arquivo fclose(tab_marca); } //*********************************************************************************** // int alterar_marcas () // //*********************************************************************************** int alterar_marcas () { char novo_reg[12], registro[15], classe[2], nome_arq[6] = "marca"; char len; int offset; FILE* tab_marca; // Verifica se a tabela de marcas existe if(fexists(nome_arq) < 0) { lcd_erase_all(); puts ("ERRO: Tabela de Marcas nao configurada!"); kbd_getc(LETRAENUMERO); return -1; } // Abre arquivo 'marca' tab_marca = fopen(nome_arq, FM_RDWR); lcd_erase_all(); puts ("Cod. Marca: "); lcd_gotoxy(13, 1); pega_num (3, 1, 999, novo_reg); offset = consulta(novo_reg, registro, tab_marca); // Se codigo nao existir => ERRO! if(offset < 0) { lcd_erase_all(); puts ("ERRO: Codigo nao cadastrado!"); kbd_getc(LETRAENUMERO); fclose(tab_marca); return -1;

Page 108: desenvolvimento de software e hardware embutido para um sistema

99

} // Senao, altera a marca else { strcpy(novo_reg, "\0"); lcd_erase_all(); sprintf(buf, "Marca: %s\nNova Marca: ", &registro[4]); puts(buf); lcd_gotoxy(13, 2); kbd_gets(&novo_reg[1], 10, 0,LETRAENUMERO); lcd_erase_all(); sprintf(buf, "Classe: %c\nNova Classe: ", registro[3]); puts(buf); lcd_gotoxy(14, 2); //kbd_gets(classe, 1, 0,SONUMERO); pega_num (1, 1, 6, classe); novo_reg[0] = classe[0]; len = strlen(novo_reg); altera(novo_reg, offset+3, len+1, tab_marca); } // Fecha arquivo fclose(tab_marca); return 0; } //*********************************************************************************** // excluir_marcas () // //*********************************************************************************** int excluir_marcas () { char cod_marca[4], registro[15], opcao[2], nome_arq[6] = "marca"; FILE* tab_marca; int offset; // Verifica se a tabela de marcas existe if(fexists(nome_arq) < 0) { lcd_erase_all(); puts ("ERRO: Tabela de Marcas nao configurada!"); kbd_getc(LETRAENUMERO); return -1; } // Abre arquivo 'marca' tab_marca = fopen(nome_arq, FM_RDWR); // Pega o codigo da marca a ser excluida lcd_erase_all(); puts("Cod. Marca: "); lcd_gotoxy(13, 1); //kbd_gets(cod_marca, 3, 0,SONUMERO); pega_num (3, 1, 999, cod_marca); offset = consulta(cod_marca, registro, tab_marca); // Se codigo nao existir => ERRO! if (offset < 0) { lcd_erase_all(); puts ("ERRO: Codigo nao cadastrado!"); kbd_getc(LETRAENUMERO); fclose(tab_marca); return -1; } // Senao, exclui a marca else { for(EVER) { lcd_erase_all(); sprintf(buf, "%s - %s", cod_marca, &registro[4]); puts(buf); puts("\nExcluir?(S/N): "); lcd_gotoxy(16, 2); kbd_gets(opcao, 1, 1,SOLETRA); if (opcao[0] == 'S') { remove(offset, tab_marca); break; } else if (opcao[0] == 'N')

Page 109: desenvolvimento de software e hardware embutido para um sistema

100

{ lcd_erase_all(); puts("Operacao Cancelada!"); kbd_getc(LETRAENUMERO); break; } else continue; } } // Fecha arquivo fclose(tab_marca); return 0; } //*********************************************************************************** // int listar_marcas () // //*********************************************************************************** int listar_marcas () { char cod_marca[4], classe[2], registro[15], nome_arq[6] = "marca"; char cod = 0, tam; int tem_registro; FILE* tab_marca; // Verifica se a tabela de marcas existe if(fexists(nome_arq) < 0) { lcd_erase_all(); puts ("ERRO: Tabela de Marcas nao configurada!"); kbd_getc(LETRAENUMERO); return -1; } // Abre arquivo 'marca' tab_marca = fopen(nome_arq, FM_RDWR); // 'tam' recebe o numero de registros existentes no arquivo tam = ( (tab_marca->pfile->size - 1) / tab_marca->tag ); lcd_erase_all(); puts("Imprimindo..."); prn_printf("\n\n\t======= TABELA DE MARCAS =======\n\n"); prn_printf("CODIGO\t\tCLASSE\t\tMARCA\n\n"); while (tam > 0) { // Codigo da marca a ser procurada cod++; if (cod < 10) strcpy(cod_marca, "00"); else if (cod > 9 && cod < 100) strcpy(cod_marca, "0"); strcat(cod_marca, itoa(cod) ); tem_registro = consulta(cod_marca, registro, tab_marca); // Se codigo nao foi encontrado, procura proximo codigo if (tem_registro < 0) continue ; // Se foi encontrado, imprime strncpy(classe, &registro[3], 1); prn_printf(cod_marca); prn_printf("\t\t"); prn_printf(classe); prn_printf("\t\t"); prn_printf(&registro[4]); prn_printf("\n"); tam--; } prn_printf("\n\n\n\n\n\n\n\n"); // Fecha arquivo fclose(tab_marca); return 0; } //*********************************************************************************** // altera_senhas () // //*********************************************************************************** int altera_senhas () { char i, opcao[2], nova_senha[9]; int address = END_SENHA; for(EVER)

Page 110: desenvolvimento de software e hardware embutido para um sistema

101

{ lcd_erase_all(); puts ("Escolha a senha a ser alterada: \n(O)perador (G)erente (R)oot"); lcd_gotoxy(33, 1); // 33 == strlen("Escolha a senha a ser alterada: ") kbd_gets(opcao, 1, 0,SOLETRA); if (opcao[0] == 'G') address += 9; else if (opcao[0] == 'R') address += 18; else continue; lcd_erase_all(); puts ("Digite a nova senha: "); lcd_gotoxy(22, 1); kbd_gets(nova_senha, 8, 0,LETRAENUMERO); for (i = 0; i < 9; i++) i2c_eepromWrite(I2C_EEPROM_A0, address++, nova_senha[i]); lcd_erase_all(); puts("Senha alterada com sucesso!!\n"); address -= 9; i2c_eepromSequentialRead(I2C_EEPROM_A0, address, buf, 9); puts(buf); kbd_getc(LETRAENUMERO); return 0; } } //*********************************************************************************** // troca_nivel_acesso () // //*********************************************************************************** int troca_nivel_acesso () { char senha_lida[9], senha[9], novo_nivel[2], nivel[2], nome_arq[9] = "operador"; char i, j; int address = END_SENHA; FILE* op; op = fopen(nome_arq, FM_RDWR); if ( op == NULL ) return -1; lcd_erase_all(); puts("Nivel(1-4): "); lcd_gotoxy(13, 1); kbd_gets(novo_nivel, 1, 0,SONUMERO); strcpy(buf, "\0"); // Busca o registro referente ao codigo do operador if ( consulta(codigo_operador, buf, op) < 0 ) { lcd_erase_all(); puts("ERRO: Operador nao cadastrado!"); kbd_getc(LETRAENUMERO); fclose(op); return -1; } // Copia o nivel do operador para a variavel 'nivel' e verifica se ele pode operar no nivel requisitado strncpy(nivel, &buf[2], 1); if (atoi(novo_nivel) > atoi(nivel) ) { lcd_erase_all(); puts("ERRO: Voce nao pode operar neste nivel!!"); kbd_getc(LETRAENUMERO); fclose(op); return -1; } puts("\nSenha: "); lcd_gotoxy(8, 2); kbd_gets(senha_lida, 8, 0,LETRAENUMERO); // Procura a senha for(i=0; i<4; i++) { for(j = 0; j < 9 ; j++) senha[j] = i2c_eepromRead(I2C_EEPROM_A0, address++); lcd_erase_all(); puts("address: "); lcd_gotoxy(10,1); address -= 9; puts( itoa(address) ); puts("\nsenha:"); lcd_gotoxy(10,2); puts(senha);

Page 111: desenvolvimento de software e hardware embutido para um sistema

102

kbd_getc(LETRAENUMERO); address += 9; // Verifica se a senha lida eh a senha do nivel requisitado if ( (strcmp(senha, senha_lida) == 0) && (atoi(novo_nivel) == (i+1) ) ) { nivel_operador = i+1; fclose(op); return 0; } } fclose(op); return -1; } //*********************************************************************************** // void incluir_operadores () // //*********************************************************************************** void incluir_operadores () { char buffer[24] = "\0", nome[21], nome_arq[9] = "operador"; int num, cod; FILE* op; // Se o arq nao existe, cria. Depois abre o arq para uso num = fexists(nome_arq); if (num < 0) fcreate(nome_arq, 24); op = fopen(nome_arq, FM_RDWR); // Calcula o numero do codigo do operador num = prox_vazio(op); cod = ( (num - 1) / op->tag ) + 1 ; // Completa o campo 'cod' para que tenha 2 caracteres if (cod < 10) strcat(buffer, "0"); strcat(buffer, itoa(cod)); // Recolhe os dados do usuario lcd_erase_all(); sprintf(buf, "Cod. Op: %s Nome: ", buffer); puts(buf); lcd_gotoxy(20, 1); kbd_gets(nome, 20, 0,LETRAENUMERO); puts("\nNivel (1-3): "); lcd_gotoxy(14, 2); //kbd_gets(&buffer[2], 1, 0,SONUMERO); pega_num (1, 1, 3, &buffer[2]); // Concatena os campos do registro strcat(buffer, nome); // Insere o registro no arquivo apontado por 'op' insere(buffer, op); // Fecha arquivo fclose(op); } //*********************************************************************************** // void alterar_operadores () // //*********************************************************************************** int alterar_operadores () { char novo_reg[22], buffer[24], nivel[2], nome_arq[9] = "operador"; char len; int offset; FILE* op; // Verifica se a tabela de operadores existe if(fexists(nome_arq) < 0) { lcd_erase_all(); puts ("ERRO: Tabela de Op. nao configurada!"); kbd_getc(LETRAENUMERO); return -1; } // Abre o arquivo op = fopen(nome_arq, FM_RDWR); // Pega o codigo do operador a ser alterado lcd_erase_all(); puts("Cod. Op: "); lcd_gotoxy(10, 1); pega_num (2, 1, 99, novo_reg);

Page 112: desenvolvimento de software e hardware embutido para um sistema

103

// Pega o registro referente ao codigo offset = consulta(novo_reg, buffer, op); if(offset < 0) { lcd_erase_all(); puts ("ERRO: Codigo nao cadastrado!"); kbd_getc(LETRAENUMERO); fclose(op); return -1; } else { lcd_erase_all(); sprintf(buf, "Nome: %s\nNovo Nome: ", &buffer[3]); puts(buf); lcd_gotoxy(12, 2); kbd_gets(&novo_reg[1], 20, 0,LETRAENUMERO); lcd_erase_all(); sprintf(buf, "Nivel: %c\nNovo Nivel: ", buffer[2]); puts(buf); lcd_gotoxy(13, 2); pega_num (1, 1, 3, nivel); novo_reg[0] = nivel[0]; len = strlen(novo_reg); altera(novo_reg, offset+2, len+1, op); } fclose(op); return 0; } //*********************************************************************************** // void excluir_operadores () // //*********************************************************************************** int excluir_operadores () { char buffer[24] = "\0", cod_op[3], opcao[2], nome_arq[9] = "operador"; int offset; FILE* op; // Verifica se a tabela de operadores existe if(fexists(nome_arq) < 0) { lcd_erase_all(); puts ("ERRO: Tabela de Op. nao configurada!"); kbd_getc(LETRAENUMERO); return -1; } op = fopen(nome_arq, FM_RDWR); // Pega o codigo do operador a ser alterado lcd_erase_all(); puts("Cod. Op: "); lcd_gotoxy(10, 1); pega_num (2, 1, 99, cod_op); offset = consulta(cod_op, buffer, op); if (offset < 0) { lcd_erase_all(); puts ("ERRO: Tabela de Op. nao configurada!"); fclose(op); kbd_getc(LETRAENUMERO); return -1; } else { for(EVER) { lcd_erase_all(); sprintf(buf, "%s - %s", cod_op, &buffer[3]); puts(buf); puts("\nExcluir?(S/N): "); lcd_gotoxy(16, 2); kbd_gets(opcao, 1, 1,SOLETRA); if (opcao[0] == 'S') { remove(offset, op); break; }

Page 113: desenvolvimento de software e hardware embutido para um sistema

104

else if (opcao[0] == 'N') { lcd_erase_all(); puts("Operacao Cancelada!"); kbd_getc(LETRAENUMERO); break; } else continue; } } // Fecha arquivo fclose(op); return 0; } //*********************************************************************************** // int listar_operadores () // //*********************************************************************************** int listar_operadores () { char cod_op[3] = "\0", nivel[2] = "\0", registro[24], nome_arq[9] = "operador"; char cod = 0, tam; int tem_registro; FILE* op; // Verifica se a tabela de operadores existe if(fexists(nome_arq) < 0) { lcd_erase_all(); puts ("ERRO: Tabela de Op. nao configurada!"); kbd_getc(LETRAENUMERO); return -1; } // Abre arquivo 'operador' op = fopen(nome_arq, FM_RDWR); // 'tam' recebe o numero de registros existentes no arquivo tam = ( (op->pfile->size - 1) / op->tag ); lcd_erase_all(); puts("Imprimindo..."); prn_printf("\n\n\t=======TABELA DE OPERADORES ======\n\n"); prn_printf("CODIGO\tNIVEL\tNOME\n\n"); while (tam > 0) { cod++; if (cod < 10) strcpy(cod_op, "0"); strcat(cod_op, itoa(cod) ); tem_registro = consulta(cod_op, registro, op); if (tem_registro < 0) continue ; strncpy(nivel, &registro[2], 1); prn_printf(cod_op); prn_printf("\t"); prn_printf(nivel); prn_printf("\t"); prn_printf(&registro[3]); prn_printf("\n"); tam--; } prn_printf("\n\n\n\n\n\n\n\n"); fclose(op); return 0; } //*********************************************************************************** // int troca_operadores () // //*********************************************************************************** int troca_operadores () { char cod_op[3], opcao[2], nome_arq[9] = "operador"; FILE* op; // Verifica se a tabela de operadores existe if(fexists(nome_arq) < 0) { lcd_erase_all(); puts ("ERRO: Tabela de Op. nao configurada!"); kbd_getc(LETRAENUMERO);

Page 114: desenvolvimento de software e hardware embutido para um sistema

105

return -1; } // Abre arquivo op = fopen(nome_arq, FM_RDWR); if (op->pfile->size == 1) { lcd_erase_all(); puts ("ERRO: Tabela de Op. vazia!!"); kbd_getc(LETRAENUMERO); fclose(op); return -1; } lcd_erase_all(); if ( strcmp(codigo_operador, "00") == 0 ) puts("Nao ha nenhum operador logado no sistema"); else { consulta(codigo_operador, buf, op); puts("Op.: "); lcd_gotoxy(6, 1); puts(codigo_operador); lcd_gotoxy(8, 1); puts(" - "); lcd_gotoxy(11, 1); puts(&buf[3]); } for (EVER) { // Pega o cod. do novo operador do sistema lcd_gotoxy(1, 2); puts("Cod. Op.: "); lcd_gotoxy(10, 2); kbd_gets(cod_op, 2, 0, SONUMERO); // Se o codigo nao existir, pega o cod. novamente if (consulta(cod_op, buf, op) < 0) continue; lcd_erase_all(); puts(cod_op); lcd_gotoxy(3, 1); puts(" - "); lcd_gotoxy(6, 1); puts(&buf[3]); lcd_gotoxy(strlen(&buf[3])+7, 1); puts("?(S/N) "); lcd_gotoxy(strlen(&buf[3])+14, 1); kbd_gets(opcao, 1, 1, SOLETRA); // Se as informacoes sao corretas... if ( opcao[0] == 'S' ) { // Atualiza 'codigo_operador' strcpy(codigo_operador, cod_op); lcd_erase_all(); puts("Operador trocado com sucesso!!"); kbd_getc(LETRAENUMERO); break; } else if ( opcao[0] == 'N' ) { lcd_erase_all(); puts("Operacao cancelada!!"); kbd_getc(LETRAENUMERO); break; } } fclose(op); return 0; } //*********************************************************************************** // void configura_cabecalho () // //*********************************************************************************** void configura_cabecalho () // FALTA PROGRAMAR AS EXCEÇÕES!!!!!!!!!!!!!!!!!!!!!!!! {

Page 115: desenvolvimento de software e hardware embutido para um sistema

106

char i, j, tamanho, c, buf[20], offset; FILE *cabecalho, *rodape; char expande[2], str[41]; int num, tam; num = fexists("cabeca"); if (num < 0) { fcreate("cabeca", 41); cabecalho = fopen("cabeca", FM_RDWR); } else { cabecalho = fopen("cabeca", FM_RDWR); tam = ( (cabecalho->pfile->size - 1) / (cabecalho->tag) ); cabecalho->offset = 1; while (tam) { remove(offset, cabecalho); cabecalho->offset += (cabecalho->tag-1); tam--; } } for(i=1; i<=5; i++) { lcd_erase_all(); sprintf(buf, "Cabecalho %d:", i); puts(buf); lcd_gotoxy(13, 1); kbd_gets(str, 40, 0,LETRAENUMERO); tamanho = strlen(str); while ((tamanho < 3) && (str[0] != '\0')) { lcd_erase(left, tamanho); puts("Minimo de 3 caracteres!"); lcd_gotoxy(36, 1); while((c = kbd_getc(LETRAENUMERO)) != ENTER); lcd_erase(left, strlen("Minimo de 3 caracteres!")); kbd_gets(str, 40, 0,LETRAENUMERO); tamanho = strlen(str); } if(str[0] != '\0') insere(str, cabecalho); // Verificar se este passo é realmente necessário, pois na passagem, pode conter lixo no str for (j = 0; j < tamanho; j++) str[j] = '\0'; } cabecalho->offset = 124; fread (buf , 4, cabecalho); lcd_erase_all(); puts("debuga cabec\n"); puts(buf); kbd_getc(LETRAENUMERO); fclose(cabecalho); num = fexists("rodape"); if (num < 0) fcreate("rodape", 41); rodape = fopen("rodape", FM_RDWR); // Configura rodape for(i=1; i<=3; i++) { lcd_erase_all(); sprintf(buf, "Rodape %d:", i); puts(buf); lcd_gotoxy(10, 1); kbd_gets(str, 40, 0,LETRAENUMERO); tamanho = strlen(str); while ((tamanho < 3) && (str[0] != '\0')) { lcd_erase(left, tamanho); puts("Minimo de 3 caracteres!"); lcd_gotoxy(33, 1); while((c = kbd_getc(LETRAENUMERO)) != ENTER); lcd_erase(left, strlen("Minimo de 3 caracteres!")); kbd_gets(str, 40, 0,LETRAENUMERO); tamanho = strlen(str); }

Page 116: desenvolvimento de software e hardware embutido para um sistema

107

if(str[0] != '\0') insere(str, cabecalho); // Verificar se este passo é realmente necessário, pois na passagem, pode conter lixo no str for (j = 0; j < tamanho; j++) str[j] = '\0'; } fclose(rodape); } //*********************************************************************************** // void configura_tab_preco () // //*********************************************************************************** void configura_tab_preco () // FAZER VALIDACAO!! CAMPOS PRECISAM TER O TAMANHO ESPECIFICADO!!!! { char num_tab[2], desistencia[3], tol_hora[3], tol_24[2], fim[3], valor[6], nome_tab[5] = "tab\0"; //char fracionado[], fracao[]; static char teste; static int num, inicio, len, num_int = 9; FILE* preco; lcd_erase_all(); puts("Digite o numero da tabela a ser\nconfigurada (1-6): "); lcd_gotoxy(20, 2); pega_num(1, 1, 6, num_tab); strcat(nome_tab, num_tab); num = fexists(nome_tab); if (num < 0) fcreate(nome_tab, 0); preco = fopen(nome_tab, FM_RDWR); lcd_erase_all(); puts("Tempo de Desistencia (xx min): \nTolerancia na Hora (xx min): "); lcd_gotoxy(32, 1); kbd_gets(desistencia, 2, 0, SONUMERO); strcpy(buf, desistencia); lcd_gotoxy(30, 2); kbd_gets(tol_hora, 2, 0, SONUMERO); //pega_codigo(2, 0, 99, tol_hora); strcat(buf, tol_hora); lcd_erase_all(); puts("Tolerancia 24h (x hs): "); lcd_gotoxy(24, 1); kbd_gets(tol_24, 1, 0, SONUMERO); strcat(buf, tol_24); num = atoi(num_tab); inicio = 0; do { strcpy(valor, "\0"); lcd_erase_all(); puts("Tabela ate hs de permanencia"); lcd_gotoxy(8, 1); puts(itoa(num)); lcd_gotoxy(14, 1); puts(itoa(inicio)); lcd_gotoxy(21, 1); if (num_int) pega_num(2, inicio+1, 24, fim); else { strcpy(fim, "24\0"); puts("24\0"); } strcat(buf, fim); puts("\nValor (R$xx.xx): "); lcd_gotoxy(18, 2); pega_valor (5, valor); strcat(buf, valor); inicio = atoi(fim); num_int --; } while(inicio < 24); len = strlen(buf); insere_seq(buf, len, preco, 1); fclose(preco); }

Page 117: desenvolvimento de software e hardware embutido para um sistema

108

//*********************************************************************************** // void listar_tab_preco () // //*********************************************************************************** void listar_tab_preco () { char tab[2], desistencia[3], tol[3], tol24[2], hora[3], valor[6], nome_tab[5] = "tab\0"; char i, j, inicio, fim, num = 0, num_intervalos; int tam; FILE* tab_preco; while (1) { lcd_erase_all(); puts("Tabela(s)? (1-6/T): "); lcd_gotoxy(21, 1); kbd_gets(tab, 1, 0,SONUMERO); // Se for digitado um numero entre 1 e 6 (inclusive), ajusta as variaveis 'inicio' e 'fim' e imprime a tabela correspondente if ( (atoi(tab) > 0) && (atoi(tab) < 7) ) { inicio = atoi(tab); fim = inicio; break; } // Se for digitado 'T', ajusta as variaveis 'inicio' e 'fim' e imprime todas as tabelas if ( tab[0] == 'T') { inicio = 1; fim = 6; break; } } puts("\nImprimindo..."); prn_printf("\n\n\t=== TABELA DE PRECOS ===\n"); for (i = inicio; i <= fim; i++) { strcat( nome_tab, itoa(i) ); if ( fexists(nome_tab) < 0 ) { prn_printf("\n\n\tA TABELA "); prn_printf( itoa(i) ); prn_printf(" NAO ESTA CONFIGURADA!\n\n\n"); strcpy(nome_tab, "tab\0"); continue; } tab_preco = fopen(nome_tab, FM_RDWR); consulta (0, buf, tab_preco); strncpy(desistencia, buf, 2); strncpy(tol, &buf[2], 2); strncpy(tol24, &buf[4], 1); desistencia[2]= '\0'; tol[2] = '\0'; tol24[1] = '\0'; prn_printf("\nTABELA "); prn_printf( itoa(i) ); prn_printf(" - Classe "); prn_printf( itoa(i) ); prn_printf("\n\nDESISTENCIA\tTOLERANCIA\tTOLERANCIA 24HS\n"); prn_printf(desistencia); prn_printf(" min\t\t"); prn_printf(tol); prn_printf(" min\t\t"); prn_printf(tol24); prn_printf(" h\n\n"); // Calcula o numero de intervalos tam = strlen(buf); num_intervalos = (tam - 5) / 7; // Imprime os intervalos da tabela for(j = 0; j < num_intervalos; j++) { // 'Zera' as variaveis strcpy(hora, "\0"); strcpy(valor, "\0");

Page 118: desenvolvimento de software e hardware embutido para um sistema

109

// Copia o valores p/ as variaveis e imprime strncpy (hora, &buf[5 + (j*7)], 2); hora[2] = '\0'; valor[5] = '\0'; strncpy (valor , &buf[7 + (j*7)], 5); prn_printf("Ate "); prn_printf(hora); prn_printf(" hs de permanencia: R$ "); prn_printf(valor); prn_printf("\n"); } strcpy(nome_tab, "tab\0"); fclose (tab_preco); } prn_printf("\n\n\n\n\n\n\n\n"); } //*********************************************************************************** // int entrada_patio () // //*********************************************************************************** int entrada_patio (void) { char placa[8], cod_marca[4], nome_marca[11], entrada_patio[23]; char temp[3], c, marca[11], erro[] = "CodigoInvalido!"; FILE *tab_marca, *cliente; static FILE* entrada; struct Time t0; struct Date d0; int num, num_mensal, offset, mensalista, cod_entrada; num = fexists("entrada"); if (num < 0) fcreate("entrada", 22); entrada = fopen("entrada", FM_RDWR); if (entrada == NULL) { fclose(entrada); return -1; } num = fexists("marca"); if (num < 0) { lcd_erase_all(); puts("Configure as Marcas!"); while((c = kbd_getc(LETRAENUMERO)) != ENTER); fclose(entrada); return -1; } tab_marca = fopen("marca", FM_RDWR); if (tab_marca == NULL) { fclose(entrada); fclose(tab_marca); return -1; } num_mensal = fexists("mensal"); if (num_mensal >= 0) cliente = fopen("mensal", FM_RDWR); // Zera a variavel "entrada_patio" for (c = 0; c < 22; c++) entrada_patio[c] = '\0'; lcd_erase_all(); lcd_cursor(lcd_cursor_blink); lcd_erase_all(); lcd_gotoxy(34,2); mensalista = -1; mensalista = consulta(placa, buf, cliente);

Page 119: desenvolvimento de software e hardware embutido para um sistema

110

if (num_mensal >= 0) fclose(cliente); offset = -1; while(offset < 0){ pega_codMarca(cod_marca); offset = consulta(cod_marca, marca, tab_marca); if(offset < 0) lcd_erase(left, 3); } lcd_gotoxy(24, 1); c = 4; while (marca[c] != '\0') { putch(marca[c]); c++; } while((c = kbd_getc(LETRAENUMERO)) != ENTER); read8583_rtc(&t0, &d0, GET_DATE_TIME); strcat(entrada_patio, placa); strcat(entrada_patio, cod_marca); if (strlen(itoa(d0.year)) == 1) strcat(entrada_patio, "0"); strcat(entrada_patio, itoa(d0.year)); if (strlen(itoa(d0.month)) == 1) strcat(entrada_patio, "0"); strcat(entrada_patio, itoa(d0.month)); if (strlen(itoa(d0.day)) == 1) strcat(entrada_patio, "0"); strcat(entrada_patio, itoa(d0.day)); if (strlen(itoa(t0.hour)) == 1) strcat(entrada_patio, "0"); strcat(entrada_patio, itoa(t0.hour)); if (strlen(itoa(t0.minute)) == 1) strcat(entrada_patio, "0"); strcat(entrada_patio, itoa(t0.minute)); if (strlen(itoa(t0.seconds)) == 1) strcat(entrada_patio, "0"); strcat(entrada_patio, itoa(t0.seconds)); cod_entrada = insere(entrada_patio, entrada); lcd_erase_all(); printf("%d", mensalista); while((c = kbd_getc(LETRAENUMERO)) != ENTER); lcd_erase_all(); lcd_erase_all(); printf("%d", cod_entrada); while((c = kbd_getc(LETRAENUMERO)) != ENTER); lcd_erase_all(); fclose(entrada); fclose(tab_marca); imprime_entrada(entrada_patio, marca, mensalista, cod_entrada); return 0; } //*********************************************************************************** // void listar_patio () // //*********************************************************************************** void listar_patio () { FILE *entrada,*mensalista; char cont,cont1,cont2; char tam,buffer[50]="",impressao[12]; struct Time hora_atual; struct Date data_atual; if(fexists("entrada") < 0) { lcd_erase_all(); puts ("ERRO: Tabela de Entrada nao configurada!"); kbd_getc(LETRAENUMERO); return; } entrada = fopen("entrada", FM_RDWR); tam = ( (entrada->pfile->size - 1) / (entrada->tag) ); if(tam==0) { lcd_erase_all(); puts ("ERRO: Tabela de Entrada vazia!"); cont=kbd_getc(LETRAENUMERO); return; } if (fexists("mensal")>=0) mensalista=fopen("mensal",FM_RDWR);

Page 120: desenvolvimento de software e hardware embutido para um sistema

111

entrada->offset=1; lcd_erase_all(); read8583_rtc(&hora_atual, &data_atual, GET_DATE_TIME); puts("Imprimindo..."); sprintf(buffer,"\n\n\t LISTA PATIO %02d/%02d/%02d %02d:%02d:%02d\0",data_atual.day,data_atual.month,data_atual.year,hora_atual.hour,hora_atual.minute,hora_atual.seconds); prn_printf(buffer); prn_printf("\n\nPLACA TIPO MARCA HORA DATA\n\0"); for(cont1=1;cont1<=tam;cont1++) { cont2=0; printer('\n'); fread (buffer,22,entrada); if ((buffer[2]>='0')&&(buffer[2]<='9')) cont2=1; strncpy(impressao,buffer,7-cont2); impressao[7-cont2]='\0'; prn_printf(impressao); prn_printf(" "); if (cont2) printer(' '); if (fexists("mensal")>=0) if (consulta(impressao,buf,mensalista)>0) printer('M'); else printer('A'); else printer('A'); prn_printf(" "); strncpy(impressao,buffer+7-cont2,3); impressao[3]='\0'; prn_printf(impressao); prn_printf(" "); strncpy(impressao,buffer+16-cont2,2); impressao[2]='\0'; prn_printf(impressao); printer(':'); strncpy(impressao,buffer+18-cont2,2); impressao[2]='\0'; prn_printf(impressao); printer(':'); strncpy(impressao,buffer+20-cont2,2); impressao[2]='\0'; prn_printf(impressao); prn_printf(" "); strncpy(impressao,buffer+14-cont2,2); impressao[2]='\0'; prn_printf(impressao); printer('/'); strncpy(impressao,buffer+12-cont2,2); impressao[2]='\0'; prn_printf(impressao); printer('/'); strncpy(impressao,buffer+10-cont2,2); impressao[2]='\0'; prn_printf(impressao); } prn_printf("\n\n\n\n\n\n\n\n\n\n\n\n"); fclose(entrada); fclose(mensalista); } //*********************************************************************************** // int saida_patio () // //*********************************************************************************** int saida_patio (void) { char codigo[7], cod_marca[4], nome_marca[11], confirma[2], reg_marca[15], temp[3], temp2[3]; static char cliente[22] = "\0"; char teste, nome_tab[5] = "tab\0", c; FILE* marca; FILE* entrada; FILE *relogio; struct Time t0; struct Date d0; struct Time tf; struct Date df; int tempo_permanencia;

Page 121: desenvolvimento de software e hardware embutido para um sistema

112

int inteiro, frac, ano, int_codigo, min_perm_temp; long int hora_perm, min_perm; st_float *valor; entrada = fopen("entrada", FM_RDWR); if ( entrada == NULL ) return -1; marca = fopen("marca", FM_RDWR); if ( marca == NULL ) { fclose(entrada); return -1; } ano = descobre_ano(); lcd_erase_all(); puts("Saida-> Codigo (ou Placa): "); lcd_gotoxy(28, 1); kbd_gets(codigo, 7, 0,LETRAENUMERO); // Se for menor que 7 eh codigo (o offset) e le direto, se for igual a 7 eh placa, // tem que fazer consulta if (strlen(codigo) < 7) { entrada->offset = codigo; int_codigo = atoi(codigo); fread(cliente, entrada->tag, entrada); } else { int_codigo = consulta(codigo, cliente, entrada); } fclose(entrada); // Consulta a marca do auto para descobrir a classe e abrir a tabela de precos correta strncpy(cod_marca, &cliente[7], 3); cod_marca[3] = '\0'; lcd_erase_all(); consulta(cod_marca, reg_marca, marca); fclose(marca); strncpy(buf, &reg_marca[3], 1); buf[1] = '\0'; strcat(nome_tab, buf); strncpy (temp, &cliente[10], 2); temp[2]='\0'; d0.year = atoi(temp); d0.year += ano; strncpy (temp, &cliente[12], 2); temp[2]='\0'; d0.month = atoi(temp); strncpy (temp, &cliente[14], 2); temp[2]='\0'; d0.day = atoi(temp); strncpy (temp, &cliente[16], 2); temp[2]='\0'; t0.hour = atoi(temp); strncpy (temp, &cliente[18], 2); temp[2]='\0'; t0.minute = atoi(temp); strncpy (temp, &cliente[20], 2); temp[2]='\0'; t0.seconds = atoi(temp); //Obtem a data e hora atual read8583_rtc(&tf, &df, GET_DATE_TIME); df.year += ano; lcd_erase_all(); lcd_gotoxy(9,1); puts(itoa(d0.day)); lcd_gotoxy(11,1); puts("/"); lcd_gotoxy(12,1); puts(itoa(d0.month)); lcd_gotoxy(14,1); puts("/"); lcd_gotoxy(15,1); puts(itoa(d0.year+2000)); lcd_gotoxy(20,1); puts(itoa(t0.hour));

Page 122: desenvolvimento de software e hardware embutido para um sistema

113

lcd_gotoxy(22,1); puts(":"); lcd_gotoxy(23,1); puts(itoa(t0.minute)); lcd_gotoxy(25,1); puts(":"); lcd_gotoxy(26,1); puts(itoa(t0.seconds)); lcd_gotoxy(9,2); puts(itoa(df.day)); lcd_gotoxy(11,2); puts("/"); lcd_gotoxy(12,2); puts(itoa(df.month)); lcd_gotoxy(14,2); puts("/"); lcd_gotoxy(15,2); puts(itoa(df.year+2000)); lcd_gotoxy(20,2); puts(itoa(tf.hour)); lcd_gotoxy(22,2); puts(":"); lcd_gotoxy(23,2); puts(itoa(tf.minute)); lcd_gotoxy(25,2); puts(":"); lcd_gotoxy(26,2); puts(itoa(tf.seconds)); kbd_getc(LETRAENUMERO); //Calcula a permanencia tempo_permanencia = calcula_permanencia(&t0, &d0, &tf, &df); hora_perm = (tempo_permanencia / 3600); min_perm = tempo_permanencia - hora_perm*3600; min_perm = (min_perm / 60); min_perm_temp = min_perm; lcd_erase_all(); puts("permanencia\n"); puts(itoa(hora_perm)); lcd_gotoxy(10, 2); puts(itoa(min_perm)); kbd_getc(LETRAENUMERO); valor = calcula_valor(hora_perm, min_perm, nome_tab); lcd_erase_all(); puts("depois de calcula_valor\n"); puts(itoa(valor->inteiro)); kbd_getc(LETRAENUMERO); lcd_erase_all(); lcd_gotoxy(9,1); puts(itoa(d0.day)); lcd_gotoxy(11,1); puts("/"); lcd_gotoxy(12,1); puts(itoa(d0.month)); lcd_gotoxy(14,1); puts("/"); lcd_gotoxy(15,1); puts(itoa(d0.year+2000)); lcd_gotoxy(20,1); puts(itoa(t0.hour)); lcd_gotoxy(22,1); puts(":"); lcd_gotoxy(23,1); puts(itoa(t0.minute)); lcd_gotoxy(25,1); puts(":"); lcd_gotoxy(26,1); puts(itoa(t0.seconds)); lcd_gotoxy(9,2); puts(itoa(df.day)); lcd_gotoxy(11,2); puts("/"); lcd_gotoxy(12,2); puts(itoa(df.month)); lcd_gotoxy(14,2); puts("/"); lcd_gotoxy(15,2);

Page 123: desenvolvimento de software e hardware embutido para um sistema

114

puts(itoa(df.year+2000)); lcd_gotoxy(20,2); puts(itoa(tf.hour)); lcd_gotoxy(22,2); puts(":"); lcd_gotoxy(23,2); puts(itoa(tf.minute)); lcd_gotoxy(25,2); puts(":"); lcd_gotoxy(26,2); puts(itoa(tf.seconds)); kbd_getc(LETRAENUMERO); sprintf(buf, "Entrada:%2d/%2d/%4d %2d:%2d:%2d Perm:%2dh %s", d0.day, d0.month, (d0.year+2000), t0.hour, t0.minute, t0.seconds, hora_perm, temp2); puts(buf); sprintf(buf, "Saida: %2d/%2d/%4d %2d:%2d:%2d R$%2d.%2d", df.day, df.month, (df.year+2000), tf.hour, tf.minute, tf.seconds, inteiro, frac); puts(buf); kbd_getc(); lcd_erase_all(); puts("Entrada:"); if (d0.day < 10) { lcd_gotoxy(9,1); puts("0"); lcd_gotoxy(10,1); puts(itoa(d0.day)); } else { lcd_gotoxy(9,1); puts(itoa(d0.day)); } lcd_gotoxy(11,1); puts("/"); if (d0.month < 10) { lcd_gotoxy(12,1); puts("0"); lcd_gotoxy(13,1); puts(itoa(d0.month)); } else { lcd_gotoxy(12,1); puts(itoa(d0.month)); } lcd_gotoxy(14,1); puts("/"); lcd_gotoxy(15,1); puts(itoa(d0.year+2000)); if (t0.hour < 10) { lcd_gotoxy(20,1); puts("0"); lcd_gotoxy(21,1); puts(itoa(t0.hour)); } else { lcd_gotoxy(20,1); puts(itoa(t0.hour)); } lcd_gotoxy(22,1); puts(":"); if (t0.minute < 10) { lcd_gotoxy(23,1); puts("0");

Page 124: desenvolvimento de software e hardware embutido para um sistema

115

lcd_gotoxy(24,1); puts(itoa(t0.minute)); } else { lcd_gotoxy(23,1); puts(itoa(t0.minute)); } lcd_gotoxy(25,1); puts(":"); if (t0.seconds < 10) { lcd_gotoxy(26,1); puts("0"); lcd_gotoxy(27,1); puts(itoa(t0.seconds)); } else { lcd_gotoxy(26,1); puts(itoa(t0.seconds)); } lcd_gotoxy(29,1); puts("Perm.:"); if(hora_perm < 10) { lcd_gotoxy(35,1); puts("0"); lcd_gotoxy(36,1); puts(itoa(hora_perm)); } else { lcd_gotoxy(35,1); puts(itoa(hora_perm)); } lcd_gotoxy(37,1); puts(":"); if(min_perm < 10) { lcd_gotoxy(38,1); puts("0"); lcd_gotoxy(39,1); puts(itoa(min_perm)); } else { lcd_gotoxy(38,1); puts(itoa(min_perm)); } puts("\nSaida:"); if (df.day < 10) { lcd_gotoxy(9,2); puts("0"); lcd_gotoxy(10,2); puts(itoa(df.day)); } else { lcd_gotoxy(9,2); puts(itoa(df.day)); } lcd_gotoxy(11,2); puts("/"); if (df.month < 10)

Page 125: desenvolvimento de software e hardware embutido para um sistema

116

{ lcd_gotoxy(12,2); puts("0"); lcd_gotoxy(13,2); puts(itoa(df.month)); } else { lcd_gotoxy(12,2); puts(itoa(df.month)); } lcd_gotoxy(14,2); puts("/"); lcd_gotoxy(15,2); puts(itoa(df.year+2000)); if (tf.hour < 10) { lcd_gotoxy(20,2); puts("0"); lcd_gotoxy(21,2); puts(itoa(tf.hour)); } else { lcd_gotoxy(20,2); puts(itoa(tf.hour)); } lcd_gotoxy(22,2); puts(":"); if (tf.minute < 10) { lcd_gotoxy(23,2); puts("0"); lcd_gotoxy(24,2); puts(itoa(tf.minute)); } else { lcd_gotoxy(23,2); puts(itoa(tf.minute)); } lcd_gotoxy(25,2); puts(":"); if (tf.seconds < 10) { lcd_gotoxy(26,2); puts("0"); lcd_gotoxy(27,2); puts(itoa(tf.seconds)); } else { lcd_gotoxy(26,2); puts(itoa(tf.seconds)); } lcd_gotoxy(29,2); puts("R$.:"); lcd_gotoxy(34,2); puts(itoa(valor->inteiro)); lcd_gotoxy(37,2); puts("."); lcd_gotoxy(38,2); puts(itoa(valor->frac)); kbd_getc(LETRAENUMERO); lcd_erase_all(); puts("Imprimir Recibo de Saida? (S/N):"); lcd_gotoxy(33,1);

Page 126: desenvolvimento de software e hardware embutido para um sistema

117

inteiro = 1; int_codigo = 0; while (!(int_codigo)) { c = kbd_getc(SOLETRA); switch (c) { case 'N': case 'n': inteiro = 0; int_codigo = 1; break; case 'S': inteiro = 1; int_codigo = 1; break; } } if (inteiro) int_codigo = 2; else int_codigo = 1; do { //CABECALHOS if (!(fexists("cabeca") < 0)) { FILE *cabecalho; char tam; cabecalho = fopen("cabeca", FM_RDWR); if (cabecalho == NULL) { fclose(cabecalho); return -1; } //'tam' recebe o numero de registros existentes no arquivo tam = ( (cabecalho->pfile->size - 1) / (cabecalho->tag) ); cabecalho->offset = 1; while(tam) { fread(buf, 40, cabecalho); prn_printf("\t"); prn_printf(buf); prn_printf("\n"); cabecalho->offset ++; tam--; } fclose(cabecalho); prn_printf ("\n\n"); } if (int_codigo == 2) sprintf (buf, " ==== RECIBO DE SAIDA ===="); if (int_codigo == 1) sprintf (buf, " ==== TICKET DE SAIDA ===="); //SAIDA: CODIGO DE ENTRADA prn_printf(buf); prn_printf("\n\n"); sprintf(buf, "Saida: %d", int_codigo); prn_printf(buf); prn_printf("\n\n"); prn_printf(" ENTRADA SAIDA PERM. \n"); sprintf(buf, " %d/%d/%d %d/%d/%d %d:%d ", d0.day, d0.month, (d0.year+2000), df.day, df.month, (df.year+2000), hora_perm, min_perm_temp); prn_printf(buf); prn_printf("\n");

Page 127: desenvolvimento de software e hardware embutido para um sistema

118

sprintf(buf, " %d:%d %d:%d", t0.hour, t0.minute, tf.hour, tf.minute); prn_printf(buf); prn_printf("\n\n\n"); strncpy(buf, &cliente[0], 7); buf[7] = '\0'; prn_printf("\t"); prn_printf(buf); prn_printf(" - "); strncpy(buf, &reg_marca[4], 10); buf[10] = '\0'; prn_printf(buf); prn_printf("\n\n"); if(!(fexists("rodape") < 0)) { FILE *rodape; char tam; rodape = fopen("rodape", FM_RDWR); tam = ( (rodape->pfile->size - 1) / (rodape->tag) ); rodape->offset = 1; printer('\n'); while(tam) { fread(buf, 40, rodape); prn_printf("\t"); prn_printf(buf); prn_printf("\n"); rodape->offset ++; tam--; } fclose(rodape); } prn_printf("\n\n\n"); prn_printf("\n\n\n"); lcd_erase_all(); puts ("Pressione qualquer tecla para continuar."); kbd_getc(LETRAENUMERO); int_codigo--; }while (int_codigo); } st_float* calcula_valor(int hora_perm, int min_perm, char nome_tab[]) { char tempo_str[3], tempo_str2[3], valor_intervalo[3] = "00"; int desist, tol, tol24, i = 5, intervalo, len, temp, temp2; int dias, horas; st_float valor; FILE* preco; lcd_erase_all(); puts("nome_tab\n"); puts(nome_tab); kbd_getc(LETRAENUMERO); valor.inteiro = 0; valor.frac = 0; preco = fopen(nome_tab, FM_RDWR); if ( preco == NULL ) return -1; // Le a tabela de precos consulta(0, buf, preco); strncpy(tempo_str, buf, 2); tempo_str[2] = '\0'; desist = atoi(tempo_str); // Tolerancia na hora strncpy(tempo_str, &buf[2], 2); tempo_str[2] = '\0'; tol = atoi(tempo_str); // Tolerancia 24h strncpy(tempo_str, &buf[4], 1); tempo_str[1] = '\0'; tol24 = atoi(tempo_str); // Calculamos os dias de permanencia e as horas restantes(sem contar os dias) de permanencia dias = hora_perm / 24; horas = hora_perm % 24; // Verifica o tempo de desistencia if( (hora_perm == 0) && (min_perm <= desist) ) {

Page 128: desenvolvimento de software e hardware embutido para um sistema

119

valor.inteiro = 0; valor.frac = 0; lcd_erase_all(); puts("Saiu: tempo de desistencia"); kbd_getc(LETRAENUMERO); fclose(preco); return &valor; } // Verifica o tempo de tolerancia na hora if( min_perm <= tol ) min_perm = 0; // Verifica o tempo de tolerancia nas 24h ==> VERIFICAR!!!!!!!!!! if( ((min_perm == 0) && (horas <= tol24)) || ((min_perm > 0) && (horas < tol24)) ) { min_perm = 0; horas = 0; } // Se 'min_perm' for maior que os tempos de tolerancia e desistencia, eles sao contados nas horas de permanencia if (min_perm > 0) horas++; lcd_erase_all(); puts("tab_preco\n"); puts(buf); kbd_getc(LETRAENUMERO); //* Se ficou mais de 24h, pega o valor referente a um dia if (dias > 0) { len = strlen(buf); lcd_erase_all(); puts(&buf[len - 6]); kbd_getc(LETRAENUMERO); strncpy(tempo_str, &buf[len - 6], 2); valor.inteiro = atoi(tempo_str); strncpy(tempo_str, &buf[len - 3], 2); valor.frac = atoi(tempo_str); // Se 'horas' == 0, ficou exatamente n*24 hs no patio if (horas == 0) { temp = valor.frac * dias; temp2 = temp / 100; valor.frac = temp - (temp2 * 100); temp = valor.inteiro * dias; valor.inteiro = temp + temp2; fclose(preco); return &valor; } } //* Pega o valor referente a periodos menores que 24h e calcula o valor a ser pago while ( strcmp(valor_intervalo, "24") != 0 ) { strncpy(valor_intervalo, &buf[i], 2); valor_intervalo[2] = '\0'; intervalo = atoi(valor_intervalo); if ( horas <= intervalo ) { strncpy(tempo_str, &buf[i+2], 2); tempo_str[2] = '\0'; lcd_erase_all(); puts("Parte Inteira:\n"); puts(tempo_str); kbd_getc(LETRAENUMERO); temp = atoi(tempo_str); valor.inteiro += temp; strncpy(tempo_str, &buf[i+5], 2); tempo_str[2] = '\0'; temp = atoi(tempo_str); valor.frac += temp; if (valor.frac >= 100) { valor.frac -= 100; valor.inteiro ++; } lcd_erase_all(); puts("Saiu: ficou 24hs e uns quebrados\n"); puts(itoa(valor.inteiro)); kbd_getc(LETRAENUMERO); fclose(preco);

Page 129: desenvolvimento de software e hardware embutido para um sistema

120

return &valor; } i += 7; } lcd_erase_all(); puts("Saiu: deu merda!"); kbd_getc(LETRAENUMERO); return -1; } long int calcula_dias_corridos(struct Date *d1, struct Date *d2) { int dias_inicio_mes[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; long int dias_corridos, dia1, dia2; int j = 0; int i, ano1, ano2; //Quantos dias do ano passaram até cada uma das datas especificadas, exclusive. dia1 = dias_inicio_mes[(d1->month - 1)] + d1->day; dia2 = dias_inicio_mes[(d2->month - 1)] + d2->day; ano1 = d1->year + 2000; ano2 = d2->year + 2000; //Se estamos no mesmo ano... if (ano1 == ano2) { dias_corridos = dia2 - dia1; //Calcula-se a diferença if ( (!(ano1 % 4)) && ( (d1->month <= 2) && (d2->month > 2) ) ) dias_corridos++; //Se o ano eh bissexto, a data inicial eh anterior a fevereiro e a data final eh apos fevereiro return dias_corridos; } //Daqui pra frente não estamos no mesmo ano... i = ano1; i++; //Ajusta os anos bissextos perdidos no caminho. while(i < ano2) { if (!(i % 4)) j++; i++; } //Mais anos bissextos: //Aqui eh o caso de termos a data inicial antes de fevereiro if (!(ano1 % 4)) if ( (d1->month == 1) || ( (d1->month == 2) && (d1->day < 29) ) ) j++; //E aqui eh o caso de termos a data final apos fevereiro if (!(ano2 % 4)) if ( (d2->month >= 2) || ( (d2->month == 2) && (d2->day == 29) ) ) j++; //Quantos dias passaram desde a data inicial ate o fim daquele ano + //Quantos dias passaram ate a data final no ultimo ano + //Varios anos inteiros perdidos no caminho + //Ajustes para anos bissextos dias_corridos = (365 - dia1) + dia2 + (d2->year - d1->year - 1)*365 + j; return dias_corridos; } /* Calcula o tempo (em horas, minutos e segundos) que passaram ente dois instantes de tempo. Os valores calculados sao retornados (por referencia) na segunda estrutura de tempo (*t2) */ long int calcula_permanencia (struct Time *t1, struct Date *d1, struct Time *t2, struct Date *d2) { const long int dia_em_segundos = 86400; long int tempo1, tempo2, dif_tempo, dias_corridos; float temp; int i; dif_tempo = 0; dias_corridos = calcula_dias_corridos(d1,d2); //Segundos decorridos desde 0:00 ate o instante de tempo inicial tempo1 = t1->hour*60; //Eh feio, mas nao da overflow! tempo1 = tempo1*60 + t1->minute*60 + t1->seconds;

Page 130: desenvolvimento de software e hardware embutido para um sistema

121

tempo2 = t2->hour*60; tempo2 = tempo2*60 + t2->minute*60 + t2->seconds; //Se estamos no mesmo dia, apenas calcula-se a diferenca if (!(dias_corridos)) { if (t1->hour > t2->hour) return -1; else { dif_tempo = (tempo2 - tempo1); return dif_tempo; } } else { for (i=0; i < (dias_corridos - 1); i++) //Seria dif_tempo = (dias_corridos - 1)*dia_em_segundos, mas... da overflow dif_tempo += dia_em_segundos; } //Tempo dos dias intermediarios (calculado acima) + //Tempo decorrido do instante inicial ate o fim do primeiro dia + //Tempo decorrido ate o instante final dif_tempo += (dia_em_segundos - tempo1) + tempo2; return dif_tempo; } //*********************************************************************************** // int incluir_mensalista() // //*********************************************************************************** int incluir_mensalista (void) { FILE *cliente; // int tamanho_nome, tamanho_classe, tamanho_placa1, tamanho_placa2; char codMensal[COD_MAX], nome[NOME_MAX], classe[2], placa1[PLC_MAX], placa2[PLC_MAX]; char c, nome_arq[9] = "mensal", buf[60]; int num, prox, cod; lcd_erase_all(); lcd_cursor(lcd_cursor_blink); num = fexists(nome_arq); if (num < 0) fcreate(nome_arq, 43); cliente = fopen(nome_arq, FM_RDWR); if (cliente == NULL) { fclose(cliente); return -1; } // Zera a variavel global "buf" strcpy(buf, "\0"); // Calcula o numero do codigo prox = prox_vazio(cliente); cod = ( (prox - 1) / cliente->tag ) + 1 ; // Completa o campo 'cod_marca' para que tenha 3 caracteres // <==== TESTAR!!!! if (cod < 10) strcpy(codMensal, "00"); else if (cod > 9 && prox < 100) strcpy(codMensal, "0"); strcat(codMensal, itoa(cod)); lcd_erase_all(); inicia_display_mensal(); // Escreve no display o codigo do cliente lcd_gotoxy(12,1); puts(codMensal); // Posiciona o cursor no nome lcd_gotoxy(21,1); pega_nome(nome, 0); // Posiciona o cursor na classe lcd_gotoxy(15,2); pega_classe(classe, 0); lcd_erase_all(); cursor_placa_mensal(); pega_placa(placa1, 0, 0, 0); lcd_gotoxy(11,2); pega_placa(placa2, 1, 0, 0); //Se for a placa2, a função aceitará ENTER como entrada strcat(buf, codMensal);

Page 131: desenvolvimento de software e hardware embutido para um sistema

122

strcat(buf, "@"); strcat(buf, nome); strcat(buf, "@"); strcat(buf, classe); strcat(buf, "@"); strcat(buf, placa1); strcat(buf, "@"); strcat(buf, placa2); lcd_erase_all(); puts(buf); while((c = kbd_getc(LETRAENUMERO)) != ENTER); lcd_erase_all(); insere(buf, cliente); fclose(cliente); return 0; } //*********************************************************************************** // int excluir_mensalista() // //*********************************************************************************** int excluir_mensalista () { FILE *cliente; char codMensal[COD_MAX]; char nome_arq[8] = "mensal", c, i, j, placa2 = FALSE, nao_confirmado; int codigo_incorreto = TRUE, offset; if(fexists(nome_arq) < 0) return -1; cliente = fopen(nome_arq, FM_RDWR); if (cliente == NULL) { fclose(cliente); return -1; } offset = 0; while (codigo_incorreto) // Fazer esta exceção. Faltam detalhes. { // Zera a variavel global "buf" strcpy(buf, "\0"); //Display lcd_erase_all(); puts("Codigo do mensalista:"); lcd_gotoxy(22,1); //Pega o codigo do mensalista a ser excluído for (i = 0; i < COD_MAX; i++) { // ESC sai if ((codMensal[i] = kbd_getc(SONUMERO)) == ESC) return -1; if (i < 3) { if (codMensal[i] == BACKSPACE) if ((i >= 1) && (i <=2)) { lcd_erase(left, 1); i -= 2; continue; } while (!(codMensal[i] >= '0' && codMensal[i] <= '9')) // Enquanto não estiver entre 0 e 9... codMensal[i] = kbd_getc(SONUMERO); putch(codMensal[i]); } else while (codMensal[i] != ENTER) { if (codMensal[i] == BACKSPACE) { lcd_erase(left, 1); i -= 2; break; }

Page 132: desenvolvimento de software e hardware embutido para um sistema

123

//ESC sai if (codMensal[i] == ESC) return -1; codMensal[i] = kbd_getc(SONUMERO); } } codMensal[3] = '\0'; // Coloca o termino de vetor no codMensal lcd_erase_all(); puts("Antes do consulta"); lcd_gotoxy(1, 1); kbd_getc(LETRAENUMERO); offset = consulta(codMensal, buf, cliente); lcd_erase_all(); puts("Passou pelo consulta"); lcd_gotoxy(1, 1); kbd_getc(LETRAENUMERO); lcd_erase_all(); puts(buf); lcd_gotoxy(1, 1); kbd_getc(LETRAENUMERO); if (offset < 0) { lcd_erase_all(); puts("Mensalista nao cadastrado!"); while((c = kbd_getc(LETRAENUMERO)) != ENTER); continue; } lcd_erase_all(); puts("Passou do offset"); lcd_gotoxy(1, 1); kbd_getc(LETRAENUMERO); //Vai procurar a placa do mensalista no buffer_mensal: cod_mensal@nome@classe@placa1@placa2 i = 4; j = 2; while (j--) { // Posiciona buf apontando para a primeira letra da placa while(buf[i] != '@') i++; i++; } lcd_gotoxy(1,2); lcd_erase_all(); puts("Placa1:"); lcd_gotoxy(8, 1); kbd_getc(LETRAENUMERO); // Escreve a placa encontrada, e a placa2 caso exista while(buf[i] != '\0') { putch(buf[i]); if (placa2 == FALSE) if (buf[i+1] == '@') // Verifica se contém placa 2 { i++; placa2 = TRUE; lcd_gotoxy(17, 1); puts("Placa2:"); lcd_gotoxy(24, 1); kbd_getc(LETRAENUMERO); } i++; } placa2 = FALSE; puts("\nExcluir?(s/n):"); lcd_gotoxy(15, 2); nao_confirmado = TRUE; while (nao_confirmado) { c = kbd_getc(SOLETRA); switch (c) {

Page 133: desenvolvimento de software e hardware embutido para um sistema

124

case 'N' : case 'n' : nao_confirmado = FALSE; break; case 'S' : case 's' : remove(offset, cliente); nao_confirmado = FALSE; codigo_incorreto = FALSE; lcd_erase_all(); puts("Mensalista excluido com sucesso!"); lcd_gotoxy(1, 1); while((c = kbd_getc(LETRAENUMERO)) != ENTER); break; default: putch(c); lcd_gotoxy(17, 2); puts("INVALIDO!"); lcd_gotoxy(26, 2); while((c = kbd_getc(LETRAENUMERO)) != ENTER); lcd_erase(left, 11); break; } } } fclose(cliente); return 0; } //*********************************************************************************** // int alterar_mensalista() // //*********************************************************************************** int alterar_mensalista () { FILE *cliente; char codMensal[COD_MAX], novo_nome[NOME_MAX], nova_classe[2] = {'\0'}, nova_placa1[PLC_MAX], nova_placa2[PLC_MAX]; char i, j = 0, k, c, tam_nome, tam_classe, tam_placa, nome_arq[8] = "mensal", nome_incorreto; int offset; if(fexists(nome_arq) < 0) return -1; cliente = fopen(nome_arq, FM_RDWR); if (cliente == NULL) { fclose(cliente); return -1; } lcd_erase_all(); // Zera a variavel global "buf" strcpy(buf, "\0"); puts("Cod.Mensal.:"); lcd_gotoxy(13, 1); //Pega o codigo do mensalista a ser excluído for (i = 0; i < COD_MAX; i++) { // ESC sai if ((codMensal[i] = kbd_getc(SONUMERO)) == ESC) return -1; if (i < 3) { if (codMensal[i] == BACKSPACE) if ((i >= 1) && (i <=2)) { lcd_erase(left, 1); i -= 2;

Page 134: desenvolvimento de software e hardware embutido para um sistema

125

continue; } while (!(codMensal[i] >= '0' && codMensal[i] <= '9')) // Enquanto não estiver entre 0 e 9... codMensal[i] = kbd_getc(SONUMERO); putch(codMensal[i]); } else while (codMensal[i] != ENTER) { if (codMensal[i] == BACKSPACE) { lcd_erase(left, 1); i -= 2; break; } //ESC sai if (codMensal[i] == ESC) return -1; codMensal[i] = kbd_getc(SONUMERO); } } codMensal[3] = '\0'; // Coloca o termino de vetor no codMensal lcd_erase_all(); offset = consulta(codMensal, buf, cliente); if (offset < 0) { lcd_erase_all(); puts("Mensalista nao cadastrado!"); while((c = kbd_getc(LETRAENUMERO)) != ENTER); fclose(cliente); return -1; } // TROCA NOME // Aponta para o nome do mensalista no buf: cod_mensal@nome@classe@placa1@placa2 i = 4; k = i; lcd_erase_all(); puts("Nome:"); lcd_gotoxy(6, 1); while(buf[i] != '@') { putch(buf[i]); i++; } putch('\n'); puts("Nome:"); lcd_gotoxy(6, 2); tam_nome = pega_nome(novo_nome, 1); nome_incorreto = TRUE; while (nome_incorreto) { if (tam_nome == 0) { //Se nenhum novo_nome é digitado, novo_nome recebe o nome antigo(buf). while (buf[k] != '@') { novo_nome[j] = buf[k]; j++; k++; } novo_nome[j] = '\0'; nome_incorreto = FALSE; } else nome_incorreto = FALSE;

Page 135: desenvolvimento de software e hardware embutido para um sistema

126

} i++; k = i; lcd_erase_all(); puts("Classe(t/d/n):"); lcd_gotoxy(15, 1); while(buf[i] != '@') { putch(buf[i]); i++; } putch('\n'); puts("Classe(t/d/n):"); lcd_gotoxy(15, 2); tam_classe = pega_classe(nova_classe, 1); if (tam_classe == 0) { j = 0; while (buf[k] != '@') { nova_classe[j] = buf[k]; j++; k++; } // nova_classe recebe final de linha nova_classe[j] = '\0'; } i++; k = i; lcd_erase_all(); puts("Placa1-"); lcd_gotoxy(8, 1); while(buf[i] != '@') { putch(buf[i]); i++; } putch('\n'); puts("Placa1-"); lcd_gotoxy(8, 2); tam_placa = pega_placa(nova_placa1, 0, 1, 0); if (tam_placa == 0) { // j passa a apontar novamente para o início do vetor j = 0; while (buf[k] != '@') { nova_placa1[j] = buf[k]; j++; k++; } // nova_placa recebe final de linha nova_placa1[j] = '\0'; } // TROCA PLACA 2 // Aponta para a placa2 do mensalista no buf: cod_mensal@nome@classe@placa1@placa2 i++; k = i; lcd_erase_all(); puts("Placa2-"); lcd_gotoxy(8, 1); if (buf[i] != '\0') while(buf[i] != '\0') { putch(buf[i]); i++; } putch('\n'); puts("Placa2-"); lcd_gotoxy(8, 2); tam_placa = pega_placa(nova_placa2, 1, 1, 0); if (tam_placa == 0) { // j passa a apontar novamente para o início do vetor j = 0; while (buf[k] != '@')

Page 136: desenvolvimento de software e hardware embutido para um sistema

127

{ nova_placa2[j] = buf[k]; j++; k++; } // nova_placa recebe final de linha nova_placa2[j] = '\0'; } // Zera a variavel global "buf" for (c = 0; c < 43; c++) buf[c] = '\0'; //Concatena TUDO strcat(buf, codMensal); strcat(buf, "@"); strcat(buf, novo_nome); strcat(buf, "@"); strcat(buf, nova_classe); strcat(buf, "@"); strcat(buf, nova_placa1); strcat(buf, "@"); strcat(buf, nova_placa2); // Testa todas as concatenacoes altera(buf, offset, 42, cliente); fclose(cliente); return 0; } //*********************************************************************************** // void listar_mensalista() //24 cima, 25 baixo //*********************************************************************************** int listar_mensalista () { FILE *cliente; char tam, i,cont; char nome_arq[] = "mensal"; if(fexists(nome_arq) < 0) return -1; cliente = fopen(nome_arq, FM_RDWR); if (cliente == NULL) { fclose(cliente); return -1; } lcd_erase_all(); // Zera a variavel global "buf" strcpy(buf, "\0"); tam = ( (cliente->pfile->size - 1) / (cliente->tag) ); cliente->offset = 1; prn_printf(" ==== LISTAGEM DE MENSALISTA ===\n\n\n"); cont=0; while(tam) { fread(buf, 42, cliente); prn_printf("Codigo:"); for (i=0;i<42;i++) if (buf[i]!='@') printer(buf[i]); else { ++cont; switch(cont) { case 1: prn_printf(" Nome:"); break; case 2: prn_printf("\nTipo:"); break; case 3: prn_printf(" Placa1:"); break; case 4: prn_printf(" Placa2:"); break; } }

Page 137: desenvolvimento de software e hardware embutido para um sistema

128

prn_printf("\n\n"); cont=0; cliente->offset ++; tam--; } prn_printf("\n\n\n\n\n\n\n\n\n\n\n\n"); fclose(cliente); fclose(cliente); return 0; } //------------------------------------------------------INICIA DISPLAY PATIO-------------------------------------------------------- void inicia_display_patio (void) { puts("Entrada:"); puts(" Placa:"); lcd_gotoxy(14, 2); puts(" Cod.Marca:"); lcd_gotoxy(14, 2); } //----------------------------------------------------TRATAMENTO DA PLACA---------------------------------------------------------- void cursor_placa_mensal (void) { puts("Placas: 1-"); // lcd_gotoxy(1,2); puts(" 2-"); lcd_gotoxy(11,1); } char pega_placa (char placa[], int placa2, int nova_placa, int placa_patio) { char c, tam_placa, erro[] = "INVALIDO!"; int i, placa_incorreta = TRUE; while(placa_incorreta) { kbd_gets(placa, PLC_MAX - 1, 0,LETRAENUMERO); //Limita em 7 caracteres tam_placa = strlen(placa); // Aceita ENTER na digitação da placa if (placa2 || nova_placa) if (tam_placa == 0) { placa_incorreta = FALSE; continue; } if (tam_placa == 6) if ((placa[0] >= 'a' && placa[0] <= 'z') || (placa[0] >= 'A' && placa[0] <= 'Z')) //Se for letra... if ((placa[1] >= 'a' && placa[1] <= 'z') || (placa[1] >= 'A' && placa[1] <= 'Z')) //Se for letra... for(i = 2; i < PLC_MAX - 2; i++) { if (placa[i] >= '0' && placa[i] <= '9') //Se não for letra... placa_incorreta = FALSE; else { placa_incorreta = TRUE; break; } } if (tam_placa == 7) if ((placa[0] >= 'a' && placa[0] <= 'z') || (placa[0] >= 'A' && placa[0] <= 'Z')) //Se for letra...

Page 138: desenvolvimento de software e hardware embutido para um sistema

129

if ((placa[1] >= 'a' && placa[1] <= 'z') || (placa[1] >= 'A' && placa[1] <= 'Z')) //Se for letra... if ((placa[2] >= 'a' && placa[1] <= 'z') || (placa[2] >= 'A' && placa[1] <= 'Z')) //Se for letra... for(i = 3; i < PLC_MAX - 1; i++) { if (placa[i] >= '0' && placa[i] <= '9') //Se não for letra... placa_incorreta = FALSE; else { placa_incorreta = TRUE; break; } } if (placa_incorreta && !placa2) { lcd_erase(left, tam_placa); puts(erro); if (nova_placa) lcd_gotoxy(8 + strlen(erro), 2); if (placa_patio) lcd_gotoxy(14 + strlen(erro), 2); else lcd_gotoxy(20, 1); while((c = kbd_getc(LETRAENUMERO)) != ENTER); // Espera ENTER lcd_erase(left, strlen(erro)); } if (placa_incorreta && placa2) { lcd_erase(left, tam_placa); puts(erro); if (nova_placa) lcd_gotoxy(8 + strlen(erro), 2); else lcd_gotoxy(20, 2); while((c = kbd_getc(LETRAENUMERO)) != ENTER); // Espera ENTER lcd_erase(left, strlen(erro)); } } return tam_placa; } //---------------------------------------------------TRATAMENTO DO CODIGO MARCA----------------------------------------------------- void pega_codMarca (char cod_marca[]) { int i; // while(codMarca_incorreta) // { for (i = 0; i < COD_MAX; i++) { cod_marca[i] = kbd_getc(SONUMERO); if (i < 3) { if (cod_marca[i] == BACKSPACE) if ((i >= 1) && (i <=2)) { lcd_erase(left, 1); i -= 2; continue; } while (!(cod_marca[i] >= '0' && cod_marca[i] <= '9')) // Enquanto não estiver entre 0 e 9... cod_marca[i] = kbd_getc(SONUMERO); putch(cod_marca[i]); } else

Page 139: desenvolvimento de software e hardware embutido para um sistema

130

while (cod_marca[i] != ENTER) { if (cod_marca[i] == BACKSPACE) { lcd_erase(left, 1); i -= 2; break; } cod_marca[i] = kbd_getc(SONUMERO); } } cod_marca[3] = '\0'; // Coloca o termino de vetor no cod_marca } //----------------------------------------------------INICIA DISPLAY MENSAL----------------------------------------------------------- void inicia_display_mensal (void) { puts("Cod.Mensal:"); lcd_gotoxy(12, 1); puts(" Nome:"); lcd_gotoxy(1, 2); puts("Classe(t/d/n):"); lcd_gotoxy(1, 1); } //------------------------------------------------------TRATAMENTO DO NOME------------------------------------------------------------ char pega_nome (char nome[], int novo_nome) { char c, tam_nome, erro[] = "Minimo 3 caracteres!"; int nome_incorreto = TRUE; while(nome_incorreto) { kbd_gets(nome, NOME_MAX - 1, 0,LETRAENUMERO); tam_nome = strlen(nome); // Aceita ENTER na digitação do nome if (novo_nome) if (tam_nome == 0) { nome_incorreto = FALSE; continue; } if (tam_nome < 3) { lcd_erase(left, tam_nome); puts(erro); if (novo_nome) lcd_gotoxy(6 + strlen(erro), 2); else lcd_gotoxy(21 + strlen(erro), 1); while((c = kbd_getc(LETRAENUMERO)) != ENTER); lcd_erase(left, strlen(erro)); } else { nome_incorreto = FALSE; } } return tam_nome; } //---------------------------------------------------TRATAMENTO DA CLASSE--------------------------------------------------------- char pega_classe (char classe[], int nova_classe) { char c, tam_classe;

Page 140: desenvolvimento de software e hardware embutido para um sistema

131

int classe_incorreta = TRUE, nao_confirmado; while (classe_incorreta) { nao_confirmado = TRUE; kbd_gets(classe, 1, 1, SOLETRA); tam_classe = strlen(classe); // Aceita ENTER na digitação da classe if (nova_classe) if (tam_classe == 0) { classe_incorreta = FALSE; continue; } switch (*classe) { case 'T' : case 't' : puts(" 24h? (s/n)"); lcd_gotoxy(27, 2); while(nao_confirmado) { c = kbd_getc(SOLETRA); switch (c) { case 'N' : case 'n' : lcd_erase(left, strlen("t 24h? (s/n)")); nao_confirmado = FALSE; break; case 'S' : case 's' : classe_incorreta = FALSE; nao_confirmado = FALSE; break; } } break; case 'D' : case 'd' : puts(" Diurno? (s/n)"); lcd_gotoxy(30, 2); while(nao_confirmado) { c = kbd_getc(SOLETRA); switch (c) { case 'N' : case 'n' : lcd_erase(left, strlen("d Diurno? (s/n)")); nao_confirmado = FALSE; break; case 'S' : case 's' : classe_incorreta = FALSE; nao_confirmado = FALSE; break; } } break; case 'N' : case 'n' : puts(" Noturno? (s/n)"); lcd_gotoxy(31, 2); while(nao_confirmado) { c = kbd_getc(SOLETRA); switch (c) { case 'N' : case 'n' : lcd_erase(left, strlen("n Noturno? (s/n)")); nao_confirmado = FALSE; break; case 'S' : case 's' : classe_incorreta = FALSE; nao_confirmado = FALSE;

Page 141: desenvolvimento de software e hardware embutido para um sistema

132

break; } } break; default: puts(" INVALIDO!"); lcd_gotoxy(26, 2); while((c = kbd_getc(LETRAENUMERO)) != ENTER); lcd_erase(left, 11); break; } } return tam_classe; } //*********************************************************************************** // int imprime_entrada (char, char, int) // //*********************************************************************************** int imprime_entrada (char ent[], char marc[], int mensal, int cod_entrada) { FILE *cabecalho, *rodape; char tam; char i, c; // Zera a variavel global "buf" strcpy(buf, "\0"); if(fexists("cabeca") < 0) { lcd_erase_all(); puts("Configure o Cabecalho!"); while((i = kbd_getc(LETRAENUMERO)) != ENTER); return -1; } if(fexists("rodape") < 0) { lcd_erase_all(); puts("Configure o Rodape!"); while((i = kbd_getc(LETRAENUMERO)) != ENTER); return -1; } /*IMPRIME CABEÇALHO*/ cabecalho = fopen("cabeca", FM_RDWR); if (cabecalho == NULL) { fclose(cabecalho); return -1; } //'tam' recebe o numero de registros existentes no arquivo tam = ( (cabecalho->pfile->size - 1) / (cabecalho->tag) ); cabecalho->offset = 1; while(tam) { fread(buf, 40, cabecalho); prn_printf(buf); prn_printf("\n"); cabecalho->offset ++; tam--; } fclose(cabecalho); if (cod_entrada != -1) { prn_printf("Entrada:"); sprintf(c, "%d", cod_entrada); lcd_erase_all(); putch(c); while((c = kbd_getc(LETRAENUMERO)) != ENTER); lcd_erase_all(); printer(c); printer('\n'); }

Page 142: desenvolvimento de software e hardware embutido para um sistema

133

/*IMPRIME DADOS DO CLIENTE*/ if (mensal >= 0) prn_printf("\nCLIENTE MENSALISTA\n"); if ((ent[2] >= '0') && (ent[2] <= '9')) { // Imprime a DATA for (i = 13; i < 15; i++) printer(ent[i]); printer('/'); for (i = 11; i < 13; i++) printer(ent[i]); printer('/'); for (i = 9; i < 11; i++) printer(ent[i]); prn_printf(" "); // Imprime a HORA for (i = 15; i < 17; i++) printer(ent[i]); printer(':'); for (i = 17; i < 19; i++) printer(ent[i]); printer('\n'); // Imprime PLACA e MARCA prn_printf("Placa: "); for (i = 0; i < 6; i++) printer(ent[i]); prn_printf(" "); prn_printf("Marca: "); c = 4; while (marc[c] != '\0') { printer(marc[c]); c++; } } else { // Imprime a DATA for (i = 14; i < 16; i++) printer(ent[i]); printer('/'); for (i = 12; i < 14; i++) printer(ent[i]); printer('/'); for (i = 10; i < 12; i++) printer(ent[i]); prn_printf(" "); // Imprime a HORA for (i = 16; i < 18; i++) printer(ent[i]); printer(':'); for (i = 18; i < 20; i++) printer(ent[i]); printer('\n'); // Imprime PLACA e MARCA prn_printf("Placa: "); for (i = 0; i < 7; i++) printer(ent[i]); prn_printf(" "); prn_printf("Marca: "); c = 4; while (marc[c] != '\0') { printer(marc[c]); c++; } } prn_printf("\n"); /*IMPRIME RODAPÉ*/ rodape = fopen("rodape", FM_RDWR); if (rodape == NULL) { fclose(rodape); return -1; } //'tam' recebe o numero de registros existentes no arquivo

Page 143: desenvolvimento de software e hardware embutido para um sistema

134

tam = ( (rodape->pfile->size - 1) / (rodape->tag) ); rodape->offset = 1; printer('\n'); while(tam) { fread(buf, 40, rodape); prn_printf(buf); prn_printf("\n"); rodape->offset ++; tam--; } fclose(rodape); printer('\n'); printer('\n'); printer('\n'); return 0; } //*********************************************************************************** // void pega_num (char cod_len, int inicio, int fim, char codigo[]) // //*********************************************************************************** void pega_num (char cod_len, int inicio, int fim, char codigo[]) { char i, len = cod_len; lcd_moven(right, cod_len); do { lcd_erase(left, len); kbd_gets(codigo, cod_len, 0, SONUMERO); len = strlen(codigo); if (len != cod_len) continue; for(i = 0; i < len; i++) if ( codigo[i] == '.' ) continue; } while ( (atoi(codigo) < inicio) || (atoi(codigo) > fim) ); } //*********************************************************************************** // int pega_valor (char val_len, char valor[]) // //*********************************************************************************** void pega_valor (char val_len, char valor[]) { char i, len = val_len, nao_eh_num; lcd_moven(right, val_len); do { nao_eh_num = 0; lcd_erase(left, len); kbd_gets(valor, val_len, 0, SONUMERO); len = strlen(valor); if ( len < val_len ) continue; for(i = 0; i < len; i++) if ( valor[i] == '.' ) nao_eh_num++; } while (!((nao_eh_num == 1) && (valor[val_len - 3] == '.'))); } int descobre_ano () { FILE *relogio; char temp[3]; int num; relogio = fopen("relogio", FM_RDWR); relogio->offset = 1; fread (temp, 2, relogio); temp[2] = '\0'; num = atoi (temp); fclose(relogio); return num; }

Page 144: desenvolvimento de software e hardware embutido para um sistema

135

APÊNDICE B – MANUAL DE USO DAS BIBLIOTECAS USADAS NO

HARDWARE

MANUAL DE USO DAS BIBLIOTECAS DO HARDARE DO SISTEMA DE ESTACIONAMENTO

TIMER0 Inicialização: Para usarmos a biblioteca de contagem de tempo usando o Timer0, o primeiro procedimento que devemos executar é incluir o cabeçalho delay_timer.h e após isso, inicializarmos o timer 0 com a função init_tmr0(). Ex.: #include "includes\delay_timer.h" //inclusão do header void main() { init_tmr0(PRE_SCALE_256); //inicialização do timer0 com prescale de 1:256 no modo 16 bits … void init_tmr0(int value) A função init_tmr0 inicializa o timer0 do PIC, onde value recebe valor do prescale para o timer0.

Value Prescale PRE_SCALE_2 1:2 PRE_SCALE_4 1:4 PRE_SCALE_8 1:8 PRE_SCALE_16 1:16 PRE_SCALE_32 1:32 PRE_SCALE_64 1:64 PRE_SCALE_128 1:128 PRE_SCALE_256 1:256

void delay_tmr0(int value) Atribui 65536-value para o TMR0, inicializa o timer0 e aguarda o overflow. Uma fórmula aproximada para o cálculo do valor necessário para um determinado tempo de delay T (em segundos), um prescale P e uma freqüência de oscilação F é:

)16()( PTFValue ×÷×≅

Exemplo de uso da biblioteca #include <pic18.h> #include "includes\delay_timer.h" void main() { TRISD0=0;

Page 145: desenvolvimento de software e hardware embutido para um sistema

136

init_tmr0(NO_SCALE); //inicialização do timer0 com prescale de 1:256 while(1) { LATD0=0; delay_tmr0(6250); LATD0=1; delay_tmr0(6250); /* T=(4*PRE_SCALE)*4*2/Fosc*(value)=0,01s (100 Hz) */ } } LCD Inicialização LCD usando um port específico: #include <pic18.h> #include <stdio.h> #define lcd_type 2 #define USE_PORTX_LCD , onde X é A, B, C ou D. p.e. USE_PORTA_LCD #include "includes\lcd.h" void putch(unsigned char c); void putch(unsigned char c) { lcd_putch(c); } void main(void) { lcd_init(); lcd_erase_all(); lcd_cursor(lcd_cursor_blink); …. LCD sem usar um port específico: #include <pic18.h> #include <stdio.h> #define lcd_type 2 #define LCD_EN A2 #define LCD_RS A0 #define LCD_RW A1 #define LCD_D4 A3 #define LCD_D5 A4 #define LCD_D6 A5 #define LCD_D7 B3 #define USE_NO_PORT_LCD #include "includes\lcd.h" void putch(unsigned char c); void putch(unsigned char c) { lcd_putch(c); }

Page 146: desenvolvimento de software e hardware embutido para um sistema

137

void main(void) { lcd_init(); lcd_erase_all(); lcd_cursor(lcd_cursor_blink); ... void lcd_init(void): Inicializa o LCD. void lcd_cursor(lcd_cursor_type): Muda o tipo do cursor do LCD. O tipo lcd_cursor_type é composto dos seguintes valores: lcd_cursor_on, lcd_cursor_off, lcd_cursor_blink e lcd_cursor_alternate. Ex. lcd_cursor(lcd_cursor_on). void lcd_gotoxy( byte x,byte y): Posiciona o cursor na coluna x e linha y no LCD. void lcd_erase(lcd_direction dir,byte n): Apaga n bytes na direção dir (right ou left são os valores possíveis para o tipo lcd_direction). Ex.: lcd_erase(right,3) – Apaga 3 caracteres à direita do cursor. void lcd_erase_all(void): Apaga todo o conteúdo do visor. byte lcd_getc(byte x,byte y): Obtém um caracter na coluna x, linha y. void lcd_moven(lcd_direction,char): Move o cursor n vezes numa direção. void lcd_putch(unsigned char): Imprime um caracter no visor do lcd. TECLADO PS/2 Inicialização Antes de usarmos a biblioteca de manipulação do teclado PS/2, devemos definir os pinos KEYB_DATA e KEYB_CLOCK. #define KEYB_DATA C4 #define KEYB_CLOCK C5 unsigned char kbd_getc(): Retorna um caracter pela entrada do teclado. Sendo válidos números, letras e teclado de funções. void kbd_gets(char string[], unsigned char lenght): Retorna um vetor de char string com tamanho máxino length pelo teclado, exibindo os caracteres no LCD. EEPROM I2C Inicialização:

Page 147: desenvolvimento de software e hardware embutido para um sistema

138

Antes de usarmos a biblioteca de manipulação da EEPROM I2C devemos inicializar o barramento I2C. Ex: #include <pic18.h> #include <stdio.h> #include <string.h> #include "includes/i2c_master.h" #include "includes/24cxx.h" #define I2C_MEMORY I2C_EEPROM_A0 void main() { i2c_init(0x45); OBS: A freqüência utilizada pela linha SCL é dada pela fórmula clock_scl=FOSC / (4 * (SSPADD+1)) , onde SSPADD é o valor a ser passado pela função i2c_init. Deve-se observar o datasheet dos componentes I2C para não usarmos uma freqüência que esteja acima da máxima projetada para o dispositivo I2C. void i2c_eepromWrite(char device,int address, char data): Escreve data no endereço address no dispositivo device. Device pode ter os seguintes valores: I2C_EEPROM - A0, A1 e A2 aterrados I2C_EEPROM_A0 - A0 alto e A1 e A2 aterrados I2C_EEPROM_A1 -…… I2C_EEPROM_A1_A0 I2C_EEPROM_A2 I2C_EEPROM_A0_A2 I2C_EEPROM_A1_A2 I2C_EEPROM_A0_A1_A2 char i2c_eepromReadCurrent(char device): Retorna um byte lido no endereço currente no dispositivo device. char i2c_eepromRead(char device,int address): Retorna um byte lido no dispositivo device no endereço address. void i2c_eepromCursor(char device,int i2c_address): Posiona o cursor de endereço do dispositivo device no endereço i2c_address. void i2c_eepromPageWrite(char device,int address, char *data,unsigned char size_str) : Escreve um vetor de char iniciando no endereço address, no dispositivo device com tamanho size_str. Uma página pode ter no máximo 16 bytes. Ex.: #include <pic18.h> #include <stdio.h> #include <string.h> #include "includes/i2c_master.h" #include "includes/24cxx.h" #define I2C_MEMORY I2C_EEPROM_A0 void main() { int addr=0x0000; char str[]="Mauricio Lopes de Oliveira\0"; char str2[20]; i2c_init(0x45);

Page 148: desenvolvimento de software e hardware embutido para um sistema

139

i2c_eepromPageWrite(I2C_MEMORY,addr,str,16); i2c_eepromPageWrite(I2C_MEMORY,addr+16,(str+16),10); } void i2c_eepromSequentialRead(char device,int address,char *data,unsigned char size_str): Realiza uma leitura sequencial de size_str bytes no dispositivo device, iniciando no endereço address. Ex.: #include <pic18.h> #include <stdio.h> #include <string.h> #include "includes/i2c_master.h" #include "includes/24cxx.h" #define I2C_MEMORY I2C_EEPROM_A0 void main() { int addr=0x0000; char str[]="Mauricio Lopes de Oliveira\0"; char str2[20]; i2c_init(0x45); i2c_eepromPageWrite(I2C_MEMORY,addr,str,16); i2c_eepromPageWrite(I2C_MEMORY,addr+16,(str+16),10); i2c_eepromSequentialRead(I2C_MEMORY,addr,str2,26); while(1); } RAM Inicialização: #define RAM_LE_H B6 // LE do Latch do byte alto do endereço de memória. #define RAM_LE_L B4 // LE do Latch do byte baixo do endereço de memória. #define PORT_RAM D //port de dados #define RAM_OE B2 //OE da RAM #define RAM_WE B1 //WE da ram #include "includes/62256.h" void ram_Init(void): Incializa a RAM. Este comando deve ser usado antes de qualquer instrução de utilização da RAM. void ram_Cursor(unsigned int address): Coloca addres no barramento de endereço da RAM. unsigned char ram_ReadByte(unsigned int address): Retorna um byte lido no endereço address. void ram_WriteByte(unsigned char value,unsigned int address): Grava um byte value no endereço address. void ram_SequentialWrite(char *val,unsigned int initial_address): Realiza uma escrita sequencial do vetor de char val iniciando em initial_address. Ex.: #include <pic18.h> #include <stdio.h> #include <string.h> #define RAM_LE_H B6 #define RAM_LE_L B4

Page 149: desenvolvimento de software e hardware embutido para um sistema

140

#define PORT_RAM D #define RAM_OE B2 #define RAM_WE B1 #include "includes/62256.h" void main(void) { char str[]="Mauricio Lopes\0"; char str2[14]; ram_Init(); ram_SequentialWrite(str,0x7FF0); ram_SequentialRead(&str2,0x7FF0,14); while(1); } void ram_SequentialRead(char *val,unsigned int initial_address,unsigned int size): Realiza uma leitura sequencial colocando no vetor de char val de initial_address até initial_address+size. Ex.: #include <pic18.h> #include <stdio.h> #include <string.h> #define RAM_LE_H B6 #define RAM_LE_L B4 #define PORT_RAM D #define RAM_OE B2 #define RAM_WE B1 #include "includes/62256.h" void main(void) { char str[]="Mauricio Lopes\0"; char str2[14]; ram_Init(); ram_SequentialWrite(str,0x7FF0); ram_SequentialRead(&str2,0x7FF0,14); while(1); } PCF8583 Inicialização: Antes de usarmos a biblioteca de manipulação da EEPROM I2C devemos inicializar o barramento I2C, observando a velocidade máxima do dispositivo para que haja a comunicação. Ex: #include <pic18.h> #include <stdio.h> #include <string.h> #include "includes/i2c_master.h" #include "includes/24cxx.h" #define I2C_MEMORY I2C_EEPROM_A0 void main() { i2c_init(0x45);

Page 150: desenvolvimento de software e hardware embutido para um sistema

141

OBS: A freqüência utilizada pela linha SCL é dada pela fórmula clock_scl=FOSC / (4 * (SSPADD+1)) , onde SSPADD é o valor a ser passado pela função i2c_init. Deve-se estar atento para as especificações do dispositivo para não usarmos uma freqüência que esteja acima da máxima projetada para o dispositivo I2C. void write8583_rtc(struct Time *t, struct Date *d, BYTE address_reg): Ajusta a hora e a data ou o alarme através das estruturas Time ou Date. Time e Date possuem as seguintes estruturas: struct Time { BYTE hour; BYTE minute; BYTE seconds; }; struct Date { BYTE year; BYTE month; BYTE day; BYTE weekday; }; A variável address_reg pode ser: SET_DATE_TIME ou SET_ALARM . Ex.: write8583_rtc(&hora,&data,SET_DATE_TIME); ou write8583_rtc(&alarm_hora,&alarm_data,SET_ALARM); void read8583_rtc(struct Time *t, struct Date *d, BYTE address_reg): Lê o clock ou o alarme do RTC através de Date e Time. A variável addres_reg pode ser: GET_DATE_TIME ou GET_ALARM Ex.: read8583_rtc(&zeit,&datum,GET_DATE_TIME); ou read8583_rtc(&alarmzeit,&alarmdatum,GET_ALARM); void configure8583_control_reg(BYTE control_reg): Configura o reg. de controle do RTC. A variável control_reg pode ser: alarm_enable - Here the alarm function is activated clock_mode32khz - Clock frequency of the PCF8583 32,768 kHz clock_mode50hz - Clock frequency of the PCF8583 50 Hz void configure8583_alarm_reg(BYTE alarm_reg): Configura o registrador de alarme do RTC. Ex. de uso do RTC: #include <pic18.h> #include <stdio.h> #include <string.h> #include "includes/i2c_master.h" #include "includes/pcf8583.h" void main(void)

Page 151: desenvolvimento de software e hardware embutido para um sistema

142

{ int op; struct Time t0; struct Date d0; i2c_init(0xFA); init_tmr0(0x08); t0.hour =15; t0.minute =0; t0.seconds =0; d0.year = 0; d0.month =5; d0.day = 31; d0.weekday =6; write8583_rtc(&t0,&d0,SET_DATE_TIME); op=2; configure8583_control_reg(clock_mode32khz); while (1) { read8583_rtc(&t0, &d0, GET_DATE_TIME); if (op!=t0.seconds) { printf("Hora %02u:%02u:%02u We:%02u\n", t0.hour, t0.minute, t0.seconds,d0.weekday); printf("Data: %02u.%02u.%02u", d0.day , d0.month , d0.year); lcd_gotoxy(1,1); op=t0.seconds; } } } IMPRESSORA Inicialização: Para fazer uso da impressora devemos antes de incluir o seu respectivo header, atrinuirmos definições (defines) com os pinos necessários para o controle da impressora. Caso eles não sejam atribuídos o padrão será o usado no hardware atualmente. Ex.: #define BUSY C0 #define STROBE C1 #define HPRINT B7 #define PPRINT D #include “includes/printer.h” void printer(unsigned char c) Esta função imprime um caracter pela impressora matricial. void prn_printf(const char *str) Esta função imprime uma string pela impressora. Ex de uso: #include <pic18.h> #include <stdio.h> #define BUSY C0 #define STROBE C1

Page 152: desenvolvimento de software e hardware embutido para um sistema

143

#define HPRINT B7 #define PPRINT D #include “includes/printer.h” void main() { printer('m'); printer('a'); printer('u'); }

Page 153: desenvolvimento de software e hardware embutido para um sistema

144

APÊNDICE C – GLOSSÁRIO DO SISTEMA DE ESTACIONAMENTO

• Classe: Divisão dos clientes com relação ao tipo de automóvel. O sistema permite um

máximo de 6 classes.

• Cliente: Motorista do automóvel. Pode ser Cliente Mensalista ou Cliente Avulso.

o Cliente Avulso: Motorista de automóvel não cadastrado no sistema.

o Cliente Mensalista (Mensal.): Motorista cadastrado no sistema que paga uma taxa

mensal pelo acesso ao estacionamento.

• Código de Marca (Cod.Marca.): Seqüência de 3 dígitos que identifica um modelo de

automóvel no sistema.

• Código do Mensalista (Cod.Mensal.): Seqüência de 3 dígitos que identifica um mensalista

no sistema.

• Código do Operador (Cod.Op.): Seqüência de 2 dígitos que identifica um operador do

sistema.

• Código do Ticket: Número inteiro aleatório gerado pelo sistema, maior ou igual a 1000 e

menor ou igual a 9999, que é impresso nos tickets de entrada emitidos pelo terminal. Usado

para identificar um automóvel no pátio e dar saída em automóveis.

• Display: Visor LCD de 2 linhas x 40 colunas que serve de interface visual entre o meio

externo e o sistema.

• Estacionamento: Local de abrangência do terminal. Área devidamente preparada para o uso

do serviço em questão.

• Gerente: Ator que administra o estacionamento.

• Tabela de Preços: Tabela que armazena o custo de permanência por fração de tempo.

• Tempo de Desistência: Duração máxima de tempo para entrar e sair sem pagar (5 minutos).

• Tempo de Tolerância na Hora: Quanto tempo a mais da hora o cliente poderá ultrapassar

sem pagar uma nova hora (5 minutos).

• Tempo de Tolerância nas 24 Horas: Tolerância em períodos superiores a 24 horas (1 hora).

• Terminal: Conjunto constituído por: 1 teclado, 1 display, e 1 unidade de processamento.

• Ticket de Entrada: Documento que contém como informação relevante o horário de entrada

do automóvel e o código do ticket.

Page 154: desenvolvimento de software e hardware embutido para um sistema

145

Caso o cliente perca o documento, a saída será realizada pela placa do automóvel.

Obedece ao seguinte modelo:

• Ticket de Recibo: Documento que é fornecido ao cliente caso solicite.

Obedece ao seguinte modelo:

CABEÇALHO1

Cabeçalho2

Cabeçalho3

Cabeçalho4

Cabeçalho5

RECIBO

ENTRADA SAÍDA PERM

mm/dd/aaaa hh:mm hh:mm

xxxyyyy (placa) marca

Rodapé1

Rodapé2

Rodapé3

Page 155: desenvolvimento de software e hardware embutido para um sistema

146

• Ticket de Saída: O documento deverá ser impresso na saída mediante pagamento

correspondente impresso no ticket.

Obedece ao seguinte modelo:

CABEÇALHO1

Cabeçalho2

Cabeçalho3

Cabeçalho4

Cabeçalho5

RECIBO

ENTRADA SAÍDA PERM

mm/dd/aaaa hh:mm hh:mm

xxxyyyy (placa) marca

Rodapé1

Rodapé2

Rodapé3

Page 156: desenvolvimento de software e hardware embutido para um sistema

147

Operador: Ator que utiliza o terminal. Pode ser um gerente ou qualquer outra pessoa operando o

terminal.

CABEÇALHO1

Cabeçalho2

Cabeçalho3

Cabeçalho4

Cabeçalho5

Saída: Código de Entrada

ENTRADA SAÍDA PERM

mm/dd/aaaa hh:mm hh:mm

xxxyyyy (placa) marca

Rodapé1

Rodapé2

Rodapé3

Cabeçalho2

Cabeçalho3

Cabeçalho4 Cabeçalho5

RECIBO

ENTRADA SAÍDA PERM mm/dd/aaaa hh:mm hh:mm xxxyyyy (placa) marca

Rodapé1 Rodapé2 Rodapé3

Page 157: desenvolvimento de software e hardware embutido para um sistema

148

APÊNDICE D – ANÁLISE DE REQUISITOS DO SISTEMA DE ESTACIONAMENTO

1 - O operador do terminal libera a entrada de um cliente do estacionamento no pátio

Fluxo normal:

o O display exibe:

Entrada:

Placa: Cod.Marca:

o O operador digita a placa do automóvel e pressiona “enter”;

o O operador digita o código de 3(três) dígitos associado a marca do automóvel;

o Assim que o operador digita o código de 3 dígitos da marca do automóvel o

sistema exibe, após o código digitado, a marca associada;

o O operador verifica que a marca do automóvel está correta e pressiona “enter”;

o O sistema imprime o ticket de entrada;

Observações:

o Como entrada para o campo placa o sistema aceita uma seqüência de 2 letras

(automóveis antigos) e no máximo 3 letras seguida por 4 algarismos;

o Como entrada para o campo Cod.Marca o sistema aceita apenas uma seqüência

de 3 números

o Modelo de relatório de Ticket de Entrada: ver Glossário

Exceções:

o A placa digitada pelo operador é incorreta.

Ação: o campo Placa no display é limpo e o sistema fica esperando o

operador digitar uma nova placa.

o O código de marca digitado pelo operador é incorreto, i.e., o código digitado

não está cadastrado na tabela de marcas.

Ação: o sistema fica esperando o operador digitar um novo código.

Page 158: desenvolvimento de software e hardware embutido para um sistema

149

o O operador verifica que o código digitado não confere com a marca exibida no

display pelo sistema.

Ação: operador pressiona “Backspace“. O sistema limpa o campo Marca. O

operador digita um novo código de marca e pressiona “enter”.

o O operador tenta dar entrada em um automóvel que já está no pátio.

Ação: O sistema exibe a mensagem: Automóvel já no estacionamento;

O operador pressiona “enter”; Sistema apaga os campos Placa e Marca

e espera o operador digitar uma nova Placa e Marca.

2 - O operador do terminal libera a saída de um cliente do estacionamento.

Fluxo normal:

o O display exibe:

Saída de automóvel

Código:

o O operador digita o código do ticket e pressiona “enter”;

o O sistema exibe no display:

Entrada: dd/mm/aaaa hh:mm:ss Permanência: hh:mm

Saída : dd/mm/aaaa hh:mm:ss Valor: R$ xx,xx R$ xx,xx

o O operador verifica o valor a pagar, recebe o pagamento do cliente e pressiona

“enter”;

o O sistema imprime o ticket de saída.

o O sistema emite o ticket de recibo se o cliente solicitar.

Observações:

o Como entrada para o campo Codigo o sistema aceita apenas uma seqüência de

exatamente 3 algarismos.

o Modelo de relatório de Ticket de Saída: ver Glossário

Exceções:

o O operador digita a placa do automóvel no campo código.

Ação: O sistema dá saída pela placa do automóvel

Page 159: desenvolvimento de software e hardware embutido para um sistema

150

o O operador digita o código de mensalista no campo código.

Ação: O sistema dá saída pelo código do mensalista

o O código de saída/mensalista ou a placa digitado pelo operador não constam no

sistema ou são inválidos.

Ação: o sistema exibe a mensagem Código Inválido. O operador pressiona

“enter”. O sistema limpa o campo Código e fica esperando o operador digitar

um novo código.

3 - O operador do terminal realiza abertura de caixa.

Fluxo Normal:

o O display exibe:

Cód. Operador:

o O operador digita o seu código e tecla “enter”.

o O display exibe:

o Valor: R$ xxx,xx

o O operador confere o valor e pressiona a tecla “enter”.

Exceções:

o O operador cancela a operação pressionando a tecla “Esc” ou a tecla

“Backspace”.

Ação: o Sistema cancela a operação e volta a exibir a tela inicial.

4 - O operador do terminal realiza entrada de caixa.

Fluxo Normal:

o O display exibe:

Valor: R$ xx,xx

o O gerente confere o valor e pressiona a tecla “enter”;

o O sistema emite um ticket de confirmação da operação.

Page 160: desenvolvimento de software e hardware embutido para um sistema

151

Observações:

o Modelo do ticket:

Código do Oper.:

Valor da Oper....:

Data/Hora.........:

5 - O operador do terminal realiza saída de caixa

Fluxo Normal:

o O display exibe:

Valor: R$ xx,xx

o O gerente confere o valor e pressiona a tecla “enter”;

o O sistema emite um ticket de confirmação da operação.

Observações:

o Modelo do ticket:

Código do Oper.;

Valor da Oper....:

Data/Hora.........:

6 - O operador do terminal lista os automóveis presentes no pátio

Fluxo normal:

o O sistema imprime a relação dos automóveis presentes no pátio.

o Modelo de Tabela de Entrada:

Placa Cód. Marca Data Hora

YYYAAAA YYY DD/MM/AA HH:MM:SS

Page 161: desenvolvimento de software e hardware embutido para um sistema

152

=== TABELA DE PRECOS ===

TABELA n – Classe n

DESISTENCIA TOLERANCIA TOLERANCIA 24HS

xx min xx min x h

Ate xx hs de permanencia: R$ xx.xx

7 - O operador do terminal lista a tabela de preços

Fluxo Normal:

o O dislay exibe:

Tabela(s) (1-6/T):

Onde T indica todas as tabelas.

o O operador digita o numero da tabela que deseja imprimir e pressiona a

tecla “enter”

o O sistema imprime a(s) tabela(s) que o operador solicitou.

Observações:

o O sistema imprime a(s) tabela(s) de preço contendo: o número da tabela; a

classe a qual se aplica; todos os intervalos de tempo e os valores

associados e se cada intervalo é ou não fracionado.

o Modelo de relatório de listagem de tabela de preços

=

=

=

T

A

B

E

L

A

o Durante a digitação do campo Tabela(s) (1-6/t) o sistema aceita apenas

seqüências de exatamente 1 número de 1 à 6 e o caractere T.

8 - O operador do terminal troca o nível de acesso (operador/gerente/root/sistema)

Fluxo Normal:

o O display exibe:

Page 162: desenvolvimento de software e hardware embutido para um sistema

153

Nivel(1-4):

Senha :

o O operador digita o nível para o qual deseja mudar;

o O sistema verifica se o operador pode mudar para aquele nível;

o O operador digita a senha para trocar de nível e pressiona “enter”;

o O sistema troca o nível de acesso restringindo/permitindo acesso à

funções específicas do sistema.

Observações:

o O nível root tem acesso a todas as funções do sistema além de poder

alterar sua senha.

o O nível sistema tem os mesmos privilégios de root, mas a senha de

sistema não pode ser alterada.

o Os níveis operador e gerente estão descritos no apêndice C

Exceções:

o A senha digitada pelo operador para troca de nível é inválida

Ação: O sistema exibe a mensagem Senha Inválida; limpa o campo

senha e espera o operador digitar novamente uma senha.

9 - O operador do terminal imprime a tabela com códigos das marcas

Fluxo normal:

o O sistema imprime a relação das marcas cadastradas no sistema com seus

respectivos código, classe e descrição.

o Modelo de Tabela de Marcas:

Cod.Marca Classe Descrição

Xx Y Descrição textual que identifica o automóvel

10 - O gerente inclui itens na tabela de marcas

Page 163: desenvolvimento de software e hardware embutido para um sistema

154

Fluxo Normal:

o O display exibe:

Cod.Marca: xxx

Marca:

o O gerente digita a marca/modelo do automóvel e pressiona “enter”;

o O display exibe

Classe:

o O gerente digita a classe do automóvel e pressiona “enter”.

Observações:

o O campo Cod.Marca exibe o código atribuído pelo sistema à marca que está

sendo cadastrada.

o Durante a digitação do campo marca, o sistema aceita apenas seqüências

alfanuméricas de pelo menos 1 caractere.

o Durante a digitação do campo classe, o sistema aceita apenas os algarismos

1,2,3,4,5 e 6;

11- O gerente remove itens na tabela de marcas

Fluxo Normal:

o O display exibe:

Cod.Marca:

o O gerente digita o código e pressiona “enter”;

o O display exibe:

XXX – ABC

Excluir? (S/N)

o Onde XXX representa o código e ABC a marca associada.

o O gerente confirma teclando “S”.

Observações:

o Durante a digitação do campo código, o sistema aceita apenas seqüências de

exatamente 3 dígitos.

Page 164: desenvolvimento de software e hardware embutido para um sistema

155

o Durante a confirmação da pergunta Excluir? (S/N) o sistema aceita apenas os

caracteres S ou N como entrada.

12 - O gerente edita itens na tabela de marcas

Fluxo Normal:

o O display exibe:

Cod.Marca:

o O gerente digita o código e pressiona “enter”;

o O display exibe:

Marca: ABC

Nova Marca:

onde ABC representa a marca associada.

o O gerente digita a nova marca e pressiona “enter”;

o O display exibe:

Classe: X

Nova Classe:

o O gerente digita a nova classe e pressiona “enter”.

Observações:

o Durante a digitação do campo código, o sistema aceita apenas seqüências de

exatamente 3 dígitos.

o Durante a digitação do campo marca, o sistema aceita apenas seqüências

alfanuméricas de pelo menos 1 caractere.

o Durante a digitação do campo classe, o sistema aceita apenas os algarismos

1,2,3,4,5 e 6;

13 - gerente inclui novos clientes mensalistas no sistema

Fluxo Normal:

o O display exibe:

Page 165: desenvolvimento de software e hardware embutido para um sistema

156

Cod.Mensal Nome:

Classe (t/d/n):

o O gerente digita o nome do mensalista e pressiona “enter”;

o O gerente digita a classe do mensalista;

o O sistema exibe a classe do mensalista associada ao caractere digitado;

o O gerente verifica a classe do mensalista e pressiona “enter”;

o O display exibe:

Placas: 1-

o O gerente digita a placa do primeiro automóvel do cliente e pressiona “enter”;

o O gerente digita a placa do segundo automóvel do cliente e pressiona “enter”;

Observações:

o O campo Cod.Mensal exibe o código atribuído pelo sistema ao mensalista que

está sendo cadastrado.

o Durante a digitação do campo nome, o sistema aceita apenas seqüências

alfanuméricas de pelo menos 3 caracteres.

o Durante a digitação dos campos placa1 e placa2, o sistema aceita apenas uma

seqüência de no mínimo 2 e no máximo 3 caracteres alfabéticos seguida por 4

dígitos.

14 - O gerente remove clientes mensalistas do sistema

Fluxo Normal:

o O display exibe:

Cód. do Mensalista: xxx

o O gerente digita o código do mensalista;

o O display exibe:

Placa1: Placa2:

Excluir? (S/N): x

o O gerente confirma pressionando S e teclando “enter”.

Page 166: desenvolvimento de software e hardware embutido para um sistema

157

Observações:

o Durante a digitação do campo código, o sistema aceita apenas seqüências de

exatamente 3 dígitos.

o Durante a confirmação da pergunta Excluir? (S/N) o sistema aceita apenas os

caracteres S e N como entrada.

15 - O gerente edita cadastro de clientes mensalistas

Fluxo Normal:

o O display exibe:

Cod.Mensal.: xxx

o O gerente digita o código do mensalista;

o O display exibe:

Nome: ABC

Nome:

o Onde ABC representa o nome atual do Cliente Mensalista.

o O gerente digita um novo nome para o mensalista e pressiona “enter”;

o O display exibe:

Classe (t/d/n): t/d/n

Classe (t/d/n):

o O gerente digita a nova classe do mensalista;

o O sistema exibe a classe do mensalista associada ao caractere digitado;

o O gerente verifica a classe do mensalista e pressiona “enter”;

o O display exibe:

Placa1- xxxyyyy

Placa1-

o Onde xxxyyyy representa a placa1 atual do Cliente Mensalista

o O gerente digita a nova placa do primeiro automóvel do cliente e pressiona “enter”;

o O display exibe:

Page 167: desenvolvimento de software e hardware embutido para um sistema

158

Placa2- xxxyyyy

Placa2-

o Onde xxxyyyy representa a placa2 atual do Cliente Mensalista

o O gerente digita a nova placa do segundo automóvel do cliente e pressiona “enter”;

Observações:

o Durante a digitação do campo nome, o sistema aceita apenas seqüências alfanuméricas

de pelo menos 3 caracteres.

o Durante a digitação do campo classe, o sistema aceita apenas os caracteres T, D, N;

o Durante a digitação dos campos placa1 e placa2, o sistema aceita apenas uma seqüência

de no mínimo 2 e no máximo 3 caracteres alfabéticos seguida por 4 dígitos.

16 - O gerente configura a tabela de preços

Fluxo Normal:

o O display exibe:

Digite o numero da tabela a ser

configurada (1-6):

o O gerente digita o numero da tebela e pressiona a tecla “enter”

o O display exibe:

Tempo de Desistência (min):

o O gerente digita o tempo de desistência e pressiona a tecla “enter”

o O display exibe:

Tolerância na Hora (min):

o O gerente digita o tempo de tolerância na hora e pressiona a tecla “enter”

o O display exibe:

Tolerância 24h (h):

o O gerente digita o tempo de tolerância nas 24h e pressiona a tecla “enter”

Page 168: desenvolvimento de software e hardware embutido para um sistema

159

o O processo abaixo é executado até que Y atinja o valor 24.

o O display exibe:

Tabela n X ate Y hs de permanencia

Onde X é o fim do intervalo de tempo anterior e começo do intervalo atual e

Y é o fim do intervalo de tempo atual. Se não existe um intervalo de tempo

anterior definido, i.e., o gerente está inserindo o valor para o primeiro

intervalo de tempo, X = 0.

o O gerente digita o valor do fim do intervalo de tempo atual e pressiona a tecla

“enter”.

o O display exibe:

Valor (R$xx.xx):

o O gerente digita o valor do intervalo e pressiona a tecla “enter”.

Observações:

o A tabela de preços inclui o tempo de desistência, o tempo de tolerância na hora

e o tempo de tolerância nas 24h.

o A tolerância nas 24h na soma dos dias não é cumulativa.

o Durante a digitação do campo No. de Tabelas o sistema aceita apenas a

digitação de uma seqüência de exatamente 1 algarismo.

o Durante a digitação dos campos Tempo de Desistência (min), Tolerância na

Hora (min) e Tolerância 24h (min) o sistema aceita apenas números que

pertençam ao intervalo [1;60].

o Durante a digitação do campo Y, o sistema permite apenas a digitação de

números que pertençam ao intervalo [1;24].

17 - O gerente configura o cabeçalho e o rodapé dos tickets de entrada, saída e recibo.

Fluxo Normal:

o O display exibe:

Cabeçalho 1:

o O gerente digita o texto para o cabeçalho 1 e pressiona “enter”;

Page 169: desenvolvimento de software e hardware embutido para um sistema

160

o O display exibe:

Cabeçalho 2:

o O gerente digita o texto para o cabeçalho 2 e pressiona “enter”;

o O display exibe:

Cabeçalho 3:

o O gerente digita o texto para o cabeçalho 3 e pressiona “enter”;

o O display exibe:

Cabeçalho 4:

o O gerente digita o texto para o cabeçalho 4 e pressiona “enter”;

o O display exibe:

Cabeçalho 5:

o O gerente digita o texto para o cabeçalho 5 e pressiona “enter”;

o O display exibe:

Rodapé 1:

o O gerente digita o texto para o rodapé 1 e pressiona “enter”;

o O display exibe:

Rodapé 2:

o O gerente digita o texto para o rodapé 2 e pressiona “enter”;

o O display exibe:

Rodapé 3:

o O gerente digita o texto para o rodapé 3 e pressiona “enter”;

Observações:

o O sistema permite um máximo de 5 linhas de cabeçalho e 3 linhas de rodapé. A fonte

pode ser impressa em tamanho normal (padrão da impressora, máximo de 40

caracteres).

o Durante a digitação dos campos Cabeçalho1-5 e Rodapé1-3, o sistema aceita apenas

seqüências alfanuméricas de pelo menos 3 caracteres.

Page 170: desenvolvimento de software e hardware embutido para um sistema

161

18 - O gerente configura a data e a hora do Sistema.

Fluxo Normal:

o O display exibe:

Datas: dd/mm/aa

Nova Data: / /

o O gerente digita a nova data e pressiona “enter”

o O display exibe:

Hora: hh:mm:ss

Nova Hora: : :

o O gerente digita a nova hora e pressiona “enter”

Observações:

o Durante a digitação do campo Data o sistema aceita apenas uma seqüência de 6

algarismos onde: o número formado pelos dois primeiros algarismos pertença ao

intervalo [0;31], o número formado pelo terceiro e quarto algarismo pertença ao

intervalo [0;12] e o número formado pelos quatro últimos algarismos pertença ao

intervalo [00;99].

Exceções:

o A data digitada pelo operador é inválida. São consideradas datas inválidas:

29/02/aaaa se o número formando por aaaa não for múltiplo de 4 ou for múltiplo

de 400; e, 31/mm/aaaa para mm igual a 04, 06, 09 ou 11.

Ação: o Sistema exibe a mensagem Data Inválida, limpa o campo Data e espera

que o operador digite uma nova data.

19 - O gerente inclui operadores no sistema

Fluxo Normal:

o O display exibe:

Codigo:

Nome:

o O gerente digita um nome que identificará o operador e pressiona “enter”;

Page 171: desenvolvimento de software e hardware embutido para um sistema

162

o O display exibe:

Nível (1-3)

o O gerente digita o nível do operador inserido

Observações:

o Durante a digitação do campo nome, o sistema aceita apenas seqüências

alfanuméricas de pelo menos 3 caracteres.

o Durante a digitação do campo Nível, o sistema aceita apenas os algarismos 1,2 e

3.

20 - O gerente edita o cadastro de operadores do sistema

Fluxo Normal:

o O display exibe:

Cod. Op:

o O gerente digita o código do operador;

o O display exibe:

Nome:

Novo Nome:

o O gerente digita o nome do operador e pressiona “enter”;

o O display exibe:

Nível:

Novo Nível:

o O gerente digita o novo nível do operador editado

Observações:

o Durante a digitação do campo código, o sistema aceita apenas seqüências de

exatamente 2 dígitos.

o Durante a digitação do campo nome, o sistema aceita seqüências alfanuméricas

de pelo menos 3 caracteres.

o Durante a digitação do campo Nível, o sistema aceita apenas os algarismos 1,2 e

3.

Page 172: desenvolvimento de software e hardware embutido para um sistema

163

21 - O gerente remove operadores do sistema

Fluxo Normal:

o O display exibe:

Cod. Op:

o O gerente digita o código do operador e pressiona “enter”;

o O display exibe:

Excluir (S/N)?

o O gerente digita “S” e pressiona “enter”;

Observações:

o Durante a digitação do campo código, o sistema aceita apenas seqüências de

exatamente 2 dígitos.

o Durante a confirmação da pergunta Excluir? (S/N) o sistema aceita apenas os

caracteres s,S,n e N como entrada.