Escolar Documentos
Profissional Documentos
Cultura Documentos
PROPÓSITO
A manipulação de bases numéricas e álgebra booleana utilizadas nos sistemas computacionais é
primordial para o profissional dominar os mecanismos de compilação e programação em
linguagem C para sistemas embarcados.
PREPARAÇÃO
Não há pré-requisitos operacionais.
OBJETIVOS
MÓDULO 1
MÓDULO 2
MÓDULO 3
MÓDULO 4
INTRODUÇÃO
Você pode observar que a tecnologia baseada em computadores se torna cada vez mais
incorporada em produtos eletrônicos. É até difícil identificar produtos eletrônicos recentes que não
tenham algum sistema computacional integrado para controlá-lo, que podemos chamar de sistema
embarcado ou embutido. Como resultado, os sistemas embarcados são encontrados, atualmente,
em todos os tipos de equipamentos eletrônicos e dispositivos. Desde pequenas quantidades de
processamento, em itens como um temporizador eletrônico de uma cafeteira, a sistemas
incorporados muito mais complexos, como consoles de jogos, televisores e até mesmo na
automação de grandes fábricas e sistemas industriais, os sistemas embarcados se tornaram
onipresentes.
Neste conteúdo, entenderemos a importância dos sistemas embarcados, como eles se
desenvolveram e as suas aplicações. Na caminhada para dominar a programação em sistemas
embarcados, começaremos com a identificação dos sistemas de numeração usados e as regras da
álgebra booleana. Veremos também uma introdução à linguagem mais utilizada na programação
de sistemas embarcados, a linguagem C.
MÓDULO 1
Foto: Shutterstock.com
Um exemplo representativo de nossa vida diária, incorporando tais sistemas, são os telefones
celulares ou smartphones. Os smartphones de última geração fornecem ao usuário um conjunto de
funcionalidades altamente sofisticadas, incluindo funções de comunicação, streaming de vídeo,
música e acesso à Internet, com uma qualidade de serviço muito satisfatória. Em parte, isso se
tornou possível graças à melhoria significativa dos circuitos que compõem o sistema embarcado,
com grande capacidade de integração de dispositivos.
Bom, você pode estar discordando da afirmação de que um smartphone é um sistema embarcado.
Com tantas funções, como não atribuir a esse aparelho uma classificação de computador, como
você já deve ter ouvido várias vezes?
Essa é uma boa discussão para desenvolvermos. As discordâncias, que, nesse caso, podem
deixar de existir daqui a algum tempo, são benéficas para o entendimento mais profundo sobre
sistemas embarcados. Vamos voltar a essa discussão após verificarmos o histórico de
desenvolvimento e os aspectos gerais sobre os sistemas embarcados.
COMENTÁRIO
Todos nós vivemos no presente e planejamos o futuro nos vários aspectos de nossa vida. Mas,
para saber exatamente para onde estamos indo, primeiro precisamos entender de onde viemos.
Para isso, precisamos de uma apreciação da História para compreendermos a nossa identidade.
Isso não é diferente para o profissional quando se trata da história de desenvolvimento das
tecnologias com as quais ele trabalha, como os sistemas embarcados, em nosso caso.
No início do projeto, o Computador de Orientação Apollo foi considerado o item mais arriscado no
projeto, pois empregava os circuitos integrados (CIs) monolíticos recentemente desenvolvidos para
reduzir o tamanho e o peso.
Desse modo, o primeiro computador a usar CIs ajudou os astronautas a coletar dados de voo em
tempo real.
Temos aqui um primeiro termo que nos permite identificar um tipo muito comum de sistema
embarcado: tempo real.
ATENÇÃO
Não confundir com o jargão, comum no dia a dia, de se referir a tempo real como algo que ocorre
enquanto as pessoas estão assistindo a algo ou esperando, neste caso, um intervalo considerado
curto para a observação, mas não necessariamente dentro de um período determinado.
Nem todos os sistemas embarcados são de tempo real, como veremos em uma classificação mais
adiante, embora este seja predominante.
Em 1961 foi criado o computador de orientação Autonetics D-17, que foi um dos primeiros
sistemas embarcados produzidos em massa, para o míssil Minuteman.
Em 1968, o primeiro sistema embarcado para um veículo foi lançado: o Volkswagen 1600, que
usava um microprocessador para controlar seu sistema de injeção eletrônica de combustível.
COMENTÁRIO
Na década de 1960, com as primeiras aplicações, o preço dos sistemas embarcados caiu e houve
um grande aumento no poder de processamento e na funcionalidade. O desenvolvimento dos
sistemas embarcados passou a se confundir com o dispositivo mais utilizado nesses sistemas, o
microcontrolador.
Em 1971 foi desenvolvido pela Texas Instruments o primeiro microcontrolador: a série TMS1000,
que se tornou comercialmente disponível em 1974, contendo um processador de 4 bits,
integrando memória somente leitura (ROM) e memória de acesso aleatório (RAM). Nessa mesma
época, um microprocessador, o Intel 4004, foi projetado para calculadoras e outros sistemas
pequenos, mas ainda exigia memória externa e chips de suporte.
COMENTÁRIO
ATENÇÃO
Embora, nesse contexto, um sistema embarcado seja geralmente mais complexo do que uma
solução tradicional, a maior parte da complexidade está contida no próprio microcontrolador.
Poucos componentes adicionais são necessários e a maior parte do esforço de projeto passa para
o software embarcado, também conhecido como firmware .
O protótipo e o teste do firmware podem ser mais rápidos em comparação com o projeto e a
construção de um novo circuito sem processador embutido.
Hoje, o Linux é usado em vários dispositivos embarcados, como os que se baseiam nos
computadores de placa única e tamanho reduzido, incluindo os Raspberry Pi e o BeagleBone.
Embora usem técnicas semelhantes às dos computadores, eles não podem ser utilizados como um
computador de uso geral, que tem uma variedade de programas diferentes para tarefas diferentes.
Dessa forma, sua função pode ser focada no que eles precisam fazer, tornando-os mais baratos e
eficientes.
Assim, podemos definir um sistema embarcado como qualquer sistema de computador contido em
um produto que não seja descrito como um computador.
Uma definição mais completa foi dada por Henzinger e Sifakis (2006):
“Um sistema embarcado é um sistema de computador para fins especiais que consiste em uma
combinação de componentes de software e hardware sujeitos a restrições físicas. Essas restrições
físicas vêm do ambiente do sistema e de sua plataforma de execução”.
Assim, um sistema embarcado está em interação com seu mundo externo, também conhecido
como seu ambiente, que pode ser, por exemplo, um processo físico, alguns dispositivos técnicos
em um sistema maior ou algum operador humano. Sua função consiste em abastecer seu
ambiente conectado com serviços específicos, como, por exemplo, a observação, a supervisão ou
o controle de uma planta industrial.
Essa função específica de um sistema embarcado o torna um sistema de computador para fins
especiais, em contraste com os sistemas de computador para fins mais gerais, como
computadores de mesa ou laptops.
Observe o uso de sensores, para capturar dados do ambiente, e dos atuadores, que atuam em
movimentos de motores, por exemplo, para estabelecer o controle. Dentro do controlador principal,
temos o firmware que gerencia as entradas e saídas de interface com o usuário, mostrador e
botões, por exemplo. Como todo sistema computacional, o sincronismo é realizado por um circuito
de relógio (clock ).
Os sistemas embarcados, em sua maioria, são gerenciados por microcontroladores, mas também
por microprocessadores e processadores digitais de sinais (DSP), estes com firmwares
embarcados.
FPGAs podem ser reprogramados, mas não os ASICs. Assim, não existe para os mesmos a
possibilidade de alterar a funcionalidade depois da fabricação.
FPGAs e ASICs podem acionar componentes externos com grande quantidade de portas para
manuseio de interfaces elétricas diversas.
No caso dos sistemas embarcados que integram um software, para que o sistema cumpra sua
função, cada parte deve fornecer ao projetista vantagens específicas:
Bare Metal ‒ significa que não há, de fato, nenhum sistema operacional. Essa é a
abordagem original de trabalho com sistemas embarcados, e trata-se, ainda, da mais
popular, por ser econômica e eficiente. Na programação bare metal , escreve-se um
firmware , executado diretamente no hardware, sem ter a abstração subjacente dos sistemas
operacionais. Geralmente, os programas bare metal terão um carregador de programa
(bootloader ) mínimo para iniciar o processador, o relógio e a memória, saltando para o
programa principal.
RTOS ‒ significa "sistema operacional de tempo real". Um sistema RTOS fornece garantias
exatas em relação ao tempo em que as operações serão concluídas, trazendo o que há de
bom no Bare Metal , que não possui sistema operacional.
Linux ‒ ele se comporta mais como um "computador real", o que é ótimo por muitas razões.
No entanto, por causa disso, não fornece garantias de determinismo no tempo de execução.
Raspeberry pi e BeagleBone estão nessa solução.
Ser classificado em uma categoria não exclui a classificação em outra. Assim, um sistema pode
ser autônomo, de tempo real e móvel, como, por exemplo, uma câmera digital.
CÂMERA DIGITAL
As câmeras que usamos hoje são inteligentes e têm muitos recursos que não estavam presentes
nos primeiros modelos, tudo por causa do sistema embarcado usado nelas. Uma câmera digital
tem basicamente três funções:
Armazenar esses dados da imagem.
Apresentá-los.
Funções adicionais, como foco automático, alteração da imagem para contraste e brilho,
estabilização da imagem, detecção de sorrisos para disparo, dentre outras, são proporcionadas por
sensores e processamento de alto desempenho do sistema embarcado.
As câmeras digitais mais usadas hoje estão integradas, como todos esses recursos, nos
smartphones. As imagens são armazenadas e processadas na forma de dados digitais binários.
Não há necessidade, como no passado, de utilizar filme para armazenar as imagens. Esse recurso
aumentou a capacidade de armazenamento e facilitou a transferência de imagens.
COMENTÁRIO
Podemos dizer que a câmera é um dos exemplos importantes de sistemas embarcados. Possui
processador próprio, sensores, atuadores e memória para armazenamento.
Hoje, os carros usam sistemas embarcados para substituir os antigos sistemas tradicionais. Os
automóveis que usam sistemas embarcados podem consistir em centenas de processadores ou
controladores.
Airbag;
Sistema de navegação;
ROBÔS INDUSTRIAIS
Os sistemas embarcados têm muitas aplicações nas indústrias. Hoje, todo o processo industrial
está sendo levado para a automação.
Um robô industrial é um sistema embarcado que possui uma variedade de formas, sendo que cada
uma executa uma série de tarefas diferentes. Alguns robôs industriais são usados para mover
peças, ferramentas, materiais etc. Alguns são usados em operações de montagem, enquanto
outros, na fabricação.
Esses robôs aumentaram muito a produtividade nos processos industriais, sendo amplamente
utilizados onde operações precisas são necessárias ou nas operações pesadas em locais de difícil
acesso e insalubres para humanos.
Foto: Shutterstock.com
Depois de colocar as roupas na máquina, todo o processo consiste nas funções dedicadas de
lavar, enxaguar e centrifugar, com as temporizações para cada ciclo podendo ser alteradas por
meio do teclado.
SMARTPHONES
Bluetooth
Processador de áudio
Circuitos para comunicação com rede sem fio (WiFi)
Conectividade USB
Sistema operacional
Câmera integrada
Memória de armazenamento
Processador central
Podemos considerar que o processador central, junto com todo o hardware periférico sincronizado,
usando um software embarcado, constitui um sistema embarcado.
Smartphones podem, dessa forma, ser considerados como um sistema embarcado complexo e
sofisticado.
Outro ponto de vista pode considerar o smartphone como um sistema completo, um dispositivo de
computação de uso geral que executa o sistema operacional no qual o usuário trabalha. No
entanto, eles contêm vários sistemas embarcados, como o núcleo do modem e as soluções de
chip único para Wi-Fi, Bluetooth e GPS. Nessa forma de avaliar, um smartphone moderno não é
um computador com poucos recursos, nem um sistema embarcado de última geração, mas um
computador de uso geral completo. Eles são, primeiro, um computador móvel e, depois, um
sistema de chamadas telefônicas.
COMENTÁRIO
A diferença entre o sistema embarcado e o sistema de uso geral está diminuindo hoje em dia. O
smartphone pode estar na categoria de computador de uso geral porque podemos usar vários
aplicativos. Podemos modificar, instalar e desinstalar os aplicativos.
Por outro lado, ele vem com sistema operacional pré-instalado e não podemos modificá-lo. Aqui,
“modificar” significa que não podemos instalar outro sistema operacional, como fazemos em um
PC, como Linux e Windows. Além disso, não podemos atualizar a funcionalidade do smartphone
além do permitido pelo fabricante. Portanto, essas condições estão de acordo com a definição do
sistema embarcado.
A) I, II e III
B) I, III e IV
C) II e III
D) II, III e IV
E) Somente a II
PORQUE
GABARITO
PORQUE
Smartphones são sistemas embarcados complexos, assim como outros dispositivos modernos,
como as Smart TVs e os tablets. Porém, a justificativa para serem classificados como sistemas
embarcados não é o fato de serem um computador de uso geral.
A classificação como computador de uso geral é aceita pela diversidade de aplicativos e utilitários
que podem ser usados. Porém, a classificação como sistema embarcado vem da combinação de
hardware e software com sensores, atuadores e outros dispositivos adicionais, todos projetados
para executar uma função dedicada.
MÓDULO 2
O sistema numérico é a técnica que usamos para representar e manipular números. Assim, esse
sistema deve ter símbolos exclusivos para cada valor, ser consistente, facilmente reproduzível e
fornecer valores comparáveis. Nos familiarizamos desde crianças com o sistema decimal que
forma a base de como os humanos contam. O sistema decimal tem uma base 10 porque fornece
10 símbolos (0 a 9) para representar todos os números. Nós passamos a usar o sistema decimal,
muito provavelmente, porque temos 10 dedos para contar. No entanto, os sistemas computacionais
não possuem essa facilidade.
Para contar, um sistema computacional só consegue usar a informação ligado ou desligado, que
pode ser representada, respectivamente, por 1 e 0.
Quando estamos fazendo uma contagem, primeiro percorremos todos os dígitos: 0, 1, 2 ... 8, 9.
Depois de atingir o 9, você não tem mais dígitos para representar o próximo número. Então, você
muda de volta para 0 e adiciona 1 ao dígito das dezenas, chegando ao 10. O processo se repete
continuamente.
Embora tudo isso seja muito básico, você não deve ignorar o que está acontecendo. O dígito mais
à direita representa o número de unidades, o próximo dígito representa o número de dezenas, o
seguinte, o número de centenas, e assim por diante. Você deve ter notado um padrão. Vejamos o
que acontece, matematicamente, usando, como exemplo, o número 375:
Como podemos observar, existem 3 grupos de 100 unidades em 375. Não por coincidência,
Finalmente, existem 5 grupos de uma unidade e, como qualquer número elevado a 0 é igual
Podemos concluir que um número decimal pode ser escrito por um polinômio em potências de 10.
Assim, 375 na base 10 pode ser considerado como:
Falar sobre números escritos em bases múltiplas pode causar confusão. Por exemplo, 10 na base
2 não é igual a 10 na base 10. Portanto, quando necessário, usaremos uma notação padrão em
que um subscrito denota a base dos números. Por exemplo, nossa versão na base 2 do valor 10
agora se apresenta como 102.
Conforme observado, todos sabemos o valor de um número de base 10, porque sempre usamos a
base de 10, e isso vem naturalmente para nós. No entanto, se entendermos os padrões da
notação posicional da base 10, podemos entender melhor as outras bases. De acordo com o que
vimos na base 10, temos que qualquer número inteiro positivo b, (b > 1), pode ser escolhido como
a base (ou raiz) de um sistema numérico. Se a base for b, então b dígitos são usados [0,1,2,3, ...,
b-1]. Esse padrão pode ser usado na definição de outras bases. Assim, um número na base 2
(binário) é representado por dígitos 0 e 1, e um número na base 8 (octal) é representado por
dígitos de 0 a 7. Para bases maiores que 10, geralmente, usamos letras para representar dígitos
maiores que 9. Um exemplo é o sistema numérico de base 16, conhecido como sistema
hexadecimal. Neste, usamos dígitos 0-9, e depois A (representando 10 em decimal), B
(representando 11) etc. A imagem a seguir resume o padrão de representação dessas bases.
Esses estados podem ser representados usando os dois dígitos, 1 e 0, respectivamente. Esses
dois dígitos formam o sistema numérico binário, também referido como sistema de base 2, pois
tem apenas dois dígitos. Essa informação, ligado ou desligado, representa o que chamamos de um
bit para um computador. Assim, um bit é a unidade mais básica de armazenamento em um
computador.
Quando se trata de colocar valores e dígitos nesse sistema, colocamos valores correspondentes
às potências, ou aos pesos, ascendentes de 2 da direita para a esquerda. Assim, o número 1011
em binário pode ser representado na notação posicional como:
10112
Atenção! Para visualização completa da equação utilize a rolagem horizontal
Você pode manipular os bits à esquerda e à direita com operadores bit a bit na programação
embarcada para alterar com eficiência o valor de um número no nível do código de máquina.
Agora que sabemos os fundamentos do sistema binário, vamos aprender como converter entre
decimal e binário. Começamos com a conversão binária para decimal. Sabemos que o sistema
binário tem valores nominais de potências de 2.
Esses valores são pesos para os dígitos (0 ou 1) nessas posições. Funciona assim:
Vamos pegar o número binário 1011 e convertê-lo para o sistema numérico decimal usando a
notação posicional que já conhecemos:
10112 = 1×23 + 0×22 + 1×21 + 1×20 = 1×8 + 0×4 + 1×2 + 1×1 = 11
Atenção! Para visualização completa da equação utilize a rolagem horizontal
Os restos que reunimos, na ordem inversa, formam nosso número binário. Veja esses passos na
imagem a seguir.
Você deve observar um padrão semelhante aos anteriores vistos, na base 10 e na base 2. Depois
que chegarmos ao 7, ficamos sem dígitos diferentes para qualquer número maior. Precisamos de
uma maneira para representar o oito de alguma forma. Portanto, adicionamos outro dígito,
alteramos o 7 de volta para 0 e terminamos com 10.
Dado um número binário, um número octal equivalente, representado por 3 bits, é calculado
agrupando 3 bits da direita para a esquerda e substituindo cada grupo de 3 bits pelo dígito octal
correspondente. Mas por que 3 bits em um número binário são agrupados para obter o número
octal?
Portanto, três dígitos binários são suficientes para representar todos os 8 dígitos octais.
Em termos simples, conte todas as combinações possíveis de três dígitos binários, que são 2x2x2
= 8.
Portanto, 3 bits são suficientes para representar qualquer dígito octal. Consequentemente, grupos
de 3 bits em um número binário são formados para obter um número octal equivalente.
Caso o número de bits em um número binário não seja múltiplo de 3, adicione o número
necessário de 0s na posição mais significativa do número binário.
EXEMPLO
Para converter 100011002 em número octal:
Faça o agrupamento de 3 bits do número binário fornecido (da direita para a esquerda) 010
001 100.
O raciocínio inverso pode ser usado para converter de octal para binário. O número octal é
convertido em binário, substituindo cada dígito octal por um grupo de três dígitos binários.
EXEMPLO
Dígitos octais 4 6 7.
Escreva o valor binário de 3 bits para cada dígito 100 110 111.
dígito. Isso ocorre porque 4 bits (24 = 16) são suficientes para representar os 16 símbolos
alfanuméricos.
hexadecimal, esse endereço é mapeado para D33716, mais fácil de lembrar e trabalhar.
Agora, pelo que vimos da conversão de binário para octal, você consegue deduzir como foi feita
essa conversão?
Caso o número de bits em um número binário não seja múltiplo de 4, devemos adicionar o número
necessário de 0s na posição mais significativa do número binário. Dessa forma, o agrupamento de
4 bits do número binário fornecido (da direita para a esquerda) fica 1101 0011 0011 0111.
Assim, para cada conjunto de 4 bits, temos os números decimais 13, 3, 3 e 7. O número 13 em
hexadecimal é representado pela letra D. Logo, o número hexadecimal equivalente é D33716.
VOCÊ SABIA
Números hexadecimais também são usados para descrever as cores na página da web.
Cada cor é composta por três cores primárias (vermelho, verde e azul) popularmente chamadas
RGB. Na maioria dos mapas coloridos, cada cor é geralmente escolhida em uma paleta de 16
milhões de cores. Portanto, são necessários 24 bits para representar cada cor com três
componentes (8 bits para o vermelho, 8 bits para o verde, 8 bits para o componente azul). Fica
difícil lembrar o código de cores binário de 24 bits. Assim, os códigos de cores são escritos na
forma hexadecimal para representação compacta.
Por exemplo, o código de 24 bits para amarelo é 11111111, 11111111, 00000000. O equivalente
hexadecimal é FF0, bem mais fácil de usar e memorizar.
ETAPA 01
Escreva o número da posição para cada símbolo alfanumérico do número fornecido.
ETAPA 02
Obtenha o valor posicional de cada símbolo, elevando seu número de posição ao valor da base b
do número fornecido.
ETAPA 03
Multiplique cada dígito com o respectivo valor posicional para obter um valor decimal.
ETAPA 04
Adicione todos esses valores decimais para obter o número decimal equivalente.
3628 = 3×82 + 6×81 + 2×80 = 3×64 + 6×8 + 2×1 = 24210
Atenção! Para visualização completa da equação utilize a rolagem horizontal
ETAPA 01
Divida o número fornecido pelo valor da base (b) do sistema numérico em que será convertido.
ETAPA 02
Observe o valor de resto da divisão.
ETAPA 03
Continue dividindo o quociente pelo valor base e guarde o resto até que o quociente seja zero.
ETAPA 04
Escreva os restos anotados na ordem inversa (de baixo para cima).
VERIFICANDO O APRENDIZADO
1. O SISTEMA DE NUMERAÇÃO MAIS CONHECIDO É O DECIMAL, QUE
OPERA COM A BASE 10. PORÉM, EXISTEM OUTROS SISTEMAS DE
NUMERAÇÃO MUITO UTILIZADOS EM SISTEMAS COMPUTACIONAIS, COMO
BINÁRIO, OCTAL, HEXADECIMAL. CONSIDERANDO A REPRESENTAÇÃO
E3, ANALISE AS AFIRMATIVAS ABAIXO.
A) I e II
B) I e III
C) II e III
D) Somente a I
E) Somente a II
A) 011111 e 38
B) 001111 e 31
C) 011111 e 31
D) 101111 e 38
1. O sistema de numeração mais conhecido é o decimal, que opera com a base 10. Porém,
existem outros sistemas de numeração muito utilizados em sistemas computacionais, como
binário, octal, hexadecimal. Considerando a representação E3, analise as afirmativas abaixo.
E3 é uma representação que pode pertencer ao sistema de numeração hexadecimal (16 bits),
além de outras a partir de 15 bits, pois essas representações usam letras maiúsculas para
representar números de 10 em diante. O MSB é o dígito mais significativo de um número binário.
Precisamos converter E3 de hexadecimal para binário. 4 bits são suficientes para representar um
símbolo alfanumérico da numeração hexadecimal. Assim, o símbolo E em hexadecimal é
convertido para 1110 (14 em decimal). O símbolo 3 em hexadecimal é convertido para 0011.
Assim, o número binário correspondente a E3 em hexadecimal é 11100011, que possui MSB igual
a 1. Por fim, para converter E3 de hexadecimal para decimal, usamos a notação posicional. Assim,
E316 = E×161 + 3×160 = 14×16 + 3×1 = 22710
Existe um padrão que deve ser observado em qualquer base numérica. Assim como na base 10
temos a representação com dígitos de 0 a 9, e na base 2 de 0 a 1, em qualquer outra base b, b
dígitos são usados [0,1,2,3, ..., b-1]. Dessa forma, na base 8, os dígitos usados vão de 0 a 7. Isso
porque, quando chegamos ao 7, ficamos sem dígitos diferentes para qualquer número maior. Por
conclusão, 38 não pode ser existir na representação octal, de base 8.
MÓDULO 3
ÁLGEBRA BOOLEANA
Você já sabe que um sistema computacional é um sistema digital no qual as quantidades variam
em níveis discretos, ligado ou desligado, 1 ou 0. Dessa forma, os sistemas digitais transportam
informações usando combinações de sinais 1s e 0s, utilizando o sistema de numeração binário que
conhecemos. Uma das melhores coisas sobre o sistema binário está no fato de que ele é muito
eficiente no tratamento de operações especiais, chamadas de operações lógicas.
As operações lógicas comparam dois bits e estabelecem um terceiro bit como resultado dessa
comparação. Operações lógicas são realizadas em um sistema digital por circuitos digitais lógicos.
Mas o que ocorre entre a entrada e saída desses circuitos lógicos para permitir o processamento
das operações lógicas?
Vamos analisar a programação de sistemas embarcados digitais sobre o ponto de vista da álgebra
booleana e da lógica matemática, fundamentais para o entendimento do processamento dos dados
nesses sistemas.
Nada poderia ser mais simples e normal para o raciocínio humano do que as regras de uma
álgebra booleana, pois essas se originaram em estudos de como raciocinamos, quais linhas de
raciocínio são válidas, o que constitui prova e outros assuntos relacionados.
VOCÊ SABIA
O nome álgebra booleana homenageia um grande matemático inglês, George Boole, que em 1854
publicou um livro clássico, Uma investigação das leis do pensamento , no qual fundamenta as
teorias matemáticas da lógica e das probabilidades. A intenção declarada de Boole era realizar
uma análise matemática da lógica.
Boole procurou dar forma simbólica ao sistema de lógica de Aristóteles. Começando com sua
investigação das leis do pensamento, Boole construiu uma “álgebra lógica”, que passou a ser
conhecida como álgebra booleana.
Os computadores digitais modernos são construídos a partir de circuitos lógicos digitais cujos
blocos de construção básicos são portas lógicas, sendo cada uma projetada para implementar uma
operação binária com uma função lógica específica.
COMENTÁRIO
Álgebra booleana, portanto, é a ferramenta usada para projetar combinações de portas lógicas
para implementar funções mais complexas, como operações matemáticas e funções de controle.
Desse modo, todas as instruções dos programas que você criará para sistemas embarcados irão
passar por circuitos lógicos (formados por portas lógicas) que podem ser representados por
expressões na álgebra booleana.
A imagem a seguir apresenta um resumo dos símbolos utilizados para representar as portas
lógicas e as suas respectivas tabelas-verdade para duas entradas, que mostram qual o resultado
na saída X para as combinações de entradas A e B. Com esse comportamento funcional, dado
pelas tabelas-verdade, as portas lógicas podem ser usadas para representar qualquer circuito
lógico.
ATENÇÃO
A álgebra booleana, sendo uma operação lógica, permite que as regras usadas na álgebra de
números sejam aplicadas à lógica. Assim como uma expressão algébrica comum pode ser
simplificada por meio dos teoremas básicos, a expressão que descreve uma determinada rede de
circuitos de computação também pode ser reduzida ou simplificada. Esse é o grande benefício
da utilização da álgebra booleana.
Ao formalizar as regras da lógica, a álgebra booleana pode ser usada para simplificar expressões
booleanas que representam circuitos lógicos. Assim, ela reduz a expressão original a uma
expressão equivalente com menos termos, o que significa que menos portas lógicas são
necessárias para implementar o circuito lógico, trazendo enorme benefício econômico aos projetos
de sistemas computacionais.
F(A,B,C,D)=A+B(C+D)C
Atenção! Para visualização completa da equação utilize a rolagem horizontal
O circuito digital da figura abaixo implementa a função f(A,B,C,D). O circuito digital consiste em
funções lógicas elementares, implícitas na função.
Primeiro, precisamos ver que a função booleana poderia ser especificada por sua tabela-verdade.
A utilização da função booleana no lugar da tabela-verdade se dá pela simplificação. Circuitos com
maior quantidade de entradas teriam que ser representados por tabelas cada vez maiores para
analisar todas as possibilidades. A função booleana, para representar corretamente a tabela-
verdade, informa quais combinações das variáveis de entrada fornecem a saída ativada, igual a 1.
Analisando a função booleana, vemos que para chegarmos à saída igual a 1, temos uma
multiplicação lógica de três partes da função: A+B(C+D) e C.
Essa multiplicação pode ser realizada por uma porta lógica AND de três entradas, como mostrado
na figura. Considerando agora as 3 partes individuais, temos:
Assim, o circuito mostrado na imagem anterior é obtido a partir das análises da função booleana.
LEI COMUTATIVA
Esta lei afirma que não importa em que ordem usamos as variáveis. Vimos que na álgebra
booleana, o OR e as operações de adição são semelhantes. No diagrama abaixo, a porta OR
mostra que a ordem das variáveis de entrada não importa de forma alguma. Para duas variáveis, a
lei comutativa da adição é escrita como:
A + B = B + A
Da mesma maneira, para duas variáveis, a lei comutativa da multiplicação é escrita como:
AB = BA
LEI ASSOCIATIVA
Esta lei estabelece que a operação pode ser realizada em qualquer ordem quando a prioridade das
variáveis for a mesma. Para três variáveis, a lei associativa da adição é escrita como:
A + (B + C) = (A + B) + C
Atenção! Para visualização completa da equação utilize a rolagem horizontal
De forma análoga, para três variáveis, a lei associativa da multiplicação é escrita como:
A (BC) = (AB) C
LEI DISTRIBUTIVA
De acordo com esta lei, se realizarmos a operação OR de duas ou mais variáveis e, em seguida,
realizarmos a operação AND do resultado com uma única variável, o resultado será semelhante a
realizar a operação AND dessa variável única com cada uma das duas ou mais variáveis e, em
seguida, executar a operação OR desse produto.
ou
A + (BC) = (A + B).(A + C)
Atenção! Para visualização completa da equação utilize a rolagem horizontal
LEI IDEMPOTENTE
AA = A
A + A = A
PROPRIEDADE DO 0
Temos uma variável de entrada A cujo valor é 0 ou 1. Quando executamos a operação AND com
0, o resultado sempre será 0. Quando executamos a operação OR com 0, o resultado sempre
será A.
(A.0) = 0
A + 0 = A
PROPRIEDADE DO 1
Temos uma variável de entrada A cujo valor é 0 ou 1. Quando executamos a operação OR com 1,
o resultado será sempre 1. Quando executamos a operação AND com 1, o resultado sempre será
A.
A + 1 = 1
A.1 = A
LEI COMPLEMENTAR
Quando é realizada uma operação AND e OR com seu complemento (negação), o resultado
será 0 e 1, respectivamente.
AA= 0
A + A = 1
Esta lei estabelece que, quando a variável vem com duas negações, o símbolo é removido e a
variável original é obtida.
A== A
LEI DE ABSORÇÃO
Esta lei nos permite absorver as variáveis semelhantes, conforme representado a seguir.
A + (AB) = A
A.(A + B) = A
A + (A.B) = (A.1)+ (A.B) = A(1 + B) = A.1 = A
A(A + B) = (A + 0).(A + B) = A + (0.B) = A
Atenção! Para visualização completa da equação utilize a rolagem horizontal
O complemento ou a negação de uma soma (OR ) de variáveis é igual ao produto (AND ) dos
complementos das variáveis.
AB = A + B
A+B = A.B
Atenção! Para visualização completa da tabela utilize a rolagem horizontal
Suponha que você recebeu a função (expressão) booleana seguinte para construir um circuito
digital. Antes, você pode tentar a simplificação da expressão para construir um circuito equivalente
menor.
AB(A+B)(B+B)
Atenção! Para visualização completa da equação utilize a rolagem horizontal
ATENÇÃO
Vamos aplicá-las.
AB(A+B)(B+B)
AB(A+B)(B+B)
AB(A+B).1
AB(A+B)
(A+B)(A+B)
A + BB
A+0
A
Expressão original
Complemento → (B+B) = 1
Propriedade de 1 → AB(A+B)1 = AB(A+B)
De Morgan → AB = A+B
Distributiva → (A+B)(A+B) = A+BB
Complemento → BB = 0
Propriedade de 0 → A+0 = A
Atenção! Para visualização completa da equação utilize a rolagem horizontal
Verifique que, com a simplificação, a expressão equivalente necessita de somente uma porta
lógica NOT para implementar o circuito digital.
AS EXPRESSÕES BOOLEANAS
Assista ao vídeo a seguir. Nele, explicamos como representar os circuitos lógicos através de
expressões booleanas e a como simplificar estas expressões.
VERIFICANDO O APRENDIZADO
AB+A(B+C)+B(B+C)
A) AB+AC+B
B) A+BC
C) AB+C
D) AC+AB+C
E) B+AC
(A+B)(B+C)
A)
B)
C)
D)
E)
GABARITO
1. Você recebeu a expressão booleana abaixo para montar o circuito digital equivalente.
Porém, resolveu simplificar a expressão utilizando as regras da álgebra booleana para usar
menos portas lógicas no circuito a ser montado. Qual a expressão simplificada?
AB+A(B+C)+B(B+C)
Partindo da expressão original, AB + A(B + C) + B(B + C), deve-se usar as regras a seguir: aplicar
a lei distributiva ao segundo e terceiro termos da expressão - AB + AB + AC + BB + BC. Aplicar a
regra (BB = B) para o quarto termo - AB + AB + AC + B + BC. Aplicar a regra (AB + AB = AB) para
os dois primeiros termos - AB + AC + B + BC. Aplicar a regra (B + BC = B) para os dois últimos
termos - AB + AC + B. Aplicar a regra (AB + B = B) ao primeiro e terceiro termos - B+AC.
Resultado final: B+AC.
2. A seguinte expressão booleana foi encontrada em um manual de portão automático.
(A+B)(B+C)
Analisando a função booleana, vemos que para chegarmos à saída igual a 1 temos uma
multiplicação lógica de duas partes da função: (A+B) e (B+C). Essa multiplicação é realizada por
uma porta lógica AND de duas entradas. Considerando agora as duas partes individuais temos:
(A+B) é obtido com uma porta OR , assim como (B+C). Desse modo, o circuito terá duas portas
OR de duas entradas e uma porta AND de duas entradas na saída, recebendo as saídas das
portas OR , como mostrado na alternativa com a figura:
MÓDULO 4
LINGUAGEM C E COMPILAÇÃO
Talvez você já tenha ouvido alguém falar que a linguagem C é muito antiga e ultrapassada. Se
você já programa em outra linguagem, essa afirmação pode trazer mais uma dificuldade de
convencê-lo da necessidade de se aprender a linguagem C.
Um bom argumento seria: C não é uma linguagem difícil de se aprender, e todos os benefícios do
seu aprendizado serão bem aproveitados em outras linguagens.
No entanto, há um argumento mais apropriado em nosso caso: uma das poucas uniformidades
na maioria dos sistemas embarcados é o uso da linguagem de programação C. Na realização
de um sistema embarcado, a programação do sistema desempenha um papel muito importante.
Portanto, a seleção correta da linguagem de programação é essencial. A predominância da
linguagem C é ampla nessa área, pois, ainda é, depois da linguagem de montagem, a que melhor
atende aos fatores mais relevantes na escolha de uma linguagem de programação para o
desenvolvimento de sistemas embarcados.
A linguagem de montagem é uma linguagem de programação por meio de símbolos que mais se
aproxima da linguagem de máquina em forma e conteúdo.
É a linguagem de programação mais básica disponível para qualquer processador, sendo por isso
chamada de linguagem de baixo nível. Com a linguagem de montagem, um programador
trabalha apenas com operações que são implementadas diretamente na unidade central de
processamento, acionando registradores e posições de memória.
A linguagem de montagem geralmente carece das conveniências das linguagens de alto nível,
como variáveis e funções, e não é portável entre várias famílias de processadores. Estas têm as
mesmas estruturas e conjunto de comandos da linguagem de máquina, mas permitem que um
programador use nomes em vez de números. Essa linguagem ainda é útil para programadores de
sistemas embarcados quando a velocidade é necessária ou quando eles precisam realizar uma
operação que não é possível em linguagens de alto nível.
Com o aumento na complexidade e na demanda de qualidade pelo software embarcado, a procura
por novas formas de desenvolvimento que facilitassem atingir novos requisitos levou à busca por
linguagens de programação mais amigáveis do que a linguagem de montagem. O uso exclusivo de
linguagem de montagem no desenvolvimento de sistemas embarcados se tornaria muito pesado e
oneroso. Uma linguagem de programação para sistemas embarcados, no entanto, precisaria
seguir alguns requisitos bem restritos, como:
DESEMPENHO
Os programas devem ser executados o mais rápido possível. O hardware não deve ficar lento
devido a um software lento.
PORTABILIDADE
O mesmo código deve ser compilado para diferentes processadores com poucas modificações,
algo que a linguagem de montagem não permite.
MANIPULAÇÃO DE BITS
Usando operadores bit a bit, pode-se alterar os bits de registradores dos processadores
embarcados, como é feito na linguagem de montagem, algo que é imprescindível quando se trata
de sistemas embarcados.
A partir desses requisitos, a escolha da linguagem C para sistemas embarcados foi natural. O
ponto forte de C, e o que a diferencia de outras linguagens, é o fato de ser uma linguagem de alto
nível com atributos de “baixo nível”. C oferece aos programadores embarcados um grau
extraordinário de controle direto do hardware sem sacrificar os benefícios das linguagens de alto
nível.
COMENTÁRIO
A natureza de “baixo nível” da linguagem C foi uma intenção clara do seu criador, Dennis M.
Ritchie (1988), que comentou em seu primeiro livro sobre a linguagem: “C é uma linguagem
relativamente de ‘nível baixo’. Essa caracterização não é pejorativa; significa simplesmente que C
lida com o mesmo tipo de objetos que a maioria dos computadores.”
A linguagem C foi projetada para implementar o Sistema Operacional Unix, ficando próxima ao
sistema operacional, o que a torna uma linguagem eficiente devido ao seu competente
gerenciamento de recursos no nível do sistema. Outro ponto importante no uso de C é que a
linguagem não é limitada, mas amplamente utilizada em sistemas operacionais, compiladores de
linguagem, drivers de rede.
Então, podemos dizer que, por projeto, a linguagem C se presta muito bem ao desenvolvimento
embarcado porque fica entre o software e o hardware de nível superior, permitindo que você
acesse e controle o hardware diretamente, sem sacrificar os benefícios de uma linguagem de alto
nível. Ela é particularmente eficaz para o hardware que precisará existir por um tempo, já que
programas escritos em C podem operar por décadas devido à alta estabilidade da linguagem.
COMENTÁRIO
COMPILAÇÃO
Um código-fonte escrito em linguagem C precisa passar por um programa, chamado compilador,
para que tenhamos um código executável que funcione em um processador, seja esse de um
sistema embarcado ou não.
Não existem muitas diferenças entre o processo de compilação em programas que rodam em
sistemas operacionais ou em um sistema embarcado. Porém, quando as ferramentas de
compilação são executadas no mesmo sistema do arquivo executável a ser gerado, caso do
Windows ou Linux, elas podem fazer muitas suposições sobre o sistema. Normalmente, esse não
é o caso no desenvolvimento de software embarcado, em que as ferramentas de compilação são
executadas em um computador diferente da plataforma de hardware de destino.
Nesse caso, estamos nos referindo à compilação para programas que são executados diretamente
no hardware, sem ter nenhuma abstração subjacente, como no caso dos sistemas operacionais.
Isso é chamado de programação bare metal . Geralmente, os programas bare metal terão um
carregamento (bootloader ) mínimo para iniciar o processador, relógio e memória, antes de saltar
para o programa principal. O processo de compilação, a conversão da representação do código-
fonte do seu software embarcado em uma imagem binária executável, pode ser sintetizado em três
etapas distintas:
ETAPA 01
Cada um dos arquivos de origem é compilado ou montado em um arquivo-objeto.
ETAPA 02
Todos os arquivos-objeto que resultam da primeira etapa devem passar pelo vinculador para
produzir um único arquivo-objeto, denominado programa relocável.
ETAPA 03
Os endereços de memória física devem ser atribuídos aos deslocamentos relativos dentro do
programa realocável em um processo denominado relocação, executado pelo localizador.
O resultado da etapa final é um arquivo contendo uma imagem binária executável que está pronta
para ser executada no sistema embarcado. O processo de compilação de software embarcado é
ilustrado na imagem a seguir. Cada uma dessas ferramentas de desenvolvimento pega um ou mais
arquivos como entrada e produz um único arquivo de saída.
ESTRUTURA DE UM PROGRAMA EM C
Antes de estudarmos os blocos de construção básicos da linguagem de programação C, vamos
examinar uma estrutura de programa C mínima para que possamos tomá-la como uma referência.
Um programa em C consiste basicamente nas seguintes partes:
Comandos do pré-processador
Funções
Variáveis
Declarações e Expressões
Comentários
int main() {
return 0;
#include <18F4550.H>
A próxima linha int main () é a função principal onde a execução do programa começa.
A próxima linha /*...*/ será ignorada pelo compilador e foi colocada para adicionar comentários ao
programa. Portanto, essas linhas são chamadas de comentários no programa.
A próxima linha printf (...) é outra função disponível em C que causa a mensagem "Bom dia! " a ser
exibida na tela.
Uma definição de pré-processador muito utilizada em sistemas embarcados é #define, que cria
uma string que será substituída por um número. Ela é útil porque permite modificar facilmente um
valor que aparece em várias partes diferentes do programa. Por exemplo:
Nesse caso, pode-se alterar 1000 para qualquer outro número e esse novo valor será usado para
substituir todas as instâncias da string TAXA. As definições de pré-processador também são uma
ótima maneira de tornar o código mais legível.
tipo nome_variavel;
ATENÇÃO
Um nome de variável pode ter letras, dígitos e o símbolo underscore “_” (sublinhado). A primeira
letra de uma variável deve ser uma letra ou o símbolo “_”.
Os programas em C podem lidar com funções e parâmetros. O tipo de dado da função determina o
tipo de valor que pode ser retornado por uma determinada sub-rotina. Sem um tipo de retorno
especificado, qualquer função retorna um valor do tipo inteiro como seu resultado. A linguagem C
também oferece suporte a tipos de dados de parâmetro, que indicam valores que devem ser
passados para uma função especificada.
ATENÇÃO
Quando uma função é declarada sem nenhum parâmetro, ou quando um valor de retorno não é
esperado, a função pode ser anotada como void .
A linguagem C suporta três tipos de dados diferentes para inteiros: int, short e long.
Em arquiteturas de 8 bits, o tamanho padrão dos valores int é normalmente definido como 16 bits,
mas a linguagem C permite que os tamanhos int sejam alternados entre 8 e 16 bits para reduzir o
consumo de memória.
O tipo de dados short int permite que os programadores especifiquem um valor inteiro com apenas
um ou dois bytes de tamanho.
Usar o tipo de dados long int aloca duas vezes a quantidade padrão de memória do tipo de dados
int.
Em alguns compiladores C para sistemas embarcados, usa-se dois tipos de variáveis para
quantidades de tamanho de bit: bit e bits. Um valor de bit corresponde a um único bit
independente, enquanto os dados variáveis de bits são usados para gerenciar e endereçar
coletivamente uma estrutura de 8 bits. Os programadores podem atribuir um valor de byte a uma
variável de bits para permitir o endereçamento de bits individuais dentro dos dados.
NÚMEROS REAIS
Uma das diferenças maiores entre os aplicativos de computador desktop e aqueles usados para
alimentar sistemas embarcados é o tratamento de números reais e tipos de dados de ponto
flutuante (float ). Esses tipos de dados incluem números negativos e números com dígitos em
ambos os lados de uma vírgula decimal.
COMENTÁRIO
Além dos tipos de dados convencionais, também existem tipos de dados complexos que podem
ser úteis para programar microcontroladores para aplicativos de sistemas embarcados. Isso inclui
tipos como ponteiros, matrizes, tipos enumerados (conjuntos finitos de valores nomeados),
estruturas (formas de estruturar outros dados) e muito mais.
MODIFICADORES
Modificadores, como long, short, signed e unsigned, podem ser acrescentados às variáveis,
alterando o alcance dos tipos de dados, como mostrado na tabela a seguir:
-2.147.483.648 a
long int Inteiro long 4
2.147.483.647
-2.147.483.648 a
signed long int Inteiro longo com sinal 4
2.147.483.647
Atenção! Para visualização completa da tabela utilize a rolagem horizontal
As funções de entrada e saída de dados mais usadas em C são printf () e scanf (). Essas funções
estão disponíveis na biblioteca C por padrão. As macros relacionadas são definidas no cabeçalho
“stdio.h”.
FUNÇÃO PRINTF()
Na linguagem de programação C, a função printf() é usada para imprimir caracteres string, float,
inteiro, octal e valores hexadecimais na tela de saída.
Usamos a função printf() com o especificador de formato %d para exibir o valor de uma variável
inteira. Da mesma maneira, usamos:
FUNÇÃO SCANF()
A função scanf() é usada para ler caracteres, strings e dados numéricos do teclado.
Considere o programa de exemplo a seguir, no qual o usuário insere um caractere. Esse valor é
atribuído à variável “ch” e, em seguida, exibido. Assim como na função printf(), o especificador de
formato % é usado na instrução scanf(). O e comercial (&) é usado antes do nome da variável “ch”
na instrução scanf() para apontar para a variável e fazer a atribuição do valor fornecido pelo
usuário.
#include <stdio.h>
int main()
char ch;
scanf("%c", &ch);
As funções printf(), scanf() e suas variações são sofisticadas e, como tal, consomem uma grande
quantidade de espaço de código compilado. Dessa forma, embora existam compiladores para
sistemas embarcados que as integrem, em funções como escrita para porta serial e display, elas
devem ser usadas com cuidado para não consumir todo o espaço de código na memória do
sistema embarcado.
OPERADORES E ESTRUTURAS
CONDICIONAIS
Operações matemáticas e manipulação de bits são realizadas por meio de operadores.
igual (=)
adição (+)
subtração (-)
multiplicação (*)
divisão (/)
incremento (++)
decremento (--)
IF E ELSE
As declarações condicionais permitem que você execute ou não uma ação com base no fato de
uma determinada condição ser verdadeira ou falsa. Essas declarações usam as palavras if e else,
por exemplo:
if (count < 0)
count = 0;
else
count ++;
x == y x igual a y
x != y x não é igual a y
x || y OU lógico
Atenção! Para visualização completa da tabela utilize a rolagem horizontal
SWITCH-CASE
Sintaxe:
switch (expressao) {
case constante1:
instrucoes1;
break;
case constante2:
instrucoes2;
break;
...
default:
instrucoes;
Para utilizar o switch-case, basta substituir a palavra expressao no código pelo nome da variável
que terá sua expressão avaliada.
Substituir a palavra constante1 pela constante a ser comparada com o conteúdo da variável em
expressao, e instrucoesX pelas instruções que se pretende executar caso a comparação seja
verdadeira.
A cláusula default funciona como o último else em um conjunto de instruções if, ou seja, se
nenhuma condição anterior for verdadeira, então as instruções em default serão executadas. A
cláusula default é opcional.
A cláusula break é responsável pela parada na execução das instruções, pois, caso não seja
colocada, as validações presentes no switch continuarão a ser executadas, mesmo que um case já
tenha resultado em verdadeiro.
For loops são mais orientados para situações em que um bloco de código deve ser executado um
número específico de vezes.
While loops são úteis quando o processador deve continuar repetindo o mesmo bloco de código
até que uma condição mude de verdadeiro para falso.
int i = 1;
i++;
VERIFICANDO O APRENDIZADO
1. PARA SISTEMAS EMBARCADOS, A COMPILAÇÃO PODE SER DEFINIDA
COMO O PROCESSO EM QUE O COMPUTADOR USA VÁRIAS
FERRAMENTAS PARA CONVERTER UMA LINGUAGEM DE PROGRAMAÇÃO
DE ALTO NÍVEL EM UMA LINGUAGEM DE MÁQUINA DE MODO QUE O
PROCESSADOR EMBARCADO POSSA ENTENDÊ-LA. RELACIONE OS
NOMES DAS FERRAMENTAS COM A CONVERSÃO QUE ELA REALIZA E
ESCOLHA A OPÇÃO CORRETA.
1-
A - ARQUIVO-FONTE PARA ARQUIVO-OBJETO
COMPILADOR
ATENÇÃO! PARA VISUALIZAÇÃO COMPLETA DA TABELA UTILIZE A
ROLAGEM HORIZONTAL
#INCLUDE <STDIO.H>
VOID MAIN()
SCANF("%D", &NUM1);
NUM2 = NUM1 % 2;
IF (NUM2 == 0)
ELSE
GABARITO
1. Para sistemas embarcados, a compilação pode ser definida como o processo em que o
computador usa várias ferramentas para converter uma linguagem de programação de alto
nível em uma linguagem de máquina de modo que o processador embarcado possa
entendê-la. Relacione os nomes das ferramentas com a conversão que ela realiza e escolha
a opção correta.
Atenção! Para visualização completa da tabela utilize a rolagem horizontal
2. Você recebeu o código abaixo. O que deve ser escrito em xxxxxxxxxxxx e yyyyyyyyyyy,
respectivamente, correspondendo ao que o código executa?
#include <stdio.h>
void main()
scanf("%d", &num1);
num2 = num1 % 2;
if (num2 == 0)
else
A expressão num2 = num1 % 2 usa o operador % para guardar na variável num2 o resto da divisão
do número fornecido pelo usuário por 2. Então, a instrução if (num2 == 0) testa se esse resultado é
zero. Sendo zero, indica que o número fornecido é par. Do contrário (else), deve ser informado que
o número é ímpar. Portanto, em xxxxxxxxxxxx deve ser usada a informação “é número par”; e em
yyyyyyyyyyy, a informação “é número ímpar”. Como as variáveis num1 e num2 foram declaradas
como inteiras, não há possibilidade de testar se o usuário entrou com um número fracionário.
CONCLUSÃO
CONSIDERAÇÕES FINAIS
Neste conteúdo, vimos como os sistemas embarcados são onipresentes no nosso dia a dia em
aplicações variadas. Avaliamos os fundamentos para o desenvolvimento desses sistemas com a
verificação das bases numéricas usadas em sistemas computacionais e as regras da álgebra
booleana que permitem simplificar circuitos digitais. Analisamos, por fim, os aspectos principais da
linguagem de programação mais utilizada para o desenvolvimento dos sistemas embarcados, a
linguagem C.
AVALIAÇÃO DO TEMA:
REFERÊNCIAS
BOLL, M.; REINHART, J. A História da lógica. Biblioteca Básica da Filosofia. Lisboa: Edições 70,
1992.
BOOLE, G. The Calculus of Logic. The Cambridge and Dublin Mathematical Journal, v. 3, 1848.
BOOLE, G. An Investigation of The Laws of Thought on Which are Founded the Mathematical
Theories of Logic and Probabilities. Londres: Macmillan, 1958.
KERNIGHAN, B. W.; RITCHIE, D.; DENNIS M. The C Programming Language. Prentice Hall
Professional Technical Reference, 1988.
HENZINGER, T. A.; SIFAKIS, J. The embedded systems design challenge. In: Formal
Methods, v. 4085, 2006.
EXPLORE+
Para aprimorar os seus conhecimentos no assunto estudado, recomendamos as seguintes leituras:
CONTEUDISTA
Marcos Santana Farias