Você está na página 1de 116

Notas de Aula Programao Embarcada - ELT024

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
29 de Agosto de 2012
1
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
1. Indentao e padro de escrita . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1. Comentrios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.6 Arquivos .c e .h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1. Diretivas de compilao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
#include . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
#dene . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
#ifdef, #ifndef, #else e #endif . . . . . . . . . . . . . . . . . . . . . . . . 12
1.8 Tipos de dados em C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Representao binria e hexadecimal . . . . . . . . . . . . . . . . . . . . . 14
Modicadores de tamanho e sinal . . . . . . . . . . . . . . . . . . . . . . . 15
Modicadores de acesso . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
Modicadores de posicionamento . . . . . . . . . . . . . . . . . . . . . . . 17
Modicador de persistncia . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.j Operaes aritmticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
1.1o Funo main() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
1.11 Rotinas de tempo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.1: Operaes com bits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
NOT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
AND . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
OR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
XOR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Shift . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Ligar um bit (bit set) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Desligar um bit (bit clear) . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Trocar o valor de um bit (bit ip) . . . . . . . . . . . . . . . . . . . . . . 26
Vericar o estado de um bit (bit test) . . . . . . . . . . . . . . . . . . . . 27
Criando funes atravs de denes . . . . . . . . . . . . . . . . . . . . . 28
1.1 Debug de sistemas embarcados . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
Externalizar as informaes . . . . . . . . . . . . . . . . . . . . . . . . . . 32
Programao incremental . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Checar possveis pontos de Memory-leak . . . . . . . . . . . . . . . . . . . 33
Cuidado com a fragmentao da memria . . . . . . . . . . . . . . . . . . 33
Otimizao de cdigo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Reproduzir e isolar o erro . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
1.1 Ponteiros e endereos de memria . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
i
2 Arquitetura de microcontroladores 36
:.1 Acesso memria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
:.: Clock e tempo de instruo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
:. Esquema eltrico e circuitos importantes . . . . . . . . . . . . . . . . . . . . . . . 41
Multiplexao nos terminais do microcontrolador . . . . . . . . . . . . . . 42
:. Registros de congurao do microcontrolador . . . . . . . . . . . . . . . . . . . . 43
3 Programao dos Perifricos 45
.1 Acesso s portasdo microcontrolador . . . . . . . . . . . . . . . . . . . . . . . . 46
.: Congurao dos perifricos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
. Barramento de Led's . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
. Display de 7 segmentos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
Multiplexao de displays . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
Criao da biblioteca . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
. Leitura de teclas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
Debounce por software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
Arranjo de leitura por matriz . . . . . . . . . . . . . . . . . . . . . . . . . 60
Criao da biblioteca . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
.6 Display LCD 2x16 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
Criao da biblioteca . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
. Comunicao serial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
RS 232 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
Criao da biblioteca . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
.8 Conversor AD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
Elementos sensores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
Processo de converso AD . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
Criao da biblioteca . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
.j Sadas PWM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
Criao da biblioteca . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
.1o Timer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
.11 Reproduo de Sons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
.1: Interrupo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
.1 Watchdog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
4 Arquitetura de desenvolvimento de software 95
.1 One single loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
.: Interrupt control system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
. Cooperative multitasking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
Fixao de tempo para execuo dos slots . . . . . . . . . . . . . . . . . . 102
Utilizao do tempo livre para interrupes . . . . . . . . . . . . . . . . . 103
5 Anexos 105
.1 cong.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
.: basico.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
. Instalar gravadores/depuradores de PIC em sistemas x64 . . . . . . . . . . . . . . 108
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 . . . . . . . . . . . . . . . . . . . . . 4
1.4 Instalao do ICD2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.5 Resumo das conguraes do ICD2 no MPLAB . . . . . . . . . . . . . . . . . . . 6
1.6 Pedido de atualizao do rmware do ICD2 . . . . . . . . . . . . . . . . . . . . . 6
1.7 Project Explorer do MPLAB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.8 Problema das Referncias Circulares . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.9 Soluo das referncias circulares com #ifndef . . . . . . . . . . . . . . . . . . . . 14
1.10 Loop innito de um device driver gerando erro no sistema . . . . . . . . . . . . . 20
1.11 Exemplo de funcionamento do vetor de interrupo . . . . . . . . . . . . . . . . . 20
2.1 Arquitetura do microcontrolador PIC 18F4550 . . . . . . . . . . . . . . . . . . . 37
2.2 Memria como um armrio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
2.3 Memria e perifricos como um armrio . . . . . . . . . . . . . . . . . . . . . . . 39
2.4 Regies de memrias disponveis no PIC18F4550 . . . . . . . . . . . . . . . . . . 39
2.5 Esquema eltrico: Microcontrolador PIC 18F4550 . . . . . . . . . . . . . . . . . . 41
2.6 Registros de congurao do microcontrolador PIC 18F4550 . . . . . . . . . . . . 43
3.1 Registros de congurao dos perifricos do PIC 18F4550 . . . . . . . . . . . . . 48
3.2 Barramento de Led's . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
3.3 Display de 7 Segmentos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
3.4 Diagrama eltrico para display de 7 segmentos com nodo comum . . . . . . . . . 52
3.5 Ligao de 4 displays de 7 segmentos multiplexados . . . . . . . . . . . . . . . . . 53
3.6 Circuito de leitura de chave . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
3.7 Oscilao do sinal no momento do chaveamento . . . . . . . . . . . . . . . . . . . 58
3.8 Circuito de debounce . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
3.9 Utilizao de ltro RC para debounce do sinal . . . . . . . . . . . . . . . . . . . . 59
3.10 Teclado em arranjo matricial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
3.11 Display Alfanumrico LCD 2x16 . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
3.12 Display Alfanumrico LCD 2x16 - verso . . . . . . . . . . . . . . . . . . . . . . . 65
3.13 Caracteres disponveis para ROM A00 . . . . . . . . . . . . . . . . . . . . . . . . 66
3.14 Caracteres disponveis para ROM A02 . . . . . . . . . . . . . . . . . . . . . . . . 67
3.15 Esquemtico de ligao do display de LCD . . . . . . . . . . . . . . . . . . . . . . 69
3.16 Sinal serializado para transmisso em RS232 . . . . . . . . . . . . . . . . . . . . . 73
3.17 Lmpada incandescente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
3.18 Potencimetro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
3.19 Potencimetro como divisor de tenso . . . . . . . . . . . . . . . . . . . . . . . . 78
3.20 Circuito integrado LM35 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
3.21 Diagrama de blocos do LM35 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
3.22 Conversor analgico digital de 2 bits . . . . . . . . . . . . . . . . . . . . . . . . . 80
3.23 Sinais PWM com variao do duty cycle . . . . . . . . . . . . . . . . . . . . . . . 83
4.1 Exemplo de mquina de estados . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
iii
4.2 Exemplo da mudana de slots no tempo . . . . . . . . . . . . . . . . . . . . . . . 103
4.3 Linha de tempo de um sistema com 1 slot . . . . . . . . . . . . . . . . . . . . . . 103
4.4 Comportamento da linha de tempo com interrupes . . . . . . . . . . . . . . . . 103
iv
Lista de Tabelas
1.1 Softwares utilizados no curso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2 Ferramentas utilizadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.3 Tipos de dados e faixa de valores . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.4 Representao decimal - binria - hexadecimal . . . . . . . . . . . . . . . . . . . . 15
1.5 Alterao de tamanho e sinal dos tipos bsicos . . . . . . . . . . . . . . . . . . . 16
1.6 Operao bit set com dene . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
1.7 Operao bit clear com dene . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
1.8 Operao bit ip com dene . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
1.9 Operao bit test com dene . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
2.1 Quantidade de operaes e tarefas . . . . . . . . . . . . . . . . . . . . . . . . . . 40
3.1 Endereos de memria para as portas do PIC 18F4550 . . . . . . . . . . . . . . . 46
3.2 Tabela de congurao do PIC para as experincias . . . . . . . . . . . . . . . . . 49
3.3 Converso binrio - hexadecimal para displays de 7 segmentos . . . . . . . . . . . 53
3.4 Lista de comandos aceitos pelo o LCD . . . . . . . . . . . . . . . . . . . . . . . . 68
3.5 Taxas de transmisso para diferentes protocolos . . . . . . . . . . . . . . . . . . . 72
3.6 Clculo do valor da taxa de transmisso da porta serial . . . . . . . . . . . . . . . 74
3.7 Faixa de frequncias mximas e mnimas para cada congurao do prescaler . . 84
v
Lista de Programas
1.1 Resumo do disp7seg.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.2 Resumo do disp7seg.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.3 Estrutura de header . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.4 Operaes aritmticas com tipos diferentes . . . . . . . . . . . . . . . . . . . . . . 18
3.1 disp7seg.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
3.2 disp7seg.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
3.3 Utilizando a biblioteca disp7seg . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
3.4 teclado.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
3.5 teclado.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
3.6 Exemplo de uso da biblioteca teclado . . . . . . . . . . . . . . . . . . . . . . . . . 63
3.7 lcd.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
3.8 lcd.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
3.9 Exemplo de uso da biblioteca de LCD . . . . . . . . . . . . . . . . . . . . . . . . 71
3.10 serial.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
3.11 serial.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
3.12 Exemplo de uso da biblioteca de comunicao serial . . . . . . . . . . . . . . . . . 76
3.13 adc.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
3.14 adc.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
3.15 Exemplo de uso da biblioteca de conversores AD . . . . . . . . . . . . . . . . . . 82
3.16 pwm.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
3.17 pwm.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
3.18 Exemplo de uso da biblioteca das sadas PWM . . . . . . . . . . . . . . . . . . . 86
3.19 timer.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
3.20 timer.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
3.21 Exemplo de uso da biblioteca de um temporizador . . . . . . . . . . . . . . . . . 88
3.22 Reproduo de sons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
3.23 Fontes de Interrupo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
3.24 Tratamento das interrupes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
3.25 Inicializao do sistema com interrupes . . . . . . . . . . . . . . . . . . . . . . 93
3.26 Inicializao do sistema com interrupes . . . . . . . . . . . . . . . . . . . . . . 94
4.1 Exemplo de arquitetura single-loop . . . . . . . . . . . . . . . . . . . . . . . . . . 96
4.2 Problema na sincronia de tempo para o single-loop . . . . . . . . . . . . . . . . . 96
4.3 Exemplo de sistema Interrupt-driven . . . . . . . . . . . . . . . . . . . . . . . . . 97
4.4 Exemplo de sistema Interrupt-driven com base de tempo . . . . . . . . . . . . . . 98
4.5 Exemplo de cooperative multitasking . . . . . . . . . . . . . . . . . . . . . . . . . 100
4.6 Exemplo de cooperative multitasking com uso do top slot . . . . . . . . . . . . . 101
4.7 Exemplo de sistema Cooperative-multitasking com slot temporizado . . . . . . . 102
5.1 cong.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
5.2 basico.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
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 pro-
gramam 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
Figura 1.3: Congurao das ferramentas de compilao
Em seguida abra o programa MPLAB e v ao menu Projects -> Set Language Tool Locati-
ons. 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 obtida no diretrio bin dentro de onde foi instalado
o GPUtils, por padro: C:\Arquivos de programas\gputils\bin. Para as opes sdcc16 e sdcc
link deve-se escolher o arquivo sdcc.exe, que encontrado no diretrio bin dentro do diretrio
onde foi instalado o SDCC por padro: C:\Arquivos de programas\SDCC\bin\. Clicar em
OK. A Tabela 1.2 apresenta um resumo destas opes.
Tabela 1.2: Ferramentas utilizadas
Executables Nome do arquivo Localizao
gpasm gpasm.exe C:\Arquivos de programas\gputils\bin\
sdcc link sdcc.exe C:\Arquivos de programas\SDCC\bin\
sdcc16 sdcc.exe C:\Arquivos de programas\SDCC\bin\
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
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.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
5 Introduo
Figura 1.4: Instalao do ICD2
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.
A cada novo arquivo criado necessrio inseri-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.
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
Notas de Aula ELT024 - Programao para Sistemas Embarcados
6 Introduo
Figura 1.5: Resumo das conguraes do ICD2 no MPLAB
Figura 1.6: Pedido de atualizao do rmware do ICD2
Notas de Aula ELT024 - Programao para Sistemas Embarcados
7 Introduo
Figura 1.7: Project Explorer do MPLAB
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.
i.q 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 a 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.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
8 Introduo
Cdigo indentado Cdigo no indentado
1 void main ( void)
{
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)
{
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
9 Introduo
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.
i. 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;
}
i.6 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 1.1 apresenta um exemplo de um arquivo de cdigo .c e o programa 1.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 a um efeito conhecido como overhead de funes, podendo inclusive causar travamentos
no sistema caso no exista espao suciente no stack.
i. 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
10 Introduo
Programa 1.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 1.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
11 Introduo
#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
12 Introduo
#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 arquivo 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
13 Introduo
Programa 1.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 1.8.
#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 1.8: 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 1.3.
Segundo o cdigo acima, o contedo que estiver entre o #ifndef e o #endif, s ser mantido
se 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 1.9.
Geralmente se utiliza como tag de controle o nome do arquivo. Esta tag deve ser nica para
cada arquivo.
i.S 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
14 Introduo
#infdef TEMP_H
#define TEMP_H
#include serial.h
char LerTemperatura(void)
void !"usta#alor(char val)
#endif
temp.h
#infdef $E%&!L_H
#define $E%&!L_H
#include temp.h
char Ler$erial(void)
void Envia$erial(char val)
#endif
serial.h
#infdef TEMP_H
''ta( ") definida*
''pula o conte+do
#endif
temp.h
Figura 1.9: Soluo das referncias circulares com #ifndef
C so apresentados na Tabela 1.3.
Tabela 1.3: 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
15 Introduo
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 1.4.
Tabela 1.4: 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
16 Introduo
negativos, em compensao podem atingir o dobro do valor de um tipo signed. Na Tabela 1.5
so apresentadas algumas variaes possveis.
Tabela 1.5: 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)
{
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 a 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)
{
while ( X!=X) ;
}
Gerando o cdigo em assembler descrito abaixo:
Notas de Aula ELT024 - Programao para Sistemas Embarcados
17 Introduo
// 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)
{
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
18 Introduo
Programa 1.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;
}
i.q 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 1.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
19 Introduo
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 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 1.10 apresentado um erro gerado atravs de um loop innito.
i.io 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
20 Introduo
Figura 1.10: 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 1.11).
0x58 Testa A
0x57 30
0x56 A recebe
0x55 Limpa A
0x59 ...
0x8D Porta B
0x8C Salva em
0x8B 50
0x8A A recebe
0x8 ...
0x03 0x55
0x0! P"lo
0x0# 0x8A
0x0$ ...
0x00 P"lo
Endereo Instruo
Figura 1.11: 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
21 Introduo
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.
void main ( void)
{
// 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)
{
for ( ; ; )
{
// aqui ent ra o
// cdi go p r i nc i p a l
}
}
void main ( void)
{
while ( 1)
{
// aqui ent ra o
// cdi go p r i nc i p a l
}
}
i.ii 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 vrgula. 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_ :
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 )
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
22 Introduo
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
}
}
}
}
i.iz 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
Nos sistemas microcontrolados, existem algumas variveis onde cada bit tem uma interpretao
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
23 Introduo
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 1 (um) se o valor for 0 (zero) e 0 se o valor for 1.
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
24 Introduo
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
25 Introduo
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)
{
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
26 Introduo
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 a 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)
{
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
27 Introduo
// 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)
{
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)
{
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
28 Introduo
}
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 1.6, 1.7, 1.8 e
1.9.
Tabela 1.6: 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
29 Introduo
Tabela 1.7: 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
30 Introduo
Tabela 1.8: 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
31 Introduo
Tabela 1.9: 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
32 Introduo
i.ij 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 a 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)
{
// 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
33 Introduo
}
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
34 Introduo
i.iq 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 apoat 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 tentarmos 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
35 Introduo
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 2
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 2.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.
36
37 Arquitetura de microcontroladores
Figura 2.1: Arquitetura do microcontrolador PIC 18F4550
Notas de Aula ELT024 - Programao para Sistemas Embarcados
38 Arquitetura de microcontroladores
z.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 2.2).
Suporte
nmero:
Existe
gaveta?
1
sim
2
sim
3
no
4
no
5
sim
6
no
Figura 2.2: Memria como um armrio
Ao invs de gavetas o marceneiro pode pensar em colocar outros sistemas de armazenamento
nos espaos (Figura 2.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 a 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 a
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 2.4).
Notas de Aula ELT024 - Programao para Sistemas Embarcados
39 Arquitetura de microcontroladores
Suporte
nmero:
Existe
gaveta?
1
Vitrine
2
Gaveta
3
Dispenser
4
No
5
Gaveta
6
Cofre
Figura 2.3: Memria e perifricos como um armrio
Stack 1
Stack 31
Reset
Baixa prioridade
Alta prioridade
Memria EEPROM
No implementado
...
GPR1
GPR3
GPR
GPR!
No implementado
S"R
#x####
#x###$
#x##1$
#x##!$
#x%"""
#&$###
#&1"""""
#x###
#x#""
#x!##
#x!""
#x3##
#x3""
#x1##
#x1""
...
#x"'#
#x"""
(
e
t
o
r

d
e
)
n
t
e
r
r
*
p
+

o
Figura 2.4: Regies de memrias disponveis no PIC18F4550
Notas de Aula ELT024 - Programao para Sistemas Embarcados
40 Arquitetura de microcontroladores
z.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 2.1.
Tabela 2.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
41 Arquitetura de microcontroladores
z.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 2.5.
Figura 2.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 a 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
42 Arquitetura de microcontroladores
Multiplexao nos terminais do microcontrolador
Conforme pode ser observado na Figura 2.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
43 Arquitetura de microcontroladores
z.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 2.6.
Figura 2.6: Registros de congurao do microcontrolador PIC 18F4550
Dos registros apresentados na Figura 2.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 ltima 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
44 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 3
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
45
46 Programao dos Perifricos
j.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 essa congurao indicando quais bits sero utilizados para entrada e
quais sero utilizados para sada (Tabela 3.1).
Tabela 3.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)
{
// 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
47 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 explcito, 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)
{
// 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 a necessidade de utilizar um asterisco extra em todas as chamadas
da "varivel", 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
48 Programao dos Perifricos
j.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 3.1 apresenta todos os registros disponveis do microcontrolador 18F4550.
Figura 3.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 3.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 experincias da apostila.
Os terminais no citados na Tabela 3.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 3.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
49 Programao dos Perifricos
Tabela 3.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
50 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
51 Programao dos Perifricos
j.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 3.2.
Figura 3.2: Barramento de Led's
Podemos notar pela Figura 3.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)
{
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
52 Programao dos Perifricos
j.q Display de 7 segmentos
Os displays de 7 segmentos (Figura 3.3) so componentes opto eletrnicos utilizados para apre-
sentar informaes para o usurio em formato numrico.
Figura 3.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 ctodo comum, ou nodo comum indicando qual o tipo de
ligao dos leds. Contudo, esta diferena no ser crtica para este estudo. Na Figura 3.4
podemos visualizar o esquema eltrico e a disposio fsica de cada led no componente.
Figura 3.4: Diagrama eltrico para display de 7 segmentos com nodo comum
http://www.hobbyprojects.com/the_diode/seven_segment_display.html
Pela Figura 3.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 ctodo 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 3.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 escolhidas por serem as
mais utilizadas 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
53 Programao dos Perifricos
Tabela 3.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 3.3. A utilizao de uma ou outra depende da ligao feita
na placa. A Figura 3.5 apresenta o esquema eltrico disponvel.
Figura 3.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)
{
Notas de Aula ELT024 - Programao para Sistemas Embarcados
54 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 3.5 apresenta o circuito com 4 displays multiplexados. Percebemos que os terminais
iguais esto ligados juntos. Percebemos tambm que os terminais de ctodo comum esto cada
um ligado a 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
ctodo comum ao terra, ou o nodo 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
55 Programao dos Perifricos
Criao da biblioteca
O programa 3.1 apresenta um exemplo de cdigo para criar uma biblioteca para os displays de 7
segmentos. O programa 3.2 apresenta o header da biblioteca. J o programa 3.3 apresenta uma
demonstrao de uso da biblioteca.
Programa 3.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
56 Programao dos Perifricos
Programa 3.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 3.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)
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
57 Programao dos Perifricos
j. 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 3.6: Circuito de leitura de chave
http://www.labbookpages.co.uk/electronics/debounce.html - Dr. Andrew Greensted
Pela Figura 3.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 3.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 3.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 3.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 3.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
58 Programao dos Perifricos
Figura 3.7: Oscilao do sinal no momento do chaveamento
http://www.labbookpages.co.uk/electronics/debounce.html - Dr. Andrew Greensted
Figura 3.8: Circuito de debounce
http://www.ikalogic.com/debouncing.php - Ibrahim Kamal
Notas de Aula ELT024 - Programao para Sistemas Embarcados
59 Programao dos Perifricos
Figura 3.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 conferncia 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)
{
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
60 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 3.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)
{
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 n 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
61 Programao dos Perifricos
Figura 3.10: Teclado em arranjo matricial
Notas de Aula ELT024 - Programao para Sistemas Embarcados
62 Programao dos Perifricos
Programa 3.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 3.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 3.5. J o programa 3.6
apresenta uma demonstrao de uso da biblioteca.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
63 Programao dos Perifricos
Programa 3.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 3.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)
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
64 Programao dos Perifricos
j.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 3.11 apresentado
um modelo genrico deste tipo de display. A Figura 3.12 apresenta o verso do display com os
terminais expostos.
Figura 3.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
65 Programao dos Perifricos
Figura 3.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 sequencial,
conforme pode ser visto na Figura 3.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 3.13. Para a ROM A02 temos a Figura 3.14.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
66 Programao dos Perifricos
Figura 3.13: Caracteres disponveis para ROM A00
http://www.sparkfun.com/datasheets/LCD/HD44780.pdf - Datasheet Hitachi
Notas de Aula ELT024 - Programao para Sistemas Embarcados
67 Programao dos Perifricos
Figura 3.14: Caracteres disponveis para ROM A02
http://www.sparkfun.com/datasheets/LCD/HD44780.pdf - Datasheet Hitachi
Notas de Aula ELT024 - Programao para Sistemas Embarcados
68 Programao dos Perifricos
Os comandos reconhecidos pelo display so apresentados na Tabela 3.4.
Tabela 3.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 3.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 3.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 3.7
e 3.9, respectivamente.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
69 Programao dos Perifricos
Figura 3.15: Esquemtico de ligao do display de LCD
Programa 3.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
70 Programao dos Perifricos
Programa 3.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
71 Programao dos Perifricos
Programa 3.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)
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
72 Programao dos Perifricos
j. 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 a simplicao do hardware. Como os dados so enviados um a um, necessrio
apenas 1 par de os, um para comunicao/transferncia dos dados e um para referncia da tenso
do sinal
7
.
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 3.5.
Tabela 3.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) muito utilizado para co-
municao entre dispositivos que transmitem ou recebem pouca quantidade de informao.
um dos protocolos mais antigos ainda em uso, tendo seu primeiro uso em 1962 para mquinas
eletromecnicas de escrever. 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.
7
Existem comunicaes seriais onde o nvel de tenso diferencial, portanto no temos uma referncia ou
ground. Alm disso a comunicao com apenas 1 par de os denominada half-duplex, onde a transmisso e
recepo no acontecem no mesmo instante
Notas de Aula ELT024 - Programao para Sistemas Embarcados
73 Programao dos Perifricos
A Figura 3.16 apresenta o sinal eltrico
8
enviado ao longo do tempo para a letra K. Notar
a regio em branco, que se estende entre +3 e -3. Ela indica a regio de tenso na qual o
sinal no est denido. Caso a tenso lida esteja entre estes limiares, seja devido rudos ou
outros problemas, o sistema de recepo no entender a mensagem e os dados sero perdidos
ou corrompidos.
Figura 3.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 3.6.
Como visto na Tabela 3.6 existem trs frmulas 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 frmulas chegamos aos seguintes valores:
n1 = 1, F
232
= 62.500, err = -7,64%
n2 = 8, F
232
= 55.555, err = 3,63%
8
Para o protocolo RS232 o nvel alto ou 1 (um) aquele com tenses positivas entre +3 e +15. O nvel lgico
baixo ou 0 (zero) interpretado entre -3 e -15 volts.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
74 Programao dos Perifricos
Tabela 3.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
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 3.6 obtemos que os bits de congurao devem ser: TXSTA(4) = 0,
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)
Notas de Aula ELT024 - Programao para Sistemas Embarcados
75 Programao dos Perifricos
Programa 3.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 n 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 }
{
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
{
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 3.10 apresenta um exemplo de cdigo para criar uma biblioteca para comunicao
serial. O arquivo de header apresentado no programa 3.11 e o exemplo de uso demonstrado no
programa 3.12.
A seguir o arquivo de header.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
76 Programao dos Perifricos
Programa 3.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 3.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)
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
77 Programao dos Perifricos
j.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
9
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 3.17).
Figura 3.17: Lmpada incandescente
Podemos utilizar uma lmpada incandescente como sensor de tenso: pega-se uma lmpada
de 220V. Liga-se a lmpada a 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 lmpada 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 3.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 3.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.
9
Com uma preciso de 10 bits conseguimos representar 2

10 valores diferentes, ou 1024 valores.


Notas de Aula ELT024 - Programao para Sistemas Embarcados
78 Programao dos Perifricos
Figura 3.18: Potencimetro
Figura 3.19: Potencimetro como divisor de tenso
http://en.wikipedia.org/wiki/File:Potentiometer_with_load.png
Figura 3.20: Circuito integrado LM35
Notas de Aula ELT024 - Programao para Sistemas Embarcados
79 Programao dos Perifricos
Um sensor ativo possui no mnimo 3 terminais: 2 para alimentao e 1 para sada do sinal.
Um exemplo deste tipo de sensor o LM35 (Figura 3.20) que utilizado para monitoramento
de temperatura.
Na Figura 3.21 apresentado o diagrama de blocos do circuito integrado do LM35. O diodo
utilizado como unidade sensora de temperatura.
Figura 3.21: Diagrama de blocos do LM35
Quando polarizado atravs de uma corrente constante, havendo mudana de temperatura a
tenso em cima do diodo muda. Os dois amplicadores e as respectivas realimentaes esto
inseridas no circuito para amplicar e estabilizar as variaes de tenso.
Processo de converso AD
Existem alguns circuitos que realizam a converso de um sinal analgico advindo de um trans-
dutor para um sinal digital com uma preciso arbitrria.
A abordagem mais simples a utilizao de comparadores. Cada comparador possui um
nvel diferente de tenso de referncia. Estes nveis so escolhidos de forma que a representao
binria faa sentido.
Exemplo: Converso de um valor analgico que varia de zero cinco volts numa palavra
digital de dois bits.
Para N bits temos N
2
representaes diferentes. interessante ento dividir a amplitude
inicial por N
2
divises iguais. Para N = 2 temos 4 representaes de 1.25v cada.
Representao binria com 2 bits Valor em tenso
00 0.625v
01 1.875v
10 3.125v
11 4.375v
O circuito eletrnico responsvel pelas comparaes pode ser visualizado na Figura 3.22.
O circuito da Figura 3.22 conhecido como conversor analgico digital do tipo ash onde
cada nvel de tenso possui seu prprio comparador. Existem outras abordagens que minimizam
Notas de Aula ELT024 - Programao para Sistemas Embarcados
80 Programao dos Perifricos
Figura 3.22: Conversor analgico digital de 2 bits
http://en.wikipedia.org/wiki/File:Flash_ADC.png - Jon Guerber
Notas de Aula ELT024 - Programao para Sistemas Embarcados
81 Programao dos Perifricos
Programa 3.13: adc.c
1 #include "adc.h"
2 #include "basico.h"
3 void InicializaAD ( void)
4 {
5 BitSet ( TRISA , 0 ) ; // s e t a o b i t 0 como ent rada
6 ADCON0 = 0b00000001 ; // s e l e c i ona o canal 0 e l i g a o ad
7 ADCON1 = 0b00001110 ; //apenas AN0 anal gi co , a r e f e r nc i a baseada na f ont e
8 ADCON2 = 0b10101010 ; //FOSC /32 , Al inhamento d i r e i t a e tempo de conv = 12 TAD
9 }
11 i nt LeValorAD ( void)
12 {
13 unsigned i nt ADvalor ;
14 BitSet ( ADCON0 , 1 ) ; // i ni c i a converso
15 while ( BitTst ( ADCON0 , 1 ) ) ; // espera t ermi nar a converso ;
16 ADvalor = ADRESH ; // l o r e s ul t ado
17 ADvalor <<= 8;
18 ADvalor += ADRESL ;
19 return ADvalor ;
20 }
Programa 3.14: adc.h
1 #i f ndef ADC_H
2 #define ADC_H
3 void InicializaAD ( void) ;
4 i nt LeValorAD ( void) ;
5 #endif //ADC_H
o uso de conversores (parte mais cara do circuito) mas inserem atraso no processo de converso.
O atraso depende do tipo de circuito que implementado.
Criao da biblioteca
Toda converso leva um determinado tempo que, conforme citado na seo anterior, depende
da arquitetura que estamos utilizando, da qualidade do conversor e, algumas vezes, do valor de
tenso que queremos converter. Para que o microcontrolador realize corretamente a converso
necessrio seguir os seguintes passos:
1. Congurar o conversor
2. Iniciar a converso
3. Monitorar o nal da converso
4. Ler o valor
Os programas 3.13 e 3.14 apresentam os arquivos de cdigo e header de uma biblioteca
exemplo para conversores analgicos para digital no microcontrolador PIC. O programa 3.15
apresenta um cdigo exemplicando o uso da biblioteca criada.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
82 Programao dos Perifricos
Programa 3.15: Exemplo de uso da biblioteca de conversores AD
1 #include "basico.h"
2 #include "config.h"
3 #include "disp7seg.h"
4 #include "adc.h"
5 // i ni c i o do programa
6 void main ( void)
7 {
8 unsigned i nt i ;
9 i nt temp = 0;
10 InicializaDisplays ( ) ;
11 InicializaAD ( ) ;
12 for ( ; ; )
13 {
14 temp = LeValorAD ( ) ;
15 temp %= 10000;
16 MudaDigito ( temp / 1000 , 3) ;
17 temp %= 1000;
18 MudaDigito ( temp / 100 , 2) ;
19 temp %= 100;
20 MudaDigito ( temp / 10 , 1) ;
21 temp %= 10;
22 MudaDigito ( temp , 0) ;
23 AtualizaDisplay ( ) ;
24 for ( i = 0; i < 1000; i++) ;
25 }
26 }
Notas de Aula ELT024 - Programao para Sistemas Embarcados
83 Programao dos Perifricos
j.q Sadas PWM
As sadas PWM so sadas digitais que possuem um chaveamento acoplado. O sinal muda seu
estado de positivo para zero vrias vezes por segundo. A porcentagem do tempo que este sinal
permanece em nvel Alto dene o ciclo de trabalho, ou duty cycle, da sada. A Figura 3.23
apresenta 3 sinais PWM com a mesma frequncia mas com duty cycle diferentes.
Figura 3.23: Sinais PWM com variao do duty cycle
Suponha uma sada PWM ligada a um resistor. Quando a sada estiver em nvel alto existe
a passagem de corrente eltrica e a resistncia aquece. Quando estiver em nvel baixo a corrente
para. Como a constante trmica do componente alta, leva-se alguns segundos para que o
resistor aquea ou esfrie, possvel ajustar a quantidade de energia mdia com uma frequncia
de sinal PWM sucientemente alta.
Em outras palavras, se a frequncia do PWM for mais alta do que a carga conseguir enxergar,
quando colocarmos o duty cycle em 50%, a carga ir receber 50% da energia total. Se for um
resistor, podemos controlar a temperatura nal deste modo, num motor podemos ajustar a
velocidade de rotao que queremos.
Como citado a frequncia do PWM tem que ser sucientemente alta. Esta frequncia depende
do circuito implementado no microcontrolador. No caso do PIC18f4550 calculada segundo a
frmula abaixo.
Freq.
PWM
=
F
OSC
[(PR2) + 1] 4 (TMR2
Prescaler
)
Com uma frequncia de oscilao de 8MHz (disponvel na placa) podemos atingir frequncias
que variam de 488Hz at 2MHz.
O problema de trabalhar, no caso do PIC, com frequncias muito altas que perdemos
resoluo na denio do duty cycle. Por exemplo, para a frequncia de PWM em 2MHz com
um clock de 8MHz temos uma resoluo de apenas 2 bits. Ou seja, podemos congurar a sada
para 0%, 25%, 50% ou 75% do valor mximo. A resoluo pode ser obtida segundo a frmula
abaixo.
Resoluo
PWM
(max) =
log(
F
OSC
F
PWM
)
log(2)
bits
O PIC18f4550 permite uma resoluo de at 10 bits. Com um oscilador principal de 8 MHz
a frequncia mxima do PWM para utilizarmos os 10 bits de resoluo 7812,5 Hz. Para uma
resoluo de 8 bits a frequncia mxima aumenta para 31.25 kHz.
Utilizando a primeira e segunda frmulas podemos montar a Tabela 3.7.
O duty cycle (em porcentagem) calculado de acordo com a frmula abaixo:
Notas de Aula ELT024 - Programao para Sistemas Embarcados
84 Programao dos Perifricos
Tabela 3.7: Faixa de frequncias mximas e mnimas para cada congurao do prescaler
Prescaler Freq. mxima (PR2 = 0) Freq. mnima (PR2 = 0)
1 2.000.000 7.812,5
4 500.000 1.953,2
16 125.000 488,3
DutyCycle
PWM
=
[CCPRxL : CCPxCON(5 : 4)]
(PR2 + 1) 4
Criao da biblioteca
Para congurar as sadas PWM devemos especicar a frequncia de trabalho atravs de PR2
e TCON2, alm do duty cycle em CCPR1L e CCPR2L. No registro TRISC congurado o
terminal como uma sada e em CCP1CON e CCP2CON denimos que ele deve trabalhar como
um PWM. O prescaler foi congurado para 16 bits de modo a obter a maior faixa de frequncia
audvel disponvel (Tabela 3.7). Notar que importante realizar primeiro a multiplicao e
somente depois a diviso, para no haver perda de informao. No programa 3.16 apresentado
um cdigo exemplo de como criar as rotinas de operao do PWM. O header desta biblioteca
apresentado no programa 3.17. Por m, o programa 3.18 apresenta um exemplo de utilizao
desta biblioteca.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
85 Programao dos Perifricos
Programa 3.16: pwm.c
1 #include "pwm.h"
2 #include "basico.h"
4 void SetaPWM1 ( unsigned char porcento )
5 {
6 // f rmul a do dut y c y c l e :
7 //DC_porcento = V / ( (PR2+1) 4;
8 //V = DC/100 (PR2+1) 4 = DC (PR2+1) /25
9 unsigned i nt val = ( ( unsigned i nt ) porcento ) ( PR2+1) ;
10 val = val / 25;
11 // garant e que tem apenas 10 b i t s
12 val &= 0x03ff ;
13 // os 8 pri mei ros b i t s so col ocados no CCPR1L
14 CCPR1L = val >> 2;
15 // os l t i mos doi s so col ocados na pos i o 5 e 4 do CCP1CON
16 CCP1CON |= ( val & 0x0003 ) << 4;
17 }
19 void SetaPWM2 ( unsigned char porcento )
20 {
21 //100 256 = 25. 600
22 unsigned i nt val = porcento PR2 ;
23 val /= 25;
24 // garant e que tem apenas 10 b i t s
25 val &= 0x03ff ;
26 // os 8 pri mei ros b i t s so col ocados no CCPR1L
27 CCPR2L = val >> 2;
28 // os l t i mos doi s so col ocados na pos i o 5 e 4 do CCP1CON
29 CCP2CON |= ( val & 0x0003 ) << 4;
30 }
32 void SetaFreqPWM ( unsigned i nt freq )
33 {
34 //PR2 = f os c /(fpwm4 pr e s c al e r )1 = (8000000/( f r e q 416) ) 1
35 PR2 = (125000/( freq ) ) 1;
36 }
38 void InicializaPWM ( void)
39 {
40 BitClr ( TRISC , 2 ) ; // conf i gur a os pi nos como s a das
41 BitClr ( TRISC , 3 ) ;
42 T2CON |= 0b00000011 ; // conf i gur a o pr e s c al e do t i mer 2 para 1: 16
43 BitSet ( T2CON , 2 ) ; // Li ga o t i mer 2
44 CCP1CON |= 0b00001100 ; // conf i gur a CCP1 como um PWM
45 CCP2CON |= 0b00001100 ; // conf i gur a CCP2 como um PWM
46 }
Programa 3.17: pwm.h
1 #i f ndef PWM_H
2 #define PWM_H
3 void SetaPWM1 ( unsigned char porcento ) ;
4 void SetaPWM2 ( unsigned char porcento ) ;
5 void SetaFreqPWM ( unsigned i nt freq ) ;
6 void InicializaPWM ( void) ;
7 #endif //PWM_H
Notas de Aula ELT024 - Programao para Sistemas Embarcados
86 Programao dos Perifricos
Programa 3.18: Exemplo de uso da biblioteca das sadas PWM
1 #include "config.h"
2 #include "basico.h"
3 #include "pwm.h"
4 #include "adc.h"
5 // i ni c i o do programa
6 void main ( void)
7 {
8 i nt temp ;
9 InicializaPWM ( ) ;
10 InicializaAD ( ) ;
11 for ( ; ; ) {
12 temp = LeValorAD ( ) ;
13 // aj ust ando a f r e q u nc i a de acordo com ent rada anal gi ca
14 SetaFreqPWM ( temp ) ;
15 // aj ust ando o dutyc y c l e para 50%
16 SetaPWM1 ( 50) ;
17 }
18 }
Notas de Aula ELT024 - Programao para Sistemas Embarcados
87 Programao dos Perifricos
Programa 3.19: timer.c
1 #include "basico.h"
2 #include "timer.h"
3 char FimTimer ( void)
4 {
5 return BitTst ( INTCON , 2 ) ;
6 }
7 void AguardaTimer ( void)
8 {
9 while ( ! BitTst ( INTCON , 2 ) ) ;
10 }
12 //tempo em micro segundos
13 void ResetaTimer ( unsigned i nt tempo )
14 {
15 //para pl aca com 8MHz 1 us = 2 c i c l o s
16 unsigned ciclos = tempo 2;
17 // over f l ow acont ece com 2^151 = 65535 (max unsi gned i nt )
18 ciclos = 65535 ciclos ;
19 ciclos = 14; // s ub t r ai tempo de overhead ( experi ment al )
20 TMR0H = ( ciclos >> 8) ; // s al v a a par t e a l t a
21 TMR0L = ( ciclos & 0x00FF ) ; // s al v a a par t e bai xa
22 BitClr ( INTCON , 2 ) ; // l i mpa a f l a g de over f l ow
23 }
25 void InicializaTimer ( void)
26 {
27 T0CON = 0b00001000 ; // conf i gur a t i mer 0 sem pr e s c al e r
28 BitSet ( T0CON , 7 ) ; // l i g a o t i mer 0
29 }
j.io Timer
Nos microcontroladores existem estruturas prprias para realizar a contagem de tempo, estas
estruturas so denominadas Timers.
O PIC18f4550 possui quatro timers. Para utilizarmos a sada PWM temos que congurar o
timer 2, que gera a base de tempo que sera comparada com o duty cycle.
Ao invs de contarmos quantas instrues so necessrias para criar um delay de um deter-
minado tempo, podemos utilizar os timers. Escolhemos o valor de tempo que queremos contar,
inicializamos as variveis e esperamos acontecer um overow
10
na contagem do timer.
Para trabalhar com o timer precisamos basicamente de uma funo de inicializao, uma
para resetar o timer e outra para indicar se o tempo congurado anteriormente j passou. Uma
quarta funo AguardaTimer(), foi construda para facilitar o desenvolvimento de algumas
rotinas comuns nos programas. Estas rotinas esto implementadas no programa 3.19 cujo header
apresentado no programa 3.20. O modo de utilizar esta biblioteca apresentado no programa
3.21.
10
Overow conhecido como estouro de varivel. Toda varivel digital possui um valor mximo, por exemplo
255 para uma varivel do tipo unsigned char. Se uma varivel unsigned char possui o valor 255 e acrescida de
1, seu valor passa a ser zero e acontece o estouro ou overow.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
88 Programao dos Perifricos
Programa 3.20: timer.h
1 #i f ndef TIMER_H
2 #define TIMER_H
3 char FimTimer ( void) ;
4 void AguardaTimer ( void) ;
5 //tempo em micro segundos
6 void ResetaTimer ( unsigned i nt tempo ) ;
7 void InicializaTimer ( void) ;
8 #endif //TIMER_H
Programa 3.21: Exemplo de uso da biblioteca de um temporizador
1 // i ni c i o do programa
2 void main ( void)
3 {
4 unsigned i nt cont ;
5 TRISD=0x00 ;
6 InicializaTimer ( ) ;
7 ResetaTimer (10000) ;
8 cont = 0;
9 for ( ; ; )
10 {
11 AguardaTimer ( ) ;
12 ResetaTimer (10000) ;
13 cont ++;
14 i f ( cont >= 50) //50 10ms = 0 , 5 s
15 {
16 PORTD ^= 0xFF ;
17 cont = 0;
18 }
19 }
20 }
Notas de Aula ELT024 - Programao para Sistemas Embarcados
89 Programao dos Perifricos
j.ii Reproduo de Sons
Se ligarmos sada PWM um auto-falante possvel reproduzir sons. Conhecendo a frequncia
de cada uma das notas musicais e a durao destas possvel reproduzir uma msica. Para
reproduzir o tempo com uma preciso melhor podemos utilizar o TIMER0 como unidade de
tempo.
Conforme visto na seo .j, o PWM utilizado na placa consegue reproduzir as frequncias
audveis a partir de 488,3Hz. Por isso escolhemos comear a escala musical a partir do C5 (D
Tenor) que possui a frequncia de 523. A segunda escala possui o dobro da frequncia (uma
oitava acima). Para reproduzir a ausncia de som escolhemos a frequncia de 125.000 Hz
11
, que
inaudvel. Isto simplica o programa.
Programa 3.22: Reproduo de sons
1 #include "config.h"
2 #include "basico.h"
3 #include "pwm.h"
4 #include "timer.h"
6 // f r e q u nc i a das
7 // not as musi cai s
8 #define C 523
9 #define CS 554
10 #define D 587
11 #define DS 622
12 #define E 659
13 #define F 698
14 #define FS 740
15 #define G 784
16 #define GS 830
17 #define A 880
18 #define AS 932
19 #define B 987
22 // segunda oi t av a
23 #define C2 C2
24 #define C2S CS2
25 #define D2 D2
26 #define D2S DS2
27 #define E2 E2
28 #define F2 F2
29 #define F2S FS2
30 #define G2 G2
31 #define G2S GS2
32 #define A2 A2
33 #define A2S AS2
34 #define B2 B2
37 //sem som
38 #define v 125000
39 // i ni c i o do programa
40 void main ( void)
41 {
42 unsigned char cont=0;
43 unsigned char pos=0;
44 // I mperi al March (SW Epi sode V)
45 unsigned char tempo [ ] = {50 , 10 , 50 , 10 , 50 , 10 ,
50 , 5 , 25 , 5 , 50 , 5 , 50 , 5 , 25 , 5 , 50 , 50 , 50 ,
10 , 50 , 10 , 50 , 10 , 50 , 5 , 25 , 5 , 50 , 5 , 50 ,
5 , 25 , 5 , 50 , 50 , 100 , 5 , 25 , 5 , 25 , 10 , 100 ,
5 , 50 , 5 , 25 , 2 , 10 , 2 , 10 , 2 , 100 , 250};
46 unsigned i nt notas [ ] = {G , v , G , v , G , v , E , v , B ,
v , G , v , E , v , B , v , G , v , D2S , v , D2S , v ,
D2S , v , E2 , v , B , v , FS , v , E , v , B , v , G , v ,
G2S , v , G , v , G , v , G2S , v , G2 , v , F2S , v , F2 ,
v , E2 , v , F2S , v };
47 InicializaPWM ( ) ;
48 InicializaTimer ( ) ;
49 SetaFreqPWM ( notas [ 0 ] ) ;
50 SetaPWM1 ( 50) ; // garant e dutyc y c l e de 50%
51 for ( ; ; )
52 {
53 AguardaTimer ( ) ;
54 ResetaTimer (10000) ;
55 cont ++;
56 i f ( cont >= tempo [ pos ] )
57 {
58 pos++;
59 SetaFreqPWM ( notas [ pos ] ) ;
60 SetaPWM1 ( 50) ;
61 cont=0;
62 }
63 }
64 }
11
Esta a mxima frequncia possvel para o PWM operado com prescaler de 16x.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
90 Programao dos Perifricos
j.iz Interrupo
At o momento todos os programas que foram desenvolvidos seguiam um uxo sequencial sendo
alterado apenas por chamadas de funes, estruturas de deciso ou loop. Um dos problemas de
se utilizar este tipo de estrutura que alguns perifricos possuem um tempo muito grande para
realizarem sua funo como o conversor AD por exemplo. Nesta situao o que fazemos iniciar
a converso e car monitorando uma varivel que indicava quando a converso tinha terminado.
Esta tcnica conhecida como pooling.
O problema de se realizar a leitura de algum perifrico por pooling que o processador perde
tempo realizando operaes desnecessrias checando a varivel de controle. Uma alternativa
utilizar um sistema que, quando a operao desejada estivesse nalizada, nos avisasse para que
pudssemos tomar uma providncia. Este procedimento chamado de interrupo.
Alguns dispositivos possuem a possibilidade de operarem com interrupes. Quando a con-
dio do dispositivo for satisfeita (m da converso para o AD, chegada de informao na serial,
mudana no valor da varivel na porta B) ele gera uma interrupo. A interrupo para o
programa no ponto em que ele estiver, salva todos os dados atuais e vai para uma funo pr-
denida. Esta funo realiza seu trabalho e assim que terminar volta o programa no mesmo
ponto onde estava antes da interrupo.
Dos dispositivos estudados at agora os que geram interrupo so:
Porta Serial: quando chega alguma informao em RCREG ou quando o buer de transmisso
TXREG estiver disponvel.
Conversor AD: quando o resultado da converso estiver disponvel para leitura.
Porta B: quando algum dos bits congurados como entrada altera seu valor.
Timer 0: quando acontece overow em seu contador
Para gerenciar a interrupo, deve-se criar uma rotina que ir vericar qual foi hardware que
gerou a interrupo e tomar as providncias necessrias. A maneira de declarar que uma deter-
minada funo ser a responsvel pelo tratamento da interrupo depende do compilador.
Para o compilador SDCC basta que coloquemos a expresso interrupt 1 aps o nome da
funo.
void NomeDaFuncao ( void) interrupt 1
{
// cdi go . . .
}
Para o compilador C18 da Microchip temos que gerar um cdigo em assembler que indicar
qual funo ser a responsvel pela interrupo.
void NomeDaFuncao ( void)
{
// cdi go . . .
}
// I ndi car a posi o no vet or de i nt e r r up e s
#pragma code hi gh_vector=0x08
void interrupt_at_high_vector ( void)
{
_asm GOTO Interrupcao _endasm
}
#pragma code
#pragma i nt e r r upt NomeDaFuncao
A funo que ir tratar da interrupo no retorna nem recebe nenhum valor.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
91 Programao dos Perifricos
Programa 3.23: Fontes de Interrupo
1 void Interrupcao ( void) interrupt 1
2 {
3 // no neces s r i o u t i l i z a r t odos os i f ' s apenas aq ue l e s
4 // das i nt e r r up e s des ej adas
5 i f ( BitTst ( PIR1 , 0 ) ) { / cdi go / } // Fl ag de over f l ow do TIMER1
6 i f ( BitTst ( PIR1 , 1 ) ) { / cdi go / } // Fl ag de comparao do TIMER2 com PR2
7 i f ( BitTst ( PIR1 , 2 ) ) { / cdi go / } // Fl ag de comparao do CCP1
8 i f ( BitTst ( PIR1 , 3 ) ) { / cdi go / } // Fl ag de f i m de operao na port a
par al e l a
9 i f ( BitTst ( PIR1 , 4 ) ) { / cdi go / } // Fl ag de f i m de t ransmi sso da Se r i a l
10 i f ( BitTst ( PIR1 , 5 ) ) { / cdi go / } // Fl ag de recepo da Se r i a l
11 i f ( BitTst ( PIR1 , 6 ) ) { / cdi go / } // Fl ag de f i m de converso do AD
12 i f ( BitTst ( PIR1 , 7 ) ) { / cdi go / } // Fl ag de l e i t u r a / e s c r i t a da port a
par al e l a
13 i f ( BitTst ( PIR2 , 0 ) ) { / cdi go / } // Fl ag de comparao do CCP2
14 i f ( BitTst ( PIR2 , 1 ) ) { / cdi go / } // Fl ag de over f l ow do TIMER3
15 i f ( BitTst ( PIR2 , 2 ) ) { / cdi go / } // Fl ag de condi o de Tenso Al t a /Baixa
16 i f ( BitTst ( PIR2 , 3 ) ) { / cdi go / } // Fl ag de det eco de c o l i s o no
barramento
17 i f ( BitTst ( PIR2 , 4 ) ) { / cdi go / } // Fl ag de f i m e s c r i t a na memoria f l a s h
18 i f ( BitTst ( PIR2 , 5 ) ) { / cdi go / } // Fl ag de i nt er r upo da USB
19 i f ( BitTst ( PIR2 , 6 ) ) { / cdi go / } // Fl ag de mudana na ent rada de
comparao
20 i f ( BitTst ( PIR2 , 7 ) ) { / cdi go / } // Fl ag de f al ha no os c i l ador
21 i f ( BitTst ( INTCON , 0 ) ) { / cdi go / } // Fl ag de mudana na PORTA B
22 i f ( BitTst ( INTCON , 1 ) ) { / cdi go / } // Fl ag de i nt er r upo ext erna INT0
23 i f ( BitTst ( INTCON , 2 ) ) { / cdi go / } // Fl ag de over f l ow no TIMER0
24 i f ( BitTst ( INTCON3 , 0 ) ) { / cdi go / } // Fl ag de i nt er r upo ext erna INT1
25 i f ( BitTst ( INTCON3 , 1 ) ) { / cdi go / } // Fl ag de i nt er r upo ext erna INT2
26 }
Existe uma correlao entre o nmero que vem depois da expresso interrupt para o com-
pilador SDCC e o nmero ao nal da expresso #pragma code high_vector para o C18. Estes
nmeros representam a posio para a qual o microcontrolador vai quando acontece uma inter-
rupo. Estas posies esto numa rea conhecida como vetor de interrupes.
Para o microcontrolador PIC18f4550 este vetor possui trs posies importantes: 0x00(0),
0x08(1) e 0x18(2). O compilador C18 usa a posio fsica e o SDCC o nmero entre parnteses.
A posio 0 (0x00) representa o endereo que o microcontrolador busca quando este acaba
de ser ligado. a posio de reset. Geralmente samos deste vetor e vamos direto para a funo
main().
As posies 1 e 2 (0x08,0x18) so reservadas para as interrupes de alta e baixa prioridade,
respectivamente. necessrio que o programador escolha quais dispositivos so de alta e quais so
de baixa prioridade. Existe ainda um modo de compatibilidade com os microcontroladores mais
antigos no qual todos os perifricos so mapeados na primeira interrupo (0x08). Utilizaremos
este modo por questo de facilidade.
Como todos os perifricos esto mapeados na mesma interrupo, a funo deve ser capaz de
diferenciar entre as diversas fontes de requisio. Uma maneira de se realizar esta vericao
atravs das ags de controle, ou seja, bits que indicam a situao de cada perifrico.
O programa 3.23 apresenta uma funo que trata de todas as fontes possveis de interrupo
para o PIC18f4550.
Em geral no necessrio tratar todas as interrupes, apenas aquelas que inuenciaro
o sistema. O programa 3.24 apresenta um exemplo de uma funo que trata as interrupes
advindas da porta B, do timer 0, da serial e do AD.
Para que a funo apresentada no programa 3.24 funcione corretamente devemos inicializar
as interrupes de modo adequado, conforme apresentado no programa 3.25.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
92 Programao dos Perifricos
Programa 3.24: Tratamento das interrupes
1 stati c unsigned i nt ADvalor ;
2 stati c unsigned char Serial ;
3 stati c unsigned i nt Tecla ;
4 void Interrupcao ( void) interrupt 1
5 {
6 char i , j ;
7 i f ( BitTst ( PIR1 , 6 ) ) //AD : f i m de converso
8 {
9 ADvalor = ADRESH ; // l o r e s ul t ado
10 ADvalor <<= 8;
11 ADvalor += ADRESL ;
12 BitClr ( PIR1 , 6 ) ; // l i mpa a f l a g
13 }
14 i f ( BitTst ( PIR1 , 5 ) ) // Se r i a l : recepo
15 {
16 // Bi t Cl r (PIR1 , 5) ;
17 Serial = RCREG ; // l i mpa soz i nho quando l
18 }
19 i f ( BitTst ( INTCON , 0 ) ) //PORTA B : mudou v al or
20 {
21 for ( i = 0; i < 4; i++){
22 PORTB |= 0xFF ;
23 BitClr ( PORTB , ( i) ) ;
24 for ( j=0; j<10; j++) ;
25 for ( j = 0; j < 4; j++){
26 i f ( ! BitTst ( PORTB , j+4) ) {
27 BitSet ( Tecla , ( i4)+j) ;
28 } el se {
29 BitClr ( Tecla , ( i4)+j) ;
30 }
31 }
32 }
33 PORTB = 0x00 ;
34 BitClr ( INTCON , 0 ) ;
35 }
36 i f ( BitTst ( INTCON , 2 ) ) //TIMER0: Overf l ow
37 {
38 //tempo maximo de i nt er r upo do t i mer 0
39 BitClr ( INTCON , 2 ) ; // l i mpa a f l a g
40 TMR0H = 0x00 ; // r e i ni c i a cont ador de tempo
41 TMR0L = 0x00 ; // r e i ni c i a cont ador de tempo
42 ADCON0 |= 0b00000010 ; // i ni c i a converso
43 }
44 }
Notas de Aula ELT024 - Programao para Sistemas Embarcados
93 Programao dos Perifricos
Programa 3.25: Inicializao do sistema com interrupes
1 void main ( void)
2 {
3 unsigned i nt i , temp , teclanova=0;
4 // conf i gurando t odas as i nt e r r up e s
5 TRISD = 0x00 ;
6 TRISB = 0xF0 ; //mantm os 4 l t i mos b i t s como ent rada
7 PORTB = 0x00 ; //mantm l i g a d a s as 4 col unas
8 InicializaSerial ( ) ;
9 InicializaDisplays ( ) ;
10 InicializaLCD ( ) ;
11 InicializaAD ( ) ;
12 InicializaTimer ( ) ;
13 BitClr ( RCON , 7 ) ; // d e s a b i l i t a IPEN (modo de c ompat i b i l i dade )
14 BitSet ( PIE1 , 6 ) ; // l i g a a i nt er r upo para o AD
15 BitSet ( PIE1 , 5 ) ; // l i g a a i nt er r upo para a recepo na s e r i a l
16 BitSet ( INTCON , 5 ) ; // l i g a a i nt er r upo para o t i mer 0
17 BitSet ( INTCON , 3 ) ; // l i g a a i nt er r upo para a port a B
18 BitSet ( INTCON , 7 ) ; // h a b i l i t a t odas as i nt e r r up e s g l o b a i s
19 BitSet ( INTCON , 6 ) ; // h a b i l i t a t odas as i nt e r r up e s de p e r i f r i c o s
20 for ( ; ; ) {
21 AtualizaDisplay ( ) ;
22 temp = ADvalor ;
23 temp %=10000;
24 MudaDigito ( temp / 1000 , 3) ;
25 temp %=1000;
26 MudaDigito ( temp / 100 , 2) ;
27 temp %=100;
28 MudaDigito ( temp / 10 , 1) ;
29 temp %=10;
30 MudaDigito ( temp , 0) ;
31 i f ( teclanova != Tecla ) {
32 teclanova = Tecla ;
33 for ( i=0; i<16; i++){
34 i f ( BitTst ( Tecla , i) ) {
35 EnviaDados ( i+48) ;
36 }
37 }
38 }
39 for ( i = 0; i < 1000; i++) ;
40 }
41 }
Notas de Aula ELT024 - Programao para Sistemas Embarcados
94 Programao dos Perifricos
Programa 3.26: Inicializao do sistema com interrupes
1 #define CLRWTD( ) _asm CLRWDT _endasm
3 // i ni c i o do programa
4 void main ( void)
5 {
6 unsigned i nt i ;
7 unsigned char temp ;
8 TRISD=0x00 ;
9 PORTD=0x00 ;
10 BitSet ( WDTCON , 0 ) ; // l i g a o si st ema de watchdog
11 for ( ; ; )
12 {
13 PORTD++;
14 for ( i = 0; i < 10000; i++)
15 {
16 CLRWTD ( ) ;
17 }
18 }
19 }
j.ij Watchdog
Por algum motivo o software pode travar em algum ponto, seja por um loop innito ou por
esperar a resposta de algum componente atravs de pooling de uma varivel.
A primeira condio pode ser evitada atravs de um projeto cuidadoso de software aliado a
uma boa validao. J a segunda exige que os hardwares adjacentes funcionem corretamente.
Se algum hardware apresenta uma falha e no envia a resposta que o microcontrolador est
esperando, este ltimo ir travar. Nestas situaes possvel utilizar o watchdog.
O watchdog um sistema que visa aumentar a segurana do projeto. Ele funciona como
um temporizador que precisa constantemente ser reiniciado. Caso no seja reiniciado no tempo
exigido, o watchdog reinicia o microcontrolador dando a possibilidade de sair de um loop innito
ou de um pooling sem resposta.
Para habilitar o watchdog necessrio alterar os registros de congurao, especicamente
o CONFIG2H (0x300002). Outro mtodo consiste em deixar o watchdog desligado no registro e
lig-lo atravs de software, como apresentado no programa 3.26.
Notar o #dene criado na primeira linha do programa 3.26. A expresso CLRWDT o
comando em assembler responsvel por resetar o watchdog. As diretivas _asm e _endasm
informam ao compilador que os comandos utilizados devem ser transcritos exatamente iguais
para o arquivo assembler a ser gerado.
Se aps ligar o watchdog no realizarmos a operao de reset dele, comentando ou excluindo a
funo CLRWTD(), o sistema ir travar to logo o tempo associado ao watchdog tenha expirado
pela primeira vez, reiniciando o sistema. Como apenas reiniciar no soluciona o problema, pois o
programa criado no ter funo para reiniciar o watchdog, o sistema continua sendo reiniciado
indenidamente.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
Captulo 4
Arquitetura de desenvolvimento de
software
Constrained by memory limitations, performance requirements, and
physical and cost considerations, each embedded system design re-
quires a middleware platform tailored precisely to its needs, unused
features occupy precious memory space, while missing capabilities
must be tacked on. - Dr. Richard Soley
No desenvolvimento de um sistema de maior porte, importante denir o tipo de arquitetura
que iremos utilizar. Neste captulo apresentamos trs abordagens possveis. A escolha deve ser
baseada no tipo de dispositivo a ser desenvolvido, na complexidade do sistema, na possibilidade
de gerar subprodutos e dos requisitos de tempo.
95
96 Arquitetura de desenvolvimento de software
Programa 4.1: Exemplo de arquitetura single-loop
1 // seo de i nc l ude s
2 #include "basico.h"
3 #include "config.h"
4 #include "teclado.h"
5 #include "disp7seg.h"
6 // f uno p r i nc i p a l
7 void main ( void)
8 {
9 // decl arao das v a r i v e i s
10 i nt ia , ib , ic ;
11 f l oat fa , fb , fc ;
12 // i n i c i a l i z a o dos p e r i f r i c o s
13 InicializaTeclado ( ) ;
14 InicializaDisplays ( ) ;
15 // l oop p r i nc i p a l
16 for ( ; ; )
17 {
18 //chamada das t a r e f a s
19 DebounceTeclas ( ) ;
20 ia = LerTeclas ( ) ;
21 ImprimeDisplay ( ia ) ; //tem que s er execut ado pel o menos a cada 10(ms)
22 }
23 }
Programa 4.2: Problema na sincronia de tempo para o single-loop
1 // l oop p r i nc i p a l
2 for ( ; ; )
3 {
4 //chamada das t a r e f a s
5 DebounceTeclas ( ) ;
6 ia = LerTeclas ( ) ;
7 ImprimeDisplay ( ia ) ; //tem que s er execut ado pel o menos a cada 10(ms)
8 ic = RecebeSerial ( ) ;
9 fa = 2. 0 ic / 3 . 1 4 ;
10 EnviaSerial ( fa & 0x00FF ) ;
11 EnviaSerial ( fa >> 8) ;
12 }
q.i One single loop
1 Innite Loop, Cupertino, CA 95014. - Endereo da Apple
Esta a estratgia utilizada at agora nos exemplos apresentados. Dentro da funo principal
colocado um loop innito. Todas as tarefas so chamadas atravs de funes.
A vantagem de se utilizar esta abordagem a facilidade de se iniciar um projeto. Para
sistemas maiores comea a car complicado coordenar as tarefas e garantir a execuo num
tempo determinstico. Outro problema a modicao/ampliao do software. Geralmente a
insero de uma funo no meio do loop pode gerar erros em outras funes devido a restries
de tempo dos perifricos associados.
No exemplo acima, a insero da comunicao serial e os clculos podem atrapalhar a escrita
no display de sete segmentos, gerando icker.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
97 Arquitetura de desenvolvimento de software
Programa 4.3: Exemplo de sistema Interrupt-driven
1 i nt ia ;
2 // t rat ament o do t e c l ado vi a i nt er r upo
3 void Interrupcao ( void) interrupt 1
4 {
5 i f ( BitTst ( INTCON , 0 ) ) //PORTA B : mudou v al or
6 {
7 ia = LerTeclas ( ) ;
8 }
9 }
11 void main ( void)
12 {
13 // i n i c i a l i z a o dos p e r i f r i c o s
14 InicializaTeclado ( ) ;
15 InicializaDisplay ( ) ;
16 // i n i c i a l i z a o da i nt er r upo
17 BitClr ( RCON , 7 ) ; // d e s a b i l i t a IPEN (modo de c ompat i b i l i dade )
18 BitSet ( INTCON , 3 ) ; // l i g a a i nt er r upo para a port a B
19 BitSet ( INTCON , 7 ) ; // h a b i l i t a t odas as i nt e r r up e s g l o b a i s
20 BitSet ( INTCON , 6 ) ; // h a b i l i t a t odas as i nt e r r up e s de p e r i f r i c o s
21 for ( ; ; ) // l oop p r i nc i p a l
22 {
23 //chamada das t a r e f a s
24 ImprimeDisplay ( ia ) ;
25 }
26 }
q.z Interrupt control system
Uma parte dos desenvolvedores de sistemas embarcados, que possuem restries de tempo de
atendimento mais rigorosos, optam por garantir estas restries atravs de interrupes.
Na maioria dos sistemas microcontroladores, as interrupes so atendidas num tempo muito
curto, cerca de alguns ciclos de instruo, o que para a maioria dos sistemas suciente. Deve-se,
entretanto, tomar cuidado com a quantidade de perifricos que geram interrupes e a prioridade
dada a cada um deles.
Outra abordagem muito utilizada a gerao de uma interrupo com tempo xo, por exem-
plo a cada 5ms.
A grande vantagem da abordagem citada que a insero de mais cdigo dentro do loop
principal no atrapalha a velocidade com que o display atualizado, que est xo em 5(ms).
Notas de Aula ELT024 - Programao para Sistemas Embarcados
98 Arquitetura de desenvolvimento de software
Programa 4.4: Exemplo de sistema Interrupt-driven com base de tempo
1 i nt ia ;
2 // e x i t e apenas uma f ont e de i nt er r upo : Timer 0
3 void Interrupcao ( void) interrupt 1
4 {
5 ResetaTimer ( 5000) ; // r e i ni c i a t i mer para prxima i nt er r upo
6 ImprimeDisplay ( ia ) ;
7 BitSet ( INTCON , 5 ) ; // r e l i g a a i nt er r upo para o t i mer 0
8 }
10 void main ( void)
11 {
12 // i n i c i a l i z a o dos p e r i f r i c o s
13 InicializaTeclado ( ) ;
14 InicializaDisplay ( ) ;
15 InicializaTimer ( ) ;
16 // i n i c i a l i z a o da i nt er r upo
17 BitClr ( RCON , 7 ) ; // d e s a b i l i t a IPEN (modo de c ompat i b i l i dade )
18 BitSet ( INTCON , 5 ) ; // l i g a a i nt er r upo para o t i mer 0
19 BitSet ( INTCON , 7 ) ; // h a b i l i t a t odas as i nt e r r up e s g l o b a i s
20 BitSet ( INTCON , 6 ) ; // h a b i l i t a t odas as i nt e r r up e s de p e r i f r i c o s
21 ResetaTimer ( 5000) ;
22 for ( ; ; ) // l oop p r i nc i p a l
23 {
24 DebounceTeclas ( ) :
25 ia = LerTeclas ( ) ;
26 }
27 }
Notas de Aula ELT024 - Programao para Sistemas Embarcados
99 Arquitetura de desenvolvimento de software
q.j Cooperative multitasking
Em computao, multitarefa ou multitasking um processo pelo qual diferentes tarefas compar-
tilham um mesmo recurso, seja ele memria, processamento ou qualquer perifrico disponvel.
Uma maneira de realizar este compartilhamento atravs de uma diviso do tempo: a tarefa
A possui um intervalo ao nal do qual deve ceder os recursos para a tarefa B. Quando a mudana
de tarefa feita pela prpria tarefa, o sistema dito cooperativo. Quando existe um sistema
externo que realiza essa troca o sistema denominado preemptivo.
Se a mudana de tarefas for extremamente rpida o efeito resultante, para o ser humano,
de que todas as tarefas esto sendo executadas simultaneamente. Uma das maneiras de se
obter este tipo de operao atravs da criao de uma mquina de estados, como mostrado na
Figura 4.1.
Inicio
Ler
Teclado
Atualiza
Display
Escreve
Serial
Atualiza
Display Ler Serial
Atualiza
Display
Figura 4.1: Exemplo de mquina de estados
Nota-se que aps a fase de inicializao o sistema entra num ciclo, como na abordagem one-
single-loop. Outra peculiaridade que algumas tarefas podem ser executadas mais de uma vez
para garantir as restries de tempo. No exemplo a tarefa de atualizao dos displays executada
trs vezes.
A transposio de uma mquina de estado para o cdigo em C realizada atravs de um
switch-case.
possvel retirar todas as atribuies para a varivel slot e colocar no slot-bottom a ex-
presso slot++. A abordagem apresentada foi escolhida por aumentar a robustez do sistema, j
que a varivel slot controla todo o uxo do programa.
A insero de uma nova tarefa realizada de maneira simples, basta adicionar outro slot, ou
seja, basta inserir um case/break com a tarefa desejada.
Como a mquina est dentro do loop innito, a cada vez que o programa passar pelo case,
ele executar apenas um slot. Esta abordagem gera ainda outro efeito. Como pode ser visto
no cdigo, naturalmente surgem duas regies: top-slot e bottom-slot. Se algum cdigo for
colocado nesta regio ele ser executado toda vez, de modo intercalado, entre os slots. Pela
Figura 4.1, percebemos que exatamente este o comportamento que queremos para a funo
AtualizaDisplay(). Deste modo, podemos remodelar o cdigo fazendo esta alterao.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
100 Arquitetura de desenvolvimento de software
Programa 4.5: Exemplo de cooperative multitasking
1 void main ( void)
2 {
3 // decl arao das v a r i v e i s
4 char slot ;
5 // f unes de i n i c i a l i z a o
6 InicializaSerial ( ) ;
7 InicializaTeclado ( ) ;
8 InicializaDisplay ( ) ;
9 for ( ; ; ) { // i ni c i o do l oop i n f i n i t o
10 // i n c i o do tops l o t
11 // f i m do tops l o t
13 // i n c i o da mquina de es t ado
14 switch( slot ) {
15 case 0:
16 LeTeclado ( ) ;
17 slot = 1;
18 break ;
19 case 1:
20 AtualizaDisplay ( ) ;
21 slot = 2;
22 break ;
23 case 2:
24 RecebeSerial ( ) ;
25 slot = 3;
26 break ;
27 case 3:
28 AtualizaDisplay ( ) ;
29 slot = 4;
30 break ;
31 case 4:
32 EnviaSerial ( ) ;
33 slot = 5;
34 break ;
35 case 5:
36 AtualizaDisplay ( ) ;
37 slot = 0;
38 break ;
39 default :
40 slot = 0;
41 break ;
42 }
43 // f i m da mquina de es t ado
45 // i n c i o do bottoms l o t
46 // f i m do bottoms l o t
47 } //f i m l oop i n f i n i t o ( ! ? )
48 }
Notas de Aula ELT024 - Programao para Sistemas Embarcados
101 Arquitetura de desenvolvimento de software
Programa 4.6: Exemplo de cooperative multitasking com uso do top slot
1 void main ( void)
2 {
3 // decl arao das v a r i v e i s
4 char slot ;
5 // f unes de i n i c i a l i z a o
6 InicializaSerial ( ) ;
7 InicializaTeclado ( ) ;
8 InicializaDisplay ( ) ;
9 for ( ; ; ) // i ni c i o do l oop i n f i n i t o
10 {
11 // i n c i o do tops l o t
12 AtualizaDisplay ( ) ;
13 // f i m do tops l o t
16 // i n c i o da mquina de es t ado
17 switch( slot )
18 {
19 case 0:
20 LeTeclado ( ) ;
21 slot = 1;
22 break ;
23 case 1:
24 RecebeSerial ( ) ;
25 slot = 2;
26 break ;
27 case 2:
28 EnviaSerial ( ) ;
29 slot = 0;
30 break ;
31 default :
32 slot = 0;
33 break ;
34 }
35 // f i m da mquina de es t ado
38 // i n c i o do bottoms l o t
40 // f i m do bottoms l o t
42 } //f i m l oop i n f i n i t o ( ! ? )
43 }
Notas de Aula ELT024 - Programao para Sistemas Embarcados
102 Arquitetura de desenvolvimento de software
Programa 4.7: Exemplo de sistema Cooperative-multitasking com slot temporizado
1 void main ( void)
2 {
3 // decl arao das v a r i v e i s
4 char slot ;
5 // f unes de i n i c i a l i z a o
6 InicializaDisplay ( ) ;
7 InicializaTimer ( ) ;
8 for ( ; ; ) // i ni c i o do l oop i n f i n i t o
9 {
10 // i n c i o do tops l o t
11 ResetaTimer ( 5000) ; //5 ms para cada s l o t
12 AtualizaDisplay ( ) ;
13 // f i m do tops l o t
16 // i n c i o da mquina de es t ado
17 switch( slot )
18 {
19 case 0:
20 LeTeclado ( ) ;
21 slot = 1;
22 break ;
23 case 1:
24 RecebeSerial ( ) ;
25 slot = 2;
26 break ;
27 case 2:
28 EnviaSerial ( ) ;
29 slot = 0;
30 break ;
31 default :
32 slot = 0;
33 break ;
34 }
35 // f i m da mquina de es t ado
38 // i n c i o do bottoms l o t
40 // f i m do bottoms l o t
41 AguardaTimer ( ) ;
42 } //f i m l oop i n f i n i t o ( ! ? )
43 }
Fixao de tempo para execuo dos slots
Do modo apresentado at agora, assim que uma funo termina, o sistema automaticamente
passa para a prxima tarefa. Uma caracterstica desejada que estas funes possuam um
tempo determinado para funcionar. Deste modo, todo o sistema se torna mais previsvel.
A maneira mais simples de realizar este procedimento criar uma rotina de tempo. Toda vez
que um slot terminar, o sistema car aguardando o tempo escolhido para reiniciar o sistema.
No exemplo apresentado inserida a funo AguardaTimer() no bottom-slot de modo que a
prxima funo s executar quando passar os 5 (ms).
Como este um modo simples de implementar um sistema multitarefa podemos notar que
se a funo ultrapassar 5 (ms) todo o cronograma ser afetado. necessrio ento garantir que
todo e cada slot ser executado em menos de 5 (ms). Isto deve ser feito atravs de testes de
bancada.
Na Figura 4.2 est um exemplo de como um sistema com 3 slots se comporta ao longo do
Notas de Aula ELT024 - Programao para Sistemas Embarcados
103 Arquitetura de desenvolvimento de software
tempo. Notar que o slot 1 (S.1) gasta um tempo de 2.0(ms), o slot 2 de 3.1 (ms) e o slot 3 apenas
1.2 (ms). J o top-slot consome 0.5 (ms) e o bottom-slot 0.3 (ms).
Top
S.1
S.2
S.3
Bottom
"vago"
0 5 10 15 20 25 30
Figura 4.2: Exemplo da mudana de slots no tempo
Podemos notar que para o ciclo do primeiro slot so gastos 0.5+2.0+0.3 = 2.8(ms). Deste
modo o sistema ca aguardando na funo AguardaTimer() durante 2.2 (ms) sem realizar
nenhum processamento til. Para o segundo slot temos um tempo "livre"de 5-(0.5+3.1+0.3)=1.1
(ms). O terceiro slot o que menos consome tempo de processamento, possuindo um tempo livre
de 5-(0.5+1.2+0.3)=3.0 (ms).
Utilizao do tempo livre para interrupes
Conforme visto anteriormente, dependendo do tempo escolhido para o slot e do tamanho da
funo, podem existir espaos vagos na linha de tempo do processador. A Figura 4.3 apresenta
uma linha de tempo de um sistema que possui apenas 1 slot. J a Figura 4.4 demonstra o mesmo
sistema sendo interrompido atravs de interrupes assncronas.
Top 1 1 1
S.1 3 3 3
Bottom 1 1 1
"vago" 3 3 3
Figura 4.3: Linha de tempo de um sistema com 1 slot
Top 1 1
S.1 1 2 3 3
Bottom 1 1 1
"vago" 2 2 2
Interr. 1
1
1
Figura 4.4: Comportamento da linha de tempo com interrupes
Notas de Aula ELT024 - Programao para Sistemas Embarcados
104 Arquitetura de desenvolvimento de software
Cada interrupo gasta um tempo de 1 (ms) conforme pode ser visto na Figura 4.4. Como
temos um tempo vago de 3 (ms) em cada ciclo basta garantir que os eventos que geram a
interrupo no ultrapassem a frequncia de 3 eventos a cada 8 (ms).
Notas de Aula ELT024 - Programao para Sistemas Embarcados
Captulo 5
Anexos
105
106 Anexos
Programa 5.1: cong.h
1 //para o compi l ador SDCC + GPUtil s
2 #i f ndef CONFIG_H
3 #define CONFIG_H
4 code char at 0x300000 CONFIG1L = 0x01 ; // Pl l de s l i g ado
5 code char at 0x300001 CONFIG1H = 0x0C ; // Os ci l ador c/ c r i s t a l ext erno HS
6 code char at 0x300003 CONFIG2H = 0x00 ; // Watchdog cont r ol ado por s of t war e
7 code char at 0x300006 CONFIG4L = 0x00 ; // Sem programao em bai xa t enso
8 #endif //CONFIG_H
10 //para o compi l ador C18
11 //#pragma c onf i g FOSC = HS // Os ci l ador c/ c r i s t a l ext erno HS
12 //#pragma c onf i g CPUDIV = OSC1_PLL2 // Pl l de s l i g ado
13 //#pragma c onf i g WDT = OFF // Watchdog cont r ol ado por s of t war e
14 //#pragma c onf i g LVP = OFF // Sem programao em bai xa t enso \\\ hl i ne
.i cong.h
O arquivo cong.h possui as diretivas de compilao para congurao do microcontrolador.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
107 Anexos
Programa 5.2: basico.h
1 // f uno para l i mpar o watchdog
2 #define CLRWTD( ) _asm CLRWDT _endasm
3 // f unes de b i t
4 #define Bi t Set ( arg , bi t ) ( ( arg ) |= (1<<bi t ) )
5 #define Bi t Cl r ( arg , bi t ) ( ( arg ) &= ~(1<<bi t ) )
6 #define Bi tFl p ( arg , bi t ) ( ( arg ) ^= (1<<bi t ) )
7 #define Bi tTst ( arg , bi t ) ( ( arg ) & (1<<bi t ) )
8 // de f i ne ' s para r e g i s t r o s e s p e c i a i s
9 #define PORTA ( ( vol ati l e near unsigned char ) 0xF80)
10 #define PORTB ( ( vol ati l e near unsigned char ) 0xF81)
11 #define PORTC ( ( vol ati l e near unsigned char ) 0xF82)
12 #define PORTD ( ( vol ati l e near unsigned char ) 0xF83)
13 #define PORTE ( ( vol ati l e near unsigned char ) 0xF84)
14 #define TRISA ( ( vol ati l e near unsigned char ) 0xF92)
15 #define TRISB ( ( vol ati l e near unsigned char ) 0xF93)
16 #define TRISC ( ( vol ati l e near unsigned char ) 0xF94)
17 #define TRISD ( ( vol ati l e near unsigned char ) 0xF95)
18 #define TRISE ( ( vol ati l e near unsigned char ) 0xF96)
19 #define INTCON ( ( vol ati l e near unsigned char ) 0xFF2)
20 #define INTCON2 ( ( vol ati l e near unsigned char ) 0xFF1)
21 #define PIE1 ( ( vol ati l e near unsigned char ) 0xF9D)
22 #define PIR1 ( ( vol ati l e near unsigned char ) 0xF9E)
23 #define TMR0L ( ( vol ati l e near unsigned char ) 0xFD6)
24 #define TMR0H ( ( vol ati l e near unsigned char ) 0xFD7)
25 #define T0CON ( ( vol ati l e near unsigned char ) 0xFD5)
26 #define SPPCON ( ( vol ati l e near unsigned char ) 0xF65)
27 #define SPPCFG ( ( vol ati l e near unsigned char ) 0xF63)
28 #define ADCON2 ( ( vol ati l e near unsigned char ) 0xFC0)
29 #define ADCON1 ( ( vol ati l e near unsigned char ) 0xFC1)
30 #define ADCON0 ( ( vol ati l e near unsigned char ) 0xFC2)
31 #define ADRESL ( ( vol ati l e near unsigned char ) 0xFC3)
32 #define ADRESH ( ( vol ati l e near unsigned char ) 0xFC4)
33 #define RCSTA ( ( vol ati l e near unsigned char ) 0xFAB)
34 #define TXSTA ( ( vol ati l e near unsigned char ) 0xFAC)
35 #define TXREG ( ( vol ati l e near unsigned char ) 0xFAD)
36 #define RCREG ( ( vol ati l e near unsigned char ) 0xFAE)
37 #define SPBRG ( ( vol ati l e near unsigned char ) 0xFAF)
38 #define SPBRGH ( ( vol ati l e near unsigned char ) 0xFB0)
39 #define BAUDCON ( ( vol ati l e near unsigned char ) 0xFB8)
40 #define RCON ( ( vol ati l e near unsigned char ) 0xFD0)
41 #define WDTCON ( ( vol ati l e near unsigned char ) 0xFD1)
42 #define T2CON ( ( vol ati l e near unsigned char ) 0xFCA)
43 #define PR2 ( ( vol ati l e near unsigned char ) 0xFCB)
44 #define CCP2CON ( ( vol ati l e near unsigned char ) 0xFBA)
45 #define CCPR2L ( ( vol ati l e near unsigned char ) 0xFBB)
46 #define CCP1CON ( ( vol ati l e near unsigned char ) 0xFBD)
47 #define CCPR1L ( ( vol ati l e near unsigned char ) 0xFBE)
.z basico.h
O header basico.h possui o endereo de todos os registros do microcontrolador PIC18f4550 que
utilizado nesta apostila. Alm disso contm alguns denes importantes como as funes inline
para limpar a ag de watchdog e para manipulao de bits.
Notas de Aula ELT024 - Programao para Sistemas Embarcados
108 Anexos
.j Instalar gravadores/depuradores de PIC em sistemas x64
Os passos a seguir devem ser seguidos para instalar os device drivers corretamente em sistemas
operacionais de 64 bits. Atualmente apenas os seguintes aparelhos so suportados:
MPLAB REAL ICE in-circuit emulator
MPLAB ICE 2000 with USB converter
MPLAB ICD 2 (P/N 10-00397)
MPLAB ICD 3
MPLAB PM3 (P/N 10-00398)
PIC32MX Starter Kit
Antes de Comear
O dispostivo no deve ser plugado numa porta USB antes de comear a instalao do Driver.
Se voc j plugou o dispositivo e apareceu a informao "Novo hardware encontrado", clique
em cancelar. Desligue o dispositivo e continue com os passos a seguir.
Se voc j utilizou o setup do windows voc instalou os drivers errados. Siga as instrues
de remoo dos drivers antes de prosseguir.
Passo 1
Conecte o dispositivo ao PC usando o cabo USB. Para os dispositivos que exigem alimentao
externa, ligue-a. Se estiver usando um hub USB, tenha certeza que o este possui energia suci-
ente para alimentar o dispositivo.
Passo 2
A primeira vez que o dispositivo conectado aparece uma mensagem indicando que o sistema
encontrou um novo hardware. Quando aparecer uma janela, escolha a opo Localizar e insta-
lar o driver (recomendado) Nota: Se aparecer uma mensagem perguntando sobre permisso no
Windows 7, clique em sim/continuar.
Passo 3
Escolha a opo: Procurar o driver no meu computador (avanado)
Passo 4
Quando aparecer uma janela pedindo para voc indicar o caminho, procure em C:\Arquivos
de programa (x86)\Microchip\MPLAB IDE\Drivers64. Clique em continuar
Passo 5
A prxima tela ir perguntar se voc quer continuar a instalar o dispositivo. Clique em Instalar
para continuar.
Passo 6
A prxima tela indicar que o software foi instalado corretamente. Clique em fechar para termi-
nar a instalao.
Passo 7
Vericar se o driver est instalado e visivel no Gerenciador de dispositivos em Custom USB
Drivers>Microchip Custom USB Driver Abra a janela do gerenciador de dispositivos (Iniciar-
>Painel de controle->Sistema->Gerenciador de dispositivos). Se o driver no fora instalado
corretamente, continue na seo de soluo de erros (a seguir)
Notas de Aula ELT024 - Programao para Sistemas Embarcados
109 Anexos
Soluo de erros
Se houve algum problema na instalao do driver siga os passos a seguir.
O Windows tentar instalar o driver mesmo se no encontrar o arquivo correto. No gerenci-
ador de dispositivos dentro da opo Outros dispositivos voc deve encontrar um Dispositivo
no conhecido.
Clique com o boto direito no Dispositivo no conhecido e selecione a opo Atualizar o
Driver do menu.
Na primeira tela de dilogo selecione Procurar no meu computador pelos arquivos do driver.
Continuar a partir do passo 4.
Notas de Aula ELT024 - Programao para Sistemas Embarcados