Sie sind auf Seite 1von 64

LIVRO

UNIDADE 2

Microcontroladores e
Microprocessadores
Programao embarcada

Victor Gonalves de Carvalho Feitosa Perim


2017 por Editora e Distribuidora Educacional S.A.
Todos os direitos reservados. Nenhuma parte desta publicao poder ser reproduzida ou transmitida de qualquer
modo ou por qualquer outro meio, eletrnico ou mecnico, incluindo fotocpia, gravao ou qualquer outro tipo
de sistema de armazenamento e transmisso de informao, sem prvia autorizao, por escrito, da Editora e
Distribuidora Educacional S.A.

2017
Editora e Distribuidora Educacional S.A.
Avenida Paris, 675 Parque Residencial Joo Piza
CEP: 86041-100 Londrina PR
e-mail: editora.educacional@kroton.com.br
Homepage: http://www.kroton.com.br/
Sumrio

Unidade 2 | Programao embarcada 5

Seo 2.1 - Reviso de algoritmos e introduo linguagem C 7


Seo 2.2 - Programao em linguagem C 26
Seo 2.3 - Ambiente de trabalho e simulao 46
Unidade 2

Programao embarcada

Convite ao estudo
Na Unidade 1, estudamos os principais conceitos sobre os
sistemas de comutao, nesta segunda unidade, estudaremos
uma ferramenta fundamental no desenvolvimento de produtos
eletrnicos processados: a programao em linguagem C, com
nfase em sistemas embarcados. Para todos os componentes
de um programa em C existe um ou mais instrues equivalentes
em linguagem Assembly (ou de mquina), e no incio desse
estudo compreenderemos a correspondncia entre um cdigo
em C e o seu cdigo embarcado (linguagem de mquina), ou
seja, compilado em zeros e uns. Em seguida, relembraremos
todos os elementos bsicos para a construo de um programa
em C. Relembrar porque esperado que voc j tenha
estudado alguma linguagem de programao de mais alto
nvel sobre o Assembly, como Java, C, FORTRAN, BASIC, entre
outros presentes nos cursos de Engenharia e TI (Tecnologia
da Informao). Assim, esse estudo ser uma grande reviso
de conceitos e aplicaes da linguagem C, direcionados para
desenvolvimento de sistemas embarcados. Se voc j possui
grande experincia com a linguagem C, encontrar mais
facilidade nesta unidade. No entanto, no salte nenhum tpico,
o contedo aqui indispensvel para sua bagagem. Aproveite
para absorver todos os detalhes que no estavam claros,
alm das particularidades dos sistemas embarcados, como o
sincronismo de tarefas em tempo real. Por outro lado, se voc
no possui experincia sobre programao, ou j estudou,
mas de forma superficial, no se preocupe. Toda a informao
bsica necessria estar nesse material, com uma sequncia
e detalhamento pensados para tornar seu estudo completo e
eficaz. Ao fim das sees desta unidade, depois de estudar os
principais aspectos da linguagem C para microcontroladores,
aplicaremos a seguinte situao-problema:

Uma empresa de automao residencial consolidada no


mercado e preocupada em trabalhar com as tecnologias mais
modernas, sempre atualizando os seus projetos de produtos e
servios, contrata voc como o responsvel pelos projetos de
eletrnica e automao. Apesar de ainda no ter experincia
com perifricos, voc, ao fim desta unidade, estar pronto para
elaborar algoritmos e implement-los na linguagem C, para as
situaes mais simples.

Vamos comear?

6 U2 - Programao embarcada
Seo 2.1
Reviso de algoritmos e introduo linguagem C
Dilogo aberto

Agora que voc est ficando mais experiente com os sistemas


embarcados, e j sabe elaborar algoritmos bsicos e implementar
em um cdigo em Assembly, ser apresentado a um mtodo de
linguagem e algoritmos mais sofisticados. A linguagem C, com a sua
sucessora, C++, a mais utilizada atualmente para o desenvolvimento
de sistemas embarcados, pois completa para atender s
necessidades de desenvolvimento, abstrata, porm, permite acesso
direto memria, aos registradores e ao ncleo, e foi elaborada para
isso. Vamos estudar os elementos usados na programao em C,
como implementar algoritmos atravs dos comandos de controle,
aplicados para situaes mais complexas, como sincronismo de
tarefas paralelas em tempo real. Como visto anteriormente, voc deve
gerar uma soluo para o problema abordado nesta seo. Fique
tranquilo, pois aqui esto todas as informaes que voc precisa para
resolver esse problema sem grandes dificuldades. Apenas prossiga
em cada parte depois de ter realmente entendido o que leu. Nessa
situao-problema, voc foi contratado por uma renomada empresa
de automao residencial. Inicialmente, voc ser o profissional da
rea de eletrnica e automao, responsvel na criao um novo
projeto: um sistema de automao de um porto de garagem, a partir
de um controle remoto.
Como qualquer projeto, inicialmente so feitos vrios prottipos,
onde os primeiros so bsicos, e os seguintes vo recebendo novas
funcionalidades e adaptaes, o que permite uma melhor depurao
dos problemas que sempre aparecem. Dessa forma, essa primeira
proposta ser mais simples, apenas para gerar alguns resultados teis
no processo. Considerando que o chip usado para a construo do
equipamento ser um ATmega328, a sua atividade agora elaborar
um fluxograma, e a partir dele um programa bsico em C, que atue e
controle o porto de forma eficiente, a partir das trs entradas: boto
de acionamento (abre e fecha) - BOT, sensores fim de curso alto - SA,
e baixo - SB (detecta porto fechado). O porto pode ser acionado

U2 - Programao embarcada 7
pelo sistema atravs de duas sadas: um rel para subir - RS, e outro
para descer - RD, que claramente nunca podem ser acionados ao
mesmo tempo, pois danificaria o motor. Considere estes sinais de
entrada e sada como variveis binrias, assim, um teste para saber
o estado do boto pode ser feito: se BOT acionado faa, if (BOT
== 1) ou if (BOT) . O acionamento do rel para subir pode ser
executado: aciona RS ou RS = 1. Lembre-se de que voc pode
utilizar variveis de estado ou contadores. Uma das questes que
deve ser decidida antes de comear um projeto embarcado se o
circuito digital ser de lgica combinacional ou lgica sequencial,
para ento implementar o programa. Sabendo que, logo depois de
acionado, o porto no toca nenhum sensor fim de curso, at que
chegue no destino final, justifique no seu relatrio se o sistema que
voc criar deve possuir lgica sequencial ou combinacional, e quais
so as condies que definem essa escolha. Informe tambm se o
algoritmo do projeto deve ou no ser construdo obrigatoriamente
a partir de uma mquina de estados. Por fim, descreva no registro
interno de desenvolvimento desse novo modelo, como a lgica do
algoritmo pode ser implementada em um programa. Se o nico
mtodo conhecido por mquina de estados, ou se existe outra(s)
maneira(s), e qual(is) (so). Isso servir como parmetro de anlise
para voc e outros projetistas decidirem as estruturas dos prximos
algoritmos que sero feitos.
Temos trabalho pela frente, vamos l!

No pode faltar
Agora que voc j passou por ela, deve ter percebido o quo
importante foi o estudo da primeira parte, que so os fundamentos
de sistemas embarcados. Vamos ento entender como os programas
so escritos em linguagens de mais alto nvel e como as partes bsicas
estudadas se comportam durante a execuo desses programas.
Vale ressaltar a importncia de conhecer esses conceitos bsicos
para se tornar um bom profissional de eletrnica embarcada, pois no
processo de construo de sistemas mais complexos, comum que
apaream problemas ou comportamento inesperados, e se gasta
muito tempo em processos de debug, ou depurao. O profissional
que conhece todas as camadas est muito mais bem preparado para

8 U2 - Programao embarcada
resolver estas questes, e muitas vezes o problema se encontra nas
camadas inferiores, as que fazem interface com o hardware.

Cdigo Assembly equivalente


A linguagem C permite que trechos de cdigos mais longos,
complexos e trabalhosos de serem construdos em linguagem
Assembly sejam feitos de forma mais sinttica e simples. Essas
qualidades tornam o processo de programao muito mais eficiente,
o que ficar claro ao longo desta seo. Vale ressaltar que o tipo de
conjunto de instrues aplicado para os chips AVR o RISC (Reduced
Instruction Set Computer, ou computador com conjunto reduzido de
instrues (MARGUSH, 2011).

Pesquise mais
Veja as principais diferenas entre os dois tipos de conjunto de instrues
(tambm conhecidos como tipos de arquitetura ou de mquina)
no link a seguir. Disponvel em: <http://www.sistemasembarcados.
org/2015/11/15/processadores-arquitetura-risc-e-cisc/>. Acesso em: 26
jun. 2017.

Instrues de transferncia de dados


Os comandos para este tipo de ao em C so bem simples,
e todos eles utilizam o sinal de igualdade para transferir o
elemento que est direita para o elemento que est esquerda
da igualdade. Dessa forma, esse sinal ganha um novo significado
na programao, que pode ser chamado de recebe, ou seja,
a expresso X=X+1, incoerente matematicamente, deve ser
interpretada na programao como X recebe o valor anterior de
X mais um. Uma outra caracterstica importante da linguagem
C que no precisamos trazer os valores para os registradores
gerais antes de process-los, nem mesmo devolver os valores dos
resultados para a memria, uma vez que isso gerado de forma
automtica pelo compilador. Apesar de ser permitido, no uma
prtica em C escolher os endereos de memria para as variveis,
pois isso tambm responsabilidade do compilador.

U2 - Programao embarcada 9
Exemplificando
Podemos escrever em C, portanto, as instrues de movimento de
dados LDI, LDS, STS, IN, OUT e MOV, atravs do simples uso do smbolo
igual. Podemos ver um exemplo na Figura 2.1:
Figura 2.1 | Instrues em Assembly e comandos em C equivalentes

Fonte: elaborada pelo autor.

Instrues lgicas e aritmticas


So todas feitas atravs dos operadores lgicos e aritmticos,
diretamente escritos na forma convencional. Os operadores
aritmticos usados so: +, - * e /, e para as operaes lgicas: & (AND
ou E), | (OR ou OU), ~ (NOT ou NEGAO/INVERSO) e ^ (XOR
ou OU EXCLUSIVO). Lembramos que essas instrues so feitas bit
a bit, e no considerando a varivel como um nico elemento, ou
seja, 0x5A & 0xF0 0x50. Tambm podem ser usados parnteses
para representar expresses, ou mltiplas operaes. Dessa forma,
se as operaes envolverem apenas constantes, esse clculo feito
pelo compilador na hora da compilao, inserindo no programa a
ser embarcado apenas o resultado final. Por exemplo: VAR1 = (0x5A |
0xB2) & 0x0F. Vale relembrar que as operaes dentro dos parnteses
so feitas primeiro. Mais uma das vantagens da linguagem C a
compactao de operaes lgicas e aritmticas, como i++; ao invs
de i = i +1:, e x &= 0x01;, ao invs de x = x & 0x01;. Para deslocamento
(no circular) de bits, usamos >> ou <<. Ex.: x = 0xA2 >> 4; (x0x0A).
No entanto, quando as operaes dependem de alguma varivel,
ou seja, um valor que no pode ser previsto na criao do programa,
pois dado a partir das condies do sistema em que estaro sendo

10 U2 - Programao embarcada
executadas, as operaes lgicas e aritmticas so convertidas
automaticamente nas instrues em Assembly equivalentes pelo
compilador. Ex.: VAR1= (0x42 | VAR2) & VAR3.

Instrues de salto
Essas instrues em Assembly no esto diretamente mapeadas
em comando em C, mas existem alguns padres construdos a partir
delas que correspondem aos comandos de controle presentes em C,
que sero estudados mais adiante, ainda nesta seo: IF, IF/ELSE, FOR,
WHILE, DO WHILE, SWITCH, GOTO, BREAK e CONTINUE.
Lembrando que existem dois tipos de instruo de salto,
condicionadas e incondicionais. Podemos observar que as
instrues de salto condicionadas correspondem ao incio dos
comandos de controle, onde a condio testada para saber se o
bloco correspondente deve ser executado ou no. J as instrues
de salto incondicionais esto associadas aos trminos dos comandos
de controle, representado pelo fecha chaves (}), que indicam o fim
do bloco.

Exemplificando
Podemos observar tambm que, quando a condio para executar um
bloco ou trecho de programa no singular, ou seja, mltiplas condies
devem ser observadas para o tratamento, estas so feitas em Assembly
de forma sequencial, como pode ser visto no exemplo da Figura 2.2.
Figura 2.2 | Saltos em Assembly e comandos de controle em C com condies

Fonte: elaborada pelo autor.

U2 - Programao embarcada 11
A partir dessa estrutura em linguagem Assembly, correspondente
ao comando de controle IF, em linguagem C, podemos perceber
que os comandos em laos (loops) em C podem ser convertidos
para o Assembly na mesma forma, apenas com a adio de um
salto incondicional ao fim do trecho, com retorno para a condio
inicial, necessria para o programa entrar no lao (MAZIDI; NAIMI;
NAIMI, 2010).

Diretivas de compilao
As diretivas em C, que so indicadas pelo prefixo #, possuem
o mesmo papel que as estudadas para o Assembly, com algumas
pequenas modificaes:
#include - corresponde identicamente ao .INCLUDE usado
para incluir outros arquivos a serem considerados pelo compilador.
Essa diretiva muito usada quando se deseja criar programas em
mltiplos arquivos, ou programas modularizados, subdivididos em
funes, o que ser estudado por ns na prxima seo desta
unidade. Como feito anteriormente, haver, em todos os programas
em C criados por ns, o comando #include <avr/io.h> na primeira
linha, que o cabealho AVR padro, ou seja, contm todos os
nomes dos registradores para usarmos na programao, ao invs
de seus endereos.
#define - essa diretiva foi mencionada anteriormente e muito
utilizada por vrias linguagens de programao. Pode ser usada
para definir constantes ou macros, como era feito com a diretiva
de Assembly .EQU, que alm disso tambm era usada para definir
variveis. Em C, as variveis so simplesmente declaradas antes de
serem usadas, e possuem um escopo, que corresponde regio
do programa em que pode ser visualizada/acessada, estudados
logo adiante.
A diretiva em Assembly usada anteriormente para estipular o incio
do cdigo .ORG 0, no representada por uma outra diretiva em
linguagem C, mas pela funo main, que significa principal. Dessa
forma, foi estipulado para a linguagem C, que todas as funes
principais devem possuir o mesmo nome, main, (onde o programa se
inicia) diferente de algumas outras linguagens. Esta deve estar sempre
presente, mesmo que exista outras funes.

12 U2 - Programao embarcada
Estrutura do programa
Como foi estudado na seo anterior, todo o programa embarcado
segue o padro bsico de, quando ligado, executar a parte da
inicializao, onde o sistema configurado, e ocorre uma nica vez,
e em seguida entrar no seu ciclo de trabalho, onde permanece at ser
reiniciado. Dessa forma, com o uso de algum comando de iteraes,
devemos criar um loop infinito, ou seja, condicionado a uma exigncia
que ser sempre satisfeita, como pode ser visto na Figura 2.3.

Figura 2.3 | Estrutura bsica de um programa em C para sistemas embarcados


com AVR

Fonte: elaborada pelo autor.

Reflita
Se para um determinado produto ou projeto, a parte de inicializao ser
sempre igual (ela necessria) todas as vezes que este for iniciado, porque
os perifricos devem ser configurados novamente sempre que ligado?

Comandos de controle
Apesar de alguns terem sidos mencionados, vamos esclarecer
aqui o que so e como so usados esses comandos em linguagem
C, responsveis por ditar o fluxo do programa, equivalentes s
instrues de salto condicionais em Assembly. As condies lgicas
devem ser construdas com os operadores >, >=, <, <=, == (igual),
!= (diferente), ! (inverte), && e ||., onde estes dois ltimos so as
operaes lgicas AND e OR, respectivamente, mas no no modo
bit a bit, como vimos anteriormente, mas considerando a varivel

U2 - Programao embarcada 13
como um nico elemento, ou seja, o resultado da operao VAR1
&& 0x01 ser um valor booleano, verdadeiro ou falso, diferente
da operao VAR1 & 0x01, que resulta um vetor de bits. Note a
diferena entre == e = (recebe, e no, testa).
IF - significa a condio se, no modo: se a condio for
verdadeira, execute isto onde isto se refere ao trecho de programa
que est delimitado pelas chaves do respectivo IF. Por exemplo:
IF(VarPositiva==0){ Comando1; Comando2; } (BARNETT R. H.;
COX S.; O'CULL L. 2007).
Devemos ressaltar que para as decises lgicas, a linguagem
C considera qualquer valor diferente de zero como verdadeiro
(inclusive negativos), e o valor zero como falso. Dessa forma, o
comando em C acima pode ser reescrito na forma IF(!VarPositiva){
Comando1; Comando2; }.
Pois os comandos tambm sero executados apenas se a
VarPositiva for nula, uma vez que zero falso, e este est sendo
invertido pelo operador !, tornando a condio verdadeira.

Assimile
Apesar de no ser usual nem recomendado, um programa em C pode ser
escrito inteiro em uma linha, pois para o compilador isso no faz diferena,
os comandos so limitados pelo smbolo ;. A nica coisa que levada
em conta para distino de linhas so as diretivas de compilao e os
comentrios, que so tudo que vier depois de //, naquela linha. Podemos
usar tambm o modo /*comentrio */, que pode ser quebrado em linhas.

O comando de controle IF pode ou no ser acompanhado do ELSE.


Quando o programador no deseja que nada diferenciado seja feito
quando a condio no for verdadeira, o ELSE torna-se desnecessrio.
Entretanto, quando o tratamento de uma condio requer dois
casos diferenciados, o ELSE deve ser usado. Exemplo: IF(Var1==4){
comando1;}ELSE{ comando2;}.
Existe uma forma diferente para usar este comando, que usado
principalmente quando se deve escolher entre dois valores a serem
carregados para uma varivel, e a escolha depende de uma condio
lgica. atravs do operador ternrio: ? com :. Apesar do se
estar implcito, no se v a palavra IF nesse caso. Assim, IF(Var1==4)

14 U2 - Programao embarcada
{ Var2 = 0; }ELSE{ Var2 = 1;} pode ser reescrito na forma Var2 =
(Var1==4)? 0:1;. Apesar de incomum, esse operador tambm pode
ser usado genericamente. Por exemplo IF(Var1==4){cmd1; cmd2;}
ELSE{ cmd3; cmd4;} pode ser substitudo por (Var1==4)? (cmd1,
cmd2) : (cmd3, cmd4);. Lembrando que no necessrio o uso de
parnteses na condio dessa operao, mas ajuda na visualizao.
Existe uma outra particularidade do IF que poder no usar chaves,
mas, apenas se existir um nico comando (ou funo) dentro do
comando IF. Vale o mesmo para o ELSE, independentemente.
FOR - serve para criar laos (loops), geralmente com um nmero
especfico de repeties. Sua sntaxe composta por trs campos. O
primeiro corresponde aos comandos de inicializao, ou seja, tudo
que deve ser feito para preparar o programa para iniciar os loops. Esse
campo executado apenas uma vez, antes de iniciar o primeiro ciclo,
no sendo repetido em cada ciclo. O segundo campo corresponde
condio lgica, que ser verificada a cada iterao do lao, que ser
executada se a condio for satisfeita, ou seja, verdadeira. O programa
se mantm realizando os loops enquanto a condio for verdadeira,
e para quando a condio se torna falsa, continuando seu fluxo pelos
comandos seguintes ao lao FOR. O terceiro campo contm a instruo
que deve ser executada ao fim do ciclo, e geralmente o incremento
da varivel usada para contabilizar o nmero de ciclos. Esses campos
so separados pelo smbolo ; e, apesar da condio para execuo
do ciclo ser um nico bit, verdadeiro ou falso, presente no segundo
campo, os campos primeiro e terceiro podem ser independentemente
nulos ou mltiplos, tendo suas aes separadas por vrgula simples.
Podemos perceber tambm que, tanto os comandos de inicializao
dos laos, quanto os comandos feitos ao fim de cada loop, podem
estar fora dos campos do FOR que surtiro o mesmo efeito, mas serve
para melhor legibilidade. Assim, se uma rotina de trabalho A for feita 10
vezes seguidas, se usa FOR(int i=0; i<10; i = i+1){ RotinaA}.

Assimile
A rotina de trabalho corresponde a um trecho de programa, com as
instrues/comandos escolhidos em sequncia pelo programador,
responsveis por tratar/controlar/processar uma tarefa especfica. Por
exemplo, podemos fazer uma rotina para atualizar 8 leds com o valor do
resultado de uma operao, que pode ser genrica.

U2 - Programao embarcada 15
WHILE - significa enquanto. Esse comando de controle possui
apenas um parmetro, ou seja, um campo a ser preenchido, que
a condio que deve ser satisfeita para que o lao seja executado.
Geralmente, este comando usado para executar um nmero de
loops varivel, que no pode ser previsto no ato da programao.
muito utilizado para criar o loop infinito do programa, que foi visto
na Figura 1.12, na forma WHILE(1){loop infinito}, que tambm pode
ser escrito como FOR( ; ; ){loop infinito}. O exemplo anterior do FOR
tambm pode ser reescrito como : int i=0; WHILE(i<10){ RotinaA;
i++; }. Existe tambm uma variao desse comando, que utilizada
quando se deseja executar o lao antes de testar: DO{ RotinaA; i++;
}WHILE(i<10);.
SWITCH - significa chaveamento. til quando se deseja criar
um IF, porm, com mais de duas alternativas. Dessa forma, a varivel
testada no deve ser binria, mas possuir mais valores para associar
um tratamento a cada um de seus valores esperados. Muito utilizada
para se criar mquinas de estados, quando h mais de dois estados
(MIZRAHI, 2008).

Exemplificando
Uma situao pode ser tratada de acordo com o estado da varivel de
estado EstadoVar, que pode assumir de 0 at 3, visto na Figura 2.4:
Figura 2.4 | Uso do IF (a) e do SWITCH (b), em trechos equivalentes

Fonte: elaborada pelo autor.

16 U2 - Programao embarcada
BREAK - significa parada. Podemos perceber o seu uso na Figura
2.4. Este comando usado para interromper o trabalho em um lao
de repeties, que podem ser WHILE, FOR e SWITCH. Quando o
programa encontra esse comando, ele encerra as atividades daquele
ciclo e continua seu fluxo com os comandos seguintes ao lao.
Vale ressaltar que em caso de um break dentro de um loop, que,
por sua vez, est dentro de outro loop (como um WHILE dentro de
outro), este interromper apenas um lao, o primeiro acima dele.
No podemos esquecer de colocar esse comando ao final de todas
as opes do SWITCH, pois, caso contrrio, todas as alternativas
abaixo da selecionada sero executadas tambm (exceto se este
efeito for desejado, claro).
CONTINUE - significa continua. Deve estar dentro de um
lao, e quando o programa executa esse comando, as atividades
naquele ciclo so encerradas, como no break. No entanto, ao invs
do programa prosseguir com os comandos seguintes, ele volta a
realizar o prximo loop normalmente. Isso torna apenas os ciclos
em que foram executados o continue incompletos, sem a execuo
dos comandos que esto dentro do loop, e abaixo do continue.
GOTO - este comando desvia o programa para um rtulo que deve
estar em qualquer parte do programa, seguido de dois pontos. Apesar
da sua existncia, no aconselhvel a sua utilizao em programas
em linguagem C, uma vez que ele realiza saltos incondicionais no
software, tornando-o inelegvel e de difcil manuteno. Um outro
fator que confirma isso o fato de no existir nenhuma situao em
que o seu uso se faz necessrio (KERNIGHAN; RITCHIE, 1991).

Lgica de circuitos digitais: combinacional x sequencial


Voc provavelmente j ouviu falar desse tipo de classificao,
quando estudou circuitos lgicos ou digitais. De fato, um sistema
computacional ser sempre sequencial, uma vez que utiliza
memria, opera a partir de sinais de relgio, e executa as instrues
sequencialmente. No entanto, podemos classificar as aplicaes de
maneira independente, o que importante na anlise de programas
embarcados. De maneira direta, um circuito digital possui lgica
combinacional se este no utiliza memria (em conceito, e no
no chip), ou seja, no depende de eventos ocorridos no passado, e
suas sadas podem ser diretamente mapeadas a partir das entradas

U2 - Programao embarcada 17
atuais. Tambm no pode haver realimentao, ou seja, sadas
que dependem de alguma sada qualquer. Exemplo de aplicao
embarcada: Um led que acende quando um boto pressionado.
Caso a aplicao utilize algum valor do passado (memria), ou
qualquer realimentao, o sistema ser classificado como lgica
sequencial, no permitindo a existncia de sistemas hbridos.
Uma pergunta interessante : antes do sistema existir, como definir
qual ser sua classificao? Quando todas as sadas podem ser
diretamente mapeadas a partir das entradas, e esse mapeamento
se mantm para todos os instantes do processo, o sistema
combinacional (uma tabela verdade sem estados ou realimentao).
Caso contrrio, sequencial. Na automao de uma caixa dgua,
por exemplo. Quando nvel de gua est no meio, entre os sensores
alto e baixo (SB=1 e SA=0), o sistema no pode definir como ser
a sada da bomba, sem usar memria, pois pode estar nas fases
enchendo ou esvaziando. necessrio, ento, implementar uma
mquina de estados, ou usar realimentao, que a mesma coisa,
mas de maneira indireta.

Sincronismo de tarefas paralelas


Esse um tema que abrange tcnicas muito importantes para
o desenvolvimento de projetos para aplicaes de tempo real.
Dentre estas, a mais utilizada, e que serve para todas as situaes,
a utilizao de variveis como contadores, que a partir de uma base
de tempo de contagem, tambm conhecido como tick (instante,
momento), pode prover referncia de tempo para alguma tarefa do
programa. Essas tambm so conhecidas como tcnicas de timeout
(estouro de tempo). Dessa forma, se escolhe uma base de tempo
que seja um divisor inteiro comum para todos os perodos utilizados
pelas tarefas; se insere uma rotina de delay (atraso) no fim do loop
infinito com essa base (tick); e se declara um contador para cada
tarefa. Dessa forma, estas podem operar de maneira independente.

Exemplificando
Tarefa 1: Led1 (PortC) deve piscar em 5 Hz enquanto boto1 (PortA)
estiver acionado, e ficar apagado caso contrrio. Tarefa 2: O led2 (PortD)
deve trocar seu estado, apenas uma vez, depois do boto2 (PortB)

18 U2 - Programao embarcada
permanecer pressionado por dois segundos seguidos (veja a lgica,
abstraia o PortX).
Figura 2.5 | Sincronismo de duas tarefas independentes no ATmega328

Fonte: elaborada pelo autor.

Sem medo de errar


Na situao-problema desta unidade, uma empresa de
automao residencial consolidada no mercado, contrata voc
como o desenvolvedor de projetos de eletrnica e automao.
Voc recebeu a tarefa de elaborar um algoritmo bsico para o
controle de um porto de garagem. Voc deve, portanto, elaborar
um fluxograma para este algoritmo, e, a partir deste, um programa
em C. Este sistema automtico deve controlar o porto de forma
eficiente, a partir das trs entradas: boto de acionamento (abre e
fecha) - BOT, sensores fim de curso alto - SA, e baixo - SB (detecta
porto fechado). Sadas: um rel para subir - RS, e outro para descer
- RD. Voc deve, por fim, fazer uma anlise sobre a classificao da
lgica do sistema, em combinacional, ou sequencial, e quais foram
os critrios adotados, pois isso ser usado nas prximas aplicaes.
O comeo sempre mais complicado, mas uma boa forma de
iniciar imaginando o problema, de preferncia com o rascunho de
um desenho representando a situao. Deve-se anotar as variveis,
e imaginar o processo acontecendo, passo a passo, percebendo

U2 - Programao embarcada 19
como as variveis devem ser atualizadas em consequncia dos
eventos esperados. Por exemplo, vamos criar uma mquina de
estados binria, onde o sistema pode estar PARADO (zero) ou
MOVENDO (um), de acordo com a varivel de estados VAEST.
Imaginamos assim o sistema em seu estado inicial, ou seja, o
porto est fechado e parado, e a nica varivel no nula o SB
(detecta porto fechado). A nica ao seguinte a abertura do
porto, que s feita se o boto for acionado. Podemos perceber
que aqui devemos tratar o controle do porto de acordo com
uma condio, ou seja, o sistema deve, nessa condio (estado),
acionar o RS caso o boto seja pressionado. Podemos observar
tambm que possvel diferenciar se o porto est parado aberto
ou parado fechado, testando os estados dos sensores. Dessa forma,
o primeiro desvio do programa principal, que deve ocorrer para
iniciar a abertura do porto, pode ser IF((VAEST==0)&&(SB==1)
&&(BOT==1)){ VAEST=1; RS=1;}. Verifique que esta condio s
pode ser satisfeita se o porto estiver parado fechado e o boto for
pressionado, o que aciona o porto para descer e altera o estado do
sistema para MOVENDO. Note que esta mesma condio pode ser
simplificada para IF((!VAEST)&&(SB)&&(BOT)).
Agora que o porto est subindo (abrindo), devemos imaginar
qual a prxima atuao do sistema, que deve ser parar o porto
quando estiver totalmente aberto, indicado pelo sensor SA. Assim, a
condio a ser criada para isto pode ser IF((VAEST)&&(SA)){VAEST=0;
RD=0}. Percebemos que agora o porto est parado e aberto, e
nenhuma das duas condies anteriores so satisfeitas, como
desejado. A prxima ao agora fechar o porto quando o usurio
pressionar novamente o boto, e este tratamento requer a seguinte
condio lgica: IF((!VAEST)&&(SA)&&(BOT)){VAEST=1; RD=1;}, pois
ser satisfeita se o porto estiver parado aberto e o usurio acionar
o boto, fazendo o porto fechar. A ltima ao a ser feita para
fechar o ciclo parar o porto quando estiver fechado, que pode ser
realizado pelo tratamento: IF((VAEST)&&(SB)){VAEST=0; RD=0;}, o
que desliga o porto e devolve o conjunto para a primeira etapa do
processo. importante salientar que essa no a nica maneira de
se criar um algoritmo para este problema, mas uma verso simples
e direta. Outra forma de se fazer com uma mquina com 4
estados: PARABERTO, PARFECHADO, MOVSUB, MOVDESC, o que
torna a programao ainda mais fcil. Uma terceira maneira seria

20 U2 - Programao embarcada
sem usar variveis de estado, como pode ser visto na Figura 2.6.
No entanto, apesar de neste exemplo os estados no aparecerem
explicitamente, ainda existem e esto representados pelo uso das
sadas nas condies de tratamento, como se pode observar na
Figura, ou seja, se voc verificar, as sadas e os valores so RD=1
e RS=0, j sabe que o estado MOVDESC, sem precisar de uma
varivel para indicar. Sempre que o sistema depender de estados para
controlar as sadas, que podem ser representadas por realimentao
(sadas usadas como entradas, para tomar decises), dizemos que
o sistema sequencial. Isso significa que, pelo menos em algum
momento do processo, o sistema deve emitir sadas diferentes para
um mesmo estado das entradas. Por exemplo, quando o porto
est subindo, as entradas so todas nulas, e quando est descendo
tambm, mas a sada no igual nas duas situaes. Quando as
sadas podem apenas ser mapeadas a partir das entradas, ou seja,
para cada condio das entradas existe um acionamento nico das
sadas, dizemos que o conjunto combinacional, e isso depende da
natureza do problema.
Figura 2.6 | Primeira soluo proposta: com MDE: (a) diagrama da MDE; (b)
fluxograma; (c) programa

Fonte: elaborada pelo autor.

U2 - Programao embarcada 21
Figura 2.7 | Segunda soluo proposta: sem MDE: (a) fluxograma (b) programa

Fonte: elaborada pelo autor.

Se analisarmos com calma, podemos perceber que no cdigo da


primeira proposta existe um erro. Qual esse erro? Como podemos
consert-lo? O que deve ocorrer se o sistema for executado com o
programa nessa forma? (Dica: confira o diagrama e o fluxograma).
Se no encontrar, pergunte ao seu professor.

Avanando na prtica
Controle automtico de um misturador de tintas
Descrio da situao-problema
Voc trabalha em uma empresa de automao e est no
desenvolvimento do projeto de um misturador de tintas RGB - Red
Green e Blue (Vermelho, Verde e Azul). Sabendo que o sistema ser
operado a partir de ATmega328, voc recebeu a tarefa de elaborar um
programa em C que controle as trs sadas para as vlvulas das tintas,
independentemente. Quando o sistema est em funcionamento, cada
uma dessas vlvulas pode ser acionada de dois modos: atravs de
um pulso de largura estabelecida, ou chaveamento contnuo, como
o sinal de um clock (relgio), com frequncia tambm estabelecida.
O sistema que a sua equipe trabalha escravo (subordinado) de um
outro sistema de controle de mais alto nvel, ou seja, o seu programa

22 U2 - Programao embarcada
no decidir sobre os modos e os tempos de cada sada, apenas
far o acionamento e o controle a partir das informaes trazidas do
sistema mestre. Considere as duas variveis, compartilhadas entre os
dois sistemas, CMDATUALRGB, e FLAGCMDNOVO, onde esta ltima
indica se chegou um novo comando, e pode ser apagada pelo seu
programa. A primeira traz o comando, que pode ser sobrescrito, e que
segue as especificaes descritas na Figura 2.8:
Figura 2.8 | Especificaes do protocolo usado em CMDATUALRGB

Fonte: elaborada pelo autor.

Considere tambm uma sada para um alarme (lmpada), que


deve ser acionada (piscar em 1 Hz) se o sistema mestre ficar mais
de um segundo sem enviar comandos, ou se o campo d estiver
fora das especificaes. O alarme s deve cessar se receber o
comando desliga tudo (vlvulas).

Resoluo da situao-problema
Uma possvel soluo para o problema:

Figura 2.9 | Proposta para soluo do problema

Fonte: elaborada pelo autor.

U2 - Programao embarcada 23
Faa valer a pena
1. As diretivas de compilao so comandos que so usados pelo
compilador, mas no comandos que so instrues de um programa, e
ajudam o programador aumentando a legibilidade do cdigo.
A respeito das diretivas de compilao em linguagem C, voltada para o
microcontrolador ATmega328, qual das alternativas a seguir pode ser
considerada verdadeira?
a) A diretiva #define obrigatria para todos os programas embarcados e
deve ser usada para definir todas as variveis do programa.
b) A diretiva #include equivalente diretiva de Assembly .INCLUDE,
que utilizada para incluir algum arquivo para o seu programa. Apesar de
no ser obrigatrio, muito til na construo de programas embarcados,
principalmente na primeira linha: #include <avr/io.h>, incluindo os nomes
registradores para utilizao do programador.
c) A diretiva main(){ utilizada para definir onde o comeo da memria
de dados, ou seja, onde as variveis do programa estaro para serem
manipuladas. Todos os programas em linguagem C devem possuir pelo
menos uma diretiva dessa, indicando a passagem para o loop infinito.
d) A diretiva .EQU responsvel por registrar um valor em uma varivel,
mas que pode ser alterada posteriormente pelo cdigo atravs de outra
.EQU, diferentemente da diretiva #define, que associa uma varivel a um
valor definitivamente.
e) A diretiva while(TRUE) serve para indicar onde estar no cdigo o
loop infinito, que pode ser unitrio, mas pode ser mltiplo, se o programa
demandar muitos processamentos. Essa diretiva no existe em Assembly,
nem alguma correspondente.

2. A linguagem C permite que trechos de cdigos mais longos, complexos


e trabalhosos de se construir em linguagem Assembly sejam feitos de forma
mais sinttica, simples e abstrata, tornando o processo de programao
muito mais eficiente.

Fonte: elaborada pelo autor.

24 U2 - Programao embarcada
A respeito da comparao entre eles, qual das alternativas a seguir correta?
a) No so equivalentes, mas seriam se a varivel VARI1 fosse testada com o
valor zero ao invs de um, no trecho em C ( direita), e se a operao lgica
fosse XOR ^ (OU exclusivo), ao invs de OR ||(OU).
b) So perfeitamente equivalentes, ou seja, vo produzir o mesmo efeito se
forem processadas pelo ATmega328.
c) No so correspondentes, mas seriam se a primeira instruo de salto
condicionado em Assembly fosse BREQ ao invs de BRNE, e se a varivel VARI1
fosse testada com o valor zero ao invs de um no trecho em linguagem C.
d) No se correspondem, e teriam que ser reescritas de outra maneira, pois
no h nenhuma alterao que possa ser feita para torn-las equivalentes,
devido s suas estruturas no permitirem isso.
e) No so equivalentes, mas seriam se as duas variveis fossem testadas com
o valor zero ao invs de um, no trecho em C ( direita), e a operao lgica
fosse AND && (E), ao invs de OR || (OU), no mesmo trecho.

3. Um mesmo programa em linguagem C pode apresentar


comportamentos diferentes cada vez que for executado. Isso se deve
ao fato do programa no seguir sempre um mesmo caminho no seu
fluxograma, que no pode ser previsto durante a programao, pois
depende das condies que sero encontradas pelo sistema no momento
em que for executado.
Todos os programas em linguagem C que so capazes de tomar decises
possuem comandos de controle em seu corpo. A respeito desses
comandos, considere as seguintes afirmaes:
I O comando IF s pode ser usado com o ELSE e faz o programa percorrer
o menor caminho, que exigir menor processamento.
II O comando BREAK deve estar sempre dentro de um lao, e serve para
interromper a execuo desse lao, fazendo o programa continuar seu
fluxo com os comandos seguintes ao lao.
III O comando SWITCH serve para criar laos quando no possvel
prever quantas vezes o lao ser executado, e permite que o programa se
comporte de maneira diferente em cada vez que o lao for processado.
IV O comando CONTINUE serve para fazer o programa continuar pelo
seu fluxo normal, sem alterao ou salto. Deve ser inserido sempre ao fim
do loop infinito para o programa no cessar sua execuo, continuando
com um ciclo seguinte.
Quais das afirmaes podem ser consideradas verdadeiras ou falsas,
respeitando a ordem?

a) V, F, V, F. d) F, F, V, V.
b) F, F, F, V. e) F, V, V, F.
c) F, V, F, F.

U2 - Programao embarcada 25
Seo 2.2
Programao em linguagem C
Dilogo aberto

Nesta seo, estudaremos os ltimos aspectos da linguagem de


programao C, com nfase em sistemas embarcados e aplicaes
de tempo real. Para entender como esses elementos so devidamente
reunidos para a construo de uma soluo, vamos resolver algumas
questes mais avanadas sobre o problema desta unidade. Aqui,
estudaremos os tipos de dados mais avanados, como matrizes,
estruturas e ponteiros, alm das suas utilidades e aplicaes. Vamos
ver tambm como modularizar um problema complexo e pequenos
problemas especficos atravs das funes. Apesar de ainda no ter
experincia com perifricos, voc, aluno, ao fim desta unidade estar
pronto para elaborar algoritmos mais avanados e implement-los
na linguagem C, bem como resolver essa situao-problema. Nela,
uma empresa de automao residencial consolidada no mercado e
preocupada em trabalhar com as tecnologias mais modernas, sempre
atualizando os seus projetos de produtos e servios, contrata voc
como o responsvel tcnico de projetos de eletrnica e automao.
Assim que ingressou, voc recebeu a responsabilidade de elaborar
um algoritmo bsico para o controle de um porto de garagem.
Construa um fluxograma, e a partir dele um programa bsico em
C, que atue e controle o porto de forma eficiente, a partir das trs
entradas: boto de acionamento (abre e fecha) - BOT, sensores fim
de curso alto - SA, e baixo - SB (detecta porto fechado). O porto
pode ser acionado pelo sistema atravs de duas sadas: um rel
para subir - RS, e outro para descer - RD, que claramente nunca
podem ser acionados ao mesmo tempo, pois danificaria o motor.
Considere estes sinais de entrada e sada como variveis binrias,
assim, um teste para saber o estado do boto pode ser feito: se BOT
acionado faa, if (BOT == 1) ou if (BOT) . O acionamento do rel
para subir pode ser executado: aciona RS ou RS = 1. Agora que
j desenvolveu um algoritmo, voc foi requisitado para escrev-lo
em linguagem C, alm de inserir algumas adaptaes para o sistema
ficar mais robusto e preparado para a realidade. Os sinais continuam

26 U2 - Programao embarcada
sendo apenas variveis, e agora voc conta com mais dois sensores
digitais, um detecta a presena do veculo abaixo do porto - SP, para
evitar coliso, e o outro detecta sobrecarga (ou sobrecorrente) do
motor - SS, indicando bloqueio mecnico. Tambm foi adicionada
uma sada ligada a uma lanterna sinalizadora - LS, que deve piscar em
0,5 Hz quando o porto estiver em movimento ou aberto, e deve ser
desligada 5 segundos aps o fechamento do porto. O porto agora
deve fechar de forma automtica, caso o dono tenha esquecido,
10 segundos depois de permanecido aberto, sem risco de danificar
o carro, claro. Se durante o acionamento houver sobrecarga,
o motor deve parar, a lanterna piscar por 5 segundos em 2 Hz,
antes de desligar, e o porto deve voltar para sua posio anterior,
at completar o curso e parar. Para ter referncia de tempo, voc
deve usar a funo genrica delay_ms(X) (que gera um atraso de
X milissegundos na execuo do programa). No se esquea que,
durante o movimento, o sensor final no pode ficar longos perodos
(> 50 ms) sem ser verificado, pois se este for acionado e isso no
for detectado o quanto antes pelo sistema, o motor ficar ligado e a
parte mecnica ser danificada. Parece que essa uma tarefa bem
complicada, com muitas consideraes, mas se voc separar em
partes, pensando em uma considerao por vez, ver que consegue
facilmente criar todas em separado e depois unir em um nico loop
infinito. Vamos l!

No pode faltar
Depois de estudar os comandos de controle, responsveis pelas
decises sobre o fluxo do programa, nesta segunda seo, alm
dos tipos de variveis, estudaremos os aspectos mais avanados da
linguagem C.

Tipos de variveis
Todas as informaes manipuladas pelo programa devem
pertencer a algum tipo, ou seja, como seu valor representado
digitalmente, e qual so os valores mximos e mnimos permitidos.
int - tipo inteiro padro de tamanho oficial de 32-bit, apesar
de permitir outros tamanhos, de acordo com a arquitetura da
mquina que rodar o cdigo. Para ns, o AVR considera esse tipo

U2 - Programao embarcada 27
com tamanho de 16-bit, que pode assumir valores negativos, assim
o bit mais significativo representa o sinal e os demais a magnitude.
Portanto, vai de 215 at 215 1 . Pode ser escrita na forma mais
completa, signed int, que a mesma coisa.
unsigned int - tipo inteiro sem sinal, assume valores positivos
de 16-bit. Vai de 0 at 216 1 .
char - tipo caractere, que assume valores de 8-bit inteiros
sinalizados. Vai de 27 at 27 1.
unsigned char igual ao char, mas se for tratado como nmero
assume inteiros de 0 at 28 1. Os tipos char so geralmente
usados para tratar caracteres de texto, seguindo a tabela ASCII.
long - tipo inteiro sinalizado de 32-bit (ou o dobro do int),
podendo ir de 231 at 231 1.
unsigned long - tipo inteiro positivo de 32-bit. Vai de zero at
32
2 1.
float - tipo flutuante, assume valores fracionrios ou no
inteiros, sinalizados e que podem ter os valores de 3.4 * 1038 a
1.2 * 1038 , 0, e de 1.2 * 1038 at 3.4 * 1038 , preciso: 6 casas
decimais.
double - tambm tipo ponto flutuante, mas com 64-bit de
largura, vai de 2.3 * 10 308 a 1.7 * 10308 , com preciso de 15
casas decimais.
Converso de tipos: tambm chamado de typecasting
(moldagem de tipo), serve para ajustar um tipo de varivel
em outro, quando precisamos processar variveis diferentes
juntas. Apesar de no ser obrigatrio, pois este processo feito
automaticamente pelo compilador em caso de omisso,
extremamente recomendado o uso de typecasting, colocando
entre parnteses o novo tipo desejado, quando o formato do dado
precisar ser adaptado, como: float Pi = 3.14152; unsigned int Res;
Res = (unsigned int)(Pi / 0.5); //Res 6

Pesquise mais
Veja quais so as utilidades dos qualificadores de tipo: const, static, extern
e volatile. Disponvel em: <http://www.pontov.com.br/site/cpp/61-
aprendendo-o-c/242-parte-1-expressoes-em-c>. Acesso em: 20 jun. 2017.

28 U2 - Programao embarcada
Tipos complexos de dados
J estudamos os tipos primrios de variveis para a programao
em linguagem C, vamos agora estudar as matrizes, os ponteiros e as
estruturas de dados.
Matrizes - so elementos de um mesmo tipo que esto amarrados
pela matriz em que esto contidos. Podem ter quantas dimenses
forem necessrias, apesar de geralmente se utilizar apenas uma,
ou seja, variveis como vetores. As dimenses e os tamanhos da
varivel so definidos no momento em que ela declarada, sendo
as dimenses indicadas pelo nmero de pares de colchetes seguidos
ao nome da varivel, e os tamanhos de cada dimenso estipulados
pelo nmero dentro de cada par de colchete. Por exemplo: float
VarMatriz[4][2][6];. Essa matriz possui 3 dimenses, e 4, 2 e 6
representam a quantidade de elementos (float) em cada dimenso,
respectivamente. Como o ndice comea a ser contabilizado a
partir do zero, o ltimo elemento dessa matriz seria acessado como
VarMatriz[3][1][5] = 0.13142;, por exemplo. Quando se declara uma
matriz, deve-se definir o tipo dessa matriz, o que significa que todos
os elementos matriz sero desse mesmo tipo, apesar de poderem
carregar valores distintos. Dessa forma, se voc precisar ter caracteres
constantes representando as vogais para o seu cdigo, deve usar no
incio dele a declarao unsigned char Vetvogais[5]={a, e, i, o,
u};. Considerando que o primeiro elemento do vetor tem ndice
zero, se precisar transferir o caractere i para a varivel unsigned char
Vogalatual, deve usar o comando Vogalatual = Vetvogais[2];. Para
criar uma matriz de constantes, usa-se ; para separar as linhas. Por
exemplo, para se criar uma matriz, onde a primeira linha composta
pelos algarismos pares, e a segunda pelos mpares, voc deve declarar:
const unsigned int MatrizAlgs[2][5] = {0, 2, 4, 6, 8; 1, 3, 5, 7, 9};. O
nmero 7 pode ser acessado, posteriormente, por MatrizAlgs[1][3].
Vale notar, relembrando os primeiros conceitos estudados no incio
do nosso curso, que quando usado o prefixo const para declarar
constantes, esses valores so armazenados na memria de programa,
e no na memria de dados, pois como o nome diz, so constantes
e no precisam ocupar a memria voltil. Deve-se ressaltar tambm
que, exclusivamente para a declarao de constantes, os valores dos
tamanhos podem ser omitidos, uma vez que o compilador saber
seus tamanhos pela quantidade de elementos inseridos na matriz
no momento da declarao. Por exemplo: Vetvogais[]={a, e, i,

U2 - Programao embarcada 29
o, u};. O compilador saber pela atribuio que a matriz Vetvogais
possui 5 itens. Para variveis, se o seu programa for processar, por
exemplo, o peso (Kg) e a altura (m) de 10 pessoas, voc pode usar
a varivel composta float MatrizPesoAltura[2][10]; onde a primeira
linha armazenar o peso da pessoa 1 at a pessoa 10, e a segunda
linha a altura, igualmente. Assim, quando for armazenar o valor da
altura da ltima pessoa, que 1,76, deve usar MatrizPesoAltura[1][9]
= 1.760;
String - no existe de fato um tipo especial para texto, ou seja,
qualquer texto interpretado como uma sequncia, ou um vetor
de elementos tipo caractere. No entanto, a linguagem C permite
que vetores de caracteres possam ser expressados de forma mais
compacta. Assim, a declarao const char vetc[6]= {'T', 'e', 'x', 't', 'o',
'\0'}; pode ser feita como const char vetc[] = Texto;, considerando
que o compilador pe automaticamente o caractere especial \0
ao fim do vetor, o que indica o fim da string, alm de aumentar o
tamanho da string para 6.
Ponteiros - esse, geralmente, um tpico que traz muitas
confuses iniciais para os estudantes, no essencial para um
programa embarcado, mas traz muitos benefcios para a programao
com manipulao de matrizes. Um ponteiro uma varivel, mas que
no armazena um valor, mas sim um endereo de memria, onde
est o valor que deve ser acessado. Apesar da linguagem C tratar os
endereos das variveis de forma transparente para o programador,
vamos considerar que a varivel do tipo unsigned int Idade esteja no
endereo de memria de dados 0x0100, e que o valor atual dessa
varivel seja 28. Voc pode acessar esse valor durante o programa
atravs da transferncia direta VarAprocessar = Idade;. No entanto,
voc tambm pode acessar esse valor de maneira indireta, atravs
de um ponteiro. Primeiro deve-se declarar um ponteiro para o tipo
unsigned int, compatvel com a varivel a qual ele apontar, e deve
ser usado o prefixo * para indicar ao compilador que esta uma
varivel do tipo ponteiro: unsigned int *PontIdade. Considere que
este ponteiro est no endereo de memria de dados 0x0102. Vale
ressaltar que o smbolo asterisco est associado ao nome da varivel,
e no ao tipo, portanto as duas variveis poderiam ter sido declaradas
juntas: unsigned int Idade, *PontIdade;. Quando criado, o ponteiro
no possui um valor especfico, e deve ser carregado posteriormente
pelo programador com o endereo da varivel a ser apontada,

30 U2 - Programao embarcada
descrito pelo nome da varivel precedida de &. Como dito, o
programador no manipular diretamente o valor do endereo, mas,
para o nosso exemplo, ns sabemos que o valor 0x0100, e no 28,
ser ser transferido para o PontIdade em: PontIdade = &Idade;.
Interpreta-se: a varivel ponteiro PontIdade recebe o endereo
da varivel Idade, ou melhor, a partir de agora a varivel PontIdade
aponta para a varivel Idade. Isso significa que o valor de Idade pode
ser acessado indiretamente pelo ponteiro, atravs do smbolo *.
o mesmo usado para declarar uma varivel ponteiro, mas, quando
no est em uma declarao, assume um papel diferente, o que gera
confuso para muitos programadores. Este smbolo usado antes
da varivel ponteiro, indicando que o valor a ser transferido no o
que est dentro da varivel ponteiro, mas sim o que est na varivel
apontada pelo ponteiro. Dessa forma, para transferir o valor de
Idade (28) indiretamente atravs do ponteiro, j atualizado, usamos
o comando VarAprocessar = *PontIdade;. Interpreta-se: A varivel
VarAprocessar recebe o valor da varivel apontada pelo ponteiro
PontIdade. Note que se o smbolo asterisco no fosse usado, o valor
transferido para VarAprocessar seria 0x0100, que o valor que est
contido na PontIdade. Note tambm, que se por engano fosse usado
o smbolo & ao invs de *, o valor transferido para VarAprocessar
seria 0x0102, que o valor do endereo da PontIdade. Isso pode ser
visto na Figura 2.11:

Figura 2.11 | Valores na memria e consequncia de comandos em C para o


exemplo

Fonte: elaborada pelo autor.

Os ponteiros so muito utilizados na manipulao de matrizes,


e por isso, quando se deseja fazer um ponteiro apontar para um
vetor, geralmente para o primeiro elemento, ao invs de PontChar
= &Vetchar[0];, podemos usar PontChar = Vetchar;, que a mesma

U2 - Programao embarcada 31
coisa. Devemos notar tambm que, de fato, matrizes e ponteiros
so da mesma natureza, ou seja, podem ter os nomes usados um
no lugar do outro, se o ponteiro estiver apontando para o primeiro
elemento da matriz, claro. A grande diferena que o ponteiro
solto, no sentido de poder apontar para elementos diferentes durante
o programa, e a matriz no. Seria um ponteiro constante. Dessa
forma, depois de PontChar apontar para Vetchar[0], possvel usar
Pontchar[2] ao invs de Vetchar[2].

Exemplificando
verdade que para este caso anterior o uso do ponteiro no parece
muito til, foi apenas para informar as suas propriedades. Vejamos agora
um bom exemplo de utilizao do ponteiro. Considere uma rotina
para transmitir uma mensagem de texto, que pode ser escolhida entre
trs opes, atravs de um canal serial. O registrador fictcio BufferTX
usado para enviar os dados serialmente via hardware, e o registrador
FLAGBufferLivre usado para indicar que a ltima transmisso j
terminou e o canal est livre para a transmisso de um novo caractere. O
programa apresentado na Figura 2.12 pode ser usado para isso.

Figura 2.12 | Trecho de programa para transmitir caracteres

Fonte: elaborada pelo autor.

32 U2 - Programao embarcada
Devemos nos atentar para a manipulao aritmtica dos
ponteiros. Quando se incrementa um ponteiro, o seu valor no
simplesmente aumentado em uma unidade, e sim na quantidade
de bytes que correspondem ao tipo de varivel que ele aponta. Por
exemplo: float *pont; pont++;. O ponteiro ser aumentado em 4,
ou seja, vai apontar para a prxima varivel desse tipo. Alm das
matrizes, os ponteiros tambm so teis para acessar estruturas,
com o operador ->.

Pesquise mais
O uso das estruturas e ponteiros em linguagem C permitem manipulao
de formas avanadas de dados, o que pode servir para a criao de
estruturas de dados como rvores. Procure entender melhor como
isso feito. Disponvel em: <https://www.ime.usp.br/~pf/algoritmos/
aulas/binst.html> e <https://www.ime.usp.br/~pf/algoritmos/aulas/bint.
html>. Acesso em: 20 jun. 2017.

O typecasting de ponteiros deve ser escrito sempre que


necessrio. Segue a forma:
char Vet[3]; unsigned char *Pont = (char *)Vet;

Estruturas.
As estruturas de dados so semelhantes s matrizes, pois
agrupam vrios elementos. No entanto, esses elementos no
precisam ser do mesmo tipo, podendo, inclusive, criar estruturas
dentro de estruturas. As estruturas so de fato um novo tipo de
varivel, criado pelo programador, e pode ser um conjunto de
outras variveis de qualquer tipo. Desse modo, o programador
deve analisar, pela natureza do problema, quais devem ser os tipos
das variveis que comporo o conjunto, ou melhor, a estrutura.
Por exemplo, se um programa que manipular alguns valores
de caractersticas fsicas e pessoais, como: nome, peso, altura,
ano de nascimento, idade e CPF, pode ser definida a struct
CadastroPessoal, visto na Figura 2.13:

U2 - Programao embarcada 33
Figura 2.13 | Exemplo do uso de estrutura de dados

Fonte: elaborada pelo autor.

Typedef - serve para redefinir novos tipos de dados. Pode ser usado
para encurtar/abreviar nomes compostos de variveis. Por exemplo,
depois do comando: typedef const unsigned char cteUchar;, voc
pode declarar variveis do tipo citado como: cteUchar Letra = a;.
Tambm pode ser usado para no precisar escrever struct toda vez
que for declarar uma varivel a partir de estrutura. Assim, a varivel
declarada na Figura 2.13 struct cadastroPessoal Joao; poderia
ser reescrita como tcadastroPessoal Joao;, em conjunto com a
redefinio typedef struct cadastroPessoal tCadastroPessoal;, que
deve vir antes. Ateno que, um ponteiro que foi declarado a partir de
uma estrutura existente, ao ser incrementado em 1, ser adicionado
ao valor correspondente ao tamanho da estrutura, em bytes. Apesar
disto ser transparente para o programador, que apenas executa o
Pont++ para o ponteiro apontar para a prxima estrutura na memria,
em alguns casos importante saber o tamanho de uma estrutura,
que pode ser obtido pelo comando sizeof(nomedaEstrutura);. Ou
mesmo: unsigned int a = sizeof(float); //a4.

Funes
As funes so usadas para modularizar o programa, ou seja,
dividi-lo em partes para que o problema completo seja resolvido a

34 U2 - Programao embarcada
partir de tarefas menores, o que muito recomendado para a criao
de sistemas mais complexos. Alm disso, o uso de funes permite
reaproveitamento de cdigo, para que uma mesma tarefa que
usada em vrias partes do programa no precise ser reescrita. Uma
funo em programao possui os mesmos princpios das funes
matemticas. Descrever o comportamento de uma grandeza, que
a sada da funo, em funo de uma ou mais variveis de entrada.
Quando se define uma funo se define qual o tipo da varivel de sada
e qual o nome da funo, alm de quais so as variveis de entrada,
seus nomes e tipos. Apesar de em alguns casos haver a necessidade
de calcular mais de um valor de sada, cada funo pode retornar
um nico valor. No entanto, existem duas formas de contornar essa
questo: usando uma struct como varivel de sada, assim todos os
campos da estrutura podem ser retornados pela funo. Outra forma
alterar o valor de variveis acessadas globalmente, o que ficar mais
claro logo adiante.

Assimile
Os programas criados atravs de funes so chamados de
modularizados, e podem ser vistos como um processo em camadas,
onde cada camada corresponde a um grupo de funes. Dessa forma,
como todos os programas se iniciam na funo main, dizemos que
ela a primeira camada, e todas os comandos diretamente escritos na
main esto nessa mesma camada. Quando a funo main chama ou
invoca alguma outra funo dizemos que o programa desceu para
uma camada abaixo, e permanece nesta at que retorne para a camada
superior, ou seja, termine seu trabalho e volta para a main, ou invoca
uma terceira funo, desviando o programa para uma camada mais
abaixo. Como pode ser visto no fluxograma da Figura 2.14:
Figura 2.14 | Fluxograma para um programa modularizado

Fonte: elaborada pelo autor.

U2 - Programao embarcada 35
Podemos perceber que uma funo pode tambm no possuir
valores de retorno ou de entrada, ou que caracterizado pelo
indicador void, que significa vazio ou ausente. Por isso, comum
que nos programas embarcados utilizem a funo principal declarada
como: void main(void){, pois no invocada por nenhuma outra (
a raiz, ou a primeira camada), e no precisa de nenhum valor de
entrada e tambm de sada. No entanto, alguns compiladores utilizam
o padro genrico da linguagem C: int main(void){, mesmo que no
retorne nada, como o que usaremos.
A sintaxe padro para a declarao de uma funo a seguinte,
para duas entradas:
TipoVariavelSaida Nomedafuno(TipoVarEntr1 NomeVarEntr1,
TipoVarEntr1 NomeVarEntr2){
CorpoDaFuno;
Return ValordeSaida;
}

Exemplificando
Assim, para criar um programa modularizado simples, podemos usar
o exemplo para calcular a mdia de um conjunto numrico, com 2
elementos.
Figura 2.15 | Exemplo de programa modularizado equivalente Figura 2.14

Fonte: elaborada pelo autor.

36 U2 - Programao embarcada
Quando uma funo invoca outra que possui parmetros de
entrada, ele passa os valores das entradas que devem ser processados
pela segunda funo, mas no os transfere, e sim, os copia. Considere,
por exemplo, que a funo main invoca uma funo e passa a varivel
Var1 com o valor 10. Mesmo se a funo invocada alterar o valor
dessa varivel, ao retornar funo principal, a varivel conter o valor
antigo, sem a alterao, pois essa alterao foi feita em uma cpia, e
no na varivel original da main.

Escopo
Essa palavra pode parecer estranha, mas muito importante na
anlise de programas. Cada elemento do programa, como variveis,
funes e at definies possui um escopo associado a ele, ou
seja, qual a regio do programa em que ele est acessvel, o que
ele pertence. Dessa forma, se uma varivel criada dentro de uma
funo, ela s poder ser acessada dentro daquela funo, pois
considerada uma varivel local daquela funo. Nem mesmo as
funes que estiverem camadas abaixo podero acessar variveis
que foram declaradas em funes acima que a invocaram. Para criar
variveis globais, a declarao deve ser feita acima e fora da funo
main, e estas podem ser manipuladas por qualquer parte do programa.
Apesar de no ser como o comando GOTO, que no deve ser usado
em nenhuma ocasio, recomendado que o uso de variveis globais
seja evitado, exceto em algumas situaes bem especficas. Isso se
deve ao fato de que, se uma varivel ou regio da memria de dados
seja manipulada por vrias funes do programa, aumentam as
chances de conter valores indevidos, que foram alterados por outras
funes, quando uma certa funo for tratar esses dados. Por isso,
recomendado que cada funo manipule exclusivamente os dados
nela tratados, considerando as cpias que foram transferidas como
parmetro de entrada. As variveis globais so geralmente usadas para
trocar informaes entre a funo main e as rotinas de tratamento de
interrupes, o que ser estudado na prxima unidade.

Reflita
O que deve acontecer se existirem variveis globais e locais com o
mesmo nome? Sabendo que a linguagem C permite isso, o que deve

U2 - Programao embarcada 37
acontecer em um programa assim quando for executado? As variveis
se sobrepem, ou so tratadas em separado?

Modularizao em arquivos
Quando se trata de um programa com poucas funes, e que
so pequenas, a escrita pode ser feita em um nico arquivo. Caso
contrrio, recomendado que o programa, alm de modularizado
em funes, seja tambm escrito a partir de mltiplos arquivos. Isso
melhora o desenvolvimento do programa, pois cada parte tratada
individualmente, permitindo abstrair vrios outros detalhes que so do
projeto, mas no so relevantes naquele trecho. Tambm melhora a
legibilidade, pois um arquivo de programa que contenha muitas linhas
causa mais dificuldade ler o programa e encontrar partes especficas
para anlise. Podemos ver na Figura 2.16 como o exemplo da Figura
2.15 pode ser reescrito atravs de trs arquivos:
Figura 2.16 | Exemplo anterior modularizado em trs arquivos

Fonte: elaborada pelo autor.

Sem medo de errar


Vamos agora resolver a questo desta seo. Lembre-se
de que nessa situao-problema, uma empresa de automao
residencial contatou voc como o responsvel tcnico da rea de

38 U2 - Programao embarcada
projetos de eletrnica e automao. Inicialmente, voc recebeu a
responsabilidade de elaborar um algoritmo bsico para o controle de
um porto de garagem, atravs de um fluxograma. Em seguida, deve
fazer um programa em C, que atue e controle o porto de forma
eficiente, a partir das trs entradas: boto de acionamento (abre e
fecha) - BOT, sensores fim de curso alto - SA, e baixo - SB (detecta
porto fechado). Sadas: um rel para subir - RS, e outro para descer
- RD. Alm disso, voc conta com mais dois sensores digitais, um
detecta a presena do veculo abaixo do porto - SP, para evitar
coliso, e o outro detecta sobrecarga (ou sobrecorrente) do motor
- SS, indicando bloqueio mecnico. Tambm foi adicionada uma
sada ligada a uma lanterna sinalizadora - LS, que deve piscar em 0,5
Hz quando o porto estiver em movimento ou aberto, e deve ser
desligada 5 segundos aps o fechamento do porto. O porto agora
deve fechar de forma automtica, caso o dono tenha esquecido,
10 segundos depois de permanecido aberto, sem risco de danificar
o carro, claro. Se durante o acionamento houver sobrecarga, o
motor deve parar, a lanterna piscar por 5 segundos em 2 Hz, antes
de desligar, e o porto deve voltar para sua posio anterior, at
completar o curso e parar. Para ter referncia de tempo, voc deve
usar a funo genrica _delay_ms(X). No se esquea que, durante
o movimento, o sensor final no pode ficar longos perodos (>50
milissegundos) sem ser verificado, pois se este for acionado e isso no
for detectado o quanto antes pelo sistema, o motor ficar ligado e a
parte mecnica ser danificada. Inicialmente, recordaremos como foi
a soluo da situao-problema anterior, pois vamos aproveitar o que
foi feito l. Foi utilizada uma mquina de estados, com trs abordagens
diferentes. A ideia era simplesmente ligar o motor para subir o porto,
caso o boto fosse pressionado, e desligar quando o sensor fim de
curso alto for atingido. E para fechar o porto, a mesma coisa. Liga
para baixo quando o boto for pressionado, e desliga o motor quando
o sensor baixo for detectado. Agora, nessa nova situao, vamos tratar
algumas consideraes importantes, que podem ocorrer durante o
funcionamento do conjunto que deve estar preparado. Por exemplo,
na inicializao do sistema, sensato pensar que o porto pode ter
sido desligado sem terminar seu curso, entreaberto. Dessa forma,
o programa, quando iniciado, pode checar se o porto no est
completamente fechado com: if(SB), e, se no estiver, deve acionar
o porto at fech-lo. Devemos tambm considerar os sensores de

U2 - Programao embarcada 39
presena SP e de sobrecarga SS, para no causar nenhum dano fsico.
Se o SP acusar presena, o sistema deve desligar o motor e aguardar
que o objeto saia de baixo do porto, religando o motor novamente.
Isso pode ser feito atravs do comando de controle while(SP){ }, ou
seja, no faz nada enquanto SP==1. Se o SS acusar sobrecarga em
alguma situao do programa, este deve ser desviado para a funo
que trata da lanterna. Assim, a funo deve saber qual o sentido do
movimento do porto, para cima ou para baixo, para ligar novamente
o porto e verificar se a sobrecarga permanece, mesmo depois dos
5 segundos em que a lanterna acionada. O restante do programa,
ou seja, o loop infinito pode ser implementado como o programa
apresentado para a situao-problema anterior. A diferena que
agora o SS dever ser sempre verificado quando o motor estiver
acionado, e tratado com a funo citada, e o SP deve ser checado
quando o porto estiver descendo, ou seja fechando, conforme dito
anteriormente.
Figura 2.17 | Possvel soluo para a situao-problema

Fonte: elaborada pelo autor.

Avanando na prtica
Acionamento inteligente de uma lmpada
Descrio da situao-problema
Sua empresa de automao foi contratada para elaborar um
sistema de automao de uma lmpada na rea externa de um

40 U2 - Programao embarcada
condomnio, a partir de um sensor de presena. Voc foi incumbido
a desenvolver o software desse sistema, que possui apenas uma
entrada, um sensor de presena - SP, que estar conectado porta
A, e uma sada, o rel para ligar a lmpada - RL, que acionado
pela porta B do ATmega328. Voc descobriu que na verdade os
sensores disponveis no so de presena, mas de movimento, ou
seja, se uma pessoa permanecer imvel o sensor no detectar
sua presena. O sndico do condomnio te passou as seguintes
especificaes: a ideia desligar a lmpada quando no houver
ningum na rea externa com sinuca, para economizar energia,
mas a lmpada no deve ser ligada quando pessoas passarem na
calada em frente ao bar, o que pode ser detectado no SP. Por
isso, quando o SP detectar movimento, o sistema deve verificar se
o movimento ser novamente detectado nos prximos instantes,
o que confirma algum jogando sinuca, e no um pedestre
passando na calada. Desse modo, o sistema deve permanecer
por 3 segundos em uma condio de testar, filtrando o sinal de
presena. Nessa condio, se for detectado um intervalo de mais
de 0,5 segundo contnuo sem ocorrer movimento, o processo
deve descartar a presena de algum, mas se durante os 3
segundos isso no for detectado, algum est na rea e a lmpada
deve ser acesa. Depois disso, a lmpada deve permanecer acesa
incondicionalmente durante 10 segundos, e em seguida o sistema
decide se deve apagar ou deixar a lmpada acesa, a partir da
mesma condio citada. A partir dessas especificaes descritas,
uma outra equipe est responsvel por construir o hardware e as
instalaes, e voc deve construir um programa em C que controle
corretamente o acionamento da lmpada corretamente. Vamos l,
mos obra!

Resoluo da situao-problema
Para resolver essa questo, interessante recorrer ao clssico
e universal mtodo da mquina de estados, com trs estados:
AUSENTE, VERIFICAPRESENCA e PRESENCA. No primeiro, a
lmpada deve estar desligada, pois o sistema considera que a
rea externa com sinuca est vazia. Nesse estado, se o sistema
detectar movimento, pode ser algum passando na rua ou algum
que chegou na rea externa. A partir da o programa vai para o

U2 - Programao embarcada 41
segundo estado, onde vai verificar se a condio ser satisfeita para
ligar a luz. Para sincronizar as tarefas, podemos usar uma funo
delay_ms(10); ao fim do loop infinito, e usar contadores para
ter referncia temporal. Dessa forma, considerando que o loop
infinito ser executado a aproximadamente cada 10 ms, pois o
tempo de execuo do programa pode ser desprezado, podemos
usar dois contadores, um com contagem de 300, chamado cnt,
para contar os trs segundos e outro, cntaux, com 50 para contar
o 0,5 segundo. No devemos usar apenas um contador, porque
o primeiro contar continuamente os 3 segundos corridos e o
outro ser reatualizado diversas vezes, pois ser responsvel por
indicar o intervalo de tempo entre duas ocorrncias de movimento
consecutivas. Ainda nesse estado, os contadores devem
permanecer contando at algum dos dois contadores estourar,
ou seja, atingir seu limite de contagem. Se ocorrer primeiro com o
cntaux, significa que passaram 0,5 segundo sem o sensor detectar
movimento, e, portanto, um falso alarme. O programa deve ento
voltar para o primeiro estado, sem acender a lmpada. Se o cnt
estourar antes significa que os 3 segundos se passaram e o cntaux
no estourou nesse perodo. Isso apenas acontece se o cntaux for
reatualizado, retornando sua contagem a cada vez que o sensor SP
detectar movimento. Assim, se algum estiver se movimentando
no ambiente, o sensor SP gerar vrios pulsos de sinal seguidos,
com curtos intervalos. Isso far com que o programa reinicie a
contagem do cntaux muitas vezes durante os trs segundos, e o
cntaux no estourar. Quando os trs segundos se passarem, com
a continuidade do movimento detectada, o conjunto deve acionar
a lmpada e aguardar por 10 segundos. Em seguida, o teste dos 3
segundos realizada novamente, mas sem desligar a sada, pois
a(s) pessoa(s) ainda pode(m) estar l. Assim, se nesse intervalo for
detectado um perodo maior que 0,5 segundos sem o SP atuar
(cntaux estourar), a lmpada deve ser desligada e o sistema volta
para o primeiro estado. Caso contrrio, o sistema mantm a sada
acionada, seguindo para o terceiro estado, e assim por diante.

42 U2 - Programao embarcada
Figura 2.18 | Possvel programa como soluo do problema proposto

Fonte: elaborada pelo autor.

Faa valer a pena


1. A linguagem de programao C, assim como outras, composta por
um conjunto de regras de sintaxe e semntica, assim como as linguagens
humanas. Dessa forma, quando um programador desenvolve um cdigo
em linguagem C, ele deve conhecer e respeitar essas regras para que o
programa possa ser compilado e funcione conforme o esperado.

Sobre a programao de microcontroladores em linguagem C, observe as


seguintes afirmaes:

I Quando a funo Main() invoca uma outra funo, void Func1(int


a, intb);, por exemplo, no h a necessidade de usar valores para os
parmetros de entrada a e b, pois existe o indicador void, que significa
ausncia.
II A funo principal de qualquer programa embarcado pode possuir
qualquer nome, e considerada, para a abstrao de programa em
camadas, a funo raiz, ou seja, a primeira camada. Todas as outras
funes que forem invocadas pela principal tambm estaro na mesma
camada que a raiz, mas no podem retornar valores, apenas receb-los
para processamento.
III Todas as funes em C podem receber inmeros parmetros de
entrada, porm, todos esses dados devem ser do mesmo tipo. A nica
exceo quando se usa matrizes como sinais de entrada de uma funo.
IV As funes como na matemtica possuem apenas um retorno, que
para a programao foi estabelecido a possibilidade de retornar dois valores
alm de um, unicamente. No existe nenhuma outra maneira da funo

U2 - Programao embarcada 43
invocada retornar mais valores de sada para a funo que a chamou, para
este caso deve ser criada outra funo distinta, mesmo que o seu corpo
(interior) seja o mesmo.
Considerando a veracidade das afirmaes, qual das alternativas representa
a sequncia correta?

a) V, V, F, F.
b) F, F, F, F.
c) V, F, V, F.
d) F, F, V, F.
e) F, F, F, V.

2. Uma das facilidades da programao em linguagem C possibilitar o


manuseio de endereos das variveis, atravs dos ponteiros.

Considere a construo de um programa embarcado em linguagem C


para o ATmega328, onde a varivel tipo ponteiro, unsigned int *PontVet1;,
deve ser usada para acessar o terceiro elemento do vetor unsigned int
Vet1[10];. Utilizando a varivel unsigned int Var1;, qual das alternativas a
seguir representa a sintaxe e os comandos corretos para esta ao?

a) Var1 = Vet1[*PontVet1+3];, o que significa que o contedo do elemento


do vetor Vet1 indicado pelo ndice PontVet1 ser transferido para a Var1.
b) PontVet1 = *Vet1[2]; Var1 = &PontVet1;. O primeiro comando serve
para fazer o ponteiro apontar para o terceiro elemento do veto. O seguinte
busca o contedo do endereo apontado por PontVet1 e carrega para a
varivel Var1.
c) PontVet1 = Vet1; PontVet1+=2; Var1 = *PontVet1;. O primeiro comando
serve para fazer o ponteiro apontar para o primeiro elemento do vetor. O
segundo comando incrementa o ponteiro em dois endereos, fazendo ele
apontar para o terceiro elemento do vetor. O ltimo transfere o contedo
do endereo apontado por PontVet1 para a varivel Var1.
d) PontVet1 = &Vet1[3]; PontVet1++; Var1 = PontVet1;. O primeiro
comando serve para fazer o ponteiro apontar para o terceiro elemento do
vetor. O segundo comando incrementa o ponteiro para ele apontar para
o prximo elemento do vetor. O seguinte busca o contedo do endereo
apontado por PontVet1 e carrega para a varivel Var1.
e) PontVet1 = Vet1[3]; Var1 = &PontVet1;. O primeiro comando serve
para fazer o ponteiro apontar para o terceiro elemento do vetor. O ltimo
comando transfere o contedo do endereo apontado por PontVet1 para
a varivel Var1.

44 U2 - Programao embarcada
3. Na linguagem de programao C, alm das definies que podem ser
feitas com a diretiva #define, existem outras formas de se criar amarraes
de valores ou tipos de variveis.

Que utilidade o comando typedef apresenta na programao em


linguagem C?

a) O uso do typedef obrigatrio para todos os programas embarcados,


assim como o loop infinito, uma vez que responsvel por definir todos os
tipos bsicos das variveis que sero manipuladas pelo programa.
b) O typedef usado exclusivamente para estruturas de dados, pois
responsvel por associar os ponteiros e as estruturas que sero apontadas.
c) Esse comando especial tem como finalidade criar tipos de dados
universais, que podem ser utilizados na criao de outros programas,
atravs de atualizaes distribudas pela internet.
d) O typedef serve para a manipulao de matrizes, quando estas possuem
mais de duas dimenses. A partir da necessrio que esse tipo composto
de dados seja representado atravs de estruturas, definidas pelo typedef.
e) Este comando serve para redefinir novos tipos de dados. Pode ser usado
para encurtar/abreviar nomes compostos de variveis. Por exemplo, depois
do comando: typedef const unsigned char cteUchar;, voc pode declarar
variveis do tipo citado como: cteUchar Letra = a;.

U2 - Programao embarcada 45
Seo 2.3
Ambiente de trabalho e simulao
Dilogo aberto

Voc deve estar ansioso para comear a colocar em prtica


os conhecimentos adquiridos. Calma! Esse momento chegou,
enfim. Nesta seo, estudaremos todos os passos para colocar um
programa escrito em linguagem C para ser executado na placa
Arduino UNO. Vamos apresentar o programa que ser usado como
ambiente de trabalho, o AtmelStudio, criado pela prpria fabricante
do microcontrolador ATmega328, a Atmel. Depois de configurar o
software AVRDude para descarregar o cdigo para o Arduino, atravs
do AtmelStudio, criaremos um simples programa de teste (pisca o
Led) para transferi-lo para a placa, provavelmente o momento mais
empolgante desse curso, quando a teoria ganha vida, se torna real!
Depois que voc implementar e executar esse programa bsico,
estar pronto para criar programas mais complexos para serem
descarregados na placa, como os estudados anteriormente por ns,
mesmo ainda sem conhecer os perifricos. Para consolidar esse
estudo, vamos resolver as ltimas questes da situao-problema
desta unidade. Nela, uma empresa de automao residencial
consolidada no mercado contrata voc como o engenheiro de
projetos de eletrnica e automao. Assim que ingressou, voc
recebeu a responsabilidade de elaborar um algoritmo bsico para o
controle de um porto de garagem. Voc j elaborou o fluxograma
e o programa para uma situao mais simplificada na primeira seo.
Depois, voc criou um programa mais elaborado, considerando
todos os detalhes pertinentes para o controle avanado de um porto
de garagem, com o uso de funes. Agora a parte final do projeto,
que a prototipagem. Logicamente, no necessrio construir
um sistema completo, em um porto de garagem de verdade, mas
podemos descarregar o mesmo programa em uma placa, e usar 5
chaves e dois leds para representar as entradas do sistema e os dois
rels de sada, respectivamente. Apenas para o boto de acionamento
deve ser usado um boto do tipo push button (no retentivo). As

46 U2 - Programao embarcada
demais entradas, que so os sensores, so representadas por chaves
retentivas, que mantm o ltimo estado imposto (chaves retentivas).
Vamos l, mos obra!

No pode faltar
Agora que j estudamos todos os aspectos fundamentais dos
microcontroladores, e em especfico o ATmega328, estamos prontos
para criar os primeiros experimentos prticos para um sistema
embarcado.

Arduino
Como dito anteriormente, a placa que usaremos a Arduino UNO,
que se assemelha a um tutorial, mostrando passo a passo como o seu
computador pessoal ser configurado devidamente para podermos
usar a placa com sucesso. Voc pode usar alguma das placas que
esto disponveis no laboratrio da sua faculdade, que deve ser
feito atravs do seu professor. Alm disso, se voc se interessar pelo
assunto, placas como estas so bem acessveis para ter em casa, para
voc iniciar seu prprio projeto. A placa Arduino UNO pode ser vista
na Figura 2.19:
Figura 2.19 | Placa Arduino UNO

Fonte: <https://goo.gl/B6fCXn>. Acesso em: 31 maio 2017.

Afinal de contas, o que significa Arduino? E qual a sua relao


com a AVR, ou Atmel? De fato, estes no so a mesma coisa, ou
seja, no pertencem ao mesmo fabricante. O Arduino um projeto
open source (fonte aberta), ou aberto para uso e isento de direitos
autorais, que surgiu na Itlia com o objetivo de criar uma plataforma
de programao de sistemas embarcados, onde muitos detalhes
de projeto de hardware e software so pr-construdos, o que
torna o processo de prototipagem muito mais rpido. Acontece

U2 - Programao embarcada 47
que os inventores da plataforma Arduino escolheram, entre outros
concorrentes, os microcontroladores AVR, fabricados pela empresa
Atmel, para compor as suas placas, e o modelo ATmega328P para
o modelo UNO, a mais popular. Apesar de existir muitos exemplos
variados prontos para serem compilados e transferidos para placa -
o que timo para atingir resultados mais rpidos, partindo de um
ponto j feito e funcionando - o nosso foco aqui no trabalhar sobre
a plataforma Arduino. O objetivo do curso estudar os aspectos e
a programao de microcontroladores e microprocessadores, e
utilizaremos a estrutura do Arduino, que se tornou acessvel para
aplicar esses conceitos e construir sistemas reais e completos, ao
invs de simplesmente pegar prontos, sem saber como foram feitos.

Configurao do AtmelStudio
Devemos ressaltar tambm que o nico sistema operacional
abordado ser o Windows, e se voc possui outro, como Linux ou
IOS, deve procurar seguir as instrues, que so muito semelhantes
a estas, no site oficial. Disponvel em: <http://www.atmel.com/tools/
atmelavrtoolchainforlinux.aspx>. Acesso em: 17 jul. 2017.
Antes de conectar a placa ao seu computador, instale os dois
aplicativos seguintes, que sero utilizados para criar e transferir nossos
programas para a placa.
O Arduino IDE: <https://www.arduino.cc/en/Main/Software>.
Acesso em: 17 jul. 2017.
E o AtmelStudio: <http://www.atmel.com/tools/atmelstudio.
aspx#download>. Acesso em: 17 jul. 2017.
O primeiro a IDE - Integrated Development Environment, ou
ambiente de desenvolvimento integrado, composto pelo editor de
programas e compilador da Arduino, que no sero utilizados por
ns para criar programas. Aproveitaremos apenas alguns arquivos
e programas presentes em sua pasta de instalao para realizar a
gravao do microcontrolador atravs do software Atmel Studio,
atravs da sua ferramenta AVRDude, que ser integrada ao AtmelStudio.
Esse segundo software o ambiente de desenvolvimento criado
pela prpria fabricante do microcontrolador ATmega328, como se
pode perceber no nome. Deve-se levar em considerao a verso do
aplicativo disponvel, que atualmente em 2017 a stima, mas pode
ser incrementada com o tempo, e apresentar pequenas alteraes.

48 U2 - Programao embarcada
Configurao do AtmelStudio7
Depois que estiver instalado os dois programas citados, conecte
a sua placa Arduino UNO ao computador atravs do cabo USB. O
Arduino se comunica com o computador pessoal atravs de um canal
serial, ou seja, o computador enxerga o Arduino como uma porta
serial, igual aquelas que existiam nos antigos PCs, usadas para conectar
teclados e outros. Obviamente, essa ser uma porta serial virtual, uma
vez que est sendo emulada atravs de uma porta USB. Todas as
portas seriais criadas nos PCs, em particular no Windows, recebem um
nmero identificador. Para descobrir qual nmero a sua placa UNO
recebeu, v em Painel de controle, em seguida hardware e sons
e depois gerenciador de dispositivos. Verifique qual a porta COM
como na Figura 2.20, que no meu caso a porta COM3:

Figura 2.20 | Gerenciador de dispositivos do Windows

Fonte: elaborada pelo autor.

Agora que voc tem essa informao, abra o programa


AtmelStudio7. Depois de aberto, clique na opo de aba tools
(ferramentas) e depois em external tools..., conforme mostra a
Figura 2.21:

Figura 2.21 | Adicionando ferramenta externa ao AtmelStudio7

Fonte: elaborada pelo autor.

U2 - Programao embarcada 49
Agora, para adicionar uma ferramenta, clique no boto Add
(adicionar), como mostra a Figura 2.22:
Figura 2.22 | Adicionando ferramenta externa ao AtmelStudio7

Fonte: elaborada pelo autor.

Depois de abrir o Atmelstudio7:


Agora voc deve preencher os campos conforme os passos a
seguir, os quais se referem a comandos tcnicos muito especficos,
que no sero explicados nesta seo por no apresentarem
relevncia.
1. No campo Title, ou ttulo, escreva Gravador Arduino, que
ser o nome usado para a ferramenta externa. Se quiser, altere
o nome como preferir.
2. No campo Command, ou comando, escreva a sequncia:
C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/
avrdude.exe. Note que para este caso, o Windows est na
verso em ingls. Caso o seu esteja em portugus, altere
o comeo da sequncia de Program Files para Arquivos
de Programas. Verifique tambm, antes de concluir, se
o AVRDude est mesmo instalado no local indicado pelo
endereo.
3. No campo Arguments, ou argumentos, escreva: -C"C:\
Program Files (x86)\Arduino\hardware\tools\avr/
etc/avrdude.conf" -v p atmega328p -carduino
PCOM3 -b115200 -D U flash:w: "$(ProjectDir)
Debug\$(TargetName).hex":i. Novamente, repare que est
em ingls e precisa ser alterado, caso necessrio, assim
como no campo Command. Repare tambm que voc
deve ajustar o seu nmero da PCOM, de acordo com o valor
verificado em alguns passos atrs.

50 U2 - Programao embarcada
4. Deixe habilitada a opo Use Output Window, no canto
inferior esquerdo.
5. Clique em Ok.
Depois de completar os campos conforme indicado, sua tela deve
mostrar como na Figura 2.23:
Figura 2.23 | Preenchimento dos campos para o AVRdude

Fonte: elaborada pelo autor.

Agora tudo est configurado e pronto para funcionar, falta apenas


criar um projeto, fazer um programa e descarregar na placa para ver
funcionando.

Criando um projeto
Para criar um novo projeto, clique em File, New, Project,
conforme a Figura 2.24:
Figura 2.24 | Criando um projeto novo

Fonte: elaborada pelo autor.

Agora, escolha o tipo de projeto, que para ns ser sempre o GCC


C, conforme a Figura 2.25:

U2 - Programao embarcada 51
Figura 2.25 | Especificando o tipo de projeto a ser criado

Fonte: elaborada pelo autor.

Em seguida, escolha o modelo do microcontrolador que receber


o programa compilado, que no nosso caso o ATmega328P. Depois
disso, o AtmelStudio te entrega um programa esqueleto com apenas
a funo principal, a incluso do cabealho e o loop infinito.

Exemplificando
Vamos criar agora um exemplo bem bsico para visualizar o seu efeito na
placa, atravs do seu Led. Preencha a sua main.c como na Figura 2.26.
Figura 2.26 | Primeiro programa exemplo a ser compilado

Fonte: elaborada pelo autor.

52 U2 - Programao embarcada
Observe todos os comandos do programa, e perceba que todos
eles j foram estudados por ns nas sees anteriores. Apesar de j
ter sido mencionado, a funo de delay (atraso), que simplesmente
congela o processamento durante alguns instantes, para ser usada na
prtica, depende do uso de uma biblioteca especfica do AtmelStudio,
e de uma definio antes.

Assimile
No esquea de incluir o arquivo de delay, que j possui as funes de
delay prontas, precisando apenas que seja definido antes no programa
a frequncia de relgio que ser utilizada, atravs do indicador F_CPU.

Finalmente, para descarregar o programa na sua placa UNO,


ou melhor, fazer o download do programa, clique em Tools e em
seguida em Gravador Arduino, ou o nome que voc tenha escolhido
para a ferramenta externa. Quando clicado, o programa compilado
descarregado para a placa, que comea a execut-lo logo em seguida.

Reflita
Depois de rodar o cdigo pronto, faa algumas mudanas nele para ver
o comportamento, como alterar o valor de delay para 50 ou 5000 ms.

Lembre-se de salvar o programa antes de compilar, ou configure


para o AtmelStudio fazer isso de forma automtica.

Proteus ISIS
Agora vamos configurar o ambiente de simulao para nossos
projetos. Inicialmente, baixe e instale a verso gratuita do programa na
primeira opo (Proteus professional demonstation) do site: <https://
www.labcenter.com/downloads>.
Depois de abrir o programa, clique em File, New Project
Wizard, (ou no cone destacado na Figura 2.27). Escolha um nome
para o projeto e um local (pasta de arquivos) no seu computador.

U2 - Programao embarcada 53
Figura 2.27 | Especificando o tipo de projeto a ser criado

Fonte: elaborada pelo autor.

Clique em next. Depois disso, selecione a segunda opo Create


a schematic.... Escolha a opo para o tamanho da rea do seu
esquemtico, Lanscape A2, por exemplo. Clique em next. Nessa
prxima tela no h mudana, uma vez que a criao de placas de
circuito impresso no o nosso foco. Portanto, selecione Do note
create PCB layout e clique em next. Agora tambm no altere,
mantenha a escolha: no firmware Project. Clique em next. Confira
e clique em Finish.
Agora, clique no cone P, destacado pelo crculo vermelho na
Figura 2.28. No campo de pesquisa, no canto superior esquerdo
da janela Pick Devices, digite ATmega32 e escolha o modelo do
dispositivo (pode ser com ou sem o 8P no final), conforme mostra
a Figura 2.28:
Figura 2.28 | Escolha do modelo do microcontrolador usado no projeto

Fonte: elaborada pelo autor.

Clique em qualquer lugar na rea para inserir o chip no projeto.


Clique novamente no P, e agora escreva led. Pode ser qualquer um,
como o da Figura 2.29:

54 U2 - Programao embarcada
Figura 2.29 | Adicionando leds ao projeto

Fonte: elaborada pelo autor.

Antes de inserir no projeto, possvel rotacionar a posio do


led, logo acima do boto P, ao lado esquerdo da imagem geral do
projeto. Insira dois leds ao lado do microcontrolador, e os conecte
nas portas clicando nos terminais que devem ser conectados.
Aps isso, precisamos prover um sinal de GND (ground), ou sinal
TERRA. Para isso, clique no cone no canto esquerdo, Terminals
Mode, destacado em vermelho na Figura 2.30, e em seguida em
GROUND, destacado em azul. Insira um sinal GND e o conecte aos
leds e ao chip:
Figura 2.30 | Especificando o tipo de projeto a ser criado

Fonte: elaborada pelo autor.

Botes e resistores podem ser adicionados pelo mesmo processo.


Agora, para carregar o Atmega32 com o programa que compilamos,
d duplo clique no chip que aparece no projeto. Voc deve clicar no
smbolo de pastas no campo Program File (destacado em vermelho
na Figura 2.31) e encontrar no explorador de arquivos o programa
(.hex) que foi gerado no projeto do AtmelStudio, geralmente em
C:\Users\nome\Documents\Atmel Studio. Outro campo deve ser

U2 - Programao embarcada 55
ajustado, o CKSEL fuses:, destacado em azul). Se no quiser adicionar
cristais, utilize uma fonte de relgio interna, o IntRC_8MHz, por
exemplo. Clique em Ok.
Figura 2.31 | Embarcando o programa e selecionando a fonte de relgio

Fonte: elaborada pelo autor.

Por fim, depois de tudo devidamente conectado e configurado,


clique na seta de play, no canto inferior esquerdo da tela principal
(em azul), e aguarde por at uns 5 segundos. Se no houver erros no
procedimento ou no cdigo, o modelo deve representar o processo
corretamente. Agora voc pode simular todos os exerccios e
exemplos que vimos, alm dos seus prprios projetos, para encontrar
e tratar os possveis erros que aparecem. A partir de agora no vamos
tratar apenas de termos tericos, pois os perifricos so muito
teis em aplicaes reais, e j temos as ferramentas para simular e
implementar de fato sistemas mais simples.

Pesquise mais
Para saber um pouco mais sobre plataforma de desenvolvimento de projetos
com Arduino da Atmel, consulte o link a seguir. Disponvel em: <https://
www.embarcados.com.br/atmel-studio/>. Acesso em: 26 jun. 2017.

Sem medo de errar


Vamos agora resolver a questo desta seo. Na situao-
problema desta unidade, uma empresa de automao residencial
contrata voc como o engenheiro de projetos de eletrnica e
automao. Voc recebeu a responsabilidade de elaborar um
algoritmo bsico para o controle de um porto de garagem.
Depois de elaborar o fluxograma com o algoritmo necessrio, voc
implementou a soluo em um programa embarcado. Primeiro foi
adotada uma forma simplificada para o problema, para servir de base

56 U2 - Programao embarcada
para o projeto final, incluindo detalhes para um controle avanado
de porto de garagem. Chegou a hora de simular e tambm emular
esse sistema. Simular virtualmente em um programa de simulao,
e a palavra emular significa construir na prtica, mas que funciona
de maneira equivalente, no igual. Isso se d ao fato de que no
automatizaremos um porto verdadeiro, mas descarregaremos
o cdigo no Arduino e emular o processo atravs de entradas
e sadas figurativas, chaves e leds. Isso significa que se todo o
resto da parte externa for construdo de fato em um porto de
garagem verdadeiro, o sistema funcionar corretamente. O seu
funcionamento deve respeitar as seguintes exigncias tcnicas de
projeto de um porto de garagem, que atue e controle o porto de
forma eficiente, a partir das trs entradas: boto de acionamento
(abre e fecha) - BOT, sensores fim de curso alto - SA, e baixo - SB
(detecta porto fechado). Sadas: um rel para subir - RS, e outro
para descer - RD. Alm disso, voc conta com mais dois sensores
digitais, um detecta a presena do veculo abaixo do porto - SP, para
evitar coliso, e o outro detecta sobrecarga (ou sobrecorrente) do
motor - SS, indicando bloqueio mecnico. Tambm foi adicionada
uma sada ligada a uma lanterna sinalizadora - LS, que deve piscar
em 0,5 Hz quando o porto estiver em movimento ou aberto, e
deve ser desligada 5 segundos aps o fechamento do porto. O
porto agora deve fechar de forma automtica, caso o dono tenha
esquecido, 10 segundos depois de permanecido aberto, sem risco
de danificar o carro, claro. Se durante o acionamento houver
sobrecarga, o motor deve parar, a lanterna piscar por 5 segundos
em 2 Hz, antes de desligar, e o porto deve voltar para sua posio
anterior, at completar o curso e parar. Para ter referncia de tempo,
voc deve usar a funo genrica _delay_ms(X). No se esquea
que, durante o movimento, o sensor final no pode ficar longos
perodos (>50 milissegundos) sem ser verificado, pois se este for
acionado e isso no for detectado o quanto antes pelo sistema, o
motor ficar ligado e a parte mecnica ser danificada. Inicialmente,
vamos recordar como foi a soluo da situao-problema anterior,
pois vamos aproveitar o que foi feito l. Foi utilizada uma mquina de
estados, com trs abordagens diferentes. A ideia era simplesmente
ligar o motor para subir o porto, caso o boto fosse pressionado,
e desligar quando o sensor fim de curso alto for atingido. E para
fechar o porto, a mesma coisa. Liga para baixo quando o boto for

U2 - Programao embarcada 57
pressionado, e desliga o motor quando o sensor baixo for detectado.
Agora, nesta nova situao, vamos tratar algumas consideraes
importantes, que podem ocorrer durante o funcionamento do
conjunto, que deve estar preparado. Por exemplo, na inicializao
do sistema, sensato pensar que o porto pode ter sido desligado
sem terminar seu curso, entreaberto. Dessa forma, o programa,
quando iniciado, pode checar se o porto no est completamente
fechado com: if(SB), e, se no estiver, deve acionar o porto at
fech-lo. Devemos tambm considerar os sensores de presena SP
e de sobrecarga SS, para no causar nenhum dano fsico. Se o SP
acusar presena, o sistema deve desligar o motor e aguardar que
o objeto saia de baixo do porto, religando o motor novamente.
Isso pode ser feito atravs do comando de controle while(SP){ },
ou seja, no faz nada enquanto SP==1. Se o SS acusar sobrecarga
em alguma situao do programa, este deve ser desviado para a
funo que trata da lanterna. Assim, a funo deve saber qual o
sentido do movimento do porto, para cima ou para baixo, para ligar
novamente o porto e verificar se a sobrecarga permanece, mesmo
depois dos 5 segundos em que a lanterna acionada. O restante
do programa, ou seja, o loop infinito pode ser implementado como
o programa apresentado para a situao-problema anterior. A
diferena que agora o SS dever ser sempre verificado quando o
motor estiver acionado, e tratado com a funo citada, e o SP deve
ser checado quando o porto estiver descendo, ou seja fechando,
conforme dito anteriormente.

Figura 2.32 | Possvel soluo para a situao-problema

Fonte: elaborada pelo autor.

58 U2 - Programao embarcada
Avanando na prtica
Automao de uma lmpada inteligente
Descrio da situao-problema
Vamos agora emular o problema de avanando na prtica
da seo anterior, a 2.2. Nela, sua empresa de automao foi
contratada para elaborar um sistema de automao de uma
lmpada na rea externa de um bar, a partir de um sensor de
presena. Voc foi incumbido a desenvolver o software desse
sistema, que possui apenas uma entrada, um sensor de presena
- SP, que estar conectado porta A, e uma sada, o rel para
ligar a lmpada - RL, que acionado pela porta B do ATmega328.
Voc descobriu que na verdade os sensores disponveis no so de
presena, mas de movimento, ou seja, se uma pessoa permanecer
imvel, o sensor no detectar sua presena. O dono do bar
passou as seguintes especificaes: a ideia desligar a lmpada
quando no houver ningum na rea externa com sinuca, para
economizar energia, mas a lmpada no deve ser ligada quando
pessoas passarem na calada em frente ao bar, o que pode ser
detectado no SP. Por isso, quando o SP detectar movimento, o
sistema deve verificar se o movimento ser novamente detectado
nos prximos instantes, o que confirma algum jogando sinuca,
e no um pedestre passando na calada. Desse modo, o sistema
deve permanecer por 3 segundos em uma condio de testar,
filtrando o sinal de presena. Nessa condio, se for detectado
um intervalo de mais de 0,5 segundo contnuo sem ocorrer
movimento, o processo deve descartar a presena de algum, mas
se durante os 3 segundos isso no for detectado, algum est na
rea e a lmpada deve ser acesa. Depois disso, a lmpada deve
permanecer acesa incondicionalmente durante 10 segundos, e
em seguida o sistema decide se deve apagar ou deixar a lmpada
acesa, a partir da mesma condio citada. Faa um programa em C
que controle corretamente o acionamento da lmpada conforme
as especificaes.

Resoluo da situao-problema
Para resolver essa questo, interessante recorrer ao clssico
e universal mtodo da mquina de estados, com trs estados:

U2 - Programao embarcada 59
AUSENTE, VERIFICAPRESENCA e PRESENCA. No primeiro, a
lmpada deve estar desligada, pois o sistema considera que a
rea externa com sinuca est vazia. Nesse estado, se o sistema
detectar movimento, pode ser algum passando na rua ou algum
que chegou na rea externa. A partir da o programa vai para o
segundo estado, onde vai verificar se a condio ser satisfeita para
ligar a luz. Para sincronizar as tarefas, podemos usar uma funo
delay_ms(10); ao fim do loop infinito, e usar contadores para
ter referncia temporal. Dessa forma, considerando que o loop
infinito ser executado a aproximadamente cada 10 ms, pois o
tempo de execuo do programa pode ser desprezado, podemos
usar dois contadores, um com contagem de 300, chamado cnt,
para contar os trs segundos e outro, cntaux, com 50 para contar
o 0,5 segundo. No devemos usar apenas um contador, porque
o primeiro contar continuamente os 3 segundos corridos e o
outro ser reatualizado diversas vezes, pois ser responsvel por
indicar o intervalo de tempo entre duas ocorrncias de movimento
consecutivas. Ainda nesse estado, os contadores devem
permanecer contando at algum dos dois contadores estourar,
ou seja, atingir seu limite de contagem. Se ocorrer primeiro com o
cntaux, significa que passaram 0,5 segundo sem o sensor detectar
movimento, e, portanto, um falso alarme. O programa deve ento
voltar para o primeiro estado, sem acender a lmpada. Se o cnt
estourar antes significa que os 3 segundos se passaram e o cntaux
no estourou nesse perodo. Isso apenas acontece se o cntaux for
reatualizado, retornando sua contagem a cada vez que o sensor SP
detectar movimento. Assim, se algum estiver se movimentando
no ambiente, o sensor SP gerar vrios pulsos de sinal seguidos,
com curtos intervalos. Isso far com que o programa reinicie a
contagem do cntaux muitas vezes durante os trs segundos, e o
cntaux no estourar. Quando os trs segundos se passarem, com
a continuidade do movimento detectada, o conjunto deve acionar
a lmpada e aguardar por 10 segundos. Em seguida, o teste dos 3
segundos realizado novamente, mas sem desligar a sada, pois
a(s) pessoa(s) ainda pode(m) estar l. Assim, se nesse intervalo for
detectado um perodo maior que 0,5 segundo sem o SP atuar
(cntaux estourar), a lmpada deve ser desligada e o sistema volta
para o primeiro estado. Caso contrrio, o sistema mantm a sada
acionada, seguindo para o terceiro estado, e assim por diante.

60 U2 - Programao embarcada
Figura 2.33 | Possvel programa como soluo do problema proposto

Fonte: elaborada pelo autor.

Faa valer a pena


1. Todas as funes escritas na linguagem C devem sempre mostrar os
tipos e os nomes dos parmetros de entrada e de sada, no momento da
declarao, descrio e invocao. Mesmo quando no existe nenhum
parmetro de entrada ou de sada, este deve ser indicado pelo termo void.
Analisando os microcontroladores AVR programados em linguagem C, por
que a funo main do AtmelStudio precisa do retorno int ao invs de void,
apesar de no retornar nada, e para ningum?
a) Porque esse programa em especfico retorna um valor inteiro para o
compilador, no momento da compilao, indicando que o programa
foi escrito corretamente e est pronto para ser descarregado no
microcontrolador.
b) Porque a Atmel, para o AtmelStudio, escolheu utilizar o padro universal
para a linguagem C, onde a main retorna um valor para o sistema
operacional. Como feito nos computadores, a empresa resolveu manter
esse padro, mesmo sem utilizar o comando de retorno return XX; ao
final da funo main, o que no seria nunca executado por causa do loop
infinito.
c) Porque todos os programas embarcados so obrigados a manipular
pelo menos uma varivel do tipo inteiro, primordial para os processos.
d) Na verdade, esse retorno no necessrio, funciona apenas para
aumentar a legibilidade do programa, mas pode ser omitido sem nenhum
problema.
e) O termo int mostra que o tipo de varivel mais complexo que ser usado
pelo programa ser o inteiro. Assim, o programa pode manipular dados
char sem problemas. No entanto, se o programa manipular dados do tipo
flutuante, o termo int deve ser substitudo por float.

U2 - Programao embarcada 61
2. As memrias usadas internamente aos microprocessadores e
microcontroladores so diferentes e apresentam utilidades especficas.
Existem as memrias de dados, que podem ser volteis ou no, e a
memria de programa.
O programa descarregado no microcontrolador Atmega328 vai para qual
de suas memrias internas?

a) Memria Cache.
b) Memria EEPROM.
c) Memria FLASH.
d) Registradores de propsito geral.
e) Memria RAM.

3. A linguagem de programao C muito utilizada para desenvolvimento


de programas embarcados, e conta com uma coleo de regras de sintaxe
e de semntica, que devem ser conhecidas e respeitadas pelo programador.
Para um programa embarcado em linguagem C, desenvolvido para o
microcontrolador ATmega328, onde um Led est ligado a uma sada na
porta digital B, por que o comando PORTB^=0xFF; responsvel por
inverter o estado do Led?

a) Porque esse um comando especial para os microcontroladores da
famlia AVR, e, apesar de no ter nenhuma ligao com operaes lgicas,
um comando responsvel por inverter os estados da sada, tambm
conhecido em ingls como toggle.
b) Porque esse comando representa uma operao lgica AND, e em cada
vez que ela executada, o estado da sada do Led invertido.
c) Na verdade, esse comando no responsvel por inverter o estado das
sadas conectadas porta B, mas, sim, por apenas acionar os seus bits.
Dessa forma, esse comando est sempre acionando as sadas, ao invs de
ligar uma vez, e desligar na prxima, assim sucessivamente.
d) Esse comando uma abreviao do comando de atualizao do
registrador de E/S para a porta B, onde o prximo valor ser o resultado
do valor atual com a operao XOR (ou exclusivo) com os bits 0b11111111.
Essa operao lgica faz com que todos os bits da Porta B sejam invertidos,
independente dos seus estados.
e) Porque todas as vezes que uma porta configurada como sada digital
recebe algum comando com o operador ^, os seus estados so
automaticamente alternados para o outro valor binrio, o que se mostra
muito til em alguns casos especiais.

62 U2 - Programao embarcada
Referncias
BARNETT, R. H.; COX S.; O'CULL, L. Embedded C programming and the Atmel AVR. 2.
ed. Nova York: Delmar Cengage, 2007.
KERNIGHAN. B. W.; RITCHIE, D. M. The C programming language. 2. ed. New Jersey:
Prentice Hall. 1991.
LIMA C. B. D; VILLAA, M. V. M. AVR e Arduino tcnicas de projeto. Florianpolis: [s.n.],
2012.
MARGUSH, T. S. Some assembly required: assembly language programming with the
AVR microcontrollers. Nova York: CRC Press, 2011.
MAZIDI M. A.; NAIMI S.; NAIMI S. AVR microcontroller and embedded systems: using
assembly and C. Nova York: Pearson, 2010.
MIZRAHI, V. V. Treinamento em linguagem C. Nova Jersey: Pearson, 2008.
STALLINGS, W. Arquitetura e organizao de computadores. 8. ed. So Paulo: Prentice
Hall, 2009.

U2 - Programao embarcada 63