Buscar

APOSTILA MSP430 - C - PARTE II

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 41 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 41 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 41 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

Página 55 
 
10. BREVE INTRODUÇÃO A LINGUAGEM C 
(http://pt.wikipedia.org/wiki/c_(linguagem_de_programaçao)) 
 
C é uma linguagem de programação compilada de propósito geral, estruturada, imperativa, 
procedural, de alto nível, e padronizada, criada em 1972, por Dennis Ritchie, no AT&T Bell 
Labs, para desenvolver o sistema operacional UNIX (que foi originalmente escrito em 
Assembly). A linguagem C é classificada de alto nível pela própria definição desse tipo de 
linguagem. A programação em linguagens de alto nível tem como característica não ser 
necessário conhecer o processador, ao contrário das linguagens de baixo nível. As 
linguagens de baixo nível estão fortemente ligadas ao processador. A linguagem C permite 
acesso de baixo nível com a utilização de código Assembly no meio do código fonte. Assim, 
o baixo nível é realizado por Assembly e não C. Desde então, espalhou-se por muitos outros 
sistemas, e tornou-se uma das linguagens de programação mais usadas, e influenciou 
muitas outras linguagens, especialmente C++, que foi originalmente desenvolvida como uma 
extensão para C. 
 
10.1. História 
 
 
Ken Thompson e Dennis Ritchie (da esquerda pra direita), os criadores das linguagens B e 
C, respectivamente. 
 
O desenvolvimento inicial de C, ocorreu no AT&T Bell Labs, entre 1969 e 1973. Deu-se o 
nome “C” à linguagem, porque muitas de suas características derivaram da linguagem B. 
 
C foi originalmente desenvolvido, para a implementação do sistema UNIX (originalmente 
escrito em PDP-7 Assembly, por Dennis Ritchie e Ken Thompson). Em 1973, com a adição 
do tipo struct, C tornou-se poderoso o bastante para a maioria das partes do Kernel do 
UNIX, serem reescritas em C. Este foi um dos primeiros sistemas que foram implementados 
em uma linguagem, que não o Assembly, sendo exemplos anteriores, os sistemas: Multics 
(escrito em PL/I) e TRIPOS (escrito em BCPL). Segundo Ritchie, o período mais criativo 
ocorreu em 1972. 
 
Página 56 
 
10.2. K&R C 
 
Em 1978, Brian Kernighan e Dennis Ritchie publicaram a primeira edição do livro The C 
Programming Language. Esse livro, conhecido pelos programadores de C, como “K&R”, 
serviu durante muitos anos como uma especificação informal da linguagem. A versão da 
linguagem C que ele descreve é usualmente referida como “K&R C”. A segunda edição do 
livro, cobriu o padrão posterior, o ANSI C. K&R C introduziu as seguintes características na 
linguagem: 
 
• Biblioteca padrão de E/S; 
• Tipos de dado struct; 
• Tipos de dado long int; 
• Tipos de dado unsigned int; 
• O operador =+ foi alterado para +=, e =- para -= (o analisador léxico do compilador 
fazia confusão entre i =+ 10 e i = +10. O mesmo acontecia com =-). 
 
K&R C é freqüentemente considerado a parte mais básica da linguagem, cujo suporte deve 
ser assegurado por um compilador C. Durante muitos anos, mesmo após a introdução do 
padrão ANSI C, K&R C foi considerado o “menor denominador comum”, em que 
programadores de C se apoiavam quando uma portabilidade máxima era desejada, já que 
nem todos os compiladores eram atualizados o bastante para suportar o padrão ANSI C. 
Nos anos que se seguiram à publicação do K&R C, algumas características “não-oficiais” 
foram adicionadas à linguagem, suportadas por compiladores da AT&T e de outros 
vendedores. Estas incluíam: 
 
• Funções void e tipos de dados void *; 
• Funções que retornam tipos struct ou union; 
• Campos de nome struct num espaço de nome separado para cada tipo struct; 
• Atribuição a tipos de dados struct; 
• Qualificadores const para criar um objecto só de leitura; 
• Biblioteca padrão, que incorpora grande parte da funcionalidade implementada por 
vários vendedores; 
• Enumerações; 
• Cálculos de ponto-flutuante em precisão simples (no K&R C, os cálculos 
intermediários eram feitos sempre em double, porque era mais eficiente na máquina 
onde a primeira implementação do C foi feita). 
 
 
Página 57 
 
10.3. ANSI C e ISO C 
 
Durante os finais da década de 1970, a linguagem C começou a substituir a linguagem 
BASIC como a linguagem de programação de microcomputadores mais usada. Durante a 
década de 1980, foi adaptada para uso no PC IBM, e a sua popularidade começou a 
aumentar significativamente. Ao mesmo tempo, Bjarne Stroustrup, juntamente com outros 
nos laboratórios Bell, começou a trabalhar num projecto onde se adicionavam construções 
de linguagens de programação orientada por objectos à linguagem C. A linguagem que eles 
produziram, chamada C++, é nos dias de hoje a linguagem de programação de aplicações 
mais comum no sistema operativo Windows da companhia Microsoft; C permanece mais 
popular no mundo UNIX. 
 
Em 1983, o instituto norte-americano de padrões (ANSI) formou um comitê, X3J11, para 
estabelecer uma especificação do padrão da linguagem C. Após um processo longo e árduo, 
o padrão foi completo em 1989 e ratificado como ANSI X3.159-1989 “Programming 
Language C”. Esta versão da linguagem é freqüentemente referida como ANSI C. Em 1990, 
o padrão ANSI C, após sofrer umas modificações menores, foi adotado pela Organização 
Internacional de Padrões (ISO) como ISO/IEC 9899:1990, também conhecido como C89 ou 
C90. Um dos objetivos do processo de padronização ANSI C foi o de produzir um 
sobreconjunto do K&R C, incorporando muitas das características não-oficiais 
subseqüentemente introduzidas. Entretanto, muitos programas tinham sido escritos e que 
não compilavam em certas plataformas, ou com um certo compilador, devido ao uso de 
bibliotecas de funções não-padrão e ao fato de alguns compiladores não aderirem ao ANSI 
C. 
 
10.4. C99 
 
Após o processo da padronização ANSI, as especificações da linguagem C permaneceram 
relativamente estáticas por algum tempo, enquanto que a linguagem C++ continuou a 
evoluir. (em 1995, a Normative Amendment 1 criou uma versão nova da linguagem C mas 
esta versão raramente é tida em conta.) Contudo, o padrão foi submetido a uma revisão nos 
finais da década de 1990, levando à publicação da norma ISO 9899:1999 em 1999. Este 
padrão é geralmente referido como “C99”. O padrão foi adoptado como um padrão ANSI em 
Março de 2000. As novas características do C99 incluem: 
 
• funções em linha 
• remoção de restrições sobre a localização da declaração de variáveis (como em C++) 
• adição de vários tipos de dados novos, incluindo o long long int (para minimizar 
problemas na transição de 32-bits para 64-bits), um tipo de dados boolean explicito 
(chamado _Bool) e um tipo complex que representa números complexos 
 
Página 58 
 
• vetores de dados de comprimento variável (o vetor pode ter um tamanho diferente a 
cada execução de uma função, mas não cresce depois de criado) 
• suporte oficial para comentários de uma linha iniciados por //, emprestados da 
linguagem C++ 
• várias funções de biblioteca novas, tais como snprintf() 
• vários ficheiros-cabeçalho novos, tais como stdint.h 
 
O interesse em suportar as características novas de C99 parece depender muito das 
entidades. Apesar do GCC e vários outros compiladores suportarem grande parte das novas 
características do C99, os compiladores mantidos pela Microsoft e pela Borland suportam 
pouquíssimos recursos do C99, e estas duas companhias não parecem estar muito 
interessadas em adicionar tais funcionalidades, ignorando por completo as normas 
internacionais. A Microsoft parece preferir dar mais ênfase ao C++. 
 
10.5. Visão Geral 
 
C é uma linguagem imperativa e procedural, para implementação de sistemas. Seus pontos 
de design foram para ele ser compilado, fornecendo acesso de baixo nível à memória e 
baixos requerimentos do hardware. Também foi desenvolvido para ser uma linguagem de 
alto nível, para maior reaproveitamento do código. C foi útil para muitas aplicações que 
foram codificadas originalmente em Assembly. 
 
Essa propriedade não foi acidental; a linguagem C foi criada com o objetivo principal em 
mente: facilitar a criação de programas extensos com menos erros, recorrendo ao 
paradigma da programaçãoalgorítmica ou procedimental, mas sobrecarregando menos o 
autor do compilador, cujo trabalho complica-se ao ter de realizar as características 
complexas da linguagem. Para este fim, a linguagem C possui as seguintes características: 
 
• Uma linguagem nuclear extremamente simples, com funcionalidades não-essenciais, 
tais como funções matemáticas ou manuseamento de arquivos, fornecida por um 
conjunto de bibliotecas de rotinas padronizada; 
• A focalização no paradigma de programação procedimental; 
• Um sistema de tipos simples que evita várias operações que não fazem sentido 
• Uso de uma linguagem de pré-processamento, o pré-processador de C, para tarefas 
tais como a definição de macros e a inclusão de múltiplos ficheiros de código fonte; 
• Ponteiros dão maior flexibilidade à linguagem; 
• Acesso de baixo-nível, através de inclusões de código Assembly no meio do 
programa C; 
 
 
Página 59 
 
• Parâmetros que são sempre passados por valor para as funções e nunca por 
referência (É possível simular a passagem por referência com o uso de ponteiros); 
• Definição do alcance lexical de variáveis; 
• Estruturas de variáveis, (structs), que permitem que dados relacionados sejam 
combinados e manipulados como um todo. 
 
Algumas características úteis, que faltam em C, podem ser encontradas em outras 
linguagens, que incluem: 
 
• Segurança de tipo; 
• Coletor de lixo (mais comum em linguagens interpretadas); 
• Vetores que crescem automaticamete; 
• Classes ou objectos com comportamento (ver orientação a objetos); 
• Closures (a closure is a function that is evaluated in an environment containing one or 
more bound variables. When called, the function can access these variables); 
• Funções aninhadas; 
• Programação genérica; 
• Sobrecarga de operadores; 
• Meta-programação; 
• Apoio nativo de multithreading e comunicação por rede. 
 
Apesar da lista de características úteis que C não possui, ser longa, isso não tem sido um 
impedimento à sua aceitação, pois isso permite que novos compiladores de C sejam escritos 
rapidamente para novas plataformas, e também permite que o programador permaneça 
sempre em controle do que o programa está a fazer. Isto é o que por várias vezes permite o 
código de C correr de uma forma mais eficiente que muitas outras linguagens. Tipicamente, 
só código de assembly “afinado à mão” é que corre mais rapidamente, pois possui um 
controle completo da máquina, mas avanços na área de compiladores juntamente com uma 
nova complexidade nos processadores modernos permitiram que a diferença tenha sido 
rapidamente eliminada. Uma consequência da aceitação geral da linguagem C é que 
freqüentemente os compiladores, bibliotecas e até intérpretes de outras linguagens de nível 
maior sejam eles próprios implementados em C. 
 
C tem como ponto forte, a sua eficiência, e é a linguagem de programação preferida para o 
desenvolvimento de sistemas e softwares de base, apesar de também ser usada para 
desenvolver programas de computador. É também muito usada no ensino de ciência da 
computação, mesmo não tendo sido projetada para estudantes e apresentando algumas 
dificuldades no seu uso. Outra característica importante de C, é sua proximidade do código 
de máquina, que permite que um projetista seja capaz de fazer algumas previsões de como 
o software irá se comportar, ao ser executado. 
 
Página 60 
 
C tem como ponto fraco, a falta de proteção que dá ao programador. Praticamente tudo que 
se expressa em um programa em C, pode ser executado, como por exemplo, pedir o 
vigésimo membro de um vetor com apenas dez membros. Os resultados são muitas vezes 
totalmente inesperados, e os erros, difíceis de encontrar. 
 
10.6. Palavras reservadas na Linguagem C 
 
A linguagem C é do tipo “case sensitive”. E além disto, algumas palavras são reservadas, 
sendo seu uso limitado apenas as funções ou comandos que elas executam: 
 
 
 
O compilador IAR tem também algumas palavras reservadas, o que veremos ao longo deste 
treinamento. 
 
11. VARIÁVEIS, TIPOS DE DADOS E OPERADORES EM C 
 
11.1. Tipos de dados 
 
Basicamente apenas 5 tipos de dados que são utilizadas em linguagem C: 
 
• char – caractere – 8 bits, 1 byte; 
• int – inteiro – 16 bits, 2 bytes; 
• float – ponto flutuante – 32 bits, 4 bytes; 
• double – ponto flutuante de precisão dupla – 64 bits, 8 bytes; 
• void – sem valor. 
 
Cada uma destes tipos pode ainda ter os seguintes modificadores: 
 
 
Página 61 
 
• signed – utilizará o último bit para sinalizar se um dado é positivo ou negativo. Com 
isto, o dado sempre estará com um tamanho menor em um bit. 
• unsigned – não informa se o dado tem valor positivo ou negativo. Por conseqüência 
todos os bits do dado podem ser utilizados como informação; 
• short – faz com que o dado passe a ter um tamanho menor do que especificado 
em sua definição. Por exemplo: utilizar o shot int pode fazê-lo assumir o valor de 
apenas um bit, dependendo do compilador utilizado; 
• long – faz com que o dado passe a ter um tamanho maior do que especificado em 
sua definição. Por exemplo: utilizar o long int pode fazê-lo assumir o valor de 65536 
bits, dependendo do compilador utilizado 
 
 
 
 
11.1.1. Detalhes sobre números em ponto flutuante 
 
A base numérica no padrão IEEE754 é a binária. Neste padrão são adotados dois formatos 
para representação de números: precisão simples e precisão dupla. (Na base binária, um 
dígito binário é denominado bit e um byte é um conjunto de 8 bits). 
 
 
Página 62 
 
Ficou estabelecido que no padrão IEEE754, em precisão simples, um número real seria 
representado por 32 bits, (4 bytes), sendo que: 
 
• 1 bit é reservado para o sinal do número (positivo ou negativo); 
• 8 bits são reservados para o expoente da base, que é um número inteiro; 
• 23 bits são reservados para a mantissa: 
 
Pelo mesmo padrão IEEE754, em precisão dupla, um número real seria representado por 64 
bits, (8 bytes), sendo que: 
 
• 1 bit é reservado para o sinal do número (positivo ou negativo); 
• 11 bits são reservados para o expoente da base, que é um número inteiro; 
• 52 bits são reservados para a mantissa: 
 
 
Qualquer valor em ponto flutuante é sempre escrito no seguinte formato: 
 
v = S × M × 2E 
 
Onde: 
 
• S = 1 − 2 × sinal 
• M = 1 + mantissa × 2-23 
• E = expoente − 127 
 
 
 
Página 63 
 
11.2. Declarando variáveis 
 
É necessário, durante o fluxo do programa, declarar as variáveis que serão utilizadas de 
acordo com os tipos de dados mostrados anteriormente. Isto pode ser feito das seguintes 
maneiras: 
 
TIPO nome_da_variável {,outras_variáveis}; 
unsigned int tempo; 
 
As variáveis podem ser inicializadas com um determinado valor durante a sua declaração: 
 
unsigned int tempo = 100; 
 
11.2.1. Variáveis locais e globais 
 
Dependendo do local onde é declarada a variável, esta pode assumir uma função global ou 
local: 
 
• Variáveis globais são acessíveis de qualquer ponto do programa, por qualquer 
função, e devem ser declaradas no corpo principal do programa, fora de qualquer 
função, inclusive da main; 
• Variáveis locais só podem ser acessadas dentro das funções onde foram criadas. Ao 
sair desta função, a linguagem C destrói uma variável local e, portanto ela não será 
acessível por outras funções. 
 
O programa a seguir (EXEMPLO-1) dá uma demonstração de como as variáveis podem ser 
declaradas localmente ou globalmente: 
 
//****************************************************************************** 
// Exemplo de variáveis globais e locais 
// Alessandro Ferreira da Cunha 
// Tech Training - Engenharia e Treinamentos 
// Dezembro 2008 – Extraído do Livro “PIC – Programação em C”, do Fábio Pereira 
// Built with IAR Embedded Workbench Version: 4.11.2.9 
//****************************************************************************** 
#include <msp430xG46x.h> 
#include <stdio.h> 
 
int somatorio; // VARIÁVEL GLOBAL! SERÁ ACESSADA POR TODAS AS FUNÇÕES 
 
void soma (int valor) //AO ACESSAR ESTA FUNÇÃO,O PARÂMETRO VALOR RECEBE DADOS DE QUEM O CHAMOU 
{ 
 int conta; // VARIÁVEL LOCAL! SERÁ ACESSADA APENAS PELA FUNÇÃO SOMA 
 somatorio = somatorio + valor; 
 printf("0"); 
 for (conta = 1;(conta<(valor+1));conta++) 
 { 
 printf("+%u",conta); 
 } 
 printf(" = %u\r\n",somatorio); 
} 
 
void main() 
{ 
 WDTCTL = WDTPW+WDTHOLD; // Stop WDT 
 int conta; // VARIÁVEL LOCAL! SERÁ ACESSADA APENAS PELA FUNÇÃO MAIN 
 somatorio = 0; // A VARIÁVEL GLOBAL É INICIALIZADA 
 for (conta=1;conta<20;conta++) 
 { 
 soma(conta); // É CHAMADA A FUNÇÃO SOMA, ONDE É PASSADO O VALOR DE CONTA 
 } 
} 
 
Página 64 
 
Alguns comentários importantes sobre o programa E-0-1: 
• O comando printf chama uma biblioteca que emula o envio de dados pela porta 
serial do MSP430. No IAR será possível visualizar estes dados através do Terminal 
I/O, acessível em: View Terminal I/O, onde será aberta a janela mostrada abaixo. 
Para que ele funcione é necessário incluir a biblioteca padrão stdio.h 
 
O formato do comando printf é: 
printf (string, variável); 
printf (“O número de tentativas foi %d”, contador); 
Onde: 
• string: é uma constate de caracteres, sempre declarado entre aspas; 
• variável: é a declaração de uma ou mais variáveis que devem ser impressas 
juntamente com os caracteres. Para tanto é necessário seguir a formatação %wt, 
onde w é o número de caracteres que se deseja imprimir e t é uma das seguintes 
opções: 
• c = caractere; 
• s = string ou caractere; 
• u = inteiro sem sinal; 
• x = inteiro em formato hexadecimal com letras minúsculas; 
• X = inteiro em formato hexadecimal com letras maiúsculas; 
• d = inteiro decimal com sinal; 
• i = inteiro decimal com sinal; 
• o = octal sem sinal; 
• e = ponto flutuante em formato exponencial; 
• f = ponto flutuante em formado decimal; 
• Lx = hexadecimal longo (16 ou 32 bits) com letras minúsculas; 
• LX = hexadecimal longo (16 ou 32 bits) com letras maiúsculas; 
• Lu = decimal longo (16 ou 32 bits) sem sinal; 
• Ld = decimal longo (16 ou 32 bits) com sinal; 
• % = símbolo de porcentagem; 
 
Página 65 
 
Para que todos os caracteres a serem impressos na janela Terminal I/O não fiquem na 
mesma linha, são utilizados os caracteres especiais de barra invertida, que são: 
• \b = retrocesso (backspace); 
• \f = alimentação de formulário; 
• \n = nova linha; 
• \r = retorno do carro; 
• \t = tabulação horizontal; 
• \” = aspas duplas; 
• \’ = aspas simples; 
• \0 = nulo; 
• \\ = barra invertida; 
• \v = tabulação vertical; 
• \a = alerta (beep); 
• \N = constante octal, onde N é o número em octal; 
• \xN = constante hexadecimal, onde N é o número em hexadecimal; 
 
Agora observe o programa exemplo EXEMPLO-2: 
 
//****************************************************************************** 
// Exemplo de uso da função scanf 
// 
// Alessandro Ferreira da Cunha 
// Tech Training - Engenharia e Treinamentos 
// Janeiro 2009 
// Built with IAR Embedded Workbench Version: 4.11.2.9 
//****************************************************************************** 
#include <msp430xG46x.h> 
#include <stdio.h> 
 
 
void main() 
{ 
 WDTCTL = WDTPW+WDTHOLD; // Stop WDT 
 char TECLA; // VARIÁVEL LOCAL! SERÁ ACESSADA APENAS PELA FUNÇÃO MAIN 
 for ( ; ; ) 
 { 
 printf("DIGITE UMA TECLA... \n \n "); 
 scanf("%c",&TECLA); 
 printf("SUA TECLA É %c!\n \n",TECLA); 
 } 
} 
 
A novidade aqui é o comando scanf. Enquanto o comando printf, mostrado no exemplo 
anterior, emula obenvio de dados pela porta serial do MSP430, o scanf emula o 
recebimento destes dados, também pela porta serial. 
 
Isto também será possível visualizar através do Terminal I/O, acessível em: View 
Terminal I/O. Assim como no comando anterior, para que ele funcione também é necessário 
incluir a biblioteca padrão stdio.h 
 
 
Página 66 
 
O formato do comando scanf é: 
scanf (string, variável); 
scanf (“%d”, contador); 
Tendo as mesmas características e controladores vistos no printf. 
 
11.2.2. Modificadores de acesso 
Além das declarações como global ou local, as variáveis podem receber dois tipos de 
modificadores de acesso, que especificam a forma como o compilador irá acessar o 
conteúdo das variáveis: 
• const: determina que a variável será tratada como uma constante, não podendo ser 
modificada ou alteradas durante a execução do programa. Faz, então, com que a 
variável passe a ter um valor fixo, pré-estabelecido durante a declaração da variável. 
• volatile: utilizado para indicar ao compilador que a variável por ele indicada pode ter 
seu conteúdo alterado a qualquer momento. 
volatile unsigned int tempo = 100; 
 
11.2.3. Modificadores de armazenamento 
 
Indicam como o compilador irá tratar o armazenamento das variáveis. São quatro tipos: 
 
• auto: serve para declarar que uma variável é local. Porém, todas as variáveis 
declaradas internamente já são locais. Com isto, este modificador de armazenamento 
quase nunca é utilizado. 
• extern: utilizado para fazer referência a outras variáveis globais que foram declaradas 
em outros módulos do programa. Isto é muito útil quando se tem programas extensos 
onde módulos cuidam de funcionamentos específicos e precisam passar parâmetros 
para outras partes do programa. 
• static: indica que a variável ocupará uma posição permanente de memória. Isto 
também ocorre quando uma variável é declarada de modo global. Mas numa 
declaração de static, a variável é reconhecida apenas localmente, dentro da função 
em que foi criada. Se o modificador de armazenamento static for aplicado a uma 
variável que já é global, isto fará com que ela seja reconhecida apenas pelo programa 
em que está inserida. Caso haja interação deste programa com outros externos, esta 
variável não estará acessível. 
• register: faz com que o compilador tente gravar esta variável diretamente em um dos 
registradores que tem acesso direto a CPU do microcontrolador, ao invés de 
armazená-la em uma posição de memória RAM. Com isto, ganha-se em velocidade 
de processamento. 
 
static volatile unsigned int tempo = 100; 
 
Página 67 
 
11.3. Operadores 
 
11.3.1. Operador atribuição 
 
É utilizado para atribuir um determinado valor a uma variável. Seu símbolo é o “ = ” e alguns 
exemplos de atribuição são mostrados a seguir: 
unsigned int x, y; 
x = 10; 
y = x; 
A atribuição é sempre avaliada da direita para a esquerda. Isto significa que ao final deste 
programa o valor da variável y será igual a 10. 
 
11.3.2. Operadores aritméticos 
 
Indica ao compilador que ele deve fazer determinada operação aritmética entre duas 
variáveis. São os seguintes: 
 
Um exemplo de utilização pode ser visto no trecho de programa abaixo: 
unsigned int x, y, z, w; 
x = 10; 
y = x ++; 
z = y --; 
w= x + y; 
 
11.3.3. Operadores relacionais 
 
São utilizados em testes condicionais para determinar a relação existente entre os dados: 
 
 
 
Página 68 
 
11.3.4. Operadores lógicos 
 
São utilizados para fazer conjunções, disjunções ou negações entre elementos durante um 
teste condicional. 
 
11.3.5. Operadores lógicos bit a bit 
 
11.3.6. Operadores de memória, ou de ponteiro 
 
Os ponteiros serão tratados em detalhes no estudo dos dados avançados. É possível dizer 
que este é um dos pilares fundamentais da linguagem C e portanto gastaremos algumas 
horas do nosso treinamento para explicá-los em detalhes. Por hora, vamos apenas conhecer 
quais são os símbolos utilizados como operadores de memória, ou de ponteiros, e suas 
funcionalidades. As aplicações serão desenvolvidas mais a frente. São dois os símbolos: 
• & endereço do operando. É um operador unário utilizado para retornar o 
endereço de memória do seu operando. Isto significa que se escrevermos: 
 
endereço_a = &a; 
 
teremos que a variável “endereço_a” conterá o endereço em que está armazenada a 
variável a. 
• * conteúdo do endereço apontado pelo operando. Este é um operador 
unário utilizado para retornar o conteúdo da posição de memória 
endereçada pelo operandoque segue. Isto significa que se escrevermos: 
 
a = *endereço_a; 
 
teremos que o valor armazenado no local apontado pela variável “endereço_a” seja 
atribuído à variável a. 
 
 
Página 69 
 
11.3.7. Outros operadores 
Outros operadores, que não se encaixam em nenhum dos tipos citados anteriormente, mas 
que podem ser utilizados em linguagem C são: 
• ? (ponto de interrogação) Operador ternário condicional: pode fazer 
um teste condicional, substituindo o comando IF. Sua forma geral é: 
 
variável = expressão1 ? expressão2 : expressão3; 
 
Ele funciona da seguinte maneira: avalie a expressão1. Se ela for verdadeira, atribua 
a variável o valor da expressão2. Caso a expressão1 seja falsa, então a variável 
recebe o valor da expressão3. 
• , (vírgula) Separador de expressões: é utilizado para enfileirar duas ou 
mais expressões. Sua forma geral é: 
 
variável = (expressão1 , expressão2 , expressão3); 
 
Uma aplicação, como a seguir, resulta em y = 5. 
 
y = ( x = 0 , x + 5 ); 
 
• . (ponto) Separador de estruturas: é utilizado em estruturas de dados 
como separador dos elementos e será estudado quando abordarmos os 
tipos de dados avançados. 
• -> (seta) Ponteiro de elementos de estruturas: é utilizado em 
estruturas de dados como ponteiro dos elementos e será estudado quando 
abordarmos os tipos de dados avançados. 
• (tipo) Operador modelagem de dado: é possível forçar que uma 
expressão seja de determinado tipo utilizando um cast cujo formato geral é: 
 
(tipo) expressão; 
 
Onde tipo é qualquer um dos tipos de dados permitidos pela linguagem C e 
expressão é a que se quer que resulte no tipo especificado. Por exemplo: para 
realizar um cálculo e obrigar que o resultado seja apresentado em ponto flutuante, 
pode-se utilizar o seguinte cast: 
 
unsigned int x, y; 
x = 10; 
y = (float) x / 2; 
 
Página 70 
 
• sizeof Retorna o tamanho de uma variável: para ter um melhor 
controle da quantidade de memória utilizada, pode-se aplicar o operador 
sizeof a qualquer variável. Isto fará retornar qual o tamanho que esta 
variável ocupa em bytes. 
 
12. EXERCÍCIOS: Operadores, tipos e variáveis 
 
12.1. Calculadora básica (EXERCÍCIO-1) 
 
Escreva um programa em que o usuário entre com dois números e seja realizada uma 
operação matemática básica (multiplicação), mostrando o resultado na tela. Este programa 
deve rodar dentro de um loop infinito no formato for ( ; ; );. 
O programa deve conter uma mensagem no Terminal I/O solicitando que o usuário digite o 
primeiro número. Depois uma mensagem solicita a digitação de um segundo número. 
Finalmente, o resultado da multiplicação é mostrado em uma nova linha do Terminal I/O. 
 
12.2. Conversor de moeda do dia (EXERCÍCIO-2) 
 
Escreva um programa em que o usuário entre com a cotação do dólar do dia, digite qual é a 
quantidade de dólares que quer converter e seja apresentado na tela do Terminal I/O 
apresente o valor convertido em reais. 
 
12.3. Calcular a idade de um usuário – I (EXERCÍCIO-3) 
 
Escreva um programa em que o usuário entre com a data de nascimento no formato na 
seguinte seqüência: 
• DIA (DD); 
• MÊS (MM); 
• ANO (AAAA). 
Na seqüência, o usuário deve digitar a data de hoje, entrando com os valores de dia, mês e 
ano no mesmo formato. 
 
O programa deve, então, calcular a idade do usuário, informando a idade em ANOS, cujo 
valor deve ser um inteiro. 
 
12.4. Calcular a idade de um usuário – II (EXERCÍCIO-4) 
 
Modifique o programa anterior de modo que seja mostrado na tela também o valor da idade 
em DIAS e MESES. 
 
 
Página 71 
 
13. Declarações de controle e repetição 
 
As declarações de controle e repetição são algumas das estruturas mais importantes da 
linguagem C. Elas é que garantem um fluxo de programa capaz de tomar decisões e desviar 
o programa de acordo com determinadas regras. Veremos neste treinamento estas 
estruturas, definidas pelo padrão ANSI C e como utilizá-las. 
 
• Seleção (condicional): if e switch; 
• Iteração (laço): while, for e do-while; 
• Desvio (salto): break, continue, goto e return; 
• Rótulo: case, default e label; 
 
13.1. Verdadeiro ou Falso em linguagem C 
 
Diversos destes comandos de controle e repetição acontecem apenas após um teste 
condicional, onde é verificado o status de VERDADEIRO ou FALSO de uma variável. É 
necessário entender como o C observa esta condição para compreender perfeitamente 
como as decisões são tomadas: 
 
• VERDADEIRO: é considerada uma condição verdadeira para uma variável quando 
esta tem qualquer valor diferente de zero, inclusive valores negativos. 
• FALSO: é considerada uma condição falsa para uma variável quando esta tem valor 
igual a zero. 
 
13.2. If 
 
if (condição) comandoA; {else comandoB} 
 
if (condição) 
{ 
comandoA; 
comandoB; 
comandoC; 
} 
else 
{ 
comandoD; 
comandoE; 
comandoF 
} 
 
Página 72 
 
Veja um exemplo de utilização da função if rodando o programa EXEMPLO-3: 
 
//****************************************************************************** 
// Exemplo de uso da função if 
// Built with IAR Embedded Workbench Version: 4.11.2.9 
//****************************************************************************** 
#include <msp430xG46x.h> 
#include <stdio.h> 
#include <stdlib.h> 
 
 
void main() 
{ 
 WDTCTL = WDTPW+WDTHOLD; // Stop WDT 
 for ( ; ; ) // cria um loop infinito 
 { 
 
 int numero; // número mágico 
 int palpite; // chute do usuário 
 
 numero = rand(); // gera um número aleatório 
 
 printf("ADIVINHE QUAL É O NÚMERO... \n \n "); 
 scanf("%d",&palpite); 
 
 if (palpite == numero) printf ("****CERTO!!!****\n\n"); 
 else printf ("### ERRADO ###\n\n"); 
 
 } 
} 
 
Note que para conseguir gerar um número randômico, foi necessário incluir mais uma 
biblioteca de funções, a stdlib.h. 
 
13.2.1. If – Else – If comandos aninhados 
 
if (condição1) comandoA; 
else if (condição2) comandoB; 
 else if (condição3) comandoC; 
 
Veja um exemplo de utilização da função if aninhadas no programa EXEMPLO-4: 
 
//****************************************************************************** 
// Exemplo de uso da função if aninhada 
// Built with IAR Embedded Workbench Version: 4.11.2.9 
//****************************************************************************** 
#include <msp430xG46x.h> 
#include <stdio.h> 
#include <stdlib.h> 
 
void main() 
{ 
 WDTCTL = WDTPW+WDTHOLD; // Stop WDT 
 int numero; // número mágico 
 int palpite; // chute do usuário 
 numero = rand(); // gera um número aleatório 
 for ( ; ; ) // cria um loop infinito 
 { 
 printf("ADIVINHE QUAL É O NÚMERO... \n \n "); 
 scanf("%d",&palpite); 
 if (palpite == numero) printf ("****CERTO!!!****\n\n"); 
 else 
 { 
 printf ("### ERRADO ###\n\n"); 
 if (palpite < numero) printf (" --- valor alto --- \n\n"); 
 else printf (" +++ valor baixo +++ \n\n"); 
 } 
 } 
} 
 
Página 73 
 
13.2.2. Uma alternativa: o comando ? 
 
variável = expressão1 ? expressão2 : expressão3; 
 
Ele funciona da seguinte maneira: avalie a expressão1. Se ela for verdadeira, atribua a 
variável o valor da expressão2. Caso a expressão1 seja falsa, então a variável recebe o 
valor da expressão3. 
 
13.3. Switch 
 
O comando switch difere do comando if porque somente pode testar igualdades. O 
comando if pode avaliar uma expressão lógica ou relacional. 
 
switch (variável) 
{ 
case constante1: 
comandoA; 
comandoB; 
.... 
break; 
case constante2: 
comandoC; 
comandoD; 
.... 
break; 
.... 
default: 
comandoE; 
comandoF; 
.... 
} 
 
Veja no programa EXEMPLO-5 como utilizar o comando switch case: 
 
 
Página 74 
 
//****************************************************************************** 
// Exemplo de uso da função switch case 
// Built with IAR Embedded Workbench Version: 4.11.2.9 
//****************************************************************************** 
#include <msp430xG46x.h>#include <stdio.h> 
 
void main() 
{ 
 WDTCTL = WDTPW+WDTHOLD; // Stop WDT 
 int digitado; // digitado 
 for ( ; ; ) // cria um loop infinito 
 { 
 printf("DIGITE UM NÚMERO ENTRE 0 E 5: \n \n "); 
 scanf("%d",&digitado); 
 switch (digitado) 
 { 
 case 0: 
 printf("O NÚMERO DIGITADO FOI %d ! \n \n ",digitado); 
 break; 
 case 1: 
 printf("O NÚMERO DIGITADO FOI %d ! \n \n ",digitado; 
 break; 
 case 2: 
 printf("O NÚMERO DIGITADO FOI %d ! \n \n ",digitado; 
 break; 
 case 3: 
 printf("O NÚMERO DIGITADO FOI %d ! \n \n ",digitado; 
 break; 
 case 4: 
 printf("O NÚMERO DIGITADO FOI %d ! \n \n ",digitado; 
 break; 
 case 5: 
 printf("O NÚMERO DIGITADO FOI %d ! \n \n ",digitado; 
 break; 
 default: 
 printf("O NÚMERO DIGITADO NÃO ESTÁ ENTRE 0 E 5! \n \n "); 
 } 
 } 
} 
 
13.4. Laço for (para) 
 
for (inicialização ; condição ; incremento) comando; 
 
for (inicialização ; condição ; incremento) 
{ 
comandoA; 
comandoB; 
.... 
} 
 
Veja no programa EXEMPLO-6 como utilizar o laço for: 
 
//****************************************************************************** 
// Exemplo de uso da laço for 
// Built with IAR Embedded Workbench Version: 4.11.2.9 
//****************************************************************************** 
#include <msp430xG46x.h> 
#include <stdio.h> 
 
void main() 
{ 
 WDTCTL = WDTPW+WDTHOLD; // Stop WDT 
 int conta; 
 for (conta = 0 ; conta <= 10 ; conta++) printf("%u\r\n",conta); 
}
 
Página 75 
 
13.4.1. Laço infinito 
 
for ( ; ; ); 
 
13.4.2. Cláusula break no comando for 
 
Como sair de um laço infinito? Execute o programa EXEMPLO-7 e verifique seu efeito em 
um laço infinito: 
 
//****************************************************************************** 
// Exemplo de uso do comando BREAK em um laço for 
// 
// Alessandro Ferreira da Cunha 
// Tech Training - Engenharia e Treinamentos 
// Janeiro 2009 
// Built with IAR Embedded Workbench Version: 4.11.2.9 
//****************************************************************************** 
#include <msp430xG46x.h> 
#include <stdio.h> 
 
void main() 
{ 
 WDTCTL = WDTPW+WDTHOLD; // Stop WDT 
 char caractere; 
 for ( ; ; ) 
 { 
 printf ("digite algo \n"); 
 scanf("%c",&caractere); //pega um caractere 
 if (caractere == 'A') break; //sai do laço 
 } 
 printf ("você digitou um A"); 
} 
 
13.4.3. Cláusula continue no comando for 
 
Qual o efeito de trocar uma cláusula break por uma cláusula continue? Execute o programa 
EXEMPLO-8 e verifique seu efeito: 
 
//****************************************************************************** 
// Exemplo de uso da cláusula CONTINUE em um laço for 
// 
// Alessandro Ferreira da Cunha 
// Tech Training - Engenharia e Treinamentos 
// Janeiro 2009 
// Built with IAR Embedded Workbench Version: 4.11.2.9 
//****************************************************************************** 
#include <msp430xG46x.h> 
#include <stdio.h> 
 
void main() 
{ 
 WDTCTL = WDTPW+WDTHOLD; // Stop WDT 
 int inicio, fim, x; 
 printf ("digite o início \n"); 
 scanf("%d",&inicio); 
 printf ("digite o fim \n"); 
 scanf("%d",&fim); 
 for ( x = inicio ; x <= fim ; x++ ) 
 { 
 if ( x == fim) continue; 
 printf("%u\r\n",x); 
 } 
 printf (" --- ACABOU --- "); 
} 
 
Página 76 
 
13.5. Laço while (enquanto) 
 
while (condição) comando; 
 
while (condição) 
{ 
comandoA; 
comandoB; 
.... 
} 
 
Veja no programa EXEMPLO-9 como utilizar o laço while: 
 
//****************************************************************************** 
// Exemplo de uso laço while 
// Built with IAR Embedded Workbench Version: 4.11.2.9 
//****************************************************************************** 
#include <msp430xG46x.h> 
#include <stdio.h> 
 
void main() 
 { 
 WDTCTL = WDTPW+WDTHOLD; // Stop WDT 
 int i; 
 i = 1; 
 while(i < 6) 
 { 
 printf ("ainda está em %d \n",i); 
 i++; 
 } 
 printf ("acabou"); 
 } 
 
13.5.1. Cláusulas break e continue no laço while 
 
As cláusulas break e continue podem ser utilizadas também no comando while, tendo o 
mesmo efeito que se obteve de seu uso no laço for. Veja o exemplo E-0-10. 
 
//****************************************************************************** 
// Exemplo de uso das cláusulas break e continue no laço while 
// Built with IAR Embedded Workbench Version: 4.11.2.9 
//****************************************************************************** 
#include <msp430xG46x.h> 
#include <stdio.h> 
 
void main() 
 { 
 WDTCTL = WDTPW+WDTHOLD; // Stop WDT 
 int x, y, w, z; 
 w = 0 ; 
 printf("ENTRE COM UM NÚMERO \n"); 
 scanf("%d",&x); 
 printf("ENTRE COM OUTRO NÚMERO \n"); 
 scanf("%d",&y); 
 printf("ENTRE COM A QUANT. DE IMPRESSÕES \n"); 
 scanf("%d",&z); 
 while (w < z) 
 { 
 if (x == 0 || y == 0) break; 
 w++; 
 x = x * y; 
 printf("A MULTIPLICAÇÃO É %d \n",x); 
 if (x < 1000) continue; 
 printf(" ACABOU "); 
 } 
} 
 
Página 77 
 
13.5.2. Laço infinito 
 
while (1) 
 { 
 ...... 
 } 
 
 
 
13.6. Laço do-while (faça-enquanto) 
 
do comando while (condição); 
 
do 
{ 
comandoA; 
comandoB; 
.... 
} while (condição); 
 
Veja no programa EXEMPLO-11 como utilizar o laço do-while: 
 
//****************************************************************************** 
// Exemplo de uso laço do-while 
// Built with IAR Embedded Workbench Version: 4.11.2.9 
//****************************************************************************** 
#include <msp430xG46x.h> 
#include <stdio.h> 
 
/* PROGRAMA PARA LANÇAMENTO DE FOGUETES DA NASA. */ 
 
void main() 
 { 
 WDTCTL = WDTPW+WDTHOLD; // Stop WDT 
 int start; 
 printf("ENTRE COM O TEMPO PARA LANÇAMENTO \n"); 
 scanf("%d",&start); 
 /* O LAÇO DE CONTAGEM REGRESSIVA */ 
 do 
 { 
 printf("FALTAM %d SEGUNDOS \n",start); 
 start--; 
 } 
 while(start>0); 
 printf("Zero!\n FOGO!!\n"); 
} 
 
13.7. Usar um laço while (enquanto) ou um laço for (para)? 
 
Os dois laços, while e for, tem várias similaridades. Na grande maioria das situações o 
mesmo problema poderá ser resolvido tanto com um tipo de laço quanto com o outro. Para 
uma melhor compreensão do que estamos dizendo, vamos fazer uma equivalência entre os 
parâmetros que são ajustados para fazer rodar um laço for e os mesmos parâmetros para 
fazer exatamente o mesmo efeito, mas com um laço while. 
 
Página 78 
 
for ( A ; B ; C) printf (“%d\t”,i); 
 
A; 
while (B) 
{ 
printf (“%d\t”,i); 
C; 
} 
 
A escolha por um ou outro modelo dependerá apenas do estilo do programador. A forma for 
é mais compacta. Já a forma while permite uma visualização mais fácil de todas as partes 
envolvidas. Enfim: ambos geram os mesmos efeitos na linguagem C pura e podem ser 
considerados iguais pelo programador. 
 
Já a sua aplicação em microcontroladores deve ser analisada com cuidado. 
 
Dependendo do compilador e da forma como o laço é gerado, pode ser obtido programas 
em assembly maiores ou menores para executar a mesma tarefa. A velocidade com que o 
programa executa o laço também é influenciada pelo estilo de conversão que o compilador 
fará para cada um deles. 
 
Um excelente exercício é modificar as opções de otimização do IAR (por velocidade ou por 
tamanho de código) e compilar programas com resultados de saída iguais mas que façam 
uso de laços diferentes, observando o comportamento do código assembly gerado pelo 
compilador. 
 
 
Página 79 
 
13.8. Tudo junto? 
 
Veja no programa EXEMPLO-12 todos os conceitos deste capítulo reunidos em um únicoprograma: 
 
//****************************************************************************** 
// Exemplo COM TUDO JUNTO 
// 
// Alessandro Ferreira da Cunha 
// Tech Training - Engenharia e Treinamentos 
// Janeiro 2009 
// Built with IAR Embedded Workbench Version: 4.11.2.9 
//****************************************************************************** 
#include <msp430xG46x.h> 
#include <stdio.h> 
 
/* Controle de venda no lobby de um cinema */ 
 
void main() 
 { 
 WDTCTL = WDTPW+WDTHOLD; // Stop WDT 
 char c; 
 int done; 
 float total = 0; 
 printf("Por favor, escolha suas opções:\n"); 
 printf("1 -> Refrigerante.\n"); 
 printf("2 -> Balas.\n"); 
 printf("3 -> Cachorro Quente.\n"); 
 printf("4 -> Pipocas.\n"); 
 printf("= -> Fechar o pedido.\n"); 
 printf("Suas escolhas são:\n"); 
 
 done = 0; 
 while(!done) 
 { 
 scanf("%c",&c); 
 switch(c) 
 { 
 case '1': 
 printf("Refrigerante\tR$8.00\n"); 
 total+=8; 
 break; 
 case '2': 
 printf("Balas\t\t$R5.50\n"); 
 total+=5.5; 
 break; 
 case '3': 
 printf("Cachorro Quente\t\tR$10.00\n"); 
 total+=10; 
 break; 
 case '4': 
 printf("Pipocas\t\t$7.50\n"); 
 total+=7.5; 
 break; 
 case '=': 
 printf("= Total R$%.2f\n",total); 
 printf("Por favor passe o cartão.\n"); 
 done=1; 
 break; 
 default: 
 printf("Seleção inadequada.\n"); 
 } /* end switch */ 
 } /* end while */ 
}/* end main */ 
 
13.9. Comando GOTO (vá para) 
 
goto label; 
 
Página 80 
 
14. EXERCÍCIOS: Declarações de controle e repetição 
 
14.1. Configuração básica dos I/Os 
 
As seguintes configurações devem ser observadas para fazer os exercícios propostos: 
 
REGISTRADOR DE ENTRADA (Input Register PxIN) 
Cada bit colocado em um pino do microcontrolador tem seu valor refletido neste registrador. 
Isto ocorre quando a porta está configurada para entrada, sendo válida as seguintes 
informações: 
Bit = 0: A entrada está em nível lógico baixo (0 V). 
Bit = 1: A entrada está em nível lógico alto (+Vcc). 
 
REGISTRADOR DE SAÍDA (Output Registers PxOUT) 
Cada bit escrito neste registrador refletirá em um valor de tensão no pino de saída. Isto 
ocorre quando a porta está configurada para saída, sendo válida as seguintes informações:. 
Bit = 0: A saída será levada a nível lógico baixo (0 V). 
Bit = 1: A saída será levada a nível lógico alto (+Vcc). 
 
REGISTRADOR DE DIREÇÃO (Direction Registers PxDIR) 
Este registrador indicará se um pino de I/O será utilizado como entrada ou saída, de acordo 
com a seguinte configuração: 
Bit = 0: A porta será configurada como entrada. 
Bit = 1: A porta será configurada como saída. 
 
REGISTRADORES DE PULL UP / PULL DOWN (Pullup/Pulldown Resistor Enable 
Registers PxREN (MSP430x47x only)) 
Apenas nos dispositivos das famílias MSP430x47x todas as portas tem resistores 
programáveis de pull-up/down, cuja habilitação ou não é feita do seguinte modo: 
Bit = 0: Os resistores estarão desabilitados. 
Bit = 1: Os resistores estarão habilitados. 
 
REGISTRADORES DE SELEÇÃO DE FUNÇÃO (Function Select Registers PxSEL) 
Como os pinos de um microcontrolador pode ter múltiplas funções, hora funcionando como 
terminal de I/O, hora como interface de algum periférico, é necessário ajustar qual função 
será realizada a cada momento. Isto é feito de acordo com os seguintes ajustes: 
Bit = 0: O terminal funcionará como um I/O. 
Bit = 1: O terminal funcionará como um periférico. 
Nota: as interrupções por P1 e P2 são desabilitadas quando PxSEL = 1 
 
Página 81 
 
REGISTRADOR DE SINALIZAÇÃO DE INTERRUPÇÃO (Flag Register PxIFG) 
Sinalizam que uma interrupção aconteceu. A mudança de nível zero para nível um acontece 
por hardware. O contrário (de 1 0) deve ser executada por software: 
Bit = 0: não há interrupção pendente neste pino (0 V). 
Bit = 1: há uma interrupção pendente neste pino (+Vcc). 
 
REGISTRADOR DE SELEÇÃO DE BORDA DE INTERRUPÇÃO (Edge Select PxIES) 
Este registrador fará a seleção entre as bordas de transição no sinal dos pinos que 
acionarão a interrupção: 
Bit = 0: PxIFG 1 quando houver uma transição de zero para um no pino (0 V +Vcc). 
Bit = 1: PxIFG 1 quando houver uma transição de um para zero no pino (+Vcc 0 V). 
 
REGISTRADOR HABILITAÇÃO DE INTERRUPÇÃO (Interrupt Enable Register PxIE) 
Este registrador fará a habilitação de interrupção para aquele pino: 
Bit = 0: interrupções estão desabilitadas neste pino (0 V). 
Bit = 1: interrupções estão habilitadas neste pino (+Vcc). 
 
14.2. Alocação de pinos nas portas de I/O 
 
/************************************************************ 
* STANDARD BITS FOR DIGITAL I/O 
************************************************************/ 
 
#define BIT0 (0x0001); PINO 0 DA PORTA 
#define BIT1 (0x0002); PINO 1 DA PORTA 
#define BIT2 (0x0004); PINO 2 DA PORTA 
#define BIT3 (0x0008); PINO 3 DA PORTA 
#define BIT4 (0x0010); PINO 4 DA PORTA 
#define BIT5 (0x0020); PINO 5 DA PORTA 
#define BIT6 (0x0040); PINO 6 DA PORTA 
#define BIT7 (0x0080); PINO 7 DA PORTA 
 
14.3. Exemplos de configuração de portas de I/O 
 
Configurando um botão: 
 
SetupP2 bis.b #002h,&P2DIR ; P2.1 output - LED 
 
SetupP1 bis.b #001h,&P1IE ; P1.0 Interrupt enabled 
 bis.b #001h,&P1IES ; P1.0 hi/low edge 
 bic.b #001h,&P1IFG ; P1.0 IFG Cleared 
 
Configurando dois botões: 
 
SetupP2 bis.b #006h,&P2DIR ; P2.1 & P2.2 output - LED 
 
SetupP1 bis.b #003h,&P1IE ; P1.0 & P1.1 Interrupt enabled 
 bis.b #003h,&P1IES ; P1.0 & P1.1 hi/low edge 
 bic.b #003h,&P1IFG ; P1.0 & P1.1 IFG Cleared 
 
 
Página 82 
 
Identifique no diagrama elétrico da Experimenter Board, mostrado no item 9, as seguintes 
conexões, envolvendo pinos do MSP430FG4618 e hardwares externos: 
 
a) Botão S1 pino P1.0; 
b) Botão S2 pino P1.1; 
c) LED1 pino P2.1; 
d) LED2 pino P2.2; 
e) LED4 pino P5.1. 
 
Com estas informações escrevam programas em linguagem C de modo que aconteçam as 
operações solicitadas nos itens a seguir. 
 
14.4. 1 botão e 1 Led (EXERCÍCIO-5) 
 
Ao pressionar o botão S1 deve acender o LED1. Se o botão não estiver pressionado, o 
LED1 deve se manter apagado. 
 
14.5. 2 botões e 2 Leds (EXERCÍCIO-6) 
 
Ao pressionar o botão S1 deve apagar o LED1. Se o botão S1 não estiver pressionado, o 
LED1 deve se manter aceso. Ao mesmo tempo se o botão S2 for pressionado, o LED2 
deve se apagar. Se o botão S2 não estiver pressionado, o LED2 deve se manter aceso. 
 
14.6. 1 botão, 1 Led e temporização simples (EXERCÍCIO-7) 
 
Ao pressionar o botão S2 deve acender o LED1, que deve permanecer aceso por alguns 
milissegundos (tempo suficiente para perceber a retenção da informação). Se o botão não 
estiver pressionado, o LED1 deve se manter apagado. 
 
14.7. 2 botões, 2 Leds e temporização simples (EXERCÍCIO-8) 
 
Ao pressionar o botão S2 deve apagar o LED1, o que deve acontecer por alguns 
milissegundos (tempo suficiente para perceber a retenção da informação). Se o botão não 
estiver pressionado, o LED1 deve se manter aceso. Ao mesmo tempo, se o botão S1 
estiver pressionado o LED2 deve ficar apagado, o que também deve acontecer por alguns 
milissegundos (tempo suficiente para perceber a retenção da informação). Se o botão não 
estiver pressionado, o LED2 deve se manter aceso 
 
 
Página 83 
 
15. Diretivas e funções do Compilador IAR 
 
Além de todos os comandos, controles e funções da linguagem C, tem-se ainda uma série 
de diretivas que são intrínsecas ao Compilador IAR. Para estudá-las, o melhor caminho são 
os arquivos de HELP que acompanham o compilador, além dos arquivos USER GUIDE, emformato .pdf, que podem ser acessados diretamente através do menu Help do compilador. 
Dentre estes arquivos destacamos alguns que farão parte do CD que compõe o material 
didático deste treinamento. 
 
Apesar da grande quantidade de informação que estes arquivos fornecem, é interessante tê-
los sempre a mão, como uma fonte de consulta, toda vez que se está desenvolvendo um 
novo programa. 
 
Dentre as diversas diretivas e funções do compilador IAR, vamos listar dois tipos, que serão 
utilizados ao longo do treinamento: as PRAGMAS e as FUNÇÕES INTRINSECAS. As 
demais funções deverão ser consultadas pelos estudantes diretamente nos arquivos. 
 
15.1. Pragmas 
 
Pragmas são um modo de passar informações especiais para o compilador e para adicionar 
extensões específicas de vendedor à biblioteca do microcontrolador, garantindo assim sua 
portabilidade entre diversos chips. 
 
As diretivas #pragma são definidas pelo ISO/ANSI C e fazem, entre outras coisas, o 
controle do comportamento do compilador. Por exemplo, ela pode determinar que 
quantidade de memória é alocada para cada variável ou função, permitir o uso de palavras 
chaves, fornecer mensagens de alerta, etc. 
 
A lista a seguir mostra todas as diretivas #pragma que estão disponíveis no IAR, para a 
família MSP430. 
 
É necessário o uso do pré processador #pragma para que estas diretivas sejam entendidas 
pelo compilador e passem a ser tratadas como tal. 
 
 
Página 84 
 
Pragma directive Description 
basic_template_matching Makes a template function fully memory-attribute aware 
bis_nmi_ie1 Generates a BIS instruction just before the RETI instruction 
bitfields Controls the order of bitfield members 
constseg Places constant variables in a named segment 
data_alignment Gives a variable a higher (more strict) alignment 
dataseg Places variables in a named segment 
diag_default Changes the severity level of diagnostic messages 
diag_error Changes the severity level of diagnostic messages 
diag_remark Changes the severity level of diagnostic messages 
diag_suppress Suppresses diagnostic messages 
diag_warning Changes the severity level of diagnostic messages 
include_alias Specifies an alias for an include file 
inline Inlines a function 
language Controls the IAR Systems language extensions 
location Specifies the absolute address of a variable, or places groups of 
functions or variables in named segments 
message Prints a message 
no_epilogue Performs a local return sequence 
object_attribute Changes the definition of a variable or a function 
optimize Specifies the type and level of an optimization 
pack Specifies the alignment of structures and union members 
required Ensures that a symbol that is needed by another symbol is 
included in the linked output 
rtmodel Adds a runtime model attribute to the module 
segment Declares a segment name to be used by intrinsic functions 
type_attribute Changes the declaration and definitions of a variable or function 
vector Specifies the vector of an interrupt or trap function 
 
 
Página 85 
 
15.2. Funções intrínsecas 
 
São um conjunto de funções predefinidas que estão disponíveis no compilador IAR. Elas 
permitem um acesso direto ao processamento de baixo nível e podem ser extremamente 
úteis em, por exemplo, rotinas que envolvam tempo crítico de execução. 
 
Para serem reconhecidas, é necessário acrescentar o arquivo intrinsics.h, através de um 
comando include. Note que o nome destas funções sempre iniciam-se com um duplo 
undeline. 
 
Intrinsic function Description 
__bcd_add_type Performs a binary coded decimal operation 
__bic_SR_register Clears bits in the SR register 
__bic_SR_register_on_exit Clears bits in the SR register when an interrupt or monitor 
function returns 
__bis_SR_register Sets bits in the SR register 
__bis_SR_register_on_exit Sets bits in the SR register when an interrupt or monitor 
function returns 
__data16_read_addr Reads data to a 20-bit SFR register 
__data16_write_addr Writes data to a 20-bit SFR register 
__data20_read_type Reads data which has a 20-bit address 
__data20_write_type Writes data which has a 20-bit address 
__delay_cycles Provides cycle accurate code size minimized delay 
functionality 
__disable_interrupt Disables interrupts 
__enable_interrupt Enables interrupts 
__even_in_range Makes switch statements rely on the specified value being 
even and within the specified range 
__get_interrupt_state Returns the interrupt state 
__get_R4_register Returns the value of the R4 register 
__get_R5_register Returns the value of the R5 register 
__get_SP_register Returns the value of the stack pointer 
__get_SR_register Returns the value of the SR register 
 
Página 86 
__get_SR_register_on_exit Returns the value that the processor status register will 
have when the current interrupt or monitor function returns 
__low_power_mode_n Enters a MSP430 low power mode 
__low_power_mode_off_on_exit Turns off low power mode when a monitor or interrupt 
function returns 
__no_operation Inserts a NOP instruction 
__op_code Inserts a constant into the instruction stream 
__set_interrupt_state Restores the interrupt state 
__set_R4_register Writes a specific value to the R4 register 
__set_R5_register Writes a specific value to the R5 register 
__set_SP_register Writes a specific value to the SP register 
__swap_bytes Executes the SWPB instruction 
 
16. ECONOMIZANDO ENERGIA PARA PISCAR O LED 
 
Ao resolver os exercícios propostos anteriormente não fizemos uso da principal 
característica do MSP430, que é o baixo consumo de energia. Execute o programa 
EXEMPLO-13 em seu kit. Veja o seu funcionamento. 
 
//****************************************************************************** 
// MSP430xG46x Demo - Software Port Interrupt on P1.4 from LPM4 
// 
// Description: A hi/low transition on P1.4 will trigger P1_ISR which, 
// toggles P5.1. Normal mode is LPM4 ~ 0.1uA. LPM4 current can be measured 
// with the LED removed, all unused P1.x/P2.x configured as output or inputs 
// pulled high or low, and ensure the P2.0 interrupt input does not float. 
// ACLK = 32.768kHz, MCLK = SMCLK = default DCO 
// 
// K. Quiring/ M. Mitchell 
// Texas Instruments Inc. 
// October 2006 
// Built with IAR Embedded Workbench Version: 3.41A 
//****************************************************************************** 
#include <msp430xG46x.h> 
 
void main(void) 
{ 
 WDTCTL = WDTPW+WDTHOLD; // Stop WDT 
 P5DIR |= 0x002; // P5.1 output 
 P1IE |= 0x010; // P1.4 Interrupt enabled 
 P1IES |= 0x010; // P1.4 hi/low edge 
 P1IFG &= ~0x010; // P1.4 IFG Cleared 
 _BIS_SR(LPM4_bits + GIE); // LPM4, enable interrupts 
 
} 
 
// Port 1 interrupt service routine 
#pragma vector=PORT1_VECTOR 
__interrupt void Port1_ISR (void) 
{ 
 P5OUT ^= 0x02; // P5.1 = toggle 
 P1IFG &= ~0x010; // P1.4 IFG Cleared 
} 
 
 
Página 87 
 
17. Interrupções 
 
As interrupções no MSP430 são fixas e definidas pelo arranjo modular mostrado na figura 
abaixo. 
 
 
Quanto mais próximo for um módulo da CPU/NMIRS, maior a sua prioridade em interromper 
o sistema. Esta prioridade define quem será tratado primeiramente caso ocorram duas 
interrupções simultaneamente. 
 
Para o MSP430 são considerados três tipos de interrupção: 
• Reset do sistema; 
• NMI: interrupções não mascaráveis; 
• Interrupções mascaráveis. 
E funcionam de acordo com a lógica mostrada na figura a seguir. 
 
17.1. Reset do sistema 
 
O circuito de reset do sistema é mostrado na figura a seguir. Ele fornece como saída duas 
fontes de reset: o power-on reset (POR) e o power-up clear (PUC). Diferentes fontes de 
eventos e sinais podem disparar o circuito de reset do sistema. 
 
 
Página88 
 
 
 
O POR é um reset do dispositivo. Um POR só pode ser gerado caso ocorra um destes três 
eventos: 
• O dispositivo é alimentado (Powering up); 
• Um nível baixo (0 V) é inserido no terminal RST/NMI, quando este pino está 
configurado para o modo de reset; 
• Um baixo nível de tensão é detectado pelo módulo SVS, quando PORON = 1. 
 
Um PUC sempre é gerado quando um POR é gerado, porém um POR não é gerado quando 
acontece um PUC. Um PUC pode ser disparado pelos seguintes eventos: 
• Um sinal POR; 
• Expirou o tempo estipulado pelo Watchdog timer quando estava em modo watchdog; 
• Houve uma violação de segurança do Watchdog timer; 
• Houve uma violaçào de segurança no acesso a memória Flash. 
 
O Brownout Reset (BOR) é um hardware capaz de detectar se existem variações na 
tensão de alimentação do dispositivo, resetando-o a fim de evitar problemas de 
funcionamento. 
 
 
Página 89 
 
17.2. NMI – Interrupções não mascaráveis 
 
Estas três interrupções não podem ser desabilitadas pelo bit de controle geral de 
interrupções (GIE). Elas têm bits específicos para isto (ACCVIE, NMIIE, OFIE). Quando uma 
destas interrupções é aceita, todas as demais tem o seu bit de habilitação resetado. 
 
O programa dará um salto em sua execução para o endereço armazenado no vetor de 
interrupção não mascarável (0FFFCh). Será necessário que o software do usuário set 
novamente os bits destas interrupções para que elas possam ocorrer novamente. 
 
As interrupções não mascaráveis são: 
• Um borda de descida/subida no pino RST/NMI pin, quando este é configurado para o 
modo NMI; 
• Ocorre um falha no oscilador; 
• Ocorre uma violação de acesso a memória flash. 
 
17.3. Interrupções mascaráveis 
 
As interrupções mascaráveis são geradas por todos os periféricos que possuem capacidade 
de interrupção, incluindo o watchdog timer. Cada fonte de interrupção mascarável tem um bit 
que habilita ou desabilita seu funcionamento, sendo que existe ainda um bit de controle 
geral, chamado de GIE (General Interrupt Enable), presente no status register (SR). 
 
17.4. O processamento de uma interrupção 
 
Quando uma interrupção é solicitada por um periférico, é necessário que os bits de 
habilitação individual e geral (GIE) estejam setados. Isto fará com que o programa sofra um 
desvio para uma rotina de interrupção. 
 
 
Página 90 
 
17.4.1. Entrada em uma interrupção 
 
A latência para o tratamento de um interrupção dura 6 ciclos de máquina, começando pela 
aceitação de uma interrupção e terminando com a execução da primeira instrução contida 
na rotina de atendimento de interrupção. A execução lógica é descrita a seguir: 
 
1) Qualquer instrução que esteja sendo executada é finalizada; 
 
2) O valor do PC, que aponta para a próxima instrução que deveria ser executada, é 
salvo na pilha (pushed onto the stack); 
 
3) O valor do SR é salvo na pilha (pushed onto the stack); 
 
4) A interrupção que tiver a maior prioridade é selecionada, caso multiplas 
interrupções ocorram simultaneamente; 
 
5) Uma requisição de interrupção reseta o flag de interrupção dos periféricos que tem 
fonte única de interrupção (o conversor AD de 12 bits, por exemplo). Se o 
periférico tiver múltiplas flags de interrupção (portas P1 e P2, por exemplo), então 
o reset destas flags deverá acontecer por software; 
 
6) O registrador SR tem todos os seus bits zerados, com excessão do SCG0, que 
não é alterado. Isto retira o microcontrolador de qualquer LPM em que ele se 
encontra. Como o GIE também é zerado, as próximas interrupções ficam 
desabilitadas. 
 
7) O conteúdo do vetor de interrupção correspondente a quem fez a solicitação é 
carregado no PC, que passará a executar o programa a partir do que houver escrito 
ali. 
 
17.4.2. Saída de uma interrupção 
 
Toda interrupção é terminada quando uma instrução RETI (return from an interrupt service 
routine) é encontrada. Este retorno gasta 5 ciclos de máquina para executar as seguintes 
ações: 
 
1) O registrador SR é restaurado da pilha (pops from the stack) com todos os valores 
ajustados previamente (GIE, CPUOFF, etc.); 
 
2) O valor do PC é restaurado da pilha (pops from the stack) e inicia a execução no 
ponto exato em que parou ao ser interrompido. 
 
Página 91 
 
 
 
O aninhamento de interrupções é habilitado quando, durante o tratamento de uma 
interrupção, o usuário seta o bit GIE. Neste caso, havendo uma nova interrupção os 
procedimentos mostrados ocorrerão novamente, seguindo a ordem de prioridades de 
atendimento de interrupções. 
 
17.5. Os vetores de interrupção 
 
Os vetores de interrupção tem um endereçamento fixo e conhecido em todos os dispositivos 
das famílias MSP430, indo de 0FFFFh até 0FFC0h. Nestes dados, que tem 16 bits, são 
salvos os endereços onde estarão os programas que farão o atendimento as rotinas de 
interrupção. Dependendo do número de periféricos, os dispositivos MSP430 podem ter mais 
ou menos vetores de interrupção, por isto é sempre necessária uma consulta ao datasheet 
de cada dispositivo. 
 
 
Página 92 
 
17.5.1. Vetores de interrupção na família 2 (MSP430F2013) 
 
 
 
NOTES: 
1. Um reset é gerado toda vez que a CPU tenta carregar um endereço no PC que esteja for 
a do range de memória disponível no dispositivo. 
2. Fonte de múltiplos flags. 
3. A flag de interrupção é alocada no módulo. 
4. Não mascarável: o bit de interrupção individual pode ser desabilitado por um evento de 
interrupção, mas geralmente isto não é possível. 
5. Os endereços de vetores de interrupção entre 0FFDEh e 0FFC0h não são utilizados neste 
dispositivo, podendo ser utilizado como área de código regular, onde será armazenado o 
programa. 
 
 
Página 93 
 
17.5.2. Declaração dos Vetores de interrupção no MSP430F2013 
 
/************************************************************ 
* Interrupt Vectors (offset from 0xFFE0) 
************************************************************/ 
#define PORT1_VECTOR (2 * 2u) /* 0xFFE4 Port 1 */ 
#define PORT2_VECTOR (3 * 2u) /* 0xFFE6 Port 2 */ 
#define USI_VECTOR (4 * 2u) /* 0xFFE8 USI */ 
#define SD16_VECTOR (5 * 2u) /* 0xFFEA Sigma Delta ADC */ 
#define TIMERA1_VECTOR (8 * 2u) /* 0xFFF0 Timer A CC1, TA */ 
#define TIMERA0_VECTOR (9 * 2u) /* 0xFFF2 Timer A CC0 */ 
#define WDT_VECTOR (10 * 2u) /* 0xFFF4 Watchdog Timer */ 
#define NMI_VECTOR (14 * 2u) /* 0xFFFC Non-maskable */ 
#define RESET_VECTOR (15 * 2u) /* 0xFFFE Reset [Highest Priority] */ 
 
17.5.3. Vetores de interrupção na família 4 (MSP430FG4618) 
 
 
 
 
Página 94 
 
NOTES: 
1. Fonte de múltiplos flags. 
2. A flag de interrupção é alocada no módulo. 
3. Um reset é gerado toda vez que a CPU tenta carregar um endereço no PC que esteja for 
a do range de memória disponível no dispositivo. (Não mascarável: o bit de interrupção 
individual pode ser desabilitado por um evento de interrupção, mas geralmente isto não é 
possível. 
4. Os endereços de vetores de interrupção entre 0FFDAh e 0FFC0h não são utilizados neste 
dispositivo, podendo ser utilizado como área de código regular, onde será armazenado o 
programa. 
5. Violação na chave de acesso (KEYV e ACCVIFG), somente são aplicáveis aos 
dispositivos do tipo F. 
 
17.5.4. Declaração dos Vetores de interrupção no MSP430FG4618 
 
/************************************************************ 
* Interrupt Vectors (offset from 0xFFC0) 
************************************************************/ 
#define DAC12_VECTOR (14 * 2u) /* 0xFFDC DAC 12 */ 
#define DMA_VECTOR (15 * 2u) /* 0xFFDE DMA */ 
#define BASICTIMER_VECTOR (16 * 2u) /* 0xFFE0 Basic Timer / RTC */ 
#define PORT2_VECTOR (17 * 2u) /* 0xFFE2 Port 2 */ 
#define USART1TX_VECTOR (18 * 2u) /* 0xFFE4 USART 1 Transmit */ 
#define USART1RX_VECTOR (19 * 2u) /* 0xFFE6 USART 1 Receive */ 
#define PORT1_VECTOR (20 * 2u) /* 0xFFE8 Port 1 */ 
#define TIMERA1_VECTOR (21 * 2u) /* 0xFFEA Timer A CC1-2, TA */#define TIMERA0_VECTOR (22 * 2u) /* 0xFFEC Timer A CC0 */ 
#define ADC12_VECTOR (23 * 2u) /* 0xFFEE ADC */ 
#define USCIAB0TX_VECTOR (24 * 2u) /* 0xFFF0 USCI A0/B0 Transmit */ 
#define USCIAB0RX_VECTOR (25 * 2u) /* 0xFFF2 USCI A0/B0 Receive */ 
#define WDT_VECTOR (26 * 2u) /* 0xFFF4 Watchdog Timer */ 
#define COMPARATORA_VECTOR (27 * 2u) /* 0xFFF6 Comparator A */ 
#define TIMERB1_VECTOR (28 * 2u) /* 0xFFF8 Timer B CC1-2, TB */ 
#define TIMERB0_VECTOR (29 * 2u) /* 0xFFFA Timer B CC0 */ 
#define NMI_VECTOR (30 * 2u) /* 0xFFFC Non-maskable */ 
#define RESET_VECTOR (31 * 2u) /* 0xFFFE Reset [Highest Priority] */ 
 
 
Página 95 
 
18. EXERCÍCIOS: BOTÕES E LEDS EM LOW POWER MODE. 
 
Já foi identificado no diagrama elétrico da Experimenter Board, mostrado no item 9, as 
seguintes conexões, envolvendo pinos do MSP430FG4618 e hardwares externos: 
 
a) Botão S1 pino P1.0; 
b) Botão S2 pino P1.1; 
c) LED1 pino P2.1; 
d) LED2 pino P2.2; 
e) LED4 pino P5.1. 
 
Com estas informações faça modificações na segunda seqüência de exercícios, de modo 
que o programa fique em Low Power Mode e apenas saia deste estado para executar 
ações, fazendo economia de energia e realizando as mesmas atividades anteriores. 
 
18.1. 1 botão e 1 Led (EXERCÍCIO–9) 
 
Ao pressionar o botão S1 deve acender o LED1. Se o botão não estiver pressionado, o 
LED1 deve se manter apagado. 
 
18.2. 2 botões e 2 Leds (EXERCÍCIO–10) 
 
Ao pressionar o botão S1 deve apagar o LED1. Se o botão S1 não estiver pressionado, o 
LED1 deve se manter aceso. Ao mesmo tempo se o botão S2 for pressionado, o LED2 
deve se apagar. Se o botão S2 não estiver pressionado, o LED2 deve se manter aceso. 
 
18.3. 1 botão, 1 Led e temporização com Basic Timer 1 
(EXERCÍCIO–11) 
 
Ao pressionar o botão S2 deve acender o LED1, que deve permanecer aceso por 500 ms. 
Se o botão não estiver pressionado, o LED1 deve se manter apagado. 
 
18.4. 2 botões, 2 Leds e temporização Basic Timer 1 (EXERCÍCIO–12) 
 
Ao pressionar o botão S2 deve apagar o LED1, o que deve acontecer por 500 ms. Se o 
botão não estiver pressionado, o LED1 deve se manter aceso. Ao mesmo tempo, se o 
botão S1 estiver pressionado o LED2 deve ficar apagado, o que também deve acontecer 
por 500 ms. Se o botão não estiver pressionado, o LED2 deve se manter aceso

Outros materiais

Outros materiais