Escolar Documentos
Profissional Documentos
Cultura Documentos
1
Rodrigo Maximiano Antunes de Almeida
Instituto de Engenharia de Sistemas e Tecnologia da Informao,
Universidade Federal de Itajub,
Minas Gerais,
Brasil
rodrigomax @ unifei.edu.br
30 de Agosto de 2011
1
cbnd Licenciado sobre Criative Commons Attribution-NonCommercial-NoDerivs
Contedo
1 Introduo 1
1.1 Linguagem C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.: Hardware utilizado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1. Ambiente de programao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Instalao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Congurao do gravador ICD2 . . . . . . . . . . . . . . . . . . . . . . . 4
Criao de um novo projeto . . . . . . . . . . . . . . . . . . . . . . . . . 5
2 Linguagem C para sistemas embarcados 9
:.1 Indentao e padro de escrita . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
:.: Comentrios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
:. Arquivos .c e .h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
:. Diretivas de compilao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
#include . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
#dene . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
#ifdef, #ifndef, #else e #endif . . . . . . . . . . . . . . . . . . . . . . . . 14
:. Tipos de dados em C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Representao binria e hexadecimal . . . . . . . . . . . . . . . . . . . . . 16
Modicadores de tamanho e sinal . . . . . . . . . . . . . . . . . . . . . . . 17
Modicadores de acesso . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Modicadores de posicionamento . . . . . . . . . . . . . . . . . . . . . . . 19
Modicador de persistncia . . . . . . . . . . . . . . . . . . . . . . . . . . 19
:.6 Operaes aritmticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
:. Funo main() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
:.8 Rotinas de tempo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
:.j Operaes com bits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
NOT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
AND . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
OR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
XOR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Shift . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Ligar um bit (bit set) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
Desligar um bit (bit clear) . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
Trocar o valor de um bit (bit ip) . . . . . . . . . . . . . . . . . . . . . . 28
Vericar o estado de um bit (bit test) . . . . . . . . . . . . . . . . . . . . 29
Criando funes atravs de denes . . . . . . . . . . . . . . . . . . . . . 30
:.1o Debug de sistemas embarcados . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
Externalizar as informaes. . . . . . . . . . . . . . . . . . . . . . . . . . . 34
Programao incremental . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
Checar possveis pontos de Memory-leak . . . . . . . . . . . . . . . . . . . 35
Cuidado com a fragmentao da memria . . . . . . . . . . . . . . . . . . 35
Otimizao de cdigo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
Reproduzir e isolar o erro . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
i
:.11 Ponteiros e endereos de memria . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
3 Arquitetura de microcontroladores 38
.1 Acesso memria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
.: Clock e tempo de instruo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
. Esquema eltrico e circuitos importantes . . . . . . . . . . . . . . . . . . . . . . . 43
Multiplexao nos terminais do microcontrolador . . . . . . . . . . . . . . 44
. Registros de congurao do microcontrolador . . . . . . . . . . . . . . . . . . . . 45
4 Programao dos Perifricos 47
.1 Acesso s portasdo microcontrolador . . . . . . . . . . . . . . . . . . . . . . . . 48
.: Congurao dos perifricos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
. Barramento de Led's . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
. Display de 7 segmentos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
Multiplexao de displays . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
Criao da biblioteca . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
. Leitura de teclas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
Debounce por software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
Arranjo de leitura por matriz . . . . . . . . . . . . . . . . . . . . . . . . . 62
Criao da biblioteca . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
.6 Display LCD 2x16 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
Criao da biblioteca . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
. Comunicao serial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
RS 232 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
Criao da biblioteca . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
.8 Conversor AD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
Elementos sensores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
Processo de converso AD . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
Criao da biblioteca . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
.j Sadas PWM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
Criao da biblioteca . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
.1o Timer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
.11 Reproduo de Sons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
.1: Interrupo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
.1 Watchdog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
5 Arquitetura de desenvolvimento de software 97
.1 One single loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
.: Interrupt control system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
. Cooperative multitasking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
Fixao de tempo para execuo dos slots . . . . . . . . . . . . . . . . . . 104
Utilizao do tempo livrepara interrupes . . . . . . . . . . . . . . . . . 105
6 Anexos 107
6.1 cong.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
6.: basico.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
6. Instalar gravadores/depuradores de PIC em sistemas x64 . . . . . . . . . . . . . . 110
ii
Lista de Figuras
1.1 Camadas de abstrao de um sistema operacional . . . . . . . . . . . . . . . . . . 1
1.2 Pesquisa sobre linguagens utilizadas para projetos de software embarcado . . . . 2
1.3 Congurao das ferramentas de compilao . . . . . . . . . . . . . . . . . . . . . 5
1.4 Instalao do ICD2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.5 Resumo das conguraes do ICD2 no MPLAB . . . . . . . . . . . . . . . . . . . 6
1.6 Pedido de atualizao do rmware do ICD2 . . . . . . . . . . . . . . . . . . . . . 7
1.7 Project Explorer do MPLAB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.8 Comparativo de caractersticas da famlia PIC 18fxx5x . . . . . . . . . . . . . . . 8
2.1 Problema das Referncias Circulares . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.2 Soluo das referncias circulares com #ifndef . . . . . . . . . . . . . . . . . . . . 16
2.3 Loop innito de um device driver gerando erro no sistema . . . . . . . . . . . . . 22
2.4 Exemplo de funcionamento do vetor de interrupo . . . . . . . . . . . . . . . . . 22
3.1 Arquitetura do microcontrolador PIC 18F4550 . . . . . . . . . . . . . . . . . . . 39
3.2 Memria como um armrio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
3.3 Memria e perifricos como um armrio . . . . . . . . . . . . . . . . . . . . . . . 41
3.4 Regies de memrias disponveis no PIC18F4550 . . . . . . . . . . . . . . . . . . 41
3.5 Esquema eltrico: Microcontrolador PIC 18F4550 . . . . . . . . . . . . . . . . . . 43
3.6 Registros de congurao do microcontrolador PIC 18F4550 . . . . . . . . . . . . 45
4.1 Registros de congurao dos perifricos do PIC 18F4550 . . . . . . . . . . . . . 50
4.2 Barramento de Led's . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
4.3 Display de 7 Segmentos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
4.4 Diagrama eltrico para display de 7 segmentos com anodo comum . . . . . . . . . 54
4.5 Ligao de 4 displays de 7 segmentos multiplexados . . . . . . . . . . . . . . . . . 55
4.6 Circuito de leitura de chave . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
4.7 Oscilao do sinal no momento do chaveamento . . . . . . . . . . . . . . . . . . . 60
4.8 Circuito de debounce . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
4.9 Utilizao de ltro RC para debounce do sinal . . . . . . . . . . . . . . . . . . . . 61
4.10 Teclado em arranjo matricial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
4.11 Display Alfanumrico LCD 2x16 . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
4.12 Display Alfanumrico LCD 2x16 - verso . . . . . . . . . . . . . . . . . . . . . . . 67
4.13 Caracteres disponveis para ROM A00 . . . . . . . . . . . . . . . . . . . . . . . . 68
4.14 Caracteres disponveis para ROM A02 . . . . . . . . . . . . . . . . . . . . . . . . 69
4.15 Esquemtico de ligao do display de LCD . . . . . . . . . . . . . . . . . . . . . . 71
4.16 Sinal serializado para transmisso em RS232 . . . . . . . . . . . . . . . . . . . . . 75
4.17 Lmpada incandescente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
4.18 Potencimetro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
4.19 Potencimetro como divisor de tenso . . . . . . . . . . . . . . . . . . . . . . . . 80
4.20 Circuito integrado LM35 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
4.21 Diagrama de blocos do LM35 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
4.22 Conversor analgico digital de 2 bits . . . . . . . . . . . . . . . . . . . . . . . . . 82
4.23 Sinais PWM com variao do duty cycle . . . . . . . . . . . . . . . . . . . . . . . 85
iii
5.1 Exemplo de mquina de estados . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
5.2 Exemplo da mudana de slots no tempo . . . . . . . . . . . . . . . . . . . . . . . 105
5.3 Linha de tempo de um sistema com 1 slot . . . . . . . . . . . . . . . . . . . . . . 105
5.4 Comportamento da linha de tempo com interrupes . . . . . . . . . . . . . . . . 105
iv
Lista de Tabelas
1.1 Softwares utilizados no curso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.1 Tipos de dados e faixa de valores . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.2 Representao decimal - binria - hexadecimal . . . . . . . . . . . . . . . . . . . . 17
2.3 Alterao de tamanho e sinal dos tipos bsicos . . . . . . . . . . . . . . . . . . . 18
2.4 Operao bit set com dene . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.5 Operao bit clear com dene . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
2.6 Operao bit ip com dene . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
2.7 Operao bit test com dene . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.1 Quantidade de operaes e tarefas . . . . . . . . . . . . . . . . . . . . . . . . . . 42
4.1 Endereos de memria para as portas do PIC 18F4550 . . . . . . . . . . . . . . . 48
4.2 Tabela de congurao do PIC para as experincias . . . . . . . . . . . . . . . . . 51
4.3 Converso binrio - hexadecimal para displays de 7 segmentos . . . . . . . . . . . 55
4.4 Lista de comandos aceitos pelo o LCD . . . . . . . . . . . . . . . . . . . . . . . . 70
4.5 Taxas de transmisso para diferentes protocolos . . . . . . . . . . . . . . . . . . . 74
4.6 Clculo do valor da taxa de transmisso da porta serial . . . . . . . . . . . . . . . 76
4.7 Faixa de frequncias mximas e mnimas para cada congurao do prescaler . . 86
v
Lista de Programas
2.1 Resumo do disp7seg.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.2 Resumo do disp7seg.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.3 Estrutura de header . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.4 Operaes aritmticas com tipos diferentes . . . . . . . . . . . . . . . . . . . . . . 20
4.1 disp7seg.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
4.2 disp7seg.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
4.3 Utilizando a biblioteca disp7seg . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
4.4 teclado.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
4.5 teclado.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
4.6 Exemplo de uso da biblioteca teclado . . . . . . . . . . . . . . . . . . . . . . . . . 65
4.7 lcd.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
4.8 lcd.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
4.9 Exemplo de uso da biblioteca de LCD . . . . . . . . . . . . . . . . . . . . . . . . 73
4.10 serial.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
4.11 serial.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
4.12 Exemplo de uso da biblioteca de comunicao serial . . . . . . . . . . . . . . . . . 78
4.13 adc.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
4.14 adc.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
4.15 Exemplo de uso da biblioteca de conversores AD . . . . . . . . . . . . . . . . . . 84
4.16 pwm.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
4.17 pwm.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
4.18 Exemplo de uso da biblioteca das sadas PWM . . . . . . . . . . . . . . . . . . . 88
4.19 timer.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
4.20 timer.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
4.21 Exemplo de uso da biblioteca de um temporizador . . . . . . . . . . . . . . . . . 90
4.22 Reproduo de sons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
4.23 Fontes de Interupo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
4.24 Tratamento das interrupes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
4.25 Inicializao do sistema com interrupes . . . . . . . . . . . . . . . . . . . . . . 95
4.26 Inicializao do sistema com interrupes . . . . . . . . . . . . . . . . . . . . . . 96
5.1 Exemplo de arquitetura single-loop . . . . . . . . . . . . . . . . . . . . . . . . . . 98
5.2 Problema na sincronia de tempo para o single-loop . . . . . . . . . . . . . . . . . 98
5.3 Exemplo de sistema Interrupt-driven . . . . . . . . . . . . . . . . . . . . . . . . . 99
5.4 Exemplo de sistema Interrupt-driven com base de tempo . . . . . . . . . . . . . . 100
5.5 Exemplo de cooperative multitasking . . . . . . . . . . . . . . . . . . . . . . . . . 102
5.6 Exemplo de cooperative multitasking com uso do top slot . . . . . . . . . . . . . 103
5.7 Exemplo de sistema Cooperative-multitasking com slot temporizado . . . . . . . 104
6.1 cong.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
6.2 basico.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
vi
Captulo 1
Introduo
The real danger is not that computers will begin to think like men,
but that men will begin to think like computers. - Sydney J. Harris
Programao para sistemas embarcados exige uma srie de cuidados especiais, pois estes sistemas
geralmente possuem restries de memria e processamento. Por se tratar de sistemas com
funes especcas, as rotinas e tcnicas de programao diferem daquelas usadas para projetos
de aplicativos para desktops.
Tambm necessrio conhecer mais a fundo o hardware que ser utilizado, pois cada mi-
croprocessador possui uma arquitetura diferente, com quantidade e tipos de instrues diversos.
Programadores voltados para desktops no precisam se ater tanto a estes itens, pois eles progra-
mam para um sistema operacional que realiza o papel de tradutor, disponibilizando uma interface
comum, independente do hardware utilizado(Figura 1.1).
Firmware
Hardware
Sistema Operacional
Aplicao
Figura 1.1: Camadas de abstrao de um sistema operacional
Para sistemas embarcados, necessrio programar especicamente para o hardware em ques-
to. Uma opo para se obter articialmente esta camada de abstrao que era gerada pelo
sistema operacional a utilizao de dois itens: um compilador prprio para o componente em
questo e uma biblioteca de funes. O compilador ser o responsvel por traduzir a linguagem
de alto nvel em uma linguagem que o microcontrolador consegue entender. A biblioteca de
funes, ou framework, em geral, disponibilizada pelos fabricantes do microcontrolador.
i.i Linguagem C
C is quirky, awed, and an enormous success. - Dennis M. Ritchie
Neste curso ser utilizada a linguagem C. Esta uma linguagem com diversas caractersticas que
a tornam uma boa escolha para o desenvolvimento de software embarcado. Apesar de ser uma
linguagem de alto nvel, permite ao programador um acesso direto aos dispositivos de hardware.
1
2 Introduo
Tambm a escolha da maioria dos programadores e gerentes de projetos no que concerne
ao desenvolvimento de sistemas embarcados como pode ser visto na Figura 1.2.
Figura 1.2: Pesquisa sobre linguagens utilizadas para projetos de software embarcado
Fonte: http://www.embedded.com/design/218600142
A descontinuidade depois de 2004 se d devido mudana de metodologia da pesquisa. Antes
de 2005, a pergunta formulada era: Para o desenvolvimento da sua aplicao embarcada, quais
das linguagens voc usou nos ltimos 12 meses?. Em 2005 a pergunta se tornou: Meu projeto
embarcado atual programado principalmente em ______. Mltiplas selees eram possveis
antes de 2005, permitindo a soma superior a 100%, sendo o valor mdio de 209%, o que implica
que a maioria das pessoas escolheu duas ou mais opes.
O maior impacto na pesquisa pode ser visualizado na linguagem assembler: at 2004, estava
presente em 62% das respostas (na mdia). O que comprova que praticamente todo projeto de
sistema embarcado exige um pouco de assembler. Do mesmo modo, percebemos que atualmente
poucos projetos so realizados totalmente ou em sua maioria em assembler, uma mdia de apenas
7%.
i.z Hardware utilizado
People who are really serious about software should make their own
hardware. - Alan Kay
Como o enfoque deste curso a programao de sistemas embarcados e no a eletrnica, utili-
zaremos um kit de desenvolvimento pronto, baseado num microcontrolador PIC.
Como perifricos disponveis temos:
1 display LCD 2 linhas por 16 caracteres (compatvel com HD77480)
4 displays de 7 segmentos com barramento de dados compartilhados
8 leds ligados ao mesmo barramento dos displays
16 mini switches organizadas em formato matricial 4x4
1 sensor de temperatura LM35C
1 resistncia de aquecimento ligada a uma sada PWM
1 motor DC tipo ventilador ligado a uma sada PWM
1 buzzer ligado a uma sada PWM
Notas de Aula ELT024 - Programao para Sistemas Embarcados
3 Introduo
1 canal de comunicao serial padro RS-232
Cada componente ter seu funcionamento bsico explicado para permitir o desenvolvimento de
rotinas para estes.
i.j Ambiente de programao
First, solve the problem. Then, write the code. - John Johnson
O ambiente utilizado ser o MPLAB(R). Este um ambiente de desenvolvimento disponibilizado
pela Microchip(R) gratuitamente. O compilador utilizado ser o SDCC, os linkers e assemblers
sero disponibilizados pela biblioteca GPUtils.
Como o foco a aprendizagem de conceitos sobre programao embarcada, poder ser uti-
lizada qualquer plataforma de programao e qualquer compilador/linker. Caso seja utilizado
qualquer conjunto de compilador/linker diferentes deve-se prestar ateno apenas nas diretivas
para gravao.
Para a programao em ambiente Linux recomenda-se o uso da sute PIKLAB 15.10. Este
programa foi desenvolvido para KDE 3.5. Alm de permitir a integrao com o mesmo compilador
utilizado neste curso permite a programao do microcontrolador utilizando o programador ICD2
via USB.
Instalao
A Tabela 1.1 apresenta os softwares que sero utilizados no curso.
Tabela 1.1: Softwares utilizados no curso
Item Verso Licena
IDE MPLAB 8.50 Proprietrio
Compilador SDCC 2.9.00 (win32) GPL
Linker/Assembler GPUtils 0.13.7 (win32) GPL
Plugin MPLAB sdcc-mplab 0.1 GPL
Todos os softwares so gratuitos e esto disponveis na internet. Para correta instalao
deve-se instalar os softwares segundo a sequncia apresentada na Tabela 1.1. Anote o diretrio
onde cada software foi instalado.
Aps a instalao dos softwares deve-se abrir o arquivo pic16devices.txt (de preferncia no
wordpad) que foi instalado no diretrio do SDCC dentro da pasta include\pic16 (por padro
C:\Arquivos de programas\SDCC\include\pic16). No windows vista e windows 7 no possvel
editar arquivos de sistema. Neste caso clique no arquivo com o boto direito > Propriedades >
Segurana > Editar > Usurios e selecionar a opo Controle Total, depois clique em ok. Aps
isso ser possvel editar o arquivo. Procure ento a seguintes linhas:
name 18f4550
using 18f2455
Trocar a letra f minscula da primeira linha, apenas do 18f4550, para um F maisculo:
name 18F4550
using 18f2455
Notas de Aula ELT024 - Programao para Sistemas Embarcados
4 Introduo
Aps isto abrir a pasta onde foi instalado o MPLAB (por padro: C:\Arquivos de pro-
gramas\Microchip\MPLAB IDE). Abrir a pasta Core\MTC Suites. Abrir os arquivos sdc-
clink.mtc e gplink.mtc num editor de texto. Apagar o contedo do arquivo sdcclink.mtc.
Copiar todo contedo do arquivo gplink.mtc para o arquivo sdcclink.mtc. Salvar.
Aps o passo acima o arquivo sdcclink.mtc dever conter o seguinte texto:
// Microchip Language Tools
// Configuration File
// gplink
// Craig Franklin
[Tool]
Tool=gplink
ScriptExtension=lkr
DefaultOptions=
MultipleNodes=1
SpaceBetweenSwitchAndData=1
[0]
Description=Output filename
Switch=-o
Data=1
MultipleOptions=0
OutputNameSwitch=Switch
Hidden=1
[1]
Description=Map file
Switch=-m
Data=0
MultipleOptions=0
[2]
Description=COFF File
Switch=-c
Data=0
MultipleOptions=0
[3]
Description=Hex Format
OptionList=INHX8M;INHX8S;INHX32
INHX8M=-a INHX8M
INHX8S=-a INHX8S
INHX32=-a INHX32
Data=0
[4]
Description=Quiet mode
Switch=-q
Data=0
[5]
Description=Library directories
Switch=-I
Data=1
MultipleOptions=0
LibrarySwitch=Switch
Hidden=1
[6]
Description=Linker script directories
Switch=-I
Data=1
MultipleOptions=0
LinkerScriptSwitch=Switch
Hidden=1
[7]
Description=Use Shared Memory
Switch=-r
Data=0
[8]
Description=Fill Value
Switch=-f
MultipleOptions=0
Data=1
[9]
Description=Stack Size
Switch=-t
MultipleOptions=0
Data=1
[10]
Description=No List File
switch=-l
Data=0
Em seguida abrir o programa MPLAB e ir ao menu Projects -> Set Language Tool Locations.
Ser apresentada uma tela similar a da Figura 1.3.
Selecione a ferramenta Small Device C Compiler for PIC16 (SDCC16). Expanda a opo
Executables. A ferramenta gpasm e gplink so obtidas no diretrio bin dentro de onde
foi instalado o GPUtils, por padro: C:\Arquivos de programas\gputils\bin. A ferramenta
sdcc16 encontrada no diretrio bin dentro do diretrio onde foi instalado o SDCC com o
nome sdcc.exe, por padro: C:\Arquivos de programas\SDCC\bin\. Clicar em OK. Aps
estes passos a sute MPLAB est pronta para trabalhar com o compilador SDCC+GPUtils.
Congurao do gravador ICD2
Aps instalar o MPLAB j possvel fazer a instalao e congurao do gravador ou depurador
ICD2. Conecte-o a qualquer porta USB e aguarde a tela de instalao do Windows. Em algumas
verses do windows pode acontecer de voc ser perguntado se deseja instalar um software no
Notas de Aula ELT024 - Programao para Sistemas Embarcados
5 Introduo
Figura 1.3: Congurao das ferramentas de compilao
assinado digitalmente, certique-se que a verso do rmware pelo menos 1.0.0.0 da fabricante
Microchip, conforme pode ser visto na Figura 1.4 e avance.
Aps o termino da instalao abra o programa MPLAB para congurar o gravador ou depu-
rador. V ao menu Programmer -> Select Programmer -> MPLAB ICD 2. V novamente ao
menu Programmer mas desta vez escolha a opo MPLAB ICD 2 Setup Wizard.
No wizard, escolha a comunicao como USB e depois diga que a placa possui alimentao
independente Target has own power supply. Deixe as outras opes na seleo padro. Antes
de clicar em concluir verique ao nal se o resumo se parece com o da Figura 1.5.
Na primeira vez que o computador se conectar ao ICD2 possvel que o MPLAB precise
atualizar o rmware do ICD2 conforme o aviso que pode ser visto na Figura 1.6.
Criao de um novo projeto
Recomenda-se a utilizao do assistente disponvel para a criao de um novo projeto (menu
Project -> Project Wizard). Ele ir questionar sobre (entre parnteses os valores adotados neste
curso):
1. O microcontrolador a ser utilizado (PIC18F4550)
2. A sute de compilao (SDCC 16)
3. O diretrio e nome do projeto
4. Arquivos j existentes cujo programador deseja incluir no projeto
Aps estes passos o projeto estar criado. Caso a lista de arquivos do projeto no esteja
visvel v ao menu View -> Project.
Para a criao de um novo arquivo v at o menu File -> New. Neste novo arquivo digite
alguma coisa e salve-o. Caso seja o arquivo que conter a funo principal (main) costume
salv-lo com o nome de main.c.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
6 Introduo
Figura 1.4: Instalao do ICD2
Figura 1.5: Resumo das conguraes do ICD2 no MPLAB
Notas de Aula ELT024 - Programao para Sistemas Embarcados
7 Introduo
Figura 1.6: Pedido de atualizao do rmware do ICD2
A cada novo arquivo criado necessrio inser-lo no projeto. Para isso deve-se clicar na pasta
correspondente ao tipo de arquivo que se deseja incluir e em seguida Add Files como pode ser
visualizado na Figura 1.7.
Figura 1.7: Project Explorer do MPLAB
Alm dos arquivos criados pelo programador, existem trs arquivos que devem ser adicionados
ao projeto: um de linker e dois de bibliotecas.
1. Linker
(a) C:\Arquivos de programas\gputils\lkr\18f4550.lkr
2. Bibliotecas
(a) C:\Arquivos de programas\SDCC\lib\pic16\libdev18f4550.lib
(b) C:\Arquivos de programas\SDCC\lib\pic16\18f4550.lkr
O arquivo de linker o responsvel por indicar quais so os espaos de memria disponveis
no chip utilizado, onde comeam e de que tipo so (RAM, ROM, Flash) etc.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
8 Introduo
// File: 18f4550.lkr
// Sample linker script for the PIC18F4550 processor
// Not intended for use with MPLAB C18. For C18 projects,
// use the linker scripts provided with that product.
LIBPATH .
CODEPAGE NAME=page START=0x0 END=0x7FFF
CODEPAGE NAME=idlocs START=0x200000 END=0x200007 PROTECTED
CODEPAGE NAME=config START=0x300000 END=0x30000D PROTECTED
CODEPAGE NAME=devid START=0x3FFFFE END=0x3FFFFF PROTECTED
CODEPAGE NAME=eedata START=0xF00000 END=0xF000FF PROTECTED
ACCESSBANK NAME=accessram START=0x0 END=0x5F
DATABANK NAME=gpr0 START=0x60 END=0xFF
DATABANK NAME=gpr1 START=0x100 END=0x1FF
DATABANK NAME=gpr2 START=0x200 END=0x2FF
DATABANK NAME=gpr3 START=0x300 END=0x3FF
DATABANK NAME=usb4 START=0x400 END=0x4FF PROTECTED
DATABANK NAME=usb5 START=0x500 END=0x5FF PROTECTED
DATABANK NAME=usb6 START=0x600 END=0x6FF PROTECTED
DATABANK NAME=usb7 START=0x700 END=0x7FF PROTECTED
ACCESSBANK NAME=accesssfr START=0xF60 END=0xFFF PROTECTED
Percebemos pelo linker acima que existem 256 bytes de memria eeprom, no voltil, que foi
denominada eedata. Para a memria RAM est reservado um total de 2 kbytes, divididos
1
em 4
bancos de memria, sendo que o primeiro foi dividido em duas sees. Estes foram denominados
(acessram-gpr0), gpr1, gpr2, gpr3
2
.
Para o programa temos disponvel uma regio de 32 kbytes de memria ash, que vai da
posio 0x0000 at 0x7FFF. Este o mesmo endereo da memria RAM. No existe conito,
pois estamos trabalhando, no caso do PIC, com uma arquitetura Harvard. Nesta existem dois
barramentos e duas memrias diferentes: uma para o programa, denominada CODEPAGE no
linker, e uma para os dados, denominada DATABANK. Notar que apesar da memria eeprom ser
utilizada para armazenamento no voltil de dados, ela est mapeada no barramento de cdigo.
Isto se deve a construo interna do microcontrolador.
Os dados apresentados no linker e descorridos anteriormente podem ser vericados e compa-
rados com outros modelos observando a Figura 1.8.
Figura 1.8: Comparativo de caractersticas da famlia PIC 18fxx5x
1
Uma das maiores diculdades encontradas em se construir um compilador de linguagem C o gasto em termos
de recursos computacionais que dispendido para tratar estes quatro bancos como sequenciais. Na realidade eles
esto todos sobre um mesmo endereo de memria. Para acessar cada um deles necessrio atuar sobre um
registro no PIC, indicando qual banco estar ativo naquele momento.
2
gprX signica General Propouse Ram bank X
Notas de Aula ELT024 - Programao para Sistemas Embarcados
Captulo 2
Linguagem C para sistemas embarcados
C is quirky, awed, and an enormous success. - Dennis M. Ritchie
A programao para sistemas embarcados possui diversas caractersticas diferentes da progra-
mao voltada para desktop. Do mesmo modo, existem alguns conceitos que geralmente no so
explorados nos cursos de linguagens de programao em C, mas que so essenciais para o bom
desenvolvimento deste curso. Estes conceitos sero explanados neste captulo.
z.i Indentao e padro de escrita
Good programmers use their brains, but good guidelines save us
having to think out every case. - Francis Glassborow
fundamental obedecer um padro para escrita de programas, de modo que a visualizao do
cdigo seja facilitada.
Na lngua portuguesa utilizamos pargrafos para delimitar blocos de frases que possuem a
mesma ideia. Em linguagem C estes blocos so delimitados por chaves { e }.
Para demonstrar ao leitor que um pargrafo comeou utilizamos um recuo direita na pri-
meira linha. Quando necessrio realizar uma citao de itens coloca-se cada um destes itens
numa linha recuada direita, algumas vezes com um identicador como um trao - ou seta
-> para facilitar a identicao visual.
Com esse mesmo intuito, os recuos e espaamentos so utilizados para que o cdigo seja mais
facilmente entendido.
Como todo bloco de comandos iniciado e terminado com uma chave, tornou-se comum que
estas (as chaves) estejam no mesmo nvel e todo cdigo interno a elas seja deslocado direita. Se
existir um segundo bloco interno ao primeiro, este deve ser deslocado duas vezes para indicar a
hierarquia no uxo do programa. Segue abaixo um exemplo de um mesmo cdigo com diferena
apenas na indentao.
9
10 Linguagem C para sistemas embarcados
Cdigo indentado Cdigo no indentado
1 void main ( void) interrupt 0
{
unsigned i nt i ;
unsigned i nt temp ;
unsigned i nt teclanova=0;
InicializaSerial ( ) ;
InicializaDisplays ( ) ;
InicializaLCD ( ) ;
InicializaAD ( ) ;
for ( ; ; )
{
AtualizaDisplay ( ) ;
i f ( teclanova != Tecla )
{
teclanova = Tecla ;
for ( i=0; i<16; i++)
{
i f ( BitTst ( Tecla , i) )
{
EnviaDados ( i+48) ;
}
}
}
for ( i = 0; i < 1000; i++) ;
}
}
void main ( void) interrupt 0
{
unsigned i nt i ;
unsigned i nt temp ;
unsigned i nt teclanova=0;
InicializaSerial ( ) ;
InicializaDisplays ( ) ;
InicializaLCD ( ) ;
InicializaAD ( ) ;
for ( ; ; )
{
AtualizaDisplay ( ) ;
i f ( teclanova != Tecla )
{
teclanova = Tecla ;
for ( i=0; i<16; i++)
{
i f ( BitTst ( Tecla , i) )
{
EnviaDados ( i+48) ;
}
}
}
for ( i = 0; i < 1000; i++) ;
}
}
Podemos notar pelo cdigo anterior que aquele que possui indentao facilita na vericao
de quais instrues/rotinas esto subordinadas s demais.
Outra caracterstica de padronizao est na criao de nomes de funes e de variveis. Pela
linguagem C uma funo ou varivel pode ter qualquer nome desde que: seja iniciada por uma
letra, maiscula ou minscula, e os demais caracteres sejam letras, nmeros ou underscore _.
A linguagem C permite tambm que sejam declaradas duas variveis com mesmo nome caso
possuam letras diferentes apenas quanto caixa (maiscula ou minscula). Por exemplo: var e
vAr so variveis distintas, o que pode gerar erro no desenvolvimento do programa causando
dvidas e erros de digitao.
Por isso convenciona-se que os nomes de variveis sejam escritos apenas em minsculas.
Quando o nome composto, se utiliza uma maiscula para diferenci-los como, por exemplo, as
variveis contPos e contTotal.
Nomes de funo sero escritos com a primeira letra maiscula e no caso de nome composto,
cada inicial ser grafada em maisculo: InicializaTeclado(), ParaSistema().
Tags de denies (utilizados em conjunto com a diretiva #dene) sero grafados exclusiva-
mente em maisculo: NUMERODEVOLTAS, CONSTGRAVITACIONAL.
Cada chave ser colocada numa nica linha, conforme exemplo anterior, evitando-se constru-
es do tipo:
i f ( PORTA == 0x30 ) { PORTB = 0x10 ; }
Ou
i f ( PORTA == 0x30 ) {
PORTB = 0x10 ; }
As regras apresentadas visam fornecer uma identidade visual ao cdigo. Tais regras no so
absolutas, servem apenas para o contexto desta apostila. Em geral, cada instituio ou projeto
Notas de Aula ELT024 - Programao para Sistemas Embarcados
11 Linguagem C para sistemas embarcados
possui seu prprio conjunto de normas. importante ter conhecimento deste conjunto e aplic-lo
em seu cdigo.
O estilo adotado nesta apostila conhecido tambm como estilo Allman, bsd (no emacs)
ou ANSI, j que todos os documentos do padro ANSI C utilizam este estilo. Apesar disto o
padro ANSI C no especica um estilo para ser usado.
z.z Comentrios
If the code and the comments disagree, then both are probably
wrong. - Norm Schryer
Comentrios so textos que introduzimos no meio do programa fonte com a inteno de torn-
lo mais claro. uma boa prtica em programao inserir comentrios no meio dos nossos
programas. Pode-se comentar apenas uma linha usando o smbolo // (duas barras). Para
comentar mais de uma linha usa-se o smbolo /* (barra e asterisco) antes do comentrio e */
(asterisco e barra) para indicar o nal do comentrio.
#include <s t di o . h>
#define DIST 260 // di s t anc i a ent r e SP e I t a
i nt main ( i nt argc , char argv [ ] )
{
/ es s e programa s er ve para
mostrar como se i ns e r e coment ri os /
printf ( "So Paulo est %d Km de Itajub" , DIST ) ;
return 0;
}
z.j Arquivos .c e .h
Na programao em linguagem C utilizamos dois tipos de arquivos com funes distintas. Toda
implementao de cdigo feita no arquivo com extenso .c (code). nele que criamos as
funes, denimos as variveis e realizamos a programao do cdigo. Se existem dois arquivos
.c no projeto e queremos que um deles possa usar as funes do outro arquivo, necessrio
realizar um #include.
Os arquivos .h (header) tem como funo ser um espelho dos arquivos .c disponibilizando
as funes de um arquivo .c para serem utilizadas em outros arquivos. Nele colocamos todos
os prottipos das funes que queremos que os outros arquivos usem.
Se quisermos que uma funo s possa ser utilizada dentro do prprio arquivo, por motivo
de segurana ou organizao, basta declarar seu prottipo APENAS no arquivo .c.
Se for necessrio que um arquivo leia e/ou grave numa varivel de outro arquivo recomen-
dado criar funes especcas para tal nalidade.
O programa 2.1 apresenta um exemplo de um arquivo de cdigo .c e o programa 2.2 apre-
senta o respectivo arquivo de header .h.
Podemos notar que no arquivo .h a funo AtualizaDisplay() no est presente, deste modo
ela no estar disponvel para os outros arquivos. Podemos notar tambm que para ler ou
gravar a varivel digito necessrio utilizar as funes MudarDigito() e LerDigito(). Notar que
no existe acesso direto s variveis. Este tipo de abordagem insere atrasos no processamento
devido um efeito conhecido como overhead de funes, podendo inclusive causar travamentos
no sistema caso no exista espao suciente no stack.
z.q Diretivas de compilao
As diretivas de compilao so instrues que so dadas ao compilador. Elas no sero executa-
das. Todas as diretivas de compilao comeam com um sinal #, conhecido como jogo da velha
ou hash.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
12 Linguagem C para sistemas embarcados
Programa 2.1: Resumo do disp7seg.c
1 // v a r i v e l usada apenas dent ro de s t e arqui vo
2 stati c char temp ;
3 // v a r i v e l que ser usada tambm f or a do arqui vo
4 stati c char valor ;
5 // f unes usadas dent ro e f or a do arqui vo
6 void MudaDigito ( char val )
7 {
8 valor = val ;
9 }
10 char LerDigito ( void)
11 {
12 return valor ;
13 }
14 void InicializaDisplays ( void)
15 {
16 // cdi go da f uno
17 }
18 // f uno usada apenas dent ro de s t e arqui vo
19 void AtualizaDisplay ( void)
20 {
21 // cdi go da f uno
22 }
Programa 2.2: Resumo do disp7seg.h
1 #i f ndef VAR_H
2 #define VAR_H
3 void MudaDigito ( char val ) ;
4 char LerDigito ( void) ;
5 void InicializaDisplays ( void) ;
6 #endif //VAR_H
Notas de Aula ELT024 - Programao para Sistemas Embarcados
13 Linguagem C para sistemas embarcados
#include
A diretiva de compilao #include a responsvel por permitir que o programador utilize no seu
cdigo funes que foram implementadas em outros arquivos, seja por ele prprio ou por outras
pessoas. No necessrio possuir o cdigo fonte das funes que se deseja utilizar. necessrio
apenas de um arquivo que indique os prottipos das funes (como elas devem ser chamadas) e
possuir a funo disponvel em sua forma compilada.
Em geral um arquivo que possui apenas prottipos de funes denominado de Header e
possui a extenso .h.
#dene
Outra diretiva muito conhecida a #dene. Geralmente utilizada para denir uma constante,
mas pode ser utilizada para que o cdigo fonte seja modicado antes de ser compilado.
Original Compilado Resultado na Tela
#define CONST 15
void main ( void)
{
printf ( "%d" , CONST 3) ;
}
void main ( void)
{
printf ( "%d" , 15 3) ;
}
45
Funo Original Opes de uso com o #dene Resultado na Tela
void MostraSaidaPadrao ( )
{
#ifdef PADRAO Serial
char msg = "SERIAL" ;
#el se
char msg = "LCD" ;
#endif
printf ( msg ) ;
}
#include <s t di o . h>
#define PADRAO Se r i a l
void main ( void)
{
MostraSaidaPadrao ( ) ;
}
SERIAL
#include <s t di o . h>
#define PADRAO LCD
void main ( void)
{
MostraSaidaPadrao ( ) ;
}
LCD
Pelo cdigo apresentado percebemos que a mesma funo MostraSaidaPadrao(), apresenta re-
sultados diferentes dependendo de como foi denida a opo PADRAO.
Os denes tambm ajudam a facilitar a localizao dos dispositivos e ajustar as conguraes
no microcontrolador. Todo perifrico possui um ou mais endereos para os quais ele responde.
Estes endereos podem variar inclusive dentro de uma mesma famlia. Por exemplo: o endereo
da porta D (onde esto ligados os leds) 0xF83. Para ligar ou desligar um led preciso alterar
o valor que esta dentro do endereo 0xF83. Para facilitar este procedimento, denido um
ponteiro para este endereo e rotulado com o nome PORTD. Denir OFF como 0 e ON como 1
facilita a leitura do cdigo.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
14 Linguagem C para sistemas embarcados
#ifdef, #ifndef, #else e #endif
As diretivas #ifdef, #ifndef, #else e #endif so muito utilizadas quando queremos gerar dois
programas que diferem apenas num pequeno pedao de cdigo. Por exemplo dois sistemas de
controle de temperatura. O primeiro possui um display de LCD, capaz de mostrar a temperatura
textualmente. O segundo sistema executa a mesma funo que o primeiro, mas um dispositivo
mais barato, portanto possui apenas um led indicativo de sobretemperatura. O cdigo pode ser
escrito da seguinte maneira
void ImprimirTemp ( char valor )
{
#ifdef LCD
Imprime_LCD ( valor )
#el se
i f ( valor > 30)
{
led = 1;
}
el se
{
led = 0;
}
#endif //LCD
}
No momento da compilao o pr-compilador ir vericar se a tag LCD foi denida em
algum lugar. Em caso positivo o pr-compilador ir deixar tudo que estiver entre o #ifdef e o
#else e retirar tudo que est entre o #else e o #endif.
Outra funo muito utilizada destas diretivas para evitar a referncia circular. Supondo dois
arquivos, um responsvel pela comunicao serial (serial.h) e o segundo responsvel pelo controle
de temperatura (temp.h). O projeto exige que a temperatura possa ser controlada pela porta
serial e toda vez que a temperatura passar de um determinado patamar deve ser enviado um
alerta pela porta serial. O aquivo da porta serial (serial.h) tem as seguintes funes, apresentadas
a seguir.
char LerSerial ( void) ;
void EnviaSerial ( char val ) ;
O arquivo de controle da temperatura (temp.h) possui as funes apresentadas a seguir.
char LerTemperatura ( void) ;
void AjustaCalor ( char val ) ;
Toda vez que a funo LerTemperatura() for chamada, ela deve fazer um teste e se o valor for
maior que um patamar chamar a funo EnviaSerial() com o cdigo 0x30. Para isso o arquivo
temp.h deve incluir o arquivo serial.h.
#include "serial.h"
char LerTemperatura ( void) ;
void AjustaCalor ( char val ) ;
Toda vez que a funo LerSerial() receber um valor, ela deve chamar a funo AjustaCalor()
e repassar esse valor. Para isso o arquivo serial.h deve incluir o arquivo temp.h
#include "temp.h"
char LerSerial ( void) ;
void EnviaSerial ( char val ) ;
Notas de Aula ELT024 - Programao para Sistemas Embarcados
15 Linguagem C para sistemas embarcados
Programa 2.3: Estrutura de header
1 #i f ndef TAG_CONTROLE
2 #define TAG_CONTROLE
3 // t odo o cont edo do arqui vo vem aqui .
5 #endif //TAG_CONTROLE
O problema que deste modo criada uma referncia circular sem m: o compilador l o
arquivo serial.h e percebe que tem que inserir o arquivo temp.h. Inserindo o arquivo temp.h
percebe que tem que inserir o arquivo serial.h, conforme pode ser visto na Figura 2.1.
#include serial.h
char LerTemperatura(void);
void AjustaCalor(char val);
temp.h
#include temp.h
char LerSerial(void);
void EnviaSerial(char val);
serial.h
#include serial.h
char LerTemperatura(void);
void AjustaCalor(char val);
temp.h
Figura 2.1: Problema das Referncias Circulares
A soluo criar um dispositivo que permita que o contedo do arquivo seja lido apenas uma
vez. Este dispositivo implementado atravs da estrutura apresentada no programa 2.3.
Segundo o cdigo acima, o contedo que estiver entre o #ifndef e o #endif, s ser mantido
se a a tag TAG_CONTROLE NO estiver denida. Como isto verdade durante a primeira
leitura, o pr-compilador l o arquivo normalmente. Se acontecer uma referncia cclica, na
segunda vez que o arquivo for lido, a tag TAG_CONTROLE j estar denida impedindo
assim que o processo cclico continue, conforme pode ser visto na Figura 2.2.
Geralmente se utiliza como tag de controle o nome do arquivo. Esta tag deve ser nica para
cada arquivo.
z. Tipos de dados em C
19 Jan 2038 at 3:14:07 AM. The end of the world according to Unix
(2
32
seconds after Jan 1st 1970) - Unix date system
O tipo de uma varivel, informa a quantidade de memria, em bytes, que esta ir ocupar e como
esta deve ser interpretada: com ou sem frao (vrgula). Os tipos bsicos de dados na linguagem
Notas de Aula ELT024 - Programao para Sistemas Embarcados
16 Linguagem C para sistemas embarcados
#infdef TEMP_H
#define TEMP_H
#include serial.h
char LerTemperatura(void);
void AjustaCalor(char val);
#endif
temp.h
#infdef SERIAL_H
#define SERIAL_H
#include temp.h
char LerSerial(void);
void EnviaSerial(char val);
#endif
serial.h
#infdef TEMP_H
//tag j definida,
//pula o contedo
#endif
temp.h
Figura 2.2: Soluo das referncias circulares com #ifndef
C so apresentados na Tabela 2.1.
Tabela 2.1: Tipos de dados e faixa de valores
Tipo Bits Bytes Faixa de valores
char 8 1 -127 127
int 16 2 -32.768 32.767
oat 32 4 3,4 x 10
-38
3,4 x 10
38
double 64 8 3,4 x 10
-308
3,4 x 10
308
Podemos notar que as variveis que possuem maior tamanho podem armazenar valores mai-
ores. Notamos tambm que apenas os tipos oat e double possuem casas decimais.
Representao binria e hexadecimal
A grande maioria dos processadores trabalha com dados binrios, ou seja, aqueles que apenas
assumem valores 0 ou 1. Por isso os tipos apresentados anteriormente podem ser representados
utilizando a base 2. Um valor do tipo char que possui 8 bits ser representado por um nmero
de 8 algarismos, todos 0 (zeros) ou 1 (uns). Para realizarmos a converso de um nmero na base
decimal para a base 2 podemos seguir o seguinte algoritmo:
1. Dividir o nmero por 2
2. Anotar o valor do resto (0 ou 1)
3. Se o valor maior que 0 voltar ao nmero 1
4. Escrever os valores obtidos atravs do passo 2 de trs para frente.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
17 Linguagem C para sistemas embarcados
5. Apresentar o resultado
Por exemplo o nmero 18.
18/2 = 9, resto 0
9/2 = 4, resto 1
4/2 = 2, resto 0
2/2 = 1, resto 0
1/2 = 0, resto 1
Lendo do ltimo resultado para o primeiro temos que
18
10
= 10010
2
Devido a grande utilizao de nmeros binrios na programao de baixo nvel muito comum
escrevemos estes nmeros na base 16 ou hexadecimal. A vantagem de escrever o nmero nesta
base que existe uma converso simples de binrio para hexadecimal e o nmero resultante
ocupa bem menos espao na tela.
A base hexadecimal possui 16 "unidades"diferentes. Como existem apenas 10 algarismos no
sistema de numerao arbico (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) utilizamos 6 letras para complement-los
(A, B, C, D, E, F). A converso entre valores binrios, decimais e hexadecimais apresentada
na Tabela 2.2.
Tabela 2.2: Representao decimal binria - hexadecimal
Decimal Binrio Hexadecimal Decimal Binrio Hexadecimal
0 0000 0 8 1000 8
1 0001 1 9 1001 9
2 0010 2 10 1010 A
3 0011 3 11 1011 B
4 0100 4 12 1100 C
5 0101 5 13 1101 D
6 0110 6 14 1110 E
7 0111 7 15 1111 F
Para converter de binrio para hexadecimal basta dividir o nmero em grupos de 4 em 4, da
esquerda para a direita, e utilizar a tabela acima.
Por exemplo o nmero 18. Sabemos que este nmero em binrio representado por 10010
2
.
Separando o nmero de 4 em 4 algarismos temos:
1-0010
Pela tabela:
1
2
= 1
16
0010
2
= 2
16
.
Logo:
10010
2
. = 12
16
.
Modicadores de tamanho e sinal
Um modicador de tipo altera o signicado dos tipos base e produz um novo tipo. Existem
quatro tipos de modicadores, dois para o tamanho (long e short) e dois para sinal (unsigned
e signed). Um tipo declarado com o modicador long pode ter tamanho MAIOR ou IGUAL
ao tipo original. Um tipo declarado como short deve ter tamanho MENOR ou IGUAL ao tipo
original. A deciso cabe ao compilador utilizado.
Os tipos declarados como signed possuem um bit reservado para o sinal, deste o valor mximo
que podem atingir menor. Os tipos declarados como unsigned no podem assumir valores
Notas de Aula ELT024 - Programao para Sistemas Embarcados
18 Linguagem C para sistemas embarcados
negativos, em compensao podem atingir o dobro do valor de um tipo signed. Na Tabela 2.3
so apresentadas algumas variaes possveis.
Tabela 2.3: Alterao de tamanho e sinal dos tipos bsicos
Tipo Bytes Excurso mxima
unsigned char 1 0 255
signed char 1 -128 127
unsigned int 2 0 65.535
signed int 2 -32.768 32.767
long int 4 -2.147.483.648 2.147.483.647
unsigned long int 4 0 4.294.967.295
short int 2 -32.768 32.767
Na linguagem C, por padro os tipos so sinalizados, ou seja, possuem parte positiva e
negativa. Por isso raro encontrar o modicador signed.
Modicadores de acesso
Durante o processo de compilao, existe uma etapa de otimizao do programa. Durante esta
etapa, o compilador pode retirar partes do cdigo ou desfazer loops com perodos xos. Por
exemplo o cdigo abaixo:
#define X ( ( near unsigned char ) 0xF83)
void main ( void) interrupt 0
{
while ( X!=X) ;
}
Quando compilado apresenta o seguinte cdigo em assembler:
// St ar t i ng pCode b l oc k
S_Teste__main code
_main :
. line 19 // Test e . c whi l e (X!=X) ;
RETURN
Enquanto a varivel x for diferente de x o programa no sai do loop. O compilador
entende que esta condio nunca ir acontecer e elimina o loop do cdigo nal como podemos
ver no cdigo gerado, a rotina de return est logo aps a inicializao do programa _main. Para
variveis comuns o valor s alterado em atribuies diretas de valor ou de outras variveis: (x
= 4;) ou (x = y;).
Entretanto existe uma condio onde a varivel x pode alterar seu valor independentemente
do programa. Se esta varivel representar um endereo de memria associado um perifrico
fsico, seu valor pode mudar independentemente do uxo do programa. Para indicar esta situao
ao programa utilizamos a palavra reservada volatile.
#define X ( ( vol ati l e near unsigned char ) 0xF83)
void main ( void) interrupt 0
{
while ( X!=X) ;
}
Gerando o cdigo em assembler descrito abaixo:
Notas de Aula ELT024 - Programao para Sistemas Embarcados
19 Linguagem C para sistemas embarcados
// St ar t i ng pCode b l oc k
S_Teste__main code
_main :
_00105_DS_ :
. line 19 // Test e . c whi l e (X != X) ;
MOVLW 0x83 // pri mei ra par t e do endereo
MOVWF r0x00
MOVLW 0x0f // segunda par t e do endereo
MOVWF r0x01
MOVFF r0x00 , FSR0L
MOVFF r0x01 , FSR0H
MOVFF INDF0 , r0x00 // r e a l i z a pri mei ra l e i t u r a
MOVLW 0x83 // pri mei ra par t e do endereo
MOVWF r0x01
MOVLW 0x0f // segunda par t e do endereo
MOVWF r0x02
MOVFF r0x01 , FSR0L
MOVFF r0x02 , FSR0H
MOVFF INDF0 , r0x01 // r e a l i z a segunda l e i t u r a
MOVF r0x00 , W
XORWF r0x01 , W
BNZ _00105_DS_ // f az o t e s t e para i gual dade
RETURN
Podemos perceber que, deste modo, o compilador forado a ler a varivel x duas vezes e realizar
o teste para ver se ela permanece com o mesmo valor.
Em algumas situaes necessrio indicar que algumas variveis no podem receber valores
pelo programa. Para isto utilizamos a palavra reservada const. Utilizamos este modicador
para indicar que a varivel representa um local que apenas pode ser lido e no modicado, por
exemplo uma porta para entrada de dados. Nesta situao comum utilizar as palavras volatile
e const junto.
#define X ( ( vol ati l e const near unsigned char ) 0xF83)
// i ni c i o do programa
void main ( void) interrupt 0
{
X = 3;
}
Se tentarmos compilar este cdigo aparecer a seguinte mensagem de erro:
Teste . c : error 33: Attempt to assign value to a constant variable (=)
Modicadores de posicionamento
As variveis podem ser declaradas utilizando os modicadores near e far. Estes modicadores
indicam ao compilador em qual regio de memria devem ser colocadas as variveis.
A regio near geralmente se refere zero page. uma regio mais fcil de ser acessada. A
regio far exige mais tempo para executar a mesma funo que a near.
Podemos pensar nestas regies como a memria RAM e a memria Cache do computador.
A segunda mais rpida, mas possui um alto custo e por isso geralmente menor. Em algumas
situaes interessante que algumas variveis nunca saiam do cache, pois so utilizadas com
grande frequncia ou so crticas para o sistema.
Modicador de persistncia
Em geral, as variveis utilizadas dentro das funes perdem seu valor ao trmino da funo. Para
que este valor no se perca podemos utilizar um modicador de persistncia: static. Com esse
modicador a varivel passa a possuir um endereo xo de memria dado pelo compilador. Alm
Notas de Aula ELT024 - Programao para Sistemas Embarcados
20 Linguagem C para sistemas embarcados
Programa 2.4: Operaes aritmticas com tipos diferentes
1 void main ( void)
2 {
3 char var08 ;
4 i nt var16 ;
5 long i nt var32 ;
6 f l oat pont16 ;
7 double pont32 ;
8 var8 = var8 + var16 ; // 1
9 var8 = var8 + var8 ; // 2
10 var16 = var8 var8 ; // 3
11 var32 = var32 / var16 ; // 4
12 var32 = pont32 var32 ; // 5
13 pont16 = var8 / var16 ; // 6
14 pont16 = pont32 var32 ; // 7
15 pont16 = 40 / 80; // 8
16 }
disso o compilador no reutiliza este endereo em nenhuma outra parte do cdigo, garantindo
que na prxima vez que a funo for chamada o valor continue o mesmo.
// c r i a um cont ador p e r s i s t e nt e que
// i ncrementado a cada chamada de f uno
i nt ContadorPersistente ( i nt reseta )
{
stati c char variavel_persistente ;
i f ( reseta )
{
variavel_persistente = 0;
}
el se
{
return ( variavel_persistente++) ;
}
return 1;
}
z.6 Operaes aritmticas
If people do not believe that mathematics is simple, it is only be-
cause they do not realize how complicated life is. - John Louis von
Neumann
Um cuidado a se tomar, na programao em C para sistemas embarcados, o resultado de
operaes aritmticas. Por padro na linguagem C o resultado de uma operao aritmtica
possui tamanho igual ao maior operando. Observando o Programa 2.4 notamos alguns exemplos.
No caso 1 (linha 8) uma varivel char somada a um int gera como resultado um int (maior
operando). No possvel armazenar esse resultado num char, haver perda de informao.
var32 = var8 + var16 ; // 1 c or r i g i do
A soma de dois char, conforme a linha 9, segundo caso pode gerar um problema se ambos
forem muito prximo do valor limite. Por exemplo: 100 + 100 = 200, que no cabe num char,
j que este s permite armazenar valores de -128 127.
var16 = var8 + var8 ; // 2 c or r i g i do
Notas de Aula ELT024 - Programao para Sistemas Embarcados
21 Linguagem C para sistemas embarcados
O terceiro caso (linha 10) est correto, a multiplicao de dois char possui um valor mximo
de 127*127=16.129. O problema que a multiplicao de dois char gera um outro char, perdendo
informao. necessrio realizar um typecast antes.
var16 = ( ( i nt ) var8 ) var8 ; // 3 c or r i g i do
O quarto caso (linha 11) pode apresentar um problema de preciso. A diviso de dois inteiros
no armazena parte fracionria. Se isto no for crtico para o sistema est correto. Lembrar que
a diviso de nmeros inteiros mais rpida que de nmeros fracionrios.
O quinto caso (linha 12) pode apresentar um problema de preciso. O resultado da conta de
um nmero inteiro com um ponto utuante um ponto utuante. Armazenar esse valor num
outro nmero inteiro gera perda de informao.
O sexto caso (linha 13) apresenta um problema muito comum. A diviso de dois nmeros
inteiros gera um outro nmero inteiro. No importa se armazenaremos o valor numa varivel
de ponto utuante haver perda de informao pois os operandos so inteiros. Para evitar esse
problema necessrio um typecast.
pont16 = ( ( f l oat ) var8 ) / var16 ; // 6 c or r i g i do
No stimo caso (linha 14) pode haver perda de preciso pois o resultado da operao um
double, e estamos armazenando este valor num oat.
O oitavo caso (linha 15) similar ao sexto. Estamos realizando uma conta com dois nmeros
inteiros esperando que o resultado seja 0,5. Como os operandos so inteiros a expresso ser
avaliada como resultante em Zero. Uma boa prtica sempre usar .0 ou f aps o nmero
para indicar operaes com vrgula.
pont16 = 40f / 8 0 . 0 ; // 8 c or r i g i do
Devemos tomar cuidado tambm com comparaes envolvendo nmeros com ponto utuante.
f l oat x = 0 . 1 ;
while ( x != 1. 1) {
printf ( "x = %f\n" , x) ;
x = x + 0 . 1 ;
}
O trecho de cdigo acima apresenta um loop innito. Como existem restries de preciso nos
nmeros de ponto utuante (oat e double) nem todos os nmeros so representados elmente.
Os erros de arredondamento podem fazer com que a condio (x !=1.1) nunca seja satisfeita.
Sempre que houver a necessidade de comparao com nmeros de ponto utuante utilizar maior,
menor ou variaes.
f l oat x = 0 . 1 ;
while ( x < 1. 1) {
printf ( "x = %f\n" , x) ;
x = x + 0 . 1 ;
}
Apesar de sutis estes tipos de erro podem causar um mau funcionamento do sistema. Na
Figura 2.3 apresentado um erro gerado atravs de um loop innito.
z. Funo main()
Todo sistema necessita de iniciar em algum lugar. Em geral, os microcontroladores, assim que
ligados, procuram por suas instrues no primeiro ou ltimo endereo de memria, dependendo
da arquitetura utilizada. O espao de memria disponvel neste endereo geralmente muito
Notas de Aula ELT024 - Programao para Sistemas Embarcados
22 Linguagem C para sistemas embarcados
Figura 2.3: Loop innito de um device driver gerando erro no sistema
pequeno, apenas o necessrio para inserir uma instruo de pulo e o endereo onde est a funo
principal. Este espao conhecido como posio de reset. Existem ainda outros espaos de
memria similares a este que, geralmente, so alocados prximos. O conjunto destes espaos
conhecido como vetor de interrupo (Figura 2.4).
0x58 Testa A
0x57 30
0x56 A recebe
0x55 Limpa A
0x59 ...
0x8D Porta B
0x8C Salva em
0x8B 50
0x8A A recebe
0x8E ...
0x03 0x55
0x02 Pulo
0x01 0x8A
0x04 ...
0x00 Pulo
Endereo Instruo
Figura 2.4: Exemplo de funcionamento do vetor de interrupo
A maneira de indicar o ponto de incio de um programa depende do compilador. Em geral os
Notas de Aula ELT024 - Programao para Sistemas Embarcados
23 Linguagem C para sistemas embarcados
compiladores alocam a funo main() em algum lugar da memria onde haja espao disponvel.
Depois disso dispem de uma instruo de pulo para o primeiro endereo de memria, onde foi
alocada a funo main.
Para o compilador SDCC/GPUtils no MPLAB necessrio indicar que queremos que a funo
main() seja chamada toda vez que o sistema for iniciado. Por isso necessrio que a posio de
reset dentro do vetor de interrupo aponte para a funo main. Isto feito atravs do atributo
interrupt 0 logo aps o nome da funo conforme pode ser visto no cdigo abaixo.
void main ( void) interrupt 0
{
// aqui ent ra o cdi go do programa
}
Outra coisa interessante que para sistemas embarcados a funo principal no recebe nem
retorna nada. Como ela a primeira a ser chamada no h como enviar algum valor por par-
metro. Ela tambm no retorna nada pois ao trmino desta o sistema no est mais operativo.
Em geral sistemas embarcados so projetados para comearem a funcionar assim que ligados e
apenas parar sua tarefa quando desligados. Como todas as funcionalidades so chamadas dentro
da funo main()
1
espera-se que o programa continue executando as instrues dentro dela at
ser desligado ou receber um comando para desligar. Este comportamento pode ser obtido atravs
de um loop innito. Abaixo esto as duas alternativas mais utilizadas.
void main ( void) interrupt 0
{
for ( ; ; )
{
// aqui ent ra o
// cdi go p r i nc i p a l
}
}
void main ( void) interrupt 0
{
while ( 1)
{
// aqui ent ra o
// cdi go p r i nc i p a l
}
}
z.S Rotinas de tempo
Time is an illusion, lunchtime doubly so. - Ford Prefect
muito comum necessitar que o microcontrolador que um tempo sem fazer nada. Uma maneira
de atingir esse objetivo utilizar um lao FOR
2
.
unsigned char i ;
for ( i=0; i < 10; i++) ;
Notar que no estamos utilizando os colchetes. Logo aps fechar os parnteses j existe um
ponto e virgula. Para entender como esse procedimento funciona, e estimar o tempo de espera
preciso entender como o compilador traduz essa funo para assembler.
// cdi go em assembl er e q ui v al e nt e f or ( i =0; i <10; i ++);
MOVF r0x00 , W // i n i c i a l i z a W com 0 (1 c i c l o )
SUBLW 0x0a // col oca o v al or 10 (0 x0a ) no r e g i s t r o W (1 c i c l o )
MOVWF r0x00 //muda o v al or de W para F (1 c i c l o )
_00107_DS_ :
1
Em sistemas mais complexos algumas tarefas so executadas independentemente da funo principal, tendo
sua execuo controlada atravs de interrupes.
2
Este mtodo no aconselhado em sistemas de maior porte.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
24 Linguagem C para sistemas embarcados
DECFSZ r0x00 , F //decrementa F, se F > 0 execut a a prxima l i nha (1 c i c l o )
BRA _00107_DS_ //" pul a " para o l ugar marcado como _00107_DS_ (2 c i c l o s )
Percebemos pelo cdigo acima que para realizar um for precisamos de 3 passos de inicializao.
Cada iterao exige 2 passos: uma comparao e um pulo
3
, totalizando 3 ciclos de inicializao
e 3 ciclos de interao.
Se temos um processador trabalhando a 8 MHz, cada instruo executada em 0.5s.
4
Para
termos um tempo de espera de 0.5s precisamos de 1 milho de instrues. Se colocarmos loops
encadeados podemos multiplicar a quantidade de instrues que sero executadas. Para obtermos
um valor de 1 milho de instrues devemos utilizar pelo menos 3 loops encadeados. Os valores
dos loops so obtidos de maneira iterativa.
unsigned char i , j , k ;
for ( i=0; i < 34; i++) //3 + 34 (30. 003 + 3) = 1. 020. 207 i ns t r u e s
{
for ( j=0; j < 100; j++) //3 + 100 (297 + 3) = 30. 003 i ns t r u e s
{
for ( k=0; k < 98; k++) ; // 3 + 98 (3) = 297 i ns t r u e s
}
}
O cdigo acima foi projetado para gerar um atraso de tempo de meio segundo. Compilando
e realizando testes prticos podemos conrmar que o tempo real aproximadamente 0.51 (s).
Esta discrepncia acontece porque agora temos 3 loops encadeados e cada qual com sua varivel
de controle. Deste modo o compilador precisa salvar e carregar cada varivel para realizar a
comparao.
Percebemos assim que para conhecer corretamente o funcionamento do sistema necessrio,
em algumas situaes, abrir o cdigo em assembler gerado pelo compilador para entender como
este executado. Nem sempre o compilador toma as mesmas decises que ns. Alm disso ele
pode gerar otimizaes no cdigo. Existem dois tipos de otimizao: uma visando diminuir o
tempo de execuo do sistema, deixando-o mais rpido e outra que reduz o tamanho do cdigo
nal, poupando espao na memria.
A seguir apresentamos um exemplo de funo que gera delays com tempo parametrizado.
void delay ( unsigned i nt DL )
{
unsigned char i , j , k ;
while ( DL) // execut a DL vez es .
{
for ( i=0; i < 34; i++) //3 + 34 (30. 003 + 3) = 1. 020. 207 i ns t r u e s
{
for ( j=0; j < 100; j++) //3 + 100 (297 + 3) = 30. 003 i ns t r u e s
{
for ( k=0; k < 98; k++) ; // 3 + 98 (3) = 297 i ns t r u e s
}
}
}
}
z.q Operaes com bits
All of the books in the world contain no more information than is
broadcast as video in a single large American city in a single year.
Not all bits have equal value. - Carl Sagan
3
Este valor s valido quando estamos trabalhando com variveis char. Se utilizarmos variveis int o cdigo
em assembler ser diferente e teremos que realizar uma nova anlise.
4
Para 8MHz, 1 ciclo = 0.125s. No PIC, cada instruo precisa de 4 ciclos de clock, portanto 0.5s.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
25 Linguagem C para sistemas embarcados
Nos sistemas microcontrolados, existem algumas variveis onde cada bit tem uma interpretao
ou funcionalidade diferente. Por isso necessrio realizar algumas operaes que modiquem
apenas os bits desejados, mantendo o restante dos bits da varivel inalterados.
As operaes da linguagem C que nos permitem trabalhar com as variveis, levando em conta
os valores individuais de cada bit, so chamadas de bitwise operation.
importante ressaltar que as operaes de bitwise possuem funcionalidade semelhante a suas
respectivas operaes lgicas. A diferena que a lgica opera em cima da varivel como um
todo
5
enquanto a bitwise opera bit bit.
NOT
A operao NOT lgica retorna um se o valor for zero e 0 se o valor for um.
A !A
0 1
1 0
A operao bitwise NOT (operador ) executa uma NOT lgica. Isso signica que a operao
realizada para cada um dos bits da varivel, no mais para a varivel como um todo. Na tabela
seguinte apresentada a diferena entre as duas operaes.
Declarao Lgico Bitwise
char A = 12;
// A = 0b00001100
result = ! A ;
// r e s u l t = 0
result = ~A ;
// r e s u l t = 243
// A = 0b00001100
// r = 0b11110011
AND
A operao AND lgica (operador &&) retorna 0 se algum dos valores for zero, e 1 se os dois
valores forem diferentes de zero.
A B A&&B
0 0 0
0 1 0
1 0 0
1 1 1
A operao bitwise AND (operador &) executa uma AND lgica para cada par de bits e coloca
o resultado na posio correspondente:
Declarao Lgico Bitwise
char A = 8;
// A = 0b00001000
char B = 5;
// B = 0b00000101
result = A && B ;
// r e s u l t = 1
result = A & B ;
// r e s u l t = 0
// A = 0b00001000
// B = 0b00000101
// r = 0b00000000
5
Lembrar que para linguagem C uma varivel com valor 0 (zero) representa falso, e qualquer outro valor
representa verdadeiro.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
26 Linguagem C para sistemas embarcados
OR
A operao OR lgica (operador ||) retorna 1 se algum dos valores for diferente de zero, e 0 se
os dois valores forem zero.
A B A||B
0 0 0
0 1 1
1 0 1
1 1 1
A operao bitwise OR (operador |) executa uma OR lgica para cada par de bits e coloca o
resultado na posio correspondente:
Declarao Lgico Bitwise
char A = 8;
// A = 0b00001000
char B = 5;
// B = 0b00000101
result = A | | B ;
// r e s u l t = 1
result = A | B ;
// r e s u l t = 13
// A = 0b00001000
// B = 0b00000101
// r = 0b00001101
XOR
A operao XOR no possui correspondente lgica na linguagem C. Esta operao pode ser
representada como A XOR B = (A && !B)||(!A && B)
A B A B
0 0 0
0 1 1
1 0 1
1 1 0
A operao bitwise XOR (operador ) executa uma XOR lgica para cada par de bits e coloca
o resultado na posio correspondente:
Declarao Lgico Bitwise
char A = 8;
// A = 0b00001000
char B = 5;
// B = 0b00000101
// no e x i s t e em C
result = A ^ B ;
// r e s u l t = 13
// A = 0b00001000
// B = 0b00000101
// r = 0b00001101
Shift
A operao shift desloca os bits para a esquerda (operador <<) ou direita (operador >>).
necessrio indicar quantas casas sero deslocadas.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
27 Linguagem C para sistemas embarcados
Declarao Shift Esquerda Shift Direita
char A = 8;
// A = 0b00001000
result = A << 2;
// r e s u l t = 32
// A = 0b00001000
// r = 0b00100000
result = A >> 2;
// r e s u l t = 2
// A = 0b00001000
// r = 0b00000010
Para variveis unsigned e inteiras, esta operao funciona como a multiplicao/diviso por
potncia de dois. Cada shift multiplica/divide por 2 o valor. Esta uma prtica muito comum
para evitar a diviso que na maioria dos sistemas embarcados uma operao cara do ponto de
vista de tempo de processamento.
No utilizar esta operao com o intuito de multiplicar/dividir variveis com ponto xo ou
utuante nem variveis sinalizadas (signed).
Em diversas ocasies necessrio que trabalhemos com os bits de maneira individual, prin-
cipalmente quando estes bits representam sadas ou entradas digitais, por exemplo chaves ou
leds.
Supondo que temos 8 leds ligados ao microcontrolador. Cada led representado atravs de 1
bit de uma varivel. Para ligarmos ou desligarmos apenas um led por vez, no alterando o valor
dos demais, devemos nos utilizar de alguns passos de lgebra digital.
Ligar um bit (bit set)
Para ligar apenas um bit, utilizaremos uma operao OU. Supondo dois operandos A e B. Se A
1 o resultado de (A | B) 1 independente de B. Se A 0 o resultado igual ao valor de B.
Se o objetivo ligar apenas o bit da posio X devemos criar um valor onde todas as posies
so 0's com exceo da posio desejada. Para uma mscara binria de N bits temos (N>=X):
Posio N . . . X+1 X X-1 . . . 0
Valor 0 ... 0 1 0 ... 0
Se a operao OR for executada com a mscara criada, o resultado apresentar valor 1 na posio
X e manter os valores antigos para as demais posies. Exemplo: Ligar apenas o bit 2 da varivel
PORTD
// de f i ne ' s para por t as de ent rada e s a da
#define PORTD ( ( vol ati l e near unsigned char ) 0xF83)
#define TRISD ( ( vol ati l e near unsigned char ) 0xF95)
// i ni c i o do programa
void main ( void) interrupt 0
{
char mascara ; // v a r i v e l que guarda a mscara
TRISD = 0x00 ; // conf i gur a a port a D como s a da
PORTD = 0x00 ; // l i g a t odos os l e ds ( l g i c a negat i va )
// l i g a o pri mei ro b i t da v a r i v e l
mascara = 1; // b i t = 0b00000001
// rot aci onase a v a r i v e l para que o b i t 1 chegue na posi o des ej ada
mascara = mascara << 2; // b i t = 0b00000100
// Li gar o b i t 2 , des l i gando o 3o l e d
PORTD = PORTD | mascara ;
//mantm o si st ema l i g ado i ndef i ni dament e
for ( ; ; ) ;
}
Notas de Aula ELT024 - Programao para Sistemas Embarcados
28 Linguagem C para sistemas embarcados
Desligar um bit (bit clear)
Para desligar apenas um bit o procedimento similar ao utilizado para ligar. Ao invs de utilizar-
mos uma operao OU, utilizaremos uma operao AND. A operao AND tem a caracterstica
de, dados A e B valores binrios, se A 1, a resposta de (A & B) ser o prprio valor de B, se a
A=0, a resposta zero, independente de B.
Novamente necessrio gerar uma mscara. Mas para esta situao ela deve possuir todos
os bits iguais um com exceo de X, o bit que queremos desligar.
posio N . . . X+1 X X-1 . . . 0
Valor 1 ... 1 0 1 ... 1
Se a operao AND for executada com a mscara criada, o resultado apresentar valor 0 na
posio X e manter os valores antigos para as demais posies. Exemplo: Desligar apenas o bit
2 da varivel PORTD.
// de f i ne ' s para por t as de ent rada e s a da
#define PORTD ( ( vol ati l e near unsigned char ) 0xF83)
#define TRISD ( ( vol ati l e near unsigned char ) 0xF95)
// i ni c i o do programa
void main ( void) interrupt 0
{
char mascara ; // v a r i v e l que guarda a mscara
TRISD = 0x00 ; // conf i gur a a port a D como s a da
PORTD = 0xFF ; // d e s l i g a t odos os l e d s ( l g i c a negat i va )
// l i g a o pri mei ro b i t da v a r i v e l
mascara = 1; // mascara = 0b00000001
// rot aci onase a v a r i v e l para que o b i t 1 chegue na posi o des ej ada
mascara = mascara << 2; // mascara = 0b00000100
// i nver t e se os v al or e s de cada b i t
mascara = ~mascara ; // mascara = 0b11111011
// Des l i ga o b i t 2 , l i gando o 3o l e d
PORTD = PORTD & mascara ;
//mantm o si st ema l i g ado i ndef i ni dament e
for ( ; ; ) ;
}
importante notar que geramos a mscara de maneira idntica quela utilizada no caso
anterior, onde todos os valores so zero e apenas o desejado um. Depois realizamos a inverso
dos valores. Este procedimento realizado desta maneira porque no sabemos o tamanho da
palavra a ser utilizada no microcontrolador: 8 ou 16 bits. Mesmo assim devemos garantir que
todos os bits obtenham o valor correto, o que garantido pela operao de negao. A opo de
inicializar a varivel com apenas um zero e rotacionar pode no funcionar pois, na maioria dos
sistemas, a funo de rotao insere zeros medida que os bits so deslocados e precisamos que
apenas um valor seja zero.
Trocar o valor de um bit (bit ip)
Para trocar o valor de um bit utilizaremos como artifcio algbrico a operao XOR. Dado duas
variveis binrias A e B , se A 1, o valor resultante de A XOR B o oposto do valor de B, se
A=0, a resposta se mantm igual ao valor de B.
Podemos perceber que para trocar o valor de apenas um bit a mscara ser idntica quela
utilizada para ligar um bit:
posio N . . . X+1 X X-1 . . . 0
Valor 0 ... 0 1 0 ... 0
Se a operao XOR for executada com a mscara criada, o valor na posio X ser trocado, de
zero para um ou de um para zero. Exemplo: Trocar o bit 2 e 6 da varivel PORTD
Notas de Aula ELT024 - Programao para Sistemas Embarcados
29 Linguagem C para sistemas embarcados
// de f i ne ' s para por t as de ent rada e s a da
#define PORTD ( ( vol ati l e near unsigned char ) 0xF83)
#define TRISD ( ( vol ati l e near unsigned char ) 0xF95)
// i ni c i o do programa
void main ( void) interrupt 0
{
char mascara ; // v a r i v e l que guarda a mascara
TRISD = 0x00 ; // conf i gur a a port a D como s a da
PORTD = 0xF0 ; // d e s l i g a t odos os 4 pri mei ros l e ds ( l g i c a negat i va )
// l i g a o pri mei ro b i t da v a r i v e l
mascara = 1; // mascara = 0b00000001
// rot aci onase a v a r i v e l para que o b i t 1 chegue na posi o des ej ada
mascara = mascara << 2; // mascara = 0b00000100
// Li ga o b i t 2 , des l i gando o 3o l e d
PORTD = PORTD ^ mascara ;
// l i g a o pri mei ro b i t da v a r i v e l
mascara = 1; // mascara = 0b00000001
// rot aci onase a v a r i v e l para que o b i t 1 chegue na posi o des ej ada
mascara = mascara << 6; // mascara = 0b01000000
// Des l i ga o b i t 6 , l i gando o 7o l e d
PORTD = PORTD ^ mascara ;
//mantm o si st ema l i g ado i ndef i ni dament e
for ( ; ; ) ;
}
Percebemos atravs do exemplo que a utilizao do procedimento apresentado troca o valor
do bit escolhido. Foi utilizado o mesmo procedimento duas vezes. Na primeira, um bit foi ligado
e, na segunda, outro foi desligado.
Vericar o estado de um bit (bit test)
Para vericar se o bit X est um utilizaremos novamente a mesma mscara utilizada para bit set
e bit toggle:
posio N . . . X+1 X X-1 . . . 0
Valor 0 ... 0 1 0 ... 0
Realizamos ento uma operao AND com a varivel. O resultado ser zero se o bit X, da
varivel original, for zero. Se o bit da varivel original for um a resposta ser diferente de zero
6
.
Exemplo: Testar o bit 2 da varivel PORTD
// de f i ne ' s para por t as de ent rada e s a da
#define PORTD ( ( vol ati l e near unsigned char ) 0xF83)
#define TRISD ( ( vol ati l e near unsigned char ) 0xF95)
// i ni c i o do programa
void main ( void) interrupt 0
{
char mascara ; // v a r i v e l que guarda a mascara
char teste ;
TRISD = 0x00 ; // conf i gur a a port a D como s a da
teste = 0x00 ; // d e s l i g a t odos os b i t s
// rodar depoi s o mesmo programa com os b i t s l i g a d o s .
// t e s t e = 0 x f f ;
// c r i a uma v a r i v e l onde APENAS o pri mei ro b i t 1
mascara = 1; // mascara = 0b00000001
// rot aci onase a v a r i v e l para que o b i t 1 chegue na posi o des ej ada
mascara = mascara << 2; // mascara = 0b00000100
// Ve r i f i c a apenas o b i t 2
i f ( teste & mascara )
{
PORTD = 0x00 ; // se o r e s ul t ado f or ver dadei r o l i g a t odos os l e ds
6
A maioria dos compiladores C adotam uma varivel com valor diferente de zero como sendo verdadeiro.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
30 Linguagem C para sistemas embarcados
}
el se
{
PORTD = 0xff ; // se o r e s ul t ado f or f a l s o d e s l i g a t odos os l e ds
}
//mantm o si st ema l i g ado i ndef i ni dament e
for ( ; ; ) ;
}
Criando funes atravs de denes
Uma opo no uso de denes criar funes simples que podem ser escritas em apenas uma
linha. Utilizando um pouco de algebrismo e parnteses, possvel escrever as quatro operaes
anteriores numa nica linha. De posse desta simplicao podemos criar uma funo para facilitar
o uso destas operaes atravs de um dene conforme podemos ver nas tabelas 2.4, 2.5, 2.6 e
2.7.
Tabela 2.4: Operao bit set com dene
Operao Bit set
Passo a Passo
char bit = 2;
char mascara ;
mascara = 1 << bit ;
arg = arg | mascara ;
//em 1 l i nha
arg = arg | (1<<bit ) ;
//ou
arg |= (1<<bit ) ;
Exemplo de uso
//Ligando o b i t 2 da port a D
PORTD = PORTD | (1<<2) ;
//ou
PORTD |= (1<<2) ;
Com dene
#define Bi t Set ( arg , bi t ) ( ( arg ) |= (1<<bi t ) )
Exemplo de uso com de-
ne
//Ligando o b i t 2 da port a D
BitSet ( PORTD , 2 ) ;
Notas de Aula ELT024 - Programao para Sistemas Embarcados
31 Linguagem C para sistemas embarcados
Tabela 2.5: Operao bit clear com dene
Operao Bit clear
Passo a Passo
char bit = 2;
char mascara ;
mascara = 1 << bit ;
arg = arg & ~mascara ;
//em 1 l i nha
arg = arg & ~(1<<bit ) ;
//ou
arg &= ~(1<<bit ) ;
Exemplo de uso
// Desl i gando o b i t 2 da port a D
PORTD = PORTD & ~(1<<2) ;
//ou
PORTD &= ~(1<<2) ;
Com dene
#define Bi t Cl r ( arg , bi t ) ( ( arg ) &= ~(1<<bi t ) )
Exemplo de uso com de-
ne
// Desl i gando o b i t 2 da port a D
BitClr ( PORTD , 2 ) ;
Notas de Aula ELT024 - Programao para Sistemas Embarcados
32 Linguagem C para sistemas embarcados
Tabela 2.6: Operao bit ip com dene
Operao Bit ip
Passo a Passo
char bit = 2;
char mascara ;
mascara = 1 << bit ;
arg = arg ^ mascara ;
//em 1 l i nha
arg = arg ^ (1<<bit ) ;
//ou
arg ^= (1<<bit ) ;
Exemplo de uso
//Trocando o v al or do b i t 2 da port a D
PORTD = PORTD ^ (1<<2) ;
//ou
PORTD ^= (1<<2) ;
Com dene
#define Bi tFl p ( arg , bi t ) ( ( arg ) ^= (1<<bi t ) )
Exemplo de uso com de-
ne
//Trocando o v al or do b i t 2 da port a D
BitFlp ( PORTD , 2 ) ;
Notas de Aula ELT024 - Programao para Sistemas Embarcados
33 Linguagem C para sistemas embarcados
Tabela 2.7: Operao bit test com dene
Operao Bit test
Passo a Passo
char bit = 2;
char mascara ;
mascara = 1 << bit ;
i f ( arg & mascara )
//em 1 l i nha
i f ( arg & (1<<bit ) )
Exemplo de uso
//Testando o b i t 2 da port a D
i f ( PORTD | (1<<2) )
{
// . . .
}
Com dene
#define Bi tTst ( arg , bi t ) ( ( arg ) & (1<<bi t ) )
Exemplo de uso com de-
ne
//Testando o b i t 2 da port a D
i f ( BitTst ( PORTD , 2 ) )
{
// . . .
}
Notas de Aula ELT024 - Programao para Sistemas Embarcados
34 Linguagem C para sistemas embarcados
z.io Debug de sistemas embarcados
7
In the beginner's mind there are many possibilities; in the expert's
mind there are few. - Shunryu Suzuki
A vericao de sistemas embarcados apresenta algumas restries e de modo geral no possvel
inferir sobre a operao do sistema sem paralis-lo. Como este tipo de sistema possui vrios
dispositivos agregados, que funcionam independentemente do processador, necessrio utilizar
abordagens diferentes para realizar o debug.
Devemos lembrar que alm do software devemos levar em conta possveis problemas advindos
do hardware. Debounce, tempo de chaveamento, limite do barramento de comunicao so
exemplos de pontos a serem considerados no momento de depurao.
Externalizar as informaes.
A primeira necessidade conhecer o que est acontecendo em teu sistema. Na programao
tradicional para desktop comum utilizarmos de mensagens no console avisando o estado do
programa.
#include "stdio.h"
#include "serial.h"
// i ni c i o do programa
i nt main ( i nt argc , char argv [ ] )
{
printf ( "Inicializando sistema") ;
i f ( CheckForData ( ) )
{
printf ( "Chegou informacao") ;
}
el se
{
printf ( "Problemas na comunicacao") ;
}
return 0;
}
Devemos ter em mente onde necessrio colocar estes alertas e lembrar de retir-los do cdigo
nal.
Para a placa em questo utilizaremos o barramento de leds que est ligado porta D. A ope-
rao deste dispositivo ser estudada posteriormente em detalhes. Por enquanto basta sabermos
que cada bit da varivel PORTD est ligada um led diferente. Por causa da construo fsica
da placa, o led aceso com valor 0 (zero) e desligado com o valor 1 (um). Alm disso temos que
congurar a porta D. Isto feito iniciando a varivel TRISD com o valor 0x00
8
.
// de f i ne ' s para por t as de ent rada e s a da
#define PORTD ( ( vol ati l e near unsigned char ) 0xF83)
#define TRISD ( ( vol ati l e near unsigned char ) 0xF95)
// i ni c i o do programa
void main ( void) interrupt 0
{
// conf i gurando t odos os pi nos como s a das
TRISD = 0x00 ;
PORTD = 0xFF ; // d e s l i g a t odos os l e d s
// l i g a apenas o b i t 1.
BitClr ( PORTD , 1 ) ;
//mantm o si st ema l i g ado i ndef i ni dament e
for ( ; ; ) ;
7
Mais informaes sobre debug de sistemas embarcados referir ao artigo The ten secrets of embedded debug-
ging de Stan Schneider e Lori Fraleigh
8
As variveis PORTD e TRISD so denidas como unsigned char e possuem portanto 8 bits.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
35 Linguagem C para sistemas embarcados
}
Devemos utilizar os leds como sinais de aviso para entendermos o funcionamento do programa.
Isto pode ser feito atravs das seguintes ideias: Se passar desta parte liga o led X, Se entrar
no IF liga o led Y, se no entrar liga o led Z, Assim que sair do loop liga o led W.
Programao incremental
Ao invs de escrever todo o cdigo e tentar compilar, interessante realizar testes incrementais.
A cada alterao no cdigo realizar um novo teste. Evitar alterar o cdigo em muitos lugares
simultaneamente, no caso de aparecer um erro ca mais difcil saber onde ele est.
Checar possveis pontos de Memory-leak
Se for necessrio realizar alocao dinmica garantir que todas as alocaes so liberadas em
algum ponto do programa.
Cuidado com a fragmentao da memria
Sistemas com grande frequncia na alocao/liberao de memria podem fragmentar a memria
at o ponto de inviabilizar os espaos livres disponveis, eventualmente travando o sistema.
Quando trabalhar com rotinas de nvel mais baixo, mais prximo ao hardware, tente utilizar
apenas mapeamento esttico de memria.
Otimizao de cdigo
Apenas se preocupe com otimizao se estiver tendo problemas com o cumprimento de tarefas.
Mesmo assim considere em migrar para uma plataforma mais poderosa. Sistemas embarcados
preconizam segurana e no velocidade.
Caso seja necessrio otimizar o cdigo analise antes o local de realizar a otimizao. No
adianta otimizar uma funo grande se ela chamada apenas uma vez. Utilize-se de ferramentas
do tipo proler sempre que possvel. Isto evita a perda de tempo e auxilia o programador a
visualizar a real necessidade de otimizao de cdigo.
Reproduzir e isolar o erro
Quando houver algum erro deve-se primeiro entender como reproduzi-lo. No possvel tentar
corrigir o erro se no houver maneira de vericar se ele foi eliminado.
No momento em que se consegue um procedimento de como reproduzir o erro podemos
comear a visualizar onde ele pode estar. A partir deste momento devemos isolar onde o erro
est acontecendo. Uma maneira de se fazer isto em sistemas embarcados colocar um loop
innito dentro de um teste, que visa vericar alguma condio de anomalia. Se o sistema entrar
neste teste devemos sinalizar atravs dos meios disponveis, ligar/desligar algum led por exemplo.
// aqui tem um monte de cdi go . . .
i f ( PORTB >= 5) //PORTB no dever i a s er um v al or maior que 5.
{
BitClr ( PORTD , 3 ) ; // l i g a o l e d 3
for ( ; ; ) ; // t r ava o programa
}
// aqui cont i nua com um monte de cdi go . . .
Notas de Aula ELT024 - Programao para Sistemas Embarcados
36 Linguagem C para sistemas embarcados
z.ii Ponteiros e endereos de memria
Writing in C or C++ is like running a chain saw with all the safety
guards removed. - Bob Gray
Toda varivel criada armazenada em algum lugar da memria. Este lugar denido de maneira
nica atravs de um endereo.
Para conhecermos o endereo de uma varivel podemos utilizar o operador &. Cuidado! Este
operador tambm utilizado para realizao da operao bitwise AND. Exemplo:
// c r i a a v a r i v e l a num endereo de memria a s er
// deci di do pel o compi l ador
i nt a = 0;
a = a + 1;
printf ( a ) ; //imprime o v al or 1
printf ( &a ) ; //imprime o endereo de a ( por exempl o 157821)
Conhecer o endereo de uma varivel muito til quando queremos criar um ponteiro para
ela.
Ponteiro uma varivel que, ao invs de armazenar valores, armazena endereos de memria.
Atravs do ponteiro possvel manipular o que est dentro do lugar apontado por ele.
Para denir um ponteiro tambm precisamos indicar ao compilador um tipo. A diferena
que o tipo indica quanto cabe no local apontado pelo ponteiro e no o prprio ponteiro.
Sintaxe:
tipo nome da variavel ;
Exemplo:
i nt apint ;
f l oat apfloat ;
Deve-se tomar cuidado, pois nos exemplos acima, apint e apoat so variveis que armazenam
endereos de memria e no valores tipo int ou oat. O lugar APONTADO pela varivel apint
que armazena um inteiro, do mesmo modo que o lugar apontado por oat armazena um valor
fracionrio.
Se quisermos manipular o valor do endereo utilizaremos apint e apoat mas se quisermos
manipular o valor que esta dentro deste endereo devemos usar um asterisco antes do nome da
varivel. Exemplo:
apfloat = 3 . 2 ;
apfloat = 3 . 2 ;
A primeira instruo indica ao compilador que queremos que o ponteiro apoat aponte para
o endereo de memria nmero 3.2, que no existe, gerando um erro. Se quisermos guardar o
valor 3.2 no endereo de memria apontado por apoat devemos utilizar a segunda expresso.
Para trabalhar com ponteiros preciso muito cuidado. Ao ser denido, um ponteiro tem
como contedo no um endereo, mas algo indenido. Se tentamos usar o ponteiro assim mesmo,
corremos o risco de que o contedo do ponteiro seja interpretado como o endereo de algum local
da memria vital para outro programa ou at mesmo para o funcionamento da mquina. Neste
caso podemos provocar danos no programa, nos dados, ou mesmo travar a mquina.
necessrio tomar cuidado ao inicializar os ponteiros. O valor atribudo a eles deve ser
realmente um endereo disponvel na memria.
Por exemplo, podemos criar um ponteiro que aponta para o endereo de uma varivel j
denida:
// def i ni ndo a v a r i v e l i v ar
Notas de Aula ELT024 - Programao para Sistemas Embarcados
37 Linguagem C para sistemas embarcados
i nt ivar ;
// def i ni ndo o pont ei r o i p t r
i nt iptr ;
//o pont ei r o i p t r recebe o v al or do endereo da v a r i v e l i v ar
iptr = &ivar ;
// as prxi mas l i nhas so e q ui v al e nt e s
ivar = 421;
iptr = 421;
Com sistemas embarcados existem alguns endereos de memria que possuem caractersticas
especiais. Estes endereos possuem registros de congurao, interfaces com o meio externo e
variveis importantes para o projetista. pelo meio da utilizao de ponteiros que possvel
acessar tais endereos de maneira simples, atravs da linguagem C.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
Captulo 3
Arquitetura de microcontroladores
Any suciently advanced technology is indistinguishable from ma-
gic. - Arthur C. Clarke
Os microcontroladores so formados basicamente por um processador, memria e perifricos
interligados atravs de um barramento conforme Figura 3.1.
Em geral, os perifricos so tratados do mesmo modo que a memria, ou seja, para o pro-
cessador no existe diferena se estamos tratando com um valor guardado na memria RAM ou
com o valor da leitura de um conversor analgico digital. Isto acontece porque existem circuitos
eletrnicos que criam um nvel de abstrao em hardware. Deste modo todos os dispositivos
aparecem como endereos de memria.
38
39 Arquitetura de microcontroladores
Figura 3.1: Arquitetura do microcontrolador PIC 18F4550
Notas de Aula ELT024 - Programao para Sistemas Embarcados
40 Arquitetura de microcontroladores
j.i Acesso memria
A quantidade de memria disponvel que um microcontrolador pode acessar depende de dois
fatores, os tamanhos das palavras de dados e das palavras de endereo.
O tamanho da palavra de dados representa quantos bits podem ser colocados numa nica
posio da memria.
O tamanho da palavra de endereo indica quantas posies de memria o processador con-
segue enxergar.
Por exemplo, um microcontrolador cujo tamanho de dados e o tamanho da palavra de ende-
reo so ambos 8 bits possui uma possibilidade de acessar uma memria de at:
tamanho_da_palavra 2^tamanho_do_endereco
8 2^8 = 2048 bytes ou 2 kbytes
O termo possibilidade foi usado pois, apesar de poder alcanar toda essa extenso, nem
sempre existe memria fsica para armazenamento. Podemos imaginar a memria como um
armrio. Um armrio com 6 suportes pode abrigar at 6 gavetas. Depende do marceneiro fabricar
e colocar as gavetas neste armrio. Podemos at indicar a posio onde queremos guardar algum
objeto, mas se a gaveta no foi colocada no possvel armazenar nada (Figura 3.2).
Suporte
nmero:
Existe
gaveta?
1
sim
2
sim
3
no
4
no
5
sim
6
no
Figura 3.2: Memria como um armrio
Ao invs de gavetas o marceneiro pode pensar em colocar outros sistemas de armazenamento
nos espaos (Figura 3.3). Alguns destes sistemas podem permitir que o usurio enxergue o que
esta dentro mas no mexa. Alguns vo permitir que o usurio coloque coisas mas no retire.
Outros ainda podem permitir que a pessoa retire objetos mas no possa rep-los.
Esta variedade de sistemas de armazenamento representam a variedade de tipos de memria
e de interfaces de perifricos que possumos.
A memria identicada atravs de um endereo. Por estarmos tratando de sistemas digitais,
o valor do endereo codicado em binrio. Como visto anteriormente, escrever em binrio
trabalhoso e muito propenso a gerar erros. Visando facilitar esse processo, comumente adotado
o sistema hexadecimal para indicar o local de memria.
Os dispositivos so ento ligados um determinado nmero de endereo que passa a identic-
lo de forma nica. O mesmo acontece para a memria RAM e memria ROM. Elas esto ligadas
uma srie de endereos. Se, portanto, preciso salvar uma varivel na memria, tem-se que saber
quais endereos esto ligados memria RAM. Se quisermos ler alguma informao gravada na
memria ROM, preciso conhecer a localizao exata antes de realizar a leitura.
A porta D do microcontrolador PIC 4550 por exemplo est no endereo 0xF83, destinado aos
registros de funo especial ou special function register, SFR Figura 3.4).
Notas de Aula ELT024 - Programao para Sistemas Embarcados
41 Arquitetura de microcontroladores
Suporte
nmero:
Existe
gaveta?
1
Vitrine
2
Gaveta
3
Dispenser
4
No
5
Gaveta
6
Cofre
Figura 3.3: Memria e perifricos como um armrio
Stack 1
Stack 31
Reset
Baixa prioridade
Alta prioridade
Memria EEPROM
No implementado
...
GPR1
GPR3
GPR4
GPR2
No implementado
SFR
0x0000
0x0008
0x0018
0x0028
0x7FFF
0X8000
0X1FFFFF
0x000
0x0FF
0x200
0x2FF
0x300
0x3FF
0x100
0x1FF
...
0xF60
0xFFF
V
e
t
o
r
d
e
I
n
t
e
r
r
u
p
o
Figura 3.4: Regies de memrias disponveis no PIC18F4550
Notas de Aula ELT024 - Programao para Sistemas Embarcados
42 Arquitetura de microcontroladores
j.z Clock e tempo de instruo
O microcontrolador capaz de realizar apenas uma tarefa por vez. Estas tarefas so executadas
sempre a intervalos regulares denidos pelo clock do sistema. O clock dene ento a velocidade
com que o processador trabalha.
Algumas operaes so mais demoradas pois so compostas de uma quantidade maior de
tarefas. Por exemplo a soma.
A soma de nmeros inteiros feita de maneira direta enquanto para somar dois nmeros
fracionrios, que esto em notao cientca
1
, necessrio igualar as potencias antes de realizar
a soma. Por este motivo a segunda operao mais demorada que a primeira.
Exemplo:
Multiplicao de inteiros Multiplicao de fracionrios
A = 123456;
B = 34567;
C = A x B ;
//C = 4267503552
// 1. Mul t i pl i c ar os nmeros
// 123456
// 34567
// 4267503552
A = 1. 23456 x 10 ^ 5
B = 3. 4567 x 10 ^ 4
C = A x B
//C = 4. 267503552 x 10 ^9
// 1. Convert er para o mesmo expoent e
// 12. 3456 x 10 ^ 4
// 3. 4567 x 10 ^ 4
// 2. Mul t i pl i c ar os nmeros
//e somar a mant i ssa
// 12. 3456 x 10 ^ 4
// x 3. 4567 x 10 ^ 4
// 42. 67503552 x 10 ^ 8
// 3. Cor r i gi r quant i dade de casas dec .
// 4. 267503552 x 10 ^ 9
Conhecer quanto tempo o cdigo leva para ser executado permite ao desenvolvedor saber de
maneira determinstica qual a exigncia a nvel de hardware para o sistema embarcado.
Por exemplo: Um sistema precisa executar 200 operaes a cada milsimo de segundo. Cada
operao possu uma quantidade diferente de tarefas conforme podemos ver na Tabela 3.1.
Tabela 3.1: Quantidade de operaes e tarefas
Operao com: Quantidade Total de tarefas
1 tarefa 104 104
2 tarefas 63 126
3 tarefas 21 63
4 tarefas 12 48
Total 200 341
O total de tarefas a serem realizadas de 341 tarefas por milissegundo. Isso d uma quanti-
dade de 341 mil tarefas por segundo. Se cada tarefa realizada em um ciclo de clock precisamos
de um microcontrolador cujo processador trabalhe no mnimo em 341 kHz.
1
Nmeros fracionrios podem ser armazenados de dois modos no ambiente digital. O modo mais comum o
ponto utuante que se assemelha notao cientca.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
43 Arquitetura de microcontroladores
j.j Esquema eltrico e circuitos importantes
Um microcontrolador representado atravs de esquema eltrico. O esquema eltrico apresenta
ao projetista todos os componentes e suas ligaes conforme apresentado na Figura 3.5.
Figura 3.5: Esquema eltrico: Microcontrolador PIC 18F4550
Para funcionarem, todos os microcontroladores devem ser alimentados com tenso contnua.
O valor varia de modelo para modelo. Alguns podem at mesmo aceitar diversos valores. O PIC
18F4550 por exemplo pode ser alimentado com qualquer tenso contnua entre 2 e 5,5 volts.
Para gerar o clock necessrio, que denir a velocidade na qual o processador ira trabalhar,
em geral utilizado um oscilador a cristal, que possui uma tima preciso.
Alguns microcontroladores podem dispensar o cristal externo optando por utilizar uma malha
RC interna ao chip. Esta alternativa muito menos precisa e geralmente no permite valores
muito altos de clock. A vantagem que sistemas que utilizam malha RC interna como osciladores
primrios possuem um custo menor que sistemas que dependem de malhas de oscilao externa,
seja ela excitada por outra malha RC ou por um cristal.
Existem alguns circuitos que no so essenciais para o funcionamento do sistema, mas auxi-
liam muito no desenvolvimento. Entre estes tipos de circuito o mais importante o que permite
a gravao do programa no prprio circuito. Alguns microcontroladores exigem que o chip seja
retirado do circuito e colocado numa placa especial para grav-lo e somente depois recolocado
na placa para teste. Este um procedimento muito trabalhoso e, devido ao desgaste mecnico
inerente, reduz a vida til do chip.
Para evitar estes problemas, os fabricantes desenvolveram estruturas no chip que permitem
que este seja gravado mesmo estando soldado placa nal. Para isso, basta que o desenvolvedor
disponibilize o contato de alguns pinos com um conector. Este conector ser ligado um gra-
vador que facilitar o trabalho de gravao do programa. Para a famlia PIC esta tecnologia
denominada ICSP (in circuit serial programming).
Notas de Aula ELT024 - Programao para Sistemas Embarcados
44 Arquitetura de microcontroladores
Multiplexao nos terminais do microcontrolador
Conforme pode ser observado na Figura 3.5, alguns pinos/terminais possuem mais de uma des-
crio. Por exemplo o terminal 8, a descrio deste terminal RE0/AN5/CK1SPP. Isto indica
que dependendo da congurao escolhida ele pode ser um terminal:
de entrada ou sada referente ao primeiro bit da porta E (RE0)
de leitura analgica pertencente ao quinto conversor analgico - digital (AN5)
utilizado para enviar um clock externo de comunicao paralela (CK1SPP)
A escolha de qual funcionalidade ser utilizada depende do projetista. Em sistemas mais avan-
ados possvel inclusive utilizar mais de uma funcionalidade no mesmo terminal em perodos
alternados, desde que o circuito seja projetado levando esta opo em considerao.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
45 Arquitetura de microcontroladores
j.q Registros de congurao do microcontrolador
A maioria dos terminais dos microcontroladores podem ser congurados para trabalhar de di-
versas maneiras. Esta congurao realizada atravs de registros especiais. Estes registros
so posies de memria pr-denidas pelo fabricante. Para conhecer quais so e o que fazem
preciso recorrer ao datasheet do componente.
Alm dos registros de congurao dos terminais, existem registros que indicam como o mi-
crocontrolador deve operar. O microcontrolador PIC18f4550 possui dez registros que controlam
seu modo de operao, velocidade, modo de gravao, etc. Estes registros so apresentados na
Figura 3.6.
Figura 3.6: Registros de congurao do microcontrolador PIC 18F4550
Dos registros apresentados na Figura 3.6, quatro precisam necessariamente ser congurados
para que o sistema possa funcionar. Dois deles tem relao com a congurao do sistema de
clock: um especica qual a fonte do sinal de clock, que no caso da placa em questo um
cristal externo, e o outro indica qual o prescaler a ser usado (PLL).
Alm de congurar a frequncia bsica do clock necessrio desligar o watchdog. Este
um circuito para aumentar a segurana do sistema embarcado desenvolvido. Para funcionar
corretamente, o programa deve ser preparado para tal nalidade. Ele ser explicado em detalhes
na seo .1 e por isso ser mantido desligado nos prximos exemplos.
A ultima congurao necessria desabilitar a programao em baixa tenso. Devido s
ligaes feitas na placa, deixar esta opo ligada impede o funcionamento da placa enquanto
estiver ligada ao gravador. Abaixo o trecho de cdigo que realiza estas conguraes para o
compilador SDCC.
// Pl l de s l i g ado
code char at 0x300000 CONFIG1L = 0x01 ;
// Os ci l ador c/ c r i s t a l ext erno HS
code char at 0x300001 CONFIG1H = 0x0C ;
// Watchdog cont r ol ado por s of t war e
code char at 0x300003 CONFIG2H = 0x00 ;
// Sem programao em bai xa t enso
code char at 0x300006 CONFIG4L = 0x00 ;
A primeira coluna de nmeros indica a posio do registro que armazena as conguraes.
A segunda coluna representa os cdigos utilizados para congurao. Para conhecer as demais
opes de conguraes devemos consultar o manual do usurio.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
46 Arquitetura de microcontroladores
Estas conguraes so dependentes do compilador a ser usado. A seguir demonstramos os
cdigos necessrios para o compilador C18 da Microchip(R).
// Os ci l ador c/ c r i s t a l ext erno HS
#pragma c onf i g FOSC = HS
// Pl l de s l i g ado
#pragma c onf i g CPUDIV = OSC1_PLL2
// Watchdog cont r ol ado por s of t war e
#pragma c onf i g WDT = OFF
// Sem programao em bai xa t enso
#pragma c onf i g LVP = OFF
Notar que as diretivas utilizadas so completamente diferentes, mas realizam o mesmo tra-
balho.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
Captulo 4
Programao dos Perifricos
In theory, there is no dierence between theory and practice; In
practice, there is. - Chuck Reid
Perifricos so os componentes, circuitos ou sistemas ligados ao microcontrolador, interna ou
externamente. Eles podem ser utilizados para realizar interface entre o homem e o equipamento
ou incluir funcionalidades extras ao sistema, como comunicao, segurana, etc.
Os perifricos de sada
1
que sero abordados neste curso sero:
Barramento de Led's(.)
Display de 7 segmentos(.)
Display LCD 2x16(.)
Sadas PWM(.)
Entre os perifricos de entrada
2
temos:
Leitura de teclas(.)
Conversor AD(.)
Alm de sistemas de entrada e sada de dados ser abordado um dispositivo de comunicao
serial (.), um tratador de Interrupo(.1:), um Timer(.1o) e um dispositivo de segurana:
Watchdog(.1).
1
Perifricos que fornecem informaes aos usurios ou enviam comandos da a placa eletrnica para o meio
externo
2
Perifricos que recebem informaes ou comandos do meio externo
47
48 Programao dos Perifricos
q.i Acesso s portas do microcontrolador
O microcontrolador possui portas que permitem o interfaceamento do meio externo para o meio
interno. Algumas portas podem trabalhar como receptoras ou transmissoras de sinais. Algumas
podem operar dos dois modos sendo necessrio congur-las antes de sua utilizao.
O microcontrolador PIC 18F4550 possui 5 portas
PORTA: bidirecional com 7 bits
PORTB: bidirecional com 8 bits
PORTC: bidirecional com 7 bits
PORTD: bidirecional com 8 bits
PORTE: 3 bits bidirecionais e 1 bit apenas entrada
Cada porta esta ligada dois endereos de memria. O primeiro armazena o valor que
queremos ler do meio externo ou escrever para o meio externo dependendo da congurao. O
segundo endereo realiza esta congurao indicando quais bits sero utilizados para entrada e
quais sero utilizados para sada (Tabela 4.1).
Tabela 4.1: Endereos de memria para as portas do PIC 18F4550
Porta Endereo dos dados Endereo de congurao (TRIS)
PORTA 0xF80 0xF92
PORTB 0xF81 0xF93
PORTC 0xF82 0xF94
PORTD 0xF83 0xF95
PORTE 0xF84 0xF96
Aqui o conceito de ponteiros se faz extremamente necessrio. J que conhecemos os endereos
xos onde as portas se encontram, podemos criar ponteiros para tais endereos de forma que
possamos utilizar as portas como se fossem variveis. Exemplo:
// i ni c i o do programa
void main ( void) interrupt 0
{
// def i ni mos como :
// unsi gned char : poi s os 8 b i t s represent am v al or e s
// v o l a t i l e : as v a r i v e i s podem mudar a qual quer momento
//near : i ndi ca posi ci onament o do r e g i s t r o e s t a na memria
vol ati l e near unsigned char PORTD = 0xF83 ;
vol ati l e near unsigned char TRISD = 0xF95 ;
// conf i gurando t odos os pi nos como s a das
// 0 = s a da ( Output )
// 1 = ent rada ( Input )
TRISD = 0b00000000 ;
// l i g a apenas os quat ro l t i mos l e ds
PORTD = 0b11110000 ;
//mantm o si st ema l i g ado i ndef i ni dament e
for ( ; ; ) ;
}
Notar que, por serem ponteiros, sempre que precisarmos utilizar o valor de tais variveis
necessrio que coloquemos o asterisco.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
49 Programao dos Perifricos
Uma outra maneira de manipular as portas criar denes que permitem o uso das portas
como variveis, sem a necessidade de utilizar ponteiros de modo explicito, nem asteriscos no
cdigo.
// de f i ne ' s para por t as de ent rada e s a da
#define PORTD ( ( vol ati l e near unsigned char ) 0xF83)
#define TRISD ( ( vol ati l e near unsigned char ) 0xF95)
// i ni c i o do programa
void main ( void) interrupt 0
{
// conf i gurando t odos os pi nos como s a das
TRISD = 0b00000000 ;
// l i g a apenas os quat ro l t i mos l e ds
PORTD = 0b11110000 ;
//mantm o si st ema l i g ado i ndef i ni dament e
for ( ; ; ) ;
}
Como estamos criando um dene, uma boa prtica de programao utilizar apenas letras
maisculas para diferenci-lo de uma varivel comum.
Notem que usamos dois asteriscos no dene. isto que permite que utilizemos o dene como
uma varivel qualquer, sem precisar de usar um asterisco a todo momento, como no caso dos
ponteiros.
A segunda abordagem (com dene) preferida em relao primeira pois, dependendo do
compilador, gera cdigos mais rpidos alm de economizar memria. Alm disso, permite que a
denio seja feita apenas uma vez e utilizada em todo o programa.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
50 Programao dos Perifricos
q.z Congurao dos perifricos
Make everything as simple as possible, but not simpler. - Albert
Einstein
Em geral, os terminais das portas so multiplexados com outros dispositivos. Para saber como
congurar cada porta preciso conhecer os registros de congurao que atuam sobre a porta
desejada. A Figura 4.1 apresenta todos os registros disponveis do microcontrolador 18F4550.
Figura 4.1: Registros de congurao dos perifricos do PIC 18F4550
Para a placa que estamos utilizando, a congurao dos terminais do PIC segue conforme a
Tabela 4.2. Esta congurao reete a opo do autor de acordo com as possibilidades da placa
e tambm o sistema mnimo para realizao de todas as experiencias da apostila.
Os terminais no citados na Tabela 4.2 (1, 3, 5, 6, 15, 18, 23 e 24) possuem perifricos
que no sero utilizados neste curso. Os terminais 11 e 31 representam a alimentao positiva.
O comum (terra) est ligado ao 12 e ao 32. O microcontrolador utilizado (18f4550) possui o
encapsulamento DIP. Para outros encapsulamentos favor considerar o datasheet.
Da Tabela 4.2, temos que a porta A possui o primeiro bit como entrada analgica e o terceiro
e sexto como sada digital. Os dois bits digitais servem como controle de ativao do display.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
51 Programao dos Perifricos
Tabela 4.2: Tabela de congurao do PIC para as experincias
Terminal Descrio do pino Funo
2 RA0/AN0 Potencimetro / Sensor de Temperatura
4 RA2/AN2/VREF-/CVREF Display 2
7 RA5/AN4/SS/C2OUT Display 1
8 RE0/AN5/CK1SPP RS-LCD / Display 3
9 RE1/AN6/CK2SPP EN-LCD
10 RE2/AN7/OESPP RW-LCD / Display 4
13 OSC1/CLKI
Cristal
14 OSC2/CLKO/RA6
16 RC1/T1OSI/CCP2 Aquecedor
17 RC2/CCP1/P1A Ventilador / Buzzer
19 RD0/SPP0
Barramento de dados para o
LCD/7seg/Led
20 RD1/SPP1
21 RD2/SPP2
22 RD3/SPP3
25 RC6/TX/CK
RS232
26 RC7/RX/DT/SDO
27 RD4/SPP4
Barramento de dados para o
LCD/7seg/Led
28 RD5/SPP5/P1B
29 RD6/SPP6/P1C
30 RD7/SPP7/P1D
33 RB0/AN12/INT0/SDI
Sadas para alimentao do teclado
34 RB1/AN10/INT1/SCK
35 RB2/AN8/INT2/VMO
36 RB3/AN9/CCP2/VPO
37 RB4/AN11/KBI0/CSSPP
Entradas para leitura do teclado
38 RB5/KBI1/PGM
39 RB6/KBI2/PGC
40 RB7/KBI3/PGD
Notas de Aula ELT024 - Programao para Sistemas Embarcados
52 Programao dos Perifricos
TRISA = 0b00000001 ; // conf i gurando os t er mi nai s como ent rada e s a da
ADCON1 = 0b00001110 ; //apenas o pri mei ro t ermi nal anal gi co
A porta B possui os 4 primeiros bits como sadas e os quatro ltimos como entrada. Esta
porta serve para leitura da matriz de chaves. possvel realizar a leitura atravs de interrupo.
TRISB = 0b11110000 ; // conf i gurando os t er mi nai s como ent rada e s a da
// conf i gurao com i nt er r upo h a b i l i t a d a
INTCON = 0b11000101 ;
INTCON2 = 0b00000001 ;
// conf i gurao sem i nt er r upo
INTCON = 0b00000000 ;
INTCON2 = 0b00000001 ;
SPPCFG = 0b00000000 ; //RB0 e RB4 so cont r ol ados pel a port a B e no pel o SPP
A porta C possui o segundo e terceiro bit como sada PWM e o stimo e oitavo como
comunicao serial.
TRISC = 0b10000000 ; // conf i gurando os t er mi nai s como sa da , apenas RC7 ent rada
CCP1CON = 0b00001100 ; // conf i gur a o segundo t ermi nal como PWM
CCP2CON = 0b00001100 ; // conf i gur a o t e r c e i r o t ermi nal como PWM
TXTA = 0b00101100 ; // conf i gur a a t ransmi sso de dados da s e r i a l
RCSTA = 0b10010000 ; // conf i gur a a recepo de dados da s e r i a l
BAUDCON = 0b00001000 ; // conf i gur a si st ema de v e l oc i dade da s e r i a l
SPBRGH = 0b00000000 ; // conf i gur a para 56k
SPBRG = 0b00100010 ; // conf i gur a para 56k
A porta D utilizada como barramento de dados. Os valores escritos nela so transmitidos,
simultaneamente, para os leds, os displays de 7 segmentos e o display de LCD.
TRISD = 0b00000000 ; // conf i gurando os t er mi nai s como s a da
A porta E possui apenas os 3 primeiros bits congurados como sadas digitais. So utilizados
para controle de ativao dos displays e tambm como sinais de controle do LCD.
TRISE = 0b00000000 ; // conf i gurando os t er mi nai s como s a da
Notas de Aula ELT024 - Programao para Sistemas Embarcados
53 Programao dos Perifricos
q.j Barramento de Led's
Existe na placa utilizada um barramento de 8 bits, onde cada linha possui um led associado. Este
barramento est ligado diretamente com a porta D do microcontrolador conforme Figura 4.2.
Figura 4.2: Barramento de Led's
Podemos notar pela Figura 4.2 que existe um jumper (JP1) que habilita ou no o funcio-
namento destes leds. Alm disso percebemos que se o jumper estiver encaixado, os led's esto
permanentemente ligados ao 5 volts. Deste modo, para que o led acenda, necessrio colocar o
valor 0 (zero) no respectivo bit da porta D. Quando um dispositivo ligado com o valor 0 (zero)
e desligado com o valor 1 (um), dizemos que este dispositivo opera com lgica invertida.
Conforme visto preciso congurar os pinos da porta D como sada, para isso basta escrever
zero em cada um deles no registro TRISD.
void main ( void) interrupt 0
{
TRISD = 0x00 ; // conf i gur a os pi nos da port a D como s a da
PORTD = 0xF0 ; // l i g a apenas os quat ro l t i mos b i t s .
for ( ; ; ) ; //mantm o si st ema num l oop i n f i n i t o
}
Notas de Aula ELT024 - Programao para Sistemas Embarcados
54 Programao dos Perifricos
q.q Display de 7 segmentos
Os displays de 7 segmentos (Figura 4.3) so componentes opto eletrnicos utilizados para apre-
sentar informaes para o usurio em formato numrico.
Figura 4.3: Display de 7 Segmentos
Fonte: Peter Halasz - http://commons.wikimedia.org/wiki/File:Seven_segment_02_Pengo.jpg
Estes displays foram concebidos com o intuito de gerar os dez algarismos romanos: 0, 1, 2,
3, 4, 5, 6, 7, 8, 9, sendo que os algarismos 0, 6, 7 e 9 podem ser representados de mais de uma
maneira.
Alm dos algarismos possvel representar apenas algumas letras de modo no ambguo: as
maisculas A, C, E, F, H, J, L, P, S, U, Z e as minsculas: a, b, c, d, h, i, n, o, r, t, u.
Os displays podem ser do tipo catodo comum, ou anodo comum indicando qual o tipo de
ligao dos leds. Contudo, esta diferena no ser crtica para este estudo. Na Figura 4.4
podemos visualizar o esquema eltrico e a disposio fsica de cada led no componente.
Figura 4.4: Diagrama eltrico para display de 7 segmentos com anodo comum
http://www.hobbyprojects.com/the_diode/seven_segment_display.html
Pela Figura 4.4 podemos notar que para que aparea o nmero 2 no display necessrio
acender os leds a, b, g, e, d. Se estivermos utilizando um display com catodo comum, precisamos
colocar um nvel alto para ligar o led, ou seja, o led liga com valor 1 (um) e desliga com valor 0
(zero). Isto tambm conhecido como lgica positiva. Na Tabela 4.3 so apresentados os valores
em binrio e em hexadecimal para cada representao alfanumrica
3
. Dentre as letras disponveis
esto apresentadas apenas os caracteres A, b, C, d, E, F. Estas foram escolhidos por serem os
mais utilizados para apresentar valores em hexadecimal nos displays. Neste curso utilizaremos a
3
Notar que os valores hexadecimais apresentados servem apenas quando existe uma sequencia na ligao entre
a porta do microcontrolador e os pinos do display. Em alguns sistemas, o display pode ser controlado por duas
portas diferentes, ou possuir alguma alterao na sequencia de ligao. Para tais casos necessrio remontar a
tabela apresentada.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
55 Programao dos Perifricos
Tabela 4.3: Converso binrio - hexadecimal para displays de 7 segmentos
Ordem inversa Ordem direta
Display a b c d e f g Hex (0abcdefg) g f e d c b a Hex (0gfedcba)
0 1 1 1 1 1 1 0 7E 0 1 1 1 1 1 1 3F
1 0 1 1 0 0 0 0 30 0 0 0 0 1 1 0 06
2 1 1 0 1 1 0 1 6D 1 0 1 1 0 1 1 5B
3 1 1 1 1 0 0 1 79 1 0 0 1 1 1 1 4F
4 0 1 1 0 0 1 1 33 1 1 0 0 1 1 0 66
5 1 0 1 1 0 1 1 5B 1 1 0 1 1 0 1 6D
6 1 0 1 1 1 1 1 5F 1 1 1 1 1 0 1 7D
7 1 1 1 0 0 0 0 70 0 0 0 0 1 1 1 07
8 1 1 1 1 1 1 1 7F 1 1 1 1 1 1 1 7F
9 1 1 1 1 0 1 1 7B 1 1 0 1 1 1 1 6F
A 1 1 1 0 1 1 1 77 1 1 1 0 1 1 1 77
b 1 0 1 1 1 1 0 5E 1 1 1 1 1 0 0 7C
C 1 0 0 1 1 1 1 4F 0 1 1 1 0 0 1 39
d 0 1 1 1 1 0 1 3D 1 0 1 1 1 1 0 5E
E 1 0 0 1 1 1 1 4F 1 1 1 1 0 0 1 79
F 1 0 0 0 1 1 1 47 1 1 1 0 0 0 1 71
ordem direta apresentada na Tabela 4.3. A utilizao de uma ou outra depende da ligao feita
na placa. A Figura 4.5 apresenta o esquema eltrico disponvel.
Figura 4.5: Ligao de 4 displays de 7 segmentos multiplexados
Para simplicar a utilizao deste tipo de display comum criar uma tabela cujas posies
representam o valor de converso para o display. Conforme pode ser visto no cdigo a seguir.
void main ( void) interrupt 0
{
Notas de Aula ELT024 - Programao para Sistemas Embarcados
56 Programao dos Perifricos
// vet or que armazena a converso dos al gari s mos para o di s pl ay 7 seg
const char conv [ ] = {0x3F , 0x06 , 0x5B , 0x4F , 0x66 , 0x6D , 0x7D , 0x07 ,
0x7F , 0x6F , 0x77 , 0x7C , 0x39 , 0x5E , 0x79 , 0x71 };
unsigned i nt var , time ;
TRISD = 0x00 ;
TRISA = 0x00 ;
PORTA = 0xFF ;
for ( var = 0; var < 16; var++)
{
// col oca os c ar ac t e r e s em s equnci a na s a da
PORTD = conv [ var ] ;
//apenas para cont ar tempo
for ( time = 0; time < 65000; time++) ;
}
}
Multiplexao de displays
Cada display exige 7 ou 8 terminais de controle, caso tambm seja utilizado o ponto decimal.
Para utilizar 4 displays, por exemplo um relgio com dois dgitos para horas e dois para minutos,
precisaramos de 32 terminais de sada, o que pode ser um custo
4
muito alto para o projeto.
Uma tcnica que pode ser utilizada a multiplexao dos displays. Esta tcnica leva em conta
um efeito biolgico denominado percepo retiniana. O olho humano incapaz de perceber
mudanas mais rpidas que 1/30 (s). Outro fator importante que as imagens mais claras
cam gravadas na retina devido ao tempo que leva para sensibilizar e dessensibilizar as clulas
(bastonetes).
Deste modo podemos ligar e desligar rapidamente o display que a imagem continuar na
retina. Se ligarmos cada display, um por vez, sequencialmente, de maneira sucientemente
rpida, teremos a impresso que todos esto ligados. A frequncia de chaveamento deve ser
mais rpida que 30Hz.
A Figura 4.5 apresenta o circuito com 4 displays multiplexados. Percebemos que os terminais
iguais esto ligados juntos. Percebemos tambm que os terminais de catodo comum esto cada
um ligado uma sada diferente. Com esta arquitetura reduzimos a quantidade de terminais
necessrios de 32 para 12, uma economia de 20 terminais.
Mas esta economia tem um custo, o sistema se torna mais complexo pois no podemos ligar
dois displays ao mesmo tempo.
O controle de qual display ser ligado feito atravs do transistor que permite a ligao do
catodo comum ao terra, ou o anodo comum ao VCC (depende do tipo de dispositivo. Para o
correto funcionamento no basta agora acender os leds corretos para formar o nmero, temos
que seguir um algoritmo mais complexo:
1. colocar no barramento de dados o valor a ser mostrado no display X
2. ligar o display X atravs da linha de comando
3. esperar um tempo adequado para evitar icker
5
4. desligar o display
5. escolher o prximo display (X+1)
6. voltar ao passo 1
4
Microcontroladores com mais terminais possuem um custo superior, mesmo possuindo os mesmos perifricos
internamente.
5
Se a taxa de atualizao dos displays for muito baixa, estes vo apresentar uma variao na intensidade, como
se estivessem piscando. Este efeito chamado de icker.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
57 Programao dos Perifricos
Criao da biblioteca
O programa 4.1 apresenta um exemplo de cdigo para criar uma biblioteca para os displays de 7
segmentos. O programa 4.2 apresenta o header da biblioteca. J o programa 4.3 apresenta uma
demonstrao de uso da biblioteca.
Programa 4.1: disp7seg.c
1 #include "disp7seg.h"
2 // vet or para armazenar a converso do
di s pl ay
3 stati c const char valor [ ] = {0x3F ,
0x06 , 0x5B , 0x4F , 0x66 , 0x6D ,
0x7D , 0x07 , 0x7F , 0x6F , 0x77 ,
0x7C , 0x39 , 0x5E , 0x79 , 0x71 };
4 // i ndi ca o di s pl ay at ual
5 stati c char display ;
6 // v al or e s dos d i s p l a y s
7 stati c char v0 , v1 , v2 , v3 ;
8 void MudaDigito ( char val , char pos )
9 {
10 i f ( pos == 0)
11 {
12 v0 = val ;
13 }
14 i f ( pos == 1)
15 {
16 v1 = val ;
17 }
18 i f ( pos == 2)
19 {
20 v2 = val ;
21 }
22 i f ( pos == 3)
23 {
24 v3 = val ;
25 }
26 }
28 void InicializaDisplays ( void)
29 {
30 // conf i gurao dos pi nos de c ont r ol e
31 BitClr ( TRISA , 2 ) ;
32 BitClr ( TRISA , 5 ) ;
33 BitClr ( TRISE , 0 ) ;
34 BitClr ( TRISE , 2 ) ;
35 //apenas AN0 anal gi co
36 ADCON1 = 0x0E ;
37 //Porta de dados
38 TRISD = 0x00 ;
39 }
40 void AtualizaDisplay ( void)
41 {
42 // d e s l i g a t odos os d i s p l a y s
43 PORTA = 0x00 ;
44 PORTE = 0x00 ;
45 // d e s l i g a t odos os l e d s
46 PORTD = 0x00 ;
47 // l i g a apenas o di s pl ay da vez
48 switch( display )
49 {
50 case 0:
51 PORTD = valor [ v0 ] ;
52 BitSet ( PORTA , 5 ) ;
53 display = 1;
54 break ;
55 case 1:
56 PORTD = valor [ v1 ] ;
57 BitSet ( PORTA , 2 ) ;
58 display = 2;
59 break ;
60 case 2:
61 PORTD = valor [ v2 ] ;
62 BitSet ( PORTE , 0 ) ;
63 display = 3;
64 break ;
65 case 3:
66 PORTD = valor [ v3 ] ;
67 BitSet ( PORTE , 2 ) ;
68 display = 0;
69 break ;
70 default :
71 display = 0;
72 break ;
73 }
74 }
Notas de Aula ELT024 - Programao para Sistemas Embarcados
58 Programao dos Perifricos
Programa 4.2: disp7seg.h
1 #i f ndef DISP7SEG_H
2 #define DISP7SEG_H
3 void MudaDigito ( char val , char pos ) ;
4 void AtualizaDisplay ( void) ;
5 void InicializaDisplays ( void) ;
6 #endif
Programa 4.3: Utilizando a biblioteca disp7seg
1 #include "basico.h"
2 #include "config.h"
3 #include "disp7seg.h"
5 // i ni c i o do programa
6 void main ( void) interrupt 0
7 {
8 unsigned i nt tempo ;
9 InicializaDisplays ( ) ;
10 MudaDigito ( 0 , 0) ;
11 MudaDigito ( 1 , 1) ;
12 MudaDigito ( 2 , 2) ;
13 MudaDigito ( 3 , 3) ;
14 for ( ; ; )
15 {
16 AtualizaDisplay ( ) ;
17 // gas t a um tempo para e v i t a r o e f e i t o f l i c k e r
18 for ( tempo=0; tempo <1000; tempo++) ;
19 }
20 }
Notas de Aula ELT024 - Programao para Sistemas Embarcados
59 Programao dos Perifricos
q. Leitura de teclas
Para realizar a leitura de uma tecla necessrio criar um circuito que realize a leitura de um
sinal eltrico para o valor zero e outro para o valor um. Os nveis de tenso associados dependem
muito dos circuitos envolvidos. Os nveis mais comuns so os compatveis com TTL, onde o zero
lgico representado por 0v (zero volts) e o um lgico representado por 5v (cinco volts).
Uma maneira de se obter este funcionamento com o uso de uma chave ligada ao VCC e um
pull-down ou uma chave ligada ao terra (GND) e um pull-up.
Figura 4.6: Circuito de leitura de chave
http://www.labbookpages.co.uk/electronics/debounce.html - Dr. Andrew Greensted
Pela Figura 4.6 percebemos que a tenso de sada igual a VCC quando a chave est desligada
pois no existe corrente circulando no circuito portanto a queda de tenso em R1 zero. Quando
a chave pressionada uma corrente ui de VCC para o terra passando por R1. Como no existe
nenhuma outra resistncia no circuito toda a tenso ca em cima de R1 e a tenso de sada passa
a ser zero.
Apesar do funcionamento aparentemente simples, este tipo de circuito apresenta um problema
de oscilao do sinal no momento em que a tecla pressionada. Esta oscilao conhecida como
bouncing (Figura 4.7).
Estas oscilaes indevidas podem gerar acionamentos acidentais, causando mau funciona-
mento do programa. Para evitar isso podemos utilizar tcnicas de debounce, por hardware ou
software.
A opo de debounce por hardware pode ser visualizada na Figura 4.8.
Neste circuito, o capacitor desempenha o papel de amortecedor do sinal. Um circuito com um
resistor e um capacitor possui um tempo de atraso para o sinal. Este o tempo necessrio para
carregar o capacitor. Deste modo as alteraes rpidas no sinal, devido oscilao mecnica da
chave, so ltradas e no ocorre o problema dos chaveamentos indevidos conforme pode ser visto
na Figura 4.9. Notar que o nvel do sinal ltrado no chega a zero em nenhum momento, devido
constante de tempo do ltro RC ser maior que o perodo de debounce.
Debounce por software
O debounce por software em geral utilizado em situaes onde se deseja aumentar a robustez
de uma entrada que j possua um debounce por hardware ou reduzir o custo da placa utilizando
apenas a soluo por software. A grande desvantagem deste tipo de sistema inserir um atraso
na deteco da informao.
Para realizar o debounce por software precisamos ter uma noo do tempo que a chave
precisa para estabilizar. Da Figura 4.7 temos que este tempo, para uma determinada chave de
aproximadamente 150 (s). Um ciclo de clock do sistema em questo (PIC18f4550 com cristal de
Notas de Aula ELT024 - Programao para Sistemas Embarcados
60 Programao dos Perifricos
Figura 4.7: Oscilao do sinal no momento do chaveamento
http://www.labbookpages.co.uk/electronics/debounce.html - Dr. Andrew Greensted
Figura 4.8: Circuito de debounce
http://www.ikalogic.com/debouncing.php - Ibrahim Kamal
Notas de Aula ELT024 - Programao para Sistemas Embarcados
61 Programao dos Perifricos
Figura 4.9: Utilizao de ltro RC para debounce do sinal
http://www.labbookpages.co.uk/electronics/debounce.html A. Greensted (modicado)
8MHz) de 0,5
6
(s). Antes de utilizar o valor que estamos lendo na porta em questo devemos
esperar 300 ciclos de clock aps alguma mudana para ter certeza que o sinal se estabilizou, ou
seja, a fase de bouncing acabou.
Notar que, no cdigo, o contador iniciado com o valor 22. Atravs da anlise do assembler
podemos saber que cada ciclo de conferencia do sinal possui 14 instrues. Assim necessrio
que o sinal permanea com o mesmo valor durante 308 ciclos para que a varivel valAtual receba
o valor da porta B. Estes valores podem ser determinados empiricamente atravs de testes com
osciloscpios.
void main ( void) interrupt 0
{
unsigned char valTemp ;
unsigned char valAtual ;
unsigned char tempo ;
TRISB = 0xF0 ; //mantm os 4 l t i mos b i t s como ent rada
TRISD = 0x00 ; // Conf i gura a port a D como s a da
PORTB = 0x00 ; // l i g a os 4 pri mei ros b i t s
BitClr ( INTCON2 , 7 ) ; // h a b i l i t a pul l up
ADCON1 = 0b00001110 ; // conf i gur a t odos os b i t s da port a B como d i g i t a i s
for ( ; ; )
{
//aguarda uma mudana na port a B
while ( valAtual==PORTB ) ;
//quando acont ecer alguma mudana , cont a um tempo pra ver se permanente
valTemp = PORTB ;
tempo = 22;
while ( tempo > 0)
{
i f ( valTemp == PORTB ) // se no mudar cont i nua a cont ar
{
tempo;
6
Lembrar que cada ciclo do PIC necessita de 4 ciclos de clock externo
Notas de Aula ELT024 - Programao para Sistemas Embarcados
62 Programao dos Perifricos
}
el se
{
valTemp = PORTB ; // se mudar , a t ua l i z a o si st ema e r e i ni c i a o tempo
tempo = 22;
}
}
valAtual = valTemp ; // v al or at ual i z ado ;
PORTD = valAtual ; // col oca o v al or no barramento de l e d s
}
}
Arranjo de leitura por matriz
Para cada tecla/boto que colocado no projeto, necessrio um terminal do microcontrolador.
Para um teclado maior possvel que o microcontrolador no possua terminais disponveis em
quantidade suciente. Do mesmo modo que no caso dos displays possvel multiplexar as
chaves aumentando a quantidade de chave por terminal. Novamente, este ganho, em termos de
hardware, aumenta a complexidade para o software e juntamente com este, o custo em termos
de tempo de computao.
Uma das tcnicas mais ecientes para a gerao deste teclado o arranjo em formato matri-
cial. Com esta congurao podemos, com N terminais, ler at (N/2)
2 chaves.
Conforme podemos ver na Figura 4.10, cada chave pode ser identicada unicamente pela
sua posio (linha, coluna). Os terminais ligados s linhas sero congurados como entrada,
que serviro para ler os valores das teclas. Os terminais ligados s colunas sero congurados
como sadas, fornecendo energia para as chaves. A leitura realizada ento por um processo
conhecido como varredura: liga-se uma coluna por vez e verica-se quais chaves daquela coluna
esto ligadas.
void main ( void) interrupt 0
{
unsigned char i , j ;
unsigned char chave [ 2 ] [ 4 ] = {{0 , 0 , 0 , 0} , {0 , 0 , 0 , 0}};
INTCON2 &= 0x7F ; // h a b i l i t a pul l up
ADCON1 = 0b00001110 ; //apenas AN0 anal gi co ,
TRISB = 0xF0 ; // os 4 l t i mos b i t s so ent rada
TRISD = 0x00 ; // conf i gur a a port a D como s a da
PORTD = 0xff ;
for ( ; ; )
{
for ( i = 0; i < 2; i++)
{
PORTB = 0xff ; //" d e s l i g a " t odas as col unas
for ( j = 0; j < 100; j++) ;
BitClr ( PORTB , i) ; //" l i g a " o b i t da col una correspondent e
// gas t a tempo para g ar ant i r que o pi no at i ng i u o ni v e l a l t o
for ( j = 0; j < 100; j++) ;
// r e a l i z a o t e s t e para cada b i t e a t ua l i z a a mat ri z .
for ( j = 0; j < 4; j++)
{
i f ( ! BitTst ( PORTB , j+4) )
{
chave [ i ] [ j ] = 1;
BitSet ( PORTD , j+4i) ;
}
el se
{
chave [ i ] [ j ] = 0;
BitClr ( PORTD , j+4i) ;
}
}
Notas de Aula ELT024 - Programao para Sistemas Embarcados
63 Programao dos Perifricos
Figura 4.10: Teclado em arranjo matricial
Notas de Aula ELT024 - Programao para Sistemas Embarcados
64 Programao dos Perifricos
Programa 4.4: teclado.c
1 #include "teclado.h"
2 #include "basico.h"
3 stati c unsigned i nt valor = 0x0000 ;
4 unsigned i nt LerTeclas ( void) {
5 return valor ;
6 }
7 void DebounceTeclas ( void) {
8 unsigned char i , j ;
9 stati c unsigned char tempo ;
10 stati c unsigned i nt valorNovo = 0x0000 ;
11 stati c unsigned i nt valorAntigo = 0x0000 ;
12 for ( i = 0; i < 4; i++){
13 PORTB |= 0x0F ; // d e s l i g a t odas as col unas
14 BitClr ( PORTB , ( i) ) ; // l i g a a col una correspondent e
15 // gas t a tempo sem r e a l i z a r f uno neces s r i o para g ar ant i r que o pi no
at i ng i u o ni v e l a l t o
16 for ( j=0; j<100; j++) ;
17 // r e a l i z a o t e s t e para cada b i t e a t ua l i z a a v a r i v e l
18 for ( j = 0; j < 4; j++) {
19 i f ( ! BitTst ( PORTB , j+4) ) {
20 BitSet ( valorNovo , ( i4)+j) ;
21 } el se {
22 BitClr ( valorNovo , ( i4)+j) ;
23 }
24 }
25 }
26 i f ( valorAntigo == valorNovo ) {
27 tempo ;
28 } el se {
29 tempo = 10;
30 valorAntigo = valorNovo ;
31 }
32 i f ( tempo == 0) {
33 valor = valorAntigo ;
34 }
35 }
37 void InicializaTeclado ( void) {
38 TRISB = 0xF0 ; // quat ro ent radas e quat ro s a das
39 INTCON2 &= 0x7F ; // h a b i l i t a pul l up
40 ADCON1 = 0b00001110 ; //apenas AN0 anal gi co
41 SPPCFG = 0x00 ;
42 }
}
}
}
importante notar que o cdigo acima no apresenta debounce em software para as teclas.
possvel realizar um debounce minimizando o gasto com memria e tempo, representando cada
chave como um bit diferente numa varivel. Esta ser a abordagem utilizada na gerao da
biblioteca para o teclado.
Criao da biblioteca
O programa 4.4 apresenta um exemplo de cdigo para criar uma biblioteca para um teclado de
16 teclas com leitura matricial. O header pode ser visto no programa 4.5. J o programa 4.6
apresenta uma demonstrao de uso da biblioteca.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
65 Programao dos Perifricos
Programa 4.5: teclado.h
1 #i f ndef TECLADO_H
2 #define TECLADO_H
4 unsigned i nt LerTeclas ( void) ;
5 void DebounceTeclas ( void) ;
6 void InicializaTeclado ( void) ;
7 #endif //TECLADO_H
Programa 4.6: Exemplo de uso da biblioteca teclado
1 #include "basico.h"
2 #include "config.h"
3 #include "teclado.h"
5 // i ni c i o do programa
6 void main ( void) interrupt 0
7 {
8 InicializaTeclado ( ) ;
9 TRISD = 0x00 ; // Conf i gura a port a D como s a da
10 PORTD = 0xFF ; // d e s l i g a t odos os l e d s
11 while (1==1)
12 {
13 DebounceTeclas ( ) ;
14 PORTD = LerTeclas ( ) ;
15 }
16 }
Notas de Aula ELT024 - Programao para Sistemas Embarcados
66 Programao dos Perifricos
q.6 Display LCD 2x16
O display de LCD utilizado neste curso possui duas linhas por 16 colunas de caracteres, compat-
vel com o HD44780 que um padro muito utilizado na indstria. Na Figura 4.11 apresentado
um modelo genrico deste tipo de display. A Figura 4.12 apresenta o verso do display com os
terminais expostos.
Figura 4.11: Display Alfanumrico LCD 2x16
Este mesmo tipo de display pode ser encontrado em diversas verses com tamanhos e cores
diferentes sendo os mais comuns de 1x8, 2x16 e 4x40. Pode ainda ter 16 ou 14 terminais,
dependendo se existe ou no retro iluminao. Estes terminais so identicados como:
1. Terra
2. VCC (+5V)
3. Ajuste do contraste
4. Seleo de registro(RS)
5. Read/Write (RW)
6. Clock, Enable (EN)
7. Bit 0
8. Bit 1
9. Bit 2
10. Bit 3
11. Bit 4
12. Bit 5
13. Bit 6
14. Bit 7
15. Backlight + (opcional)
16. Backlight Gnd (opcional)
Trabalharemos apenas com 11 terminais: os 3 de controle do display (RS,RW,EN) e os 8
para o barramento de dados. Este tipo de display possui, integrado, um microcontrolador para
realizar as rotinas de manuteno do estado do display, controle da luminosidade e interface com
Notas de Aula ELT024 - Programao para Sistemas Embarcados
67 Programao dos Perifricos
Figura 4.12: Display Alfanumrico LCD 2x16 - verso
o restante do sistema eletrnico. A comunicao realizada atravs de um barramento paralelo
de 8 bits, por onde so enviados os dados/comandos.
O terminal RS indica ao display se o barramento contm um comando a ser executado (0)
ou uma informao para ser exibida (1).
O terminal RW indica ao display se ele receber um valor (0) ou se estamos requisitando
alguma informao (1).
O terminal EN indica ao display que ele pode ler/executar o que est no barramento de
dados.
Ateno, o display utilizado apresenta os terminais colocados de maneira no sequncial,
conforme pode ser visto na Figura 4.12. Deste modo no qualquer display que compatvel.
As informaes so enviadas atravs da codicao ASCII, sendo que os caracteres de 0
127 so padronizados. Os caracteres de 128 255 dependem do fabricante do display. possvel
tambm criar algumas representaes, smbolos denidos pelo usurio e armazenar na memria
interna do display. Para um display com a ROM do tipo A00 temos os caracteres denidos na
Figura 4.13. Para a ROM A02 temos a Figura 4.14.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
68 Programao dos Perifricos
Figura 4.13: Caracteres disponveis para ROM A00
http://www.sparkfun.com/datasheets/LCD/HD44780.pdf - Datasheet Hitachi
Notas de Aula ELT024 - Programao para Sistemas Embarcados
69 Programao dos Perifricos
Figura 4.14: Caracteres disponveis para ROM A02
http://www.sparkfun.com/datasheets/LCD/HD44780.pdf - Datasheet Hitachi
Notas de Aula ELT024 - Programao para Sistemas Embarcados
70 Programao dos Perifricos
Os comandos reconhecidos pelo display so apresentados na Tabela 4.4.
Tabela 4.4: Lista de comandos aceitos pelo o LCD
Instruo RS RW Barramento de dados (bit) Tempo
7 6 5 4 3 2 1 0
Limpa todo o display e congura o endereo
para 0.
0 0 0 0 0 0 0 0 0 1 37 us
Congura o endereo para 0. Retorna o dis-
play para o incio se houve alguma operao
de shift.
0 0 0 0 0 0 0 0 1 - 1.52 ms
Congura a movimentao do cursor e o modo
de shift do display
0 0 0 0 0 0 0 1 ID S 37 us
Congura o display (D) inteiro para desligado
ou ligado, cursor (C) ligado ou desligado e
blinking (B) do cursor.
0 0 0 0 0 0 1 D C B 37 us
Move o cursor e/ou o display sem alterar o
contedo
0 0 0 0 0 1 SC RL - - 37 us
Congura o tamanho da palavra (DL), n-
mero de linhas (N) e fonte dos caracteres (F)
0 0 0 0 1 DL N F - - 37 us
Desloca o cursor para a posio desejada: li-
nha e coluna.
0 0 1 X 0 0 Coluna 37 us
Verica se o display est disponvel ou se esta
ocupado com alguma operao interna.
0 1 BF - - - - - - - 10 us
Denies das opes
ID: 1 Incrementa, 0 Decrementa
S: 1 O display acompanha o deslocamento
SC: 1 Desloca o display, 0 Desloca o cursor
RL: 1 Move para direita, 0 Move para esquerda
DL: 1 8 bits, 0 4 bits
N: 1 2 linhas, 0 1 linha
F: 1 5x10 pontos, 0 5x8 pontos
BF: 1 Ocupado, 0 Disponvel
X: 1 2a linha, 0 1a linha
Coluna: nible que indica a coluna
http://www.sparkfun.com/datasheets/LCD/HD44780.pdf - Datasheet Hitachi (modicado)
Os terminais de dados esto ligados porta D, juntamente com o display de 7 segmentos e
barramento de dados. Para estes dispositivos funcionarem em conjunto necessrio multiplexa-
los no tempo. Os terminais de controle esto ligados porta E conforme o esquema apresentado
na Figura 4.15.
Criao da biblioteca
Para facilitar o controle do display, podemos criar trs funes, uma para inicializao, uma para
escrever um caractere e a ltima para enviar um comando. Estas funes esto apresentadas no
programa 4.8, que constitui um exemplo de biblioteca. Alm destas trs funes necessrio ter
uma funo de delay, que garanta um determinado tempo para que as informaes sejam lidas
corretamente pelo LCD.
O header desta biblioteca e um exemplo de como us-la so apresentados nos programas 4.7
e 4.9, respectivamente.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
71 Programao dos Perifricos
Figura 4.15: Esquemtico de ligao do display de LCD
Programa 4.7: lcd.h
1 #i f ndef LCD_H
2 #define LCD_H
3 void EnviaComando ( char cmd ) ;
4 void EnviaDados ( char valor ) ;
5 void InicializaLCD ( void) ;
6 #endif //LCD_H
Notas de Aula ELT024 - Programao para Sistemas Embarcados
72 Programao dos Perifricos
Programa 4.8: lcd.c
1 #include "lcd.h"
2 #include "basico.h"
3 #define RS 0
4 #define EN 1
5 #define RW 2
7 void InicializaLCD ( void)
8 {
9 // I n i c i a l i z a o LCD
10 Delay2ms ( ) ;
11 Delay2ms ( ) ;
12 Delay2ms ( ) ;
13 Delay2ms ( ) ;
14 Delay2ms ( ) ;
15 // c onf i g . de di r eo (E/S)
16 BitClr ( TRISE , RS ) ; //RS
17 BitClr ( TRISE , EN ) ; //EN
18 BitClr ( TRISE , RW ) ; //RW
19 TRISD = 0x00 ; //dados
20 ADCON1 = 0b00001110 ;
21 // conf i gur a o di s pl ay
22 //8 b i t s , 2 l i nhas , 5x8
23 EnviaComando (0 x38 ) ;
24 //modo i ncrement al
25 EnviaComando (0 x06 ) ;
26 // di s pl ay , cursor e b l i nk i ng on
27 EnviaComando (0 x0F ) ;
28 // zera cont adores i nt er nos
29 EnviaComando (0 x03 ) ;
30 // l i mpar di s pl ay
31 EnviaComando (0 x01 ) ;
32 // posi o i n i c i a l
33 EnviaComando (0 x80 ) ;
34 }
36 void Delay40us ( void) {
37 unsigned char i ;
38 for ( i=0; i < 25; i++) ;
39 }
41 void Delay2ms ( void) {
42 unsigned char i ;
43 for ( i=0; i < 200; i++){
44 Delay40us ( ) ;
45 }
46 }
47 void EnviaDados ( char valor )
48 {
49 //dados
50 BitSet ( PORTE , RS ) ;
51 // h a b i l i t a e s c r i t a
52 BitClr ( PORTE , RW ) ;
53 PORTD = valor ;
54 // h a b i l i t a l e i t u r a
55 BitSet ( PORTE , EN ) ;
56 Delay40us ( ) ;
57 // termi na l e i t u r a
58 BitClr ( PORTE , EN ) ;
59 // dei xa em n v e l bai xo
60 BitClr ( PORTE , RS ) ;
61 // dei xa em n v e l bai xo
62 BitClr ( PORTE , RW ) ;
63 Delay40us ( ) ;
64 }
66 void EnviaComando ( char cmd )
67 {
68 //comando
69 BitClr ( PORTE , RS ) ;
70 // h a b i l i t a e s c r i t a
71 BitClr ( PORTE , RW ) ;
72 PORTD = cmd ;
73 // h a b i l i t a l e i t u r a
74 BitSet ( PORTE , EN ) ;
75 Delay2ms ( ) ;
76 // termi na l e i t u r a
77 BitClr ( PORTE , EN ) ;
78 // dei xa em n v e l bai xo
79 BitClr ( PORTE , RS ) ;
80 // dei xa em n v e l bai xo
81 BitClr ( PORTE , RW ) ;
82 Delay2ms ( ) ;
83 }
Notas de Aula ELT024 - Programao para Sistemas Embarcados
73 Programao dos Perifricos
Programa 4.9: Exemplo de uso da biblioteca de LCD
1 #include "basico.h"
2 #include "config.h"
3 #include "lcd.h"
5 // i ni c i o do programa
6 void main ( void) interrupt 0
7 {
8 unsigned i nt i , j ;
9 char msg [ ] = "Hello World!" ;
10 InicializaLCD ( ) ;
11 for ( i=0; i<11; i++)
12 {
13 EnviaDados ( msg [ i ] ) ;
14 for ( j = 0; j < 65000; j++) ;
15 }
16 for ( ; ; ) ;
17 }
Notas de Aula ELT024 - Programao para Sistemas Embarcados
74 Programao dos Perifricos
q. Comunicao serial
Em geral a comunicao entre dois dispositivos eletrnicos realizada de modo serial, isto , as
informaes so passadas bit bit do transmissor para o receptor. Este tipo de comunicao
possui algumas vantagens em relao comunicao paralela, na qual a palavra (byte) enviada
toda de uma vez.
A primeira vantagem a simplicao do hardware. Como os dados so enviados um a um,
necessrio apenas um o de comunicao e um para retorno.
A segunda a maior taxa de transmisso, o que a primeira vista inconsistente j que num
mesmo ciclo de clock a comunicao paralela envia mais de um bit, enquanto a serial apenas um.
Este fato acontece pois para frequncias muito altas pode existir atraso entre um o e outro se os
cabos da comunicao paralela possurem qualquer diferena. Alm disso existe o problema do
crosstalking, onde o campo magntico gerado por um cabo induz uma pequena tenso no outro
cabo, atrapalhando a comunicao. Estes problemas aumentam com a frequncia limitando
assim a mxima transferncia possvel pelo barramento paralelo. este o motivo que levou os
projetistas de hardware a desenvolverem o protocolo SATA, em detrimento ao IDE/ATA, para
comunicao entre o HD e a placa me conforme pode ser visto na Tabela 4.5.
Tabela 4.5: Taxas de transmisso para diferentes protocolos
Protocolo Taxa (Mbit/s) Taxa (Mb/s)
ATA 33 (Ultra DMA) 264 33
ATA 66 (Ultra DMA) 528 66
ATA 100 (Ultra DMA) 800 100
ATA 133 (Ultra DMA) 1064 133
Serial ATA (SATA-150) 1200 150
Serial ATA 2 (SATA-300) 2400 300
Serial ATA 3 (SATA-600) 4800 600
RS 232
O protocolo de comunicao RS232 (Recommended Standard 232) um protocolo muito uti-
lizado para comunicao entre dispositivos que transmitem ou recebem pouca quantidade de
informaes. um dos protocolos mais antigos sendo utilizado pela primeira vez em 1962 para
mquinas de escrever eletromecnicas. O padro RS232 reviso C datado de 1969. Em 1986
aparece a reviso D pela EIA (Electronic Industries Alliance). A verso atual do protocolo
datada de 1997 pela TIA (Telecommunications Industry Association) sendo chamada TIA-232-F.
O procedimento de envio de um valor pela serial atravs do padro RS232 pode ser visto
como uma operao de bit-shift.
Por exemplo a letra K: em ASCII codicada como 76
10
e em binrio como 11010010
2
. Na
maioria dos dispositivos primeiro se envia o bit menos signicativo. Antes de iniciar a transmisso
dos bits, enviado um bit de comeo, indicando que haver transmisso a partir daquele instante.
Aps isso o bit menos signicativo enviado para a sada do microcontrolador. Realiza-se ento
um shift para direita e o novo bit menos signicativo reenviado. Esta operao realizada
oito vezes. Aps esse procedimento envia-se um bit de parada, que pode ter a durao de um ou
dois bits.
A Figura 4.16 apresenta o sinal eltrico
7
enviado ao longo do tempo para a letra K. Notar a
regio em branco, que se extende entre +3 e -3. Ela indica a regio de tenso na qual o sinal no
7
Para o protocolo RS232 o nvel alto ou 1 (um) aquele com tenses positivas entre +3 e +15. O nvel logico
baixo ou 0 (zero) interpretado entre -3 e -15 volts.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
75 Programao dos Perifricos
est denido. Caso a tenso lida esteja nestes limiares, seja devido ruidos ou outros problemas,
o sistema de recepo no entender a mensagem e os dados podem ser corrompidos.
Figura 4.16: Sinal serializado para transmisso em RS232
Para o correto funcionamento do protocolo devemos garantir compatibilidade no nvel fsico
(do hardware) e lgico (no software).
Para o hardware basta compatibilizar o tipo de conector, os nveis de tenso e a pinagem dos
conectores.
Para o nvel de software temos que denir a codicao utilizada (ASCII, UTF-8, etc),
especicar o uxo de caracteres (quantidade de bits por caractere, tamanho do start/stop bit,
paridade) e a taxa de transmisso desejada.
Estas conguraes so realizadas atravs de 5 registros TXSTA, RCSTA, BAUDCON, SP-
BRGH e SPBRG.
Os registros TXSTA e RCSTA so responsveis por congurar o meio de transmisso: pre-
sena/ausncia de bit de parada, tamanho da palavra de um caractere, transmisso sncrona/as-
sncrona.
O registro BAUDCON responsvel por congurar o controle de velocidade de transmisso.
Os registros SPBRGH e SPBRG representam o byte mais alto e o mais baixo da palavra de
16 bits que indica a taxa de transmisso.
A taxa de transmisso pode ser calculada segundo a Tabela 4.6.
Como visto na Tabela 4.6 existem trs formulas diferentes para calcular a taxa de transmisso.
A melhor maneira de congurar a taxa de transmisso da porta serial vericar qual dos mtodos
gera o menor erro para uma dada taxa de transmisso.
Por exemplo, queremos uma taxa de transmisso de 57,6 kbps. A frequncia disponvel um
cristal de 8MHz. Usando as trs formulas chegamos aos seguintes valores:
n1 = 1; F
232
= 62.500, err = -7,64%
n2 = 8, F
232
= 55.555, err = 3,63%
n3 = 32, F
232
= 57.142, err = 0,79%
A equao que gera o menor erro a terceira. Como queremos trabalhar com uma comuni-
cao assncrona, da Tabela 4.6 obtemos que os bits de congurao devem ser: TXSTA(4) = 0,
Notas de Aula ELT024 - Programao para Sistemas Embarcados
76 Programao dos Perifricos
Tabela 4.6: Clculo do valor da taxa de transmisso da porta serial
Bits de Congurao Preciso Taxa de transmisso
TXSTA:4 BAUDCON:3 TXSTA:2
0 0 0 8bits F
232
=
F
OSC
[64 (n + 1)]
0 0 1 8bits
F
232
=
F
OSC
[16 (n + 1)]
0 1 0 16bits
0 1 1 16bits
F
232
=
F
OSC
[4 (n + 1)]
1 0 x 8bits
1 1 x 16bits
x no importa, n valor do par SPBRGH:SPBRG
BAUDCON(3) = 1 e TXSTA(2) = 1. A seguir temos todo o processo de congurao da porta
serial RS232.
BitClr ( BAUDCON , 0 ) ; // De s a b i l i t a aut o det eco de v e l oc i dade
BitSet ( BAUDCON , 3 ) ; // Regi s t r o de gerao de s i na l com 16 b i t s
BitClr ( BAUDCON , 6 ) ; //Operao de recepo e s t a at i v a
BitClr ( RCSTA , 1 ) ; // De s a b i l i t a b i t de erro de overrun
BitClr ( RCSTA , 2 ) ; // De s a b i l i t a b i t erro na comunicao
BitClr ( RCSTA , 4 ) ; // Hab i l i t a b i t de recepo
BitClr ( RCSTA , 6 ) ; // Sel eci ona 8 b i t s
BitSet ( RCSTA , 7 ) ; // Conf i gura RX/TX como pi nos de comunicao
BitSet ( TXSTA , 2 ) ; //Modo de a l t a v e l oc i dade h a b i l i t a d o
BitSet ( TXSTA , 3 ) ; //Envia b i t de parada ( break char act er b i t )
BitClr ( TXSTA , 4 ) ; //Modo ass ncrono
BitSet ( TXSTA , 5 ) ; // Hab i l i t a t ransmi sso
BitClr ( TXSTA , 6 ) ; // Sel eci ona 8 b i t s
SPBRGH = 0x00 ; // Conf i gura para 56k (SPBRGH|SPBRG = 32)
SPBRG = 0x22 ; // Conf i gura para 56k (SPBRGH|SPBRG = 32)
BitSet ( TRISC , 6 ) ; // Conf i gura pi no de recepo como ent rada
BitClr ( TRISC , 7 ) ; // Conf i gura pi no de envi o como s a da
O procedimento de serializao dos bits feito de maneira automtica pelo hardware. En-
quanto ele est realizando este processo no devemos mexer no registro que armazena o byte a
ser enviado. Por isso devemos vericar se o registro est disponvel. Isto feito atravs do bit 4
do registro PIR. Quando este valor estiver em 1 basta escrever o valor que desejamos transmitir
no registro TXREG.
void EnviaSerial ( unsigned char c)
{
while ( ! BitTst ( PIR1 , 4 ) ) ; //aguarda o r e g i s t r o f i c a r d i s p o n v e l
TXREG=c ; // col oca o v al or para s er envi ado
}
O processo de desserializao tambm realizado de modo automtico pelo hardware do
dispositivo. Assim que um byte estiver disponvel o sistema seta o bit 5 do registro PIR1 e
podemos ento ler o valor disponvel no registro RCREG.
unsigned char RecebeSerial ( void)
{
char resp = 0;
i f ( BitTst ( PIR1 , 5 ) ) // Ve r i f i c a se e x i s t e algum v al or d i s p o n v e l
{
Notas de Aula ELT024 - Programao para Sistemas Embarcados
77 Programao dos Perifricos
Programa 4.10: serial.c
1 #include "serial.h"
2 #include "basico.h"
4 void EnviaSerial ( unsigned char c)
5 {
6 while ( ! BitTst ( PIR1 , 4 ) ) ; //aguarda o r e g i s t r o f i c a r d i s p o n v e l
7 TXREG=c ; // col oca o v al or para s er envi ado
8 }
10 unsigned char RecebeSerial ( void)
11 {
12 char resp = 0;
13 i f ( BitTst ( PIR1 , 5 ) ) // Ve r i f i c a se e x i s t e algum v al or d i s p o ni v e l
14 {
15 resp = RCREG ; // ret orna o v al or
16 }
17 return resp ; // ret orna zero
18 }
20 void InicializaSerial ( void)
21 {
22 TXSTA = 0b00101100 ; // conf i gur a a t ransmi sso de dados da s e r i a l
23 RCSTA = 0b10010000 ; // conf i gur a a recepo de dados da s e r i a l
24 BAUDCON = 0b00001000 ; // conf i gur a si st ema de v e l oc i dade da s e r i a l
25 SPBRGH = 0b00000000 ; // conf i gur a para 56k
26 SPBRG = 0b00100010 ; // conf i gur a para 56k
27 BitSet ( TRISC , 6 ) ; // pi no de recepo de dados
28 BitClr ( TRISC , 7 ) ; // pi no de envi o de dados
29 }
resp = RCREG ; // ret orna o v al or
}
return resp ; // ret orna zero
}
A metodologia apresentada para leitura e escrita de valores conhecida como pooling. Neste
tipo de abordagem camos parados esperando que o valor esteja disponvel para leitura/escrita.
Este o mtodo mais simples para se controlar qualquer tipo de dispositivo. O problema que
o processador ca travado em uma tarefa gastando tempo que seria til para realizar outras
operaes. A melhor alternativa para resolver este problema atravs de interrupes, que sero
abordadas apenas no tpico .1:.
Criao da biblioteca
O programa 4.10 apresenta um exemplo de cdigo para criar uma biblioteca para comunicao
serial. O arquivo de header apresentado no progrma 4.11 e o exemplo de uso demonstrado no
programa 4.12.
A seguir o arquivo de header.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
78 Programao dos Perifricos
Programa 4.11: serial.h
1 #i f ndef SERIAL_H
2 #define SERIAL_H
3 void EnviaSerial ( unsigned char c) ;
4 unsigned char RecebeSerial ( void) ;
5 void InicializaSerial ( void) ;
6 #endif //SERIAL_H
Programa 4.12: Exemplo de uso da biblioteca de comunicao serial
1 #include "basico.h"
2 #include "config.h"
3 #include "serial.h"
5 // i ni c i o do programa
6 void main ( void) interrupt 0
7 {
8 unsigned i nt i , j ;
9 char msg [ ] = "Hello World!" ;
10 unsigned char resp ;
11 TRISD = 0x00 ; // acesso aos l e d s
12 InicializaSerial ( ) ;
13 j=0;
14 for ( ; ; )
15 {
16 // del ay
17 for ( i = 0; i < 65000; i++) ;
18 // envi a dados
19 EnviaSerial ( msg [ j ] ) ;
20 j++;
21 i f ( j > 11)
22 {
23 j=0;
24 EnviaSerial ( 13) ;
25 }
26 // recebe dados
27 resp = RecebeSerial ( ) ;
28 i f ( resp ! =0)
29 {
30 PORTD = resp ;
31 }
32 }
33 }
Notas de Aula ELT024 - Programao para Sistemas Embarcados
79 Programao dos Perifricos
q.S Conversor AD
Um conversor de analgico para digital um circuito capaz de transformar um valor de tenso
numa informao binria. O circuito que utilizaremos possui uma preciso de 10 bits, ou seja,
ele capaz de sentir uma variao de praticamente um milsimo
8
da excurso mxima do sinal.
Para a congurao que iremos utilizar, com uma fonte de 5v, isto signica uma sensibilidade
de 4.88mV.
Elementos sensores
A converso AD muito utilizada para realizarmos a leitura de sensores. Todo sensor baseado
num transdutor. Um elemento transdutor aquele que consegue transformar um tipo de grandeza
em outro, por exemplo uma lmpada incandescente (Figura 4.17).
Figura 4.17: Lmpada incandescente
Podemos utilizar uma lampada incandescente como sensor de tenso: pega-se uma lmpada
de 220V. Liga-se a lmpada uma tomada desconhecida. Se o brilho for forte a tomada possui
220V, se o brilho for de baixa intensidade, a tomada possui 127V. Se a lmpada no ascender
existe algum problema na ao, na tomada ou at mesmo na lmpada. A lampada um
transdutor de tenso para luminosidade.
Para a eletrnica estamos interessados em transdutores cuja sada seja uma variao de
tenso, corrente ou resistncia.
Um sistema muito simples de transdutor de ngulo para resistncia o potencimetro (Fi-
gura 4.18).
Se o potencimetro estiver alimentado pelos terminais da extremidade, o terminal central fun-
ciona como um divisor de tenso. O valor de sada proporcional posio do cursor. Podemos
aproximar o potencimetro como duas resistncias conforme apresentado na Figura 4.19.
Deste modo a tenso aplicada em RL (supondo que RL muito maior que R2) :
V
RL
=
V
S
R
2
R
1
+R
2
= V
S
(
R
2
R
Pot
)
Se na construo do potencimetro a variao da resistncia ao longo da trilha foi feita de modo
constante, a resistncia varia de maneira linear com a posio do cursor. Deste modo podemos
utilizar o potencimetro como um transdutor de ngulo.
Diversas medidas podem ser realizadas utilizando o conceito de divisor de tenso: luminosi-
dade com LDR's, fora com strain-gages, deslocamento com potencimetros lineares, etc.
Existem alguns sensores que possuem circuitos de amplicao e condicionamento do sinal
embutidos no mesmo envlucro que o elemento sensor. A estes tipos de sensores damos a deno-
minao de ativos.
8
Com uma preciso de 10 bits conseguimos representar 2